public object VisitClassStmt(Class stmt) { Environment.Define(stmt.Name.Lexeme, null); Dictionary <String, CoxFunction> methods = new Dictionary <String, CoxFunction>(); Object superclass = null; if (stmt.Superclass != null) { superclass = Evaluate(stmt.Superclass); if (!(superclass is CoxClass)) { throw new RuntimeError(stmt.Name, "Superclass must be a class."); } Environment = new Environment(Environment); Environment.Define("super", superclass); } foreach (Function method in stmt.Methods) { CoxFunction function = new CoxFunction(method, Environment, method.Name.Lexeme.Equals("init")); methods.Add(method.Name.Lexeme, function); } CoxClass klass = new CoxClass(stmt.Name.Lexeme, (CoxClass)superclass, methods); if (superclass != null) { Environment = Environment.Enclosing; } Environment.Assign(stmt.Name, klass); return(null); }
public CoxFunction FindMethod(CoxInstance instance, String name) { CoxClass klass = this; while (klass != null) { if (klass.Methods.ContainsKey(name)) { return(klass.Methods[name].Bind(instance)); } klass = klass.Superclass; } return(null); }
public object VisitSuperExpr(Super expr) { int distance = Locals[expr]; CoxClass superclass = (CoxClass)Environment.GetAt(distance, "super"); // "this" is always one level nearer than "super"'s environment. CoxInstance receiver = (CoxInstance)Environment.GetAt(distance - 1, "this"); CoxFunction method = superclass.FindMethod(receiver, expr.Method.Lexeme); if (method == null) { throw new RuntimeError(expr.Method, $"Undefined property '{expr.Method.Lexeme}'."); } return(method); }
public CoxClass(String name, CoxClass superclass, Dictionary <String, CoxFunction> methods) { Name = name; Superclass = superclass; Methods = methods; }
public CoxInstance(CoxClass klass) { Klass = klass; }