use of com.github.anba.es6draft.ast.scope.Name in project es6draft by anba.
the class ClassPropertyGenerator method InitializePrivateName.
private void InitializePrivateName(StoreToArray<Object> target, PrivateNameProperty privateName, CodeVisitor mv) {
// TODO: The spec uses a separate lexical environment for private names.
Name name = privateName.getName();
Value<DeclarativeEnvironmentRecord> scopeEnvRec = getLexicalEnvironmentRecord(Types.DeclarativeEnvironmentRecord, mv);
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(scopeEnvRec, name);
MutableValue<Object> arrayElement = target.element(Object.class, mv);
arrayElement.store(mv, __ -> {
mv.anew(Methods.PrivateName_new, mv.vconst(name.getIdentifier()));
});
op.initializeBinding(scopeEnvRec, name, arrayElement, mv);
}
use of com.github.anba.es6draft.ast.scope.Name in project es6draft by anba.
the class ComprehensionGenerator method visit.
/**
* Runtime Semantics: ComprehensionComponentEvaluation
* <p>
* ComprehensionFor : for ( ForBinding of AssignmentExpression )
*/
@Override
public Void visit(ComprehensionFor node, CodeVisitor mv) {
Jump lblTest = new Jump(), lblLoop = new Jump();
Variable<ScriptIterator<?>> iter = iterators.next();
/* steps 1-2 */
expressionBoxed(node.getExpression(), mv);
/* steps 3-4 */
mv.loadExecutionContext();
mv.lineInfo(node.getExpression());
mv.invoke(Methods.IteratorOperations_iterate);
mv.store(iter);
/* step 5 (not applicable) */
/* step 6 */
mv.nonDestructiveGoTo(lblTest);
/* steps 6.d-e */
mv.mark(lblLoop);
mv.load(iter);
mv.lineInfo(node);
mv.invoke(Methods.Iterator_next);
/* steps 6.f-j */
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);
// stack: [nextValue] -> []
Variable<Object> nextValue = mv.newVariable("nextValue", Object.class);
mv.store(nextValue);
newDeclarativeEnvironment(scope, mv);
mv.store(env);
getEnvRec(env, envRec, mv);
for (Name name : BoundNames(node.getBinding())) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(envRec, name);
op.createMutableBinding(envRec, name, false, mv);
}
BindingInitialization(codegen, envRec, node.getBinding(), nextValue, mv);
mv.load(env);
pushLexicalEnvironment(mv);
mv.exitVariableScope();
} else {
// stack: [nextValue] -> []
mv.pop();
}
/* step 6.k */
mv.enterScope(node);
new IterationGenerator<ComprehensionFor>(codegen) {
@Override
protected Completion iterationBody(ComprehensionFor node, Variable<ScriptIterator<?>> iterator, CodeVisitor mv) {
elements.next().accept(ComprehensionGenerator.this, mv);
return Completion.Normal;
}
@Override
protected MutableValue<Object> enterIteration(ComprehensionFor node, CodeVisitor mv) {
return mv.enterIteration();
}
@Override
protected List<TempLabel> exitIteration(ComprehensionFor node, CodeVisitor mv) {
return mv.exitIteration();
}
}.generate(node, iter, mv);
mv.exitScope();
/* steps 6.l-m */
if (scope.isPresent()) {
popLexicalEnvironment(mv);
}
/* steps 6.a-c */
mv.mark(lblTest);
mv.load(iter);
mv.lineInfo(node);
mv.invoke(Methods.Iterator_hasNext);
mv.ifne(lblLoop);
return null;
}
use of com.github.anba.es6draft.ast.scope.Name 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();
}
use of com.github.anba.es6draft.ast.scope.Name in project es6draft by anba.
the class NodeSourceTextModuleRecord method ParseModule.
/**
* ParseModule ( sourceText )
*
* @param scriptLoader
* the script loader
* @param sourceCodeId
* the source code identifier
* @param source
* the module source code
* @return the parsed module record
* @throws IOException
* if there was any I/O error
* @throws ParserException
* if the module source contains any syntax errors
* @throws CompilationException
* if the parsed module source cannot be compiled
*/
public static NodeSourceTextModuleRecord ParseModule(ScriptLoader scriptLoader, SourceIdentifier sourceCodeId, ModuleSource source) throws IOException, ParserException, CompilationException {
// Add an implicit "require" binding to the lexical environment of the module.
com.github.anba.es6draft.ast.Module parsedBody = scriptLoader.parseModule(source.toSource(), source.sourceCode());
ModuleScope moduleScope = parsedBody.getScope();
if (!moduleScope.isDeclared(new Name("require"))) {
moduleScope.addImplicitBinding(new Name("require"));
}
SourceTextModuleRecord sourceText = SourceTextModuleRecord.ParseModule(scriptLoader, sourceCodeId, parsedBody);
return new NodeSourceTextModuleRecord(sourceText);
}
use of com.github.anba.es6draft.ast.scope.Name in project es6draft by anba.
the class FunctionDeclarationInstantiationGenerator method generate.
private void generate(FunctionNode function, CodeVisitor mv) {
Variable<ExecutionContext> context = mv.getParameter(EXECUTION_CONTEXT, ExecutionContext.class);
Variable<LexicalEnvironment<FunctionEnvironmentRecord>> env = mv.newVariable("env", LexicalEnvironment.class).uncheckedCast();
Variable<FunctionEnvironmentRecord> envRec = mv.newVariable("envRec", FunctionEnvironmentRecord.class);
Variable<FunctionObject> fo = null;
Variable<Undefined> undefined = mv.newVariable("undef", Undefined.class);
mv.loadUndefined();
mv.store(undefined);
FunctionScope fscope = function.getScope();
boolean hasParameters = !function.getParameters().getFormals().isEmpty();
Variable<Iterator<?>> iterator = null;
if (hasParameters) {
iterator = mv.newVariable("iterator", Iterator.class).uncheckedCast();
mv.loadParameter(ARGUMENTS, Object[].class);
mv.invoke(Methods.Arrays_asList);
mv.invoke(Methods.List_iterator);
mv.store(iterator);
}
/* step 1 (omitted) */
/* step 2 */
getLexicalEnvironment(context, env, mv);
/* step 3 */
getEnvironmentRecord(env, envRec, mv);
/* step 4 */
// RuntimeInfo.Function code = func.getCode();
/* step 5 */
boolean strict = IsStrict(function);
/* step 6 */
FormalParameterList formals = function.getParameters();
/* step 7 */
List<Name> parameterNames = BoundNames(formals);
HashSet<Name> parameterNamesSet = new HashSet<>(parameterNames);
/* step 8 */
boolean hasDuplicates = parameterNames.size() != parameterNamesSet.size();
/* step 9 */
boolean simpleParameterList = IsSimpleParameterList(formals);
/* step 10 */
boolean hasParameterExpressions = ContainsExpression(formals);
// invariant: hasDuplicates => simpleParameterList
assert !hasDuplicates || simpleParameterList;
// invariant: hasParameterExpressions => !simpleParameterList
assert !hasParameterExpressions || !simpleParameterList;
/* step 11 */
Set<Name> varNames = VarDeclaredNames(function);
/* step 12 */
List<StatementListItem> varDeclarations = VarScopedDeclarations(function);
/* step 13 */
Set<Name> lexicalNames = LexicallyDeclaredNames(function);
/* step 14 */
HashSet<Name> functionNames = new HashSet<>();
/* step 15 */
ArrayDeque<HoistableDeclaration> functionsToInitialize = new ArrayDeque<>();
/* step 16 */
for (StatementListItem item : reverse(varDeclarations)) {
if (item instanceof HoistableDeclaration) {
HoistableDeclaration d = (HoistableDeclaration) item;
Name fn = BoundName(d);
if (functionNames.add(fn)) {
functionsToInitialize.addFirst(d);
}
}
}
if (!functionsToInitialize.isEmpty()) {
fo = mv.newVariable("fo", FunctionObject.class);
}
/* step 17 */
// Optimization: Skip 'arguments' allocation if it's not referenced within the function.
boolean argumentsObjectNeeded = function.getScope().needsArguments();
Name arguments = function.getScope().arguments();
argumentsObjectNeeded &= arguments != null;
/* step 18 */
if (function.getThisMode() == FunctionNode.ThisMode.Lexical) {
argumentsObjectNeeded = false;
} else /* step 19 */
if (parameterNamesSet.contains(arguments)) {
argumentsObjectNeeded = false;
} else /* step 20 */
if (!hasParameterExpressions) {
if (functionNames.contains(arguments) || lexicalNames.contains(arguments)) {
argumentsObjectNeeded = false;
}
}
/* step 21 */
for (Name paramName : function.getScope().parameterNames()) {
BindingOp<FunctionEnvironmentRecord> op = BindingOp.of(envRec, paramName);
op.createMutableBinding(envRec, paramName, false, mv);
if (hasDuplicates) {
op.initializeBinding(envRec, paramName, undefined, mv);
}
}
/* step 22 */
if (argumentsObjectNeeded) {
assert arguments != null;
Variable<ArgumentsObject> argumentsObj = mv.newVariable("argumentsObj", ArgumentsObject.class);
if (strict || !simpleParameterList) {
CreateUnmappedArgumentsObject(mv);
} else if (formals.getFormals().isEmpty()) {
CreateMappedArgumentsObject(mv);
} else {
CreateMappedArgumentsObject(env, formals, mv);
}
mv.store(argumentsObj);
BindingOp<FunctionEnvironmentRecord> op = BindingOp.of(envRec, arguments);
if (strict) {
op.createImmutableBinding(envRec, arguments, false, mv);
} else {
op.createMutableBinding(envRec, arguments, false, mv);
}
op.initializeBinding(envRec, arguments, argumentsObj, mv);
parameterNames.add(arguments);
parameterNamesSet.add(arguments);
}
/* steps 24-26 */
if (hasParameters) {
if (hasDuplicates) {
/* step 24 */
BindingInitialization(codegen, function, env, iterator, mv);
} else {
/* step 25 */
BindingInitialization(codegen, function, env, envRec, iterator, mv);
}
}
/* steps 27-28 */
HashSet<Name> instantiatedVarNames;
Variable<? extends LexicalEnvironment<?>> varEnv;
Variable<? extends DeclarativeEnvironmentRecord> varEnvRec;
if (!hasParameterExpressions) {
assert fscope == fscope.variableScope();
/* step 27.a (note) */
/* step 27.b */
instantiatedVarNames = new HashSet<>(parameterNames);
/* step 27.c */
for (Name varName : varNames) {
if (instantiatedVarNames.add(varName)) {
BindingOp<FunctionEnvironmentRecord> op = BindingOp.of(envRec, varName);
op.createMutableBinding(envRec, varName, false, mv);
op.initializeBinding(envRec, varName, undefined, mv);
}
}
/* steps 27.d-27.e */
varEnv = env;
varEnvRec = envRec;
} else {
assert fscope != fscope.variableScope();
mv.enterScope(fscope.variableScope());
/* step 28.a (note) */
/* step 28.b */
varEnv = mv.newVariable("varEnv", LexicalEnvironment.class).uncheckedCast();
newDeclarativeEnvironment(env, mv);
mv.store(varEnv);
/* step 28.c */
varEnvRec = mv.newVariable("varEnvRec", DeclarativeEnvironmentRecord.class);
getEnvironmentRecord(varEnv, varEnvRec, mv);
/* step 28.d */
setVariableEnvironment(varEnv, mv);
/* step 28.e */
instantiatedVarNames = new HashSet<>();
/* step 28.f */
Variable<Object> tempValue = null;
for (Name varName : varNames) {
if (instantiatedVarNames.add(varName)) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(varEnvRec, varName);
op.createMutableBinding(varEnvRec, varName, false, mv);
if (!parameterNamesSet.contains(varName) || functionNames.contains(varName)) {
op.initializeBinding(varEnvRec, varName, undefined, mv);
} else {
BindingOp.of(envRec, varName).getBindingValue(envRec, varName, strict, mv);
if (tempValue == null) {
tempValue = mv.newVariable("tempValue", Object.class);
}
mv.store(tempValue);
op.initializeBinding(varEnvRec, varName, tempValue, mv);
}
}
}
}
/* step 29 (B.3.3 Block-Level Function Declarations Web Legacy Compatibility Semantics) */
for (Name fname : function.getScope().blockFunctionNames()) {
if (instantiatedVarNames.add(fname)) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(varEnvRec, fname);
op.createMutableBinding(varEnvRec, fname, false, mv);
op.initializeBinding(varEnvRec, fname, undefined, mv);
}
}
/* steps 30-32 */
Variable<? extends LexicalEnvironment<?>> lexEnv;
Variable<? extends DeclarativeEnvironmentRecord> lexEnvRec;
assert strict || fscope.variableScope() != fscope.lexicalScope();
if (!strict || fscope.variableScope() != fscope.lexicalScope()) {
// NB: Scopes are unmodifiable once constructed, that means we need to emit the extra
// scope for functions with deferred strict-ness, even if this scope is not present in
// the specification.
mv.enterScope(fscope.lexicalScope());
if (!lexicalNames.isEmpty()) {
/* step 30 */
lexEnv = mv.newVariable("lexEnv", LexicalEnvironment.class).uncheckedCast();
newDeclarativeEnvironment(varEnv, mv);
mv.store(lexEnv);
/* step 32 */
lexEnvRec = mv.newVariable("lexEnvRec", DeclarativeEnvironmentRecord.class);
getEnvironmentRecord(lexEnv, lexEnvRec, mv);
} else {
// Optimization: Skip environment allocation if no lexical names are defined.
/* step 30 */
lexEnv = varEnv;
/* step 32 */
lexEnvRec = varEnvRec;
}
} else {
/* step 30 */
lexEnv = varEnv;
/* step 32 */
lexEnvRec = varEnvRec;
}
/* step 33 */
if (lexEnv != env) {
setLexicalEnvironment(lexEnv, mv);
}
/* step 34 */
List<Declaration> lexDeclarations = LexicallyScopedDeclarations(function);
/* step 35 */
for (Declaration d : lexDeclarations) {
assert !(d instanceof HoistableDeclaration);
for (Name dn : BoundNames(d)) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(lexEnvRec, dn);
if (d.isConstDeclaration()) {
op.createImmutableBinding(lexEnvRec, dn, true, mv);
} else {
op.createMutableBinding(lexEnvRec, dn, false, mv);
}
}
}
/* step 36 */
for (HoistableDeclaration f : functionsToInitialize) {
Name fn = BoundName(f);
// stack: [] -> [fo]
InstantiateFunctionObject(context, lexEnv, f, mv);
mv.store(fo);
// stack: [fo] -> []
// Resolve the actual binding name: function(a){ function a(){} }
// TODO: Can be removed when StaticIdResolution handles this case.
Name name = fscope.variableScope().resolveName(fn, false);
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(varEnvRec, name);
op.setMutableBinding(varEnvRec, name, fo, false, mv);
}
/* step 37 */
mv._return();
}
Aggregations