private void Resolve(Stmt statement) { if (statement is BlockStmt block) { BeginScope(); Resolve(block.Statements); EndScope(); } else if (statement is VariableStmt variable) { Declare(variable.Name); if (variable.Initializer != null) { Resolve(variable.Initializer); } Define(variable.Name); } else if (statement is FunctionStmt functionStatement) { Declare(functionStatement.Name); Define(functionStatement.Name); ResolveFunction(functionStatement, FunctionType.Function); } else if (statement is ConditionalStmt conditional) { Resolve(conditional.Condition); Resolve(conditional.ThenBranch); if (conditional.ElseBranch != null) { Resolve(conditional.ElseBranch); } } else if (statement is ReturnStmt returnStmt) { if (currentFunction == FunctionType.None) { Program.Error(returnStmt.Keyword, "Cannot return from top-level code."); } if (returnStmt.Value != null) { if (currentFunction == FunctionType.Initializer) { Program.Error(returnStmt.Keyword, "Cannot return a value from an initializer."); } Resolve(returnStmt.Value); } } else if (statement is WhileStmt whileStmt) { Resolve(whileStmt.Condition); Resolve(whileStmt.Body); } else if (statement is ExpressionStmt expression) { Resolve(expression.Expression); } else if (statement is PrintStmt print) { Resolve(print.Expression); } else if (statement is ClassStmt cls) { var enclosingClass = currentClass; currentClass = ClassType.Class; Declare(cls.Name); Define(cls.Name); if (cls.Superclass != null && cls.Name.Lexeme.Equals(cls.Superclass.Name.Lexeme)) { Program.Error(cls.Superclass.Name, "A class cannot inherit from itself."); } if (cls.Superclass != null) { currentClass = ClassType.Subclass; Resolve(cls.Superclass); } if (cls.Superclass != null) { BeginScope(); scopes.Peek()["super"] = true; } BeginScope(); scopes.Peek().Add("this", true); foreach (var method in cls.Methods) { var declaration = method.Name.Lexeme.Equals(LoxClass.ConstructorName) ? FunctionType.Initializer : FunctionType.Method; ResolveFunction(method, declaration); } EndScope(); if (cls.Superclass != null) { EndScope(); } currentClass = enclosingClass; } else { // After print statment was forgotten throw new System.Exception("You have forgotten something, haven't you?"); } }
private Unit execute(Stmt stmt) => stmt.accept(this);
public If(Expr condition, Stmt thenBranch, Stmt elseBranch) { this.condition = condition; this.thenBranch = thenBranch; this.elseBranch = elseBranch; }
private void Execute(Stmt statement) { if (statement is PrintStmt p) { Print(p.Expression); return; } if (statement is VariableStmt s) { object value = s.Initializer is null ? null : Evaluate(s.Initializer); env.Define(s.Name.Lexeme, value); return; } if (statement is ExpressionStmt e) { Discard(e.Expression); return; } if (statement is BlockStmt b) { ExecuteBlock(b.Statements, new Environment(env)); return; } if (statement is ConditionalStmt c) { if (IsTruthy(Evaluate(c.Condition))) { Execute(c.ThenBranch); } else if (c.ElseBranch != null) { Execute(c.ElseBranch); } return; } if (statement is WhileStmt w) { while (IsTruthy(Evaluate(w.Condition))) { Execute(w.Body); } return; } if (statement is FunctionStmt f) { var fn = new LoxFunction(f, env, false); env.Define(f.Name.Lexeme, fn); return; } if (statement is ClassStmt cl) { LoxClass superclass = null; if (cl.Superclass != null) { var scls = Evaluate(cl.Superclass); if (scls is LoxClass super) { superclass = super; } else { throw new RuntimeException(cl.Superclass.Name, "Superclass must be a class."); } } env.Define(cl.Name.Lexeme, null); if (cl.Superclass != null) { env = new Environment(env); env.Define("super", superclass); } var methods = new Dictionary <string, LoxFunction>(); foreach (var method in cl.Methods) { var func = new LoxFunction(method, env, method.Name.Lexeme.Equals(LoxClass.ConstructorName)); methods.Add(method.Name.Lexeme, func); } var cls = new LoxClass(cl.Name.Lexeme, superclass, methods); if (cl.Superclass != null) { env = env.Enclosing; } env.Assign(cl.Name, cls); return; } if (statement is ReturnStmt r) { object value = null; if (r.Value != null) { value = Evaluate(r.Value); } throw new ReturnException(value); } throw new RuntimeException("Unknown statement type."); }
public While(Expr condition, Stmt body) { this.condition = condition; this.body = body; }