Exemplo n.º 1
0
        public object visitClassStmt(Stmt.Class stmt)
        {
            object superclass = null;

            if (stmt.superclass != null)
            {
                superclass = Evaluate(stmt.superclass);
                if (!(superclass is LoxClass))
                {
                    throw new RuntimeError(stmt.superclass.name, "Superclass must be a class.");
                }
            }

            int classIndex = environment.Define(null);

            if (stmt.superclass != null)
            {
                environment = new Environment(enclosing: environment);
                environment.Define(superclass);
            }

            Dictionary <string, LoxFunction> methods = new Dictionary <string, LoxFunction>();

            foreach (Stmt.Function method in stmt.methods)
            {
                LoxFunction loxFunc = new LoxFunction(method, closure: environment, method.name.lexeme == "init");
                methods.Add(method.name.lexeme, loxFunc);
            }
            Dictionary <string, LoxFunction> staticMethods = new Dictionary <string, LoxFunction>();

            foreach (Stmt.Function method in stmt.staticMethods)
            {
                LoxFunction loxFunc = new LoxFunction(method, closure: environment, false);
                staticMethods.Add(method.name.lexeme, loxFunc);
            }
            LoxClass loxClass = new LoxClass(stmt.name.lexeme, (LoxClass)superclass, staticMethods, methods);

            if (stmt.superclass != null)
            {
                environment = environment.enclosing;
            }

            environment.Assign(classIndex, loxClass);

            return(null);
        }
Exemplo n.º 2
0
        public object visitClassStmt(Stmt.Class stmt)
        {
            ClassType enclosingClass = currentClass;

            currentClass = ClassType.CLASS;

            Declare(stmt.name);
            Define(stmt.name);
            MarkUnused(stmt.name);

            if (stmt.superclass != null)
            {
                if (stmt.superclass.name.lexeme == stmt.name.lexeme)
                {
                    Lox.ReportError(stmt.superclass.name, "Class cannot inherit from itself.");
                }
                else
                {
                    currentClass = ClassType.SUBCLASS;
                    Resolve(stmt.superclass);
                    BeginScope();
                    Peek(scopes)["super"]     = true;
                    Peek(varIndices)["super"] = GetNextIndex();
                }
            }

            BeginScope();
            // "this" is the only variable we declare at class scope. That means that when ResolveLocal()
            // is called on "this" in the methods, the resolver will compute depth = 1, index = 0.
            // In LoxFunction.Bind(), we create a new function with a closure whose only variable is "this" (at index 0)
            // and since it's a closure, it has a depth of 1 from the function body.
            Peek(scopes)["this"]     = true;
            Peek(varIndices)["this"] = GetNextIndex(); // TODO maybe change to 0

            foreach (Stmt.Function method in stmt.staticMethods)
            {
                Declare(method.name);
                Define(method.name);
                ResolveFunction(method.parameters, method.body, FunctionType.STATIC);
            }

            foreach (Stmt.Function method in stmt.methods)
            {
                Declare(method.name);
                Define(method.name);
                FunctionType declaration = FunctionType.METHOD;
                if (method.name.lexeme == "init")
                {
                    declaration = FunctionType.INITIALIZER;
                }
                ResolveFunction(method.parameters, method.body, declaration);
            }

            EndScope();

            if (stmt.superclass != null)
            {
                EndScope();
            }

            currentClass = enclosingClass;
            return(null);
        }