simple while
This commit is contained in:
		
							parent
							
								
									8adfb71887
								
							
						
					
					
						commit
						6bb2408269
					
				
					 5 changed files with 54 additions and 5 deletions
				
			
		|  | @ -117,3 +117,11 @@ func (as *AstStringer) visitIfStmt(i *IfStmt) { | ||||||
| func (as *AstStringer) visitEnvStmt(e *EnvStmt) { | func (as *AstStringer) visitEnvStmt(e *EnvStmt) { | ||||||
| 	as.str.WriteString("(env)") | 	as.str.WriteString("(env)") | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (as *AstStringer) visitWhileStmt(w *WhileStmt) { | ||||||
|  | 	as.str.WriteString("(while ") | ||||||
|  | 	w.cond.accept(as) | ||||||
|  | 	as.str.WriteString(" ") | ||||||
|  | 	w.body.accept(as) | ||||||
|  | 	as.str.WriteString(")") | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								env.go
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								env.go
									
										
									
									
									
								
							|  | @ -33,5 +33,10 @@ func (env *Environment) exists(key string) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (env *Environment) set(key string, val any) { | func (env *Environment) set(key string, val any) { | ||||||
|  | 
 | ||||||
|  | 	if env.parent != nil && env.parent.exists(key) { | ||||||
|  | 		env.parent.set(key, val) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	env.values[key] = val | 	env.values[key] = val | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -210,7 +210,12 @@ func (i *Interpreter) visitEnvStmt(e *EnvStmt) { | ||||||
| 		fmt.Printf("%*s", ident, "") | 		fmt.Printf("%*s", ident, "") | ||||||
| 		fmt.Printf("%+v\n", *e) | 		fmt.Printf("%+v\n", *e) | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|  | func (i *Interpreter) visitWhileStmt(w *WhileStmt) { | ||||||
|  | 	for isTruthy(i.evaluate(w.cond)) { | ||||||
|  | 		w.body.accept(i) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (i *Interpreter) panic(re *RuntimeError) { | func (i *Interpreter) panic(re *RuntimeError) { | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								parser.go
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								parser.go
									
										
									
									
									
								
							|  | @ -66,14 +66,20 @@ func (p *Parser) varDecl() Stmt { | ||||||
| 	return &VarStmt{name, initializer} | 	return &VarStmt{name, initializer} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // statement -> exprStmt | printStmt | block | ifStmt | env | // statement ->  exprStmt | ||||||
|  | // | ||||||
|  | //	| whileStmt | ||||||
|  | //	| printStmt | ||||||
|  | //	| blockStmt | ||||||
|  | //	| ifStmt | ||||||
|  | //	| env | ||||||
| func (p *Parser) statement() Stmt { | func (p *Parser) statement() Stmt { | ||||||
| 	if p.match(PRINT) { | 	if p.match(PRINT) { | ||||||
| 		return p.printStmt() | 		return p.printStmt() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if p.match(LEFT_BRACE) { | 	if p.match(LEFT_BRACE) { | ||||||
| 		return p.block() | 		return p.blockStmt() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if p.match(IF) { | 	if p.match(IF) { | ||||||
|  | @ -84,6 +90,10 @@ func (p *Parser) statement() Stmt { | ||||||
| 		return p.envStmt() | 		return p.envStmt() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if p.match(WHILE) { | ||||||
|  | 		return p.whileStmt() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return p.exprStmt() | 	return p.exprStmt() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -111,8 +121,8 @@ func (p *Parser) printStmt() Stmt { | ||||||
| 	return &PrintStmt{expr} | 	return &PrintStmt{expr} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // block -> "{" statement* "}" | // blockStmt -> "{" statement* "}" | ||||||
| func (p *Parser) block() Stmt { | func (p *Parser) blockStmt() Stmt { | ||||||
| 
 | 
 | ||||||
| 	stmts := []Stmt{} | 	stmts := []Stmt{} | ||||||
| 	for !p.check(RIGHT_BRACE) && !p.isAtEnd() { | 	for !p.check(RIGHT_BRACE) && !p.isAtEnd() { | ||||||
|  | @ -140,6 +150,16 @@ func (p *Parser) ifStmt() Stmt { | ||||||
| 	return &IfStmt{name, expr, then, or} | 	return &IfStmt{name, expr, then, or} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // while -> "while" "(" expression ")" statement | ||||||
|  | func (p *Parser) whileStmt() Stmt { | ||||||
|  | 	p.consume(LEFT_PAREN, "Expect '(' after 'while'.") | ||||||
|  | 	cond := p.expression() | ||||||
|  | 	p.consume(RIGHT_PAREN, "Expect ')' after 'while' expression.") | ||||||
|  | 	body := p.statement() | ||||||
|  | 
 | ||||||
|  | 	return &WhileStmt{cond, body} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // env -> "env" ";" | // env -> "env" ";" | ||||||
| func (p *Parser) envStmt() Stmt { | func (p *Parser) envStmt() Stmt { | ||||||
| 	p.consume(SEMICOLON, "Expect ';' after 'env'.") | 	p.consume(SEMICOLON, "Expect ';' after 'env'.") | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								stmt.go
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								stmt.go
									
										
									
									
									
								
							|  | @ -7,6 +7,7 @@ type StmtVisitor interface { | ||||||
| 	visitPrintStmt(p *PrintStmt) | 	visitPrintStmt(p *PrintStmt) | ||||||
| 	visitBlockStmt(b *BlockStmt) | 	visitBlockStmt(b *BlockStmt) | ||||||
| 	visitEnvStmt(e *EnvStmt) | 	visitEnvStmt(e *EnvStmt) | ||||||
|  | 	visitWhileStmt(w *WhileStmt) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type Stmt interface { | type Stmt interface { | ||||||
|  | @ -40,12 +41,18 @@ type IfStmt struct { | ||||||
| 	or   Stmt | 	or   Stmt | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type WhileStmt struct { | ||||||
|  | 	cond Expr | ||||||
|  | 	body Stmt | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (i *IfStmt) stmt()    {} | func (i *IfStmt) stmt()    {} | ||||||
|  | func (e *EnvStmt) stmt()   {} | ||||||
| func (vs *VarStmt) stmt()  {} | func (vs *VarStmt) stmt()  {} | ||||||
| func (es *ExprStmt) stmt() {} | func (es *ExprStmt) stmt() {} | ||||||
| func (p *PrintStmt) stmt() {} | func (p *PrintStmt) stmt() {} | ||||||
| func (b *BlockStmt) stmt() {} | func (b *BlockStmt) stmt() {} | ||||||
| func (e *EnvStmt) stmt()   {} | func (w *WhileStmt) stmt() {} | ||||||
| 
 | 
 | ||||||
| func (p *PrintStmt) accept(v StmtVisitor) { | func (p *PrintStmt) accept(v StmtVisitor) { | ||||||
| 	v.visitPrintStmt(p) | 	v.visitPrintStmt(p) | ||||||
|  | @ -70,3 +77,7 @@ func (i *IfStmt) accept(v StmtVisitor) { | ||||||
| func (e *EnvStmt) accept(v StmtVisitor) { | func (e *EnvStmt) accept(v StmtVisitor) { | ||||||
| 	v.visitEnvStmt(e) | 	v.visitEnvStmt(e) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (w *WhileStmt) accept(v StmtVisitor) { | ||||||
|  | 	v.visitWhileStmt(w) | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue