Search in sources :

Example 6 with BlockScope

use of com.github.anba.es6draft.ast.scope.BlockScope in project es6draft by anba.

the class DefaultCodeGenerator method ClassDefinitionEvaluation.

/**
 * 14.5.14 Runtime Semantics: ClassDefinitionEvaluation
 *
 * @param def
 *            the class definition node
 * @param className
 *            the class name or {@code null} if not present
 * @param mv
 *            the code visitor
 */
protected final void ClassDefinitionEvaluation(ClassDefinition def, Name className, CodeVisitor mv) {
    mv.enterVariableScope();
    List<Expression> classDecoratorsList = def.getDecorators();
    Variable<Callable[]> classDecorators = null;
    if (!classDecoratorsList.isEmpty()) {
        classDecorators = mv.newVariable("classDecorators", Callable[].class);
        mv.anewarray(classDecoratorsList.size(), Types.Callable);
        mv.store(classDecorators);
        int index = 0;
        for (Expression decorator : classDecoratorsList) {
            mv.astore(classDecorators, index++, __ -> {
                expressionBoxed(decorator, mv);
                CheckCallable(decorator, mv);
            });
        }
    }
    mv.enterClassDefinition();
    // step 1 (not applicable)
    // steps 2-4
    BlockScope scope = def.getScope();
    Variable<DeclarativeEnvironmentRecord> classScopeEnvRec = null;
    if (scope != null) {
        assert scope.isPresent() == (className != null);
        if (scope.isPresent()) {
            // stack: [] -> [classScope]
            newDeclarativeEnvironment(scope, mv);
            classScopeEnvRec = mv.newVariable("classScopeEnvRec", DeclarativeEnvironmentRecord.class);
            getEnvRec(classScopeEnvRec, mv);
            if (className != null) {
                // stack: [classScope] -> [classScope]
                Name innerName = scope.resolveName(className);
                BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(classScopeEnvRec, innerName);
                op.createImmutableBinding(classScopeEnvRec, innerName, true, mv);
            }
            // stack: [classScope] -> []
            pushLexicalEnvironment(mv);
        }
        mv.enterScope(def);
    }
    // steps 5-7
    // stack: [] -> [<constructorParent,proto>]
    Expression classHeritage = def.getHeritage();
    if (classHeritage == null) {
        mv.loadExecutionContext();
        mv.invoke(Methods.ClassOperations_getDefaultClassProto);
    } else if (classHeritage instanceof NullLiteral) {
        mv.loadExecutionContext();
        mv.invoke(Methods.ClassOperations_getClassProto_Null);
    } else {
        expressionBoxed(classHeritage, mv);
        mv.loadExecutionContext();
        mv.lineInfo(def);
        mv.invoke(Methods.ClassOperations_getClassProto);
    }
    // stack: [<protoParent,constructorParent>] -> [<protoParent,constructorParent>]
    Variable<OrdinaryObject> proto = mv.newVariable("proto", OrdinaryObject.class);
    mv.dup();
    mv.aload(0, Types.ScriptObject);
    mv.loadExecutionContext();
    mv.invoke(Methods.ClassOperations_createProto);
    mv.store(proto);
    // stack: [<protoParent,constructorParent>] -> [constructorParent, proto]
    mv.aload(1, Types.ScriptObject);
    mv.load(proto);
    // Push the private-name environment to ensure private names are accessible in the constructor.
    BlockScope bodyScope = def.getBodyScope();
    if (bodyScope != null) {
        List<Name> privateBoundNames = PrivateBoundNames(def);
        assert bodyScope.isPresent() == !privateBoundNames.isEmpty();
        if (bodyScope.isPresent()) {
            // stack: [] -> [classPrivateEnv]
            newDeclarativeEnvironment(bodyScope, mv);
            Variable<DeclarativeEnvironmentRecord> classPrivateEnvRec = mv.newVariable("classPrivateEnvRec", DeclarativeEnvironmentRecord.class);
            getEnvRec(classPrivateEnvRec, mv);
            HashSet<Name> declaredPrivateNames = new HashSet<>();
            for (Name name : privateBoundNames) {
                // FIXME: spec bug - missing check for already declared private names for getter/setter pairs
                if (declaredPrivateNames.add(name)) {
                    BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(classPrivateEnvRec, name);
                    op.createImmutableBinding(classPrivateEnvRec, name, true, mv);
                }
            }
            // stack: [classPrivateEnv] -> []
            pushLexicalEnvironment(mv);
        }
        mv.enterScope(bodyScope);
    }
    // steps 8-9
    // stack: [constructorParent, proto] -> [constructorParent, proto, <rti>]
    MethodName method = mv.compile(def, codegen::classDefinition);
    // Runtime Semantics: Evaluation -> MethodDefinition
    mv.invoke(method);
    // step 10 (not applicable)
    // steps 11-18
    // stack: [constructorParent, proto, <rti>] -> [F]
    mv.iconst(classHeritage != null);
    mv.loadExecutionContext();
    mv.lineInfo(def);
    mv.invoke(Methods.ClassOperations_EvaluateConstructorMethod);
    // stack: [F] -> []
    Variable<OrdinaryConstructorFunction> F = mv.newVariable("F", OrdinaryConstructorFunction.class);
    mv.store(F);
    // steps 19-21
    ClassPropertyGenerator.Result result = ClassPropertyEvaluation(codegen, def, F, proto, mv);
    Variable<Object[]> methodDecorators = result.methodDecorators;
    if (!classDecoratorsList.isEmpty()) {
        int index = 0;
        for (Expression decorator : classDecoratorsList) {
            mv.aload(classDecorators, index++, Types.Callable);
            invokeDynamicCall(mv, decorator, mv.executionContext(), mv.undefinedValue(), F);
            mv.pop();
        }
    }
    if (methodDecorators != null) {
        LabelledHashKey hashKey = new LabelledHashKey(def, "decorators");
        MethodName decoratorsMethod = mv.compile(hashKey, () -> classMethodDecorators(def, mv));
        // 0 = hint for stacktraces to omit this frame
        mv.lineInfo(0);
        mv.invoke(decoratorsMethod, mv.executionContext(), F, proto, methodDecorators);
    }
    if (scope != null) {
        // steps 22-23 (moved)
        if (className != null) {
            // stack: [] -> []
            Name innerName = scope.resolveName(className);
            BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(classScopeEnvRec, innerName);
            op.initializeBinding(classScopeEnvRec, innerName, F, mv);
        }
    }
    if (result.instanceClassField != null || result.instanceClassMethods != null) {
        MethodName initializer = compileClassFieldInitializer(def, MethodDefinition.MethodAllocation.Prototype, mv);
        // stack: [] -> [F]
        mv.load(F);
        // stack: [F] -> [F, initializer]
        mv.load(proto);
        mv.invoke(initializer);
        if (result.instanceClassField != null) {
            mv.load(result.instanceClassField);
        } else {
            mv.anull();
        }
        if (result.instanceClassMethods != null) {
            mv.load(result.instanceClassMethods);
        } else {
            mv.anull();
        }
        mv.loadExecutionContext();
        mv.invoke(Methods.ClassOperations_CreateClassFieldInitializer);
        // stack: [F, initializer] -> []
        mv.invoke(Methods.ClassOperations_setInstanceFieldsInitializer);
    }
    // Class fields: Call InitializeStaticFields.
    if (result.staticClassField != null) {
        MethodName initializer = compileClassFieldInitializer(def, MethodDefinition.MethodAllocation.Class, mv);
        // stack: [] -> [staticInitializer]
        mv.load(F);
        mv.invoke(initializer);
        mv.load(result.staticClassField);
        mv.loadExecutionContext();
        mv.invoke(Methods.ClassOperations_CreateStaticClassFieldInitializer);
        // stack: [staticInitializer] -> []
        invokeDynamicCall(mv, def, mv.executionContext(), F);
        mv.pop(ValType.Any);
    }
    if (bodyScope != null) {
        mv.exitScope();
        if (bodyScope.isPresent()) {
            popLexicalEnvironment(mv);
        }
    }
    if (scope != null) {
        mv.exitScope();
        if (scope.isPresent()) {
            popLexicalEnvironment(mv);
        }
    }
    // stack: [] -> [F]
    mv.load(F);
    mv.exitVariableScope();
    // step 24 (return F)
    mv.exitClassDefinition();
}
Also used : Name(com.github.anba.es6draft.ast.scope.Name) OrdinaryConstructorFunction(com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction) BlockScope(com.github.anba.es6draft.ast.scope.BlockScope) OrdinaryObject(com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject) LabelledHashKey(com.github.anba.es6draft.compiler.CodeVisitor.LabelledHashKey) DeclarativeEnvironmentRecord(com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord) HashSet(java.util.HashSet)

Example 7 with BlockScope

use of com.github.anba.es6draft.ast.scope.BlockScope in project es6draft by anba.

the class StatementGenerator method visit.

/**
     * Extension: 'let' statement
     */
@Override
public Completion visit(LetStatement node, CodeVisitor mv) {
    BlockScope scope = node.getScope();
    if (scope.isPresent()) {
        mv.enterVariableScope();
        Variable<LexicalEnvironment<DeclarativeEnvironmentRecord>> env = mv.newVariable("env", LexicalEnvironment.class).uncheckedCast();
        Variable<DeclarativeEnvironmentRecord> envRec = mv.newVariable("envRec", DeclarativeEnvironmentRecord.class);
        newDeclarativeEnvironment(scope, mv);
        mv.store(env);
        getEnvRec(env, envRec, mv);
        for (LexicalBinding lexical : node.getBindings()) {
            Binding binding = lexical.getBinding();
            Expression initializer = lexical.getInitializer();
            for (Name name : BoundNames(binding)) {
                BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(envRec, name);
                op.createMutableBinding(envRec, name, false, mv);
            }
            if (initializer == null) {
                // LexicalBinding : BindingIdentifier
                assert binding instanceof BindingIdentifier;
                Name name = ((BindingIdentifier) binding).getName();
                /* steps 1-2 */
                InitializeBoundNameWithUndefined(envRec, name, mv);
            } else if (binding instanceof BindingIdentifier) {
                // LexicalBinding : BindingIdentifier Initializer
                Name name = ((BindingIdentifier) binding).getName();
                /* steps 1-7 */
                InitializeBoundNameWithInitializer(codegen, envRec, name, initializer, mv);
            } else {
                // LexicalBinding : BindingPattern Initializer
                assert binding instanceof BindingPattern;
                /* steps 1-3 */
                expressionBoxed(initializer, mv);
                /* steps 4-5 */
                BindingInitialization(codegen, envRec, (BindingPattern) binding, mv);
            }
        }
        mv.load(env);
        pushLexicalEnvironment(mv);
        mv.exitVariableScope();
    }
    mv.enterScope(node);
    Completion result = node.getStatement().accept(this, mv);
    mv.exitScope();
    if (scope.isPresent() && !result.isAbrupt()) {
        popLexicalEnvironment(mv);
    }
    return result;
}
Also used : InitializeBoundName(com.github.anba.es6draft.compiler.BindingInitializationGenerator.InitializeBoundName) MethodName(com.github.anba.es6draft.compiler.assembler.MethodName) Name(com.github.anba.es6draft.ast.scope.Name) LexicalEnvironment(com.github.anba.es6draft.runtime.LexicalEnvironment) BlockScope(com.github.anba.es6draft.ast.scope.BlockScope) DeclarativeEnvironmentRecord(com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord)

Example 8 with BlockScope

use of com.github.anba.es6draft.ast.scope.BlockScope in project es6draft by anba.

the class ComprehensionGenerator method visit.

/**
     * Runtime Semantics: ComprehensionEvaluation
     */
@Override
public Void visit(LegacyComprehension node, CodeVisitor mv) {
    BlockScope scope = node.getScope();
    if (scope.isPresent()) {
        mv.enterVariableScope();
        Variable<LexicalEnvironment<DeclarativeEnvironmentRecord>> env = mv.newVariable("env", LexicalEnvironment.class).uncheckedCast();
        Variable<DeclarativeEnvironmentRecord> envRec = mv.newVariable("envRec", DeclarativeEnvironmentRecord.class);
        newDeclarativeEnvironment(scope, mv);
        mv.store(env);
        getEnvRec(env, envRec, mv);
        for (Name name : LexicallyDeclaredNames(node.getScope())) {
            BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(envRec, name);
            op.createMutableBinding(envRec, name, false, mv);
            InitializeBoundNameWithUndefined(envRec, name, mv);
        }
        mv.load(env);
        pushLexicalEnvironment(mv);
        mv.exitVariableScope();
    }
    mv.enterScope(node);
    visit((Comprehension) node, mv);
    mv.exitScope();
    if (scope.isPresent()) {
        popLexicalEnvironment(mv);
    }
    return null;
}
Also used : LexicalEnvironment(com.github.anba.es6draft.runtime.LexicalEnvironment) BlockScope(com.github.anba.es6draft.ast.scope.BlockScope) DeclarativeEnvironmentRecord(com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord) MethodName(com.github.anba.es6draft.compiler.assembler.MethodName) Name(com.github.anba.es6draft.ast.scope.Name)

Example 9 with BlockScope

use of com.github.anba.es6draft.ast.scope.BlockScope in project es6draft by anba.

the class ExpressionGenerator method visit.

/**
     * Extension: 'let' expression
     */
@Override
public ValType visit(LetExpression node, CodeVisitor mv) {
    BlockScope scope = node.getScope();
    if (scope.isPresent()) {
        mv.enterVariableScope();
        Variable<LexicalEnvironment<DeclarativeEnvironmentRecord>> env = mv.newVariable("env", LexicalEnvironment.class).uncheckedCast();
        Variable<DeclarativeEnvironmentRecord> envRec = mv.newVariable("envRec", DeclarativeEnvironmentRecord.class);
        newDeclarativeEnvironment(scope, mv);
        mv.store(env);
        getEnvRec(env, envRec, mv);
        for (LexicalBinding lexical : node.getBindings()) {
            Binding binding = lexical.getBinding();
            Expression initializer = lexical.getInitializer();
            for (Name name : BoundNames(binding)) {
                BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(envRec, name);
                op.createMutableBinding(envRec, name, false, mv);
            }
            if (initializer == null) {
                // LexicalBinding : BindingIdentifier
                assert binding instanceof BindingIdentifier;
                Name name = ((BindingIdentifier) binding).getName();
                /* steps 1-2 */
                // stack: [] -> []
                InitializeBoundNameWithUndefined(envRec, name, mv);
            } else if (binding instanceof BindingIdentifier) {
                // LexicalBinding : BindingIdentifier Initializer
                Name name = ((BindingIdentifier) binding).getName();
                /* steps 1-7 */
                InitializeBoundNameWithInitializer(codegen, envRec, name, initializer, mv);
            } else {
                // LexicalBinding : BindingPattern Initializer
                assert binding instanceof BindingPattern;
                /* steps 1-3 */
                expressionBoxed(initializer, mv);
                /* steps 4-5 */
                BindingInitializationGenerator.BindingInitialization(codegen, envRec, (BindingPattern) binding, mv);
            }
        }
        mv.load(env);
        pushLexicalEnvironment(mv);
        mv.exitVariableScope();
    }
    mv.enterScope(node);
    ValType type = node.getExpression().accept(this, mv);
    mv.exitScope();
    if (scope.isPresent()) {
        popLexicalEnvironment(mv);
    }
    return type;
}
Also used : ValType(com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType) MethodName(com.github.anba.es6draft.compiler.assembler.MethodName) Name(com.github.anba.es6draft.ast.scope.Name) FieldName(com.github.anba.es6draft.compiler.assembler.FieldName) LexicalEnvironment(com.github.anba.es6draft.runtime.LexicalEnvironment) BlockScope(com.github.anba.es6draft.ast.scope.BlockScope) DeclarativeEnvironmentRecord(com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord)

Example 10 with BlockScope

use of com.github.anba.es6draft.ast.scope.BlockScope in project es6draft by anba.

the class StatementGenerator method enterCatchScope.

private void enterCatchScope(CatchClause node, CodeVisitor mv) {
    BlockScope scope = node.getScope();
    Binding catchParameter = node.getCatchParameter();
    /* steps 1-6 */
    // stack: [e] -> []
    mv.enterVariableScope();
    {
        Variable<Object> exception = mv.newVariable("exception", Object.class);
        mv.invoke(Methods.ScriptException_getValue);
        mv.store(exception);
        /* step 1 (not applicable) */
        /* steps 2-4 */
        Variable<DeclarativeEnvironmentRecord> envRec = null;
        if (scope.isPresent()) {
            /* step 2 */
            // stack: [] -> [catchEnv]
            newCatchEnvironment(catchParameter, scope, mv);
            envRec = mv.newVariable("envRec", DeclarativeEnvironmentRecord.class);
            getEnvRec(envRec, mv);
            /* step 3 */
            if (catchParameter != null) {
                for (Name name : BoundNames(catchParameter)) {
                    BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(envRec, name);
                    op.createMutableBinding(envRec, name, false, mv);
                }
            }
            /* step 4 */
            // stack: [catchEnv] -> []
            pushLexicalEnvironment(mv);
        }
        mv.enterScope(node);
        // stack: [ex] -> []
        if (catchParameter != null) {
            BindingInitialization(codegen, envRec, catchParameter, exception, mv);
        }
    }
    mv.exitVariableScope();
}
Also used : Variable(com.github.anba.es6draft.compiler.assembler.Variable) BlockScope(com.github.anba.es6draft.ast.scope.BlockScope) ScriptObject(com.github.anba.es6draft.runtime.types.ScriptObject) FunctionObject(com.github.anba.es6draft.runtime.types.builtins.FunctionObject) InitializeBoundName(com.github.anba.es6draft.compiler.BindingInitializationGenerator.InitializeBoundName) MethodName(com.github.anba.es6draft.compiler.assembler.MethodName) Name(com.github.anba.es6draft.ast.scope.Name)

Aggregations

BlockScope (com.github.anba.es6draft.ast.scope.BlockScope)13 Name (com.github.anba.es6draft.ast.scope.Name)9 MethodName (com.github.anba.es6draft.compiler.assembler.MethodName)8 DeclarativeEnvironmentRecord (com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord)7 InitializeBoundName (com.github.anba.es6draft.compiler.BindingInitializationGenerator.InitializeBoundName)5 LexicalEnvironment (com.github.anba.es6draft.runtime.LexicalEnvironment)5 Jump (com.github.anba.es6draft.compiler.assembler.Jump)3 Completion (com.github.anba.es6draft.compiler.StatementGenerator.Completion)2 Variable (com.github.anba.es6draft.compiler.assembler.Variable)2 ComprehensionFor (com.github.anba.es6draft.ast.ComprehensionFor)1 Scope (com.github.anba.es6draft.ast.scope.Scope)1 TopLevelScope (com.github.anba.es6draft.ast.scope.TopLevelScope)1 WithScope (com.github.anba.es6draft.ast.scope.WithScope)1 LabelledHashKey (com.github.anba.es6draft.compiler.CodeVisitor.LabelledHashKey)1 ValType (com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType)1 BreakLabel (com.github.anba.es6draft.compiler.Labels.BreakLabel)1 FieldName (com.github.anba.es6draft.compiler.assembler.FieldName)1 MutableValue (com.github.anba.es6draft.compiler.assembler.MutableValue)1 ScriptIterator (com.github.anba.es6draft.runtime.internal.ScriptIterator)1 ScriptObject (com.github.anba.es6draft.runtime.types.ScriptObject)1