/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.compiler; import java.util.ArrayList; import java.util.List; import com.github.anba.es6draft.ast.MethodDefinition; import com.github.anba.es6draft.ast.Node; import com.github.anba.es6draft.ast.PropertyDefinition; import com.github.anba.es6draft.ast.PropertyValueDefinition; import com.github.anba.es6draft.ast.synthetic.MethodDefinitionsMethod; import com.github.anba.es6draft.compiler.assembler.MethodName; import com.github.anba.es6draft.compiler.assembler.Value; import com.github.anba.es6draft.compiler.assembler.Variable; import com.github.anba.es6draft.runtime.types.builtins.OrdinaryConstructorFunction; import com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject; /** * <h1>14 ECMAScript Language: Functions and Classes</h1> * <ul> * <li>14.5 Class Definitions * </ul> */ final class ClassPropertyGenerator extends DefaultCodeGenerator<Void> { private final Variable<OrdinaryConstructorFunction> constructor; private final Variable<OrdinaryObject> prototype; private final Variable<ArrayList<Object>> decorators; private final PropertyGenerator propgen; private ClassPropertyGenerator(CodeGenerator codegen, Variable<OrdinaryConstructorFunction> constructor, Variable<OrdinaryObject> prototype, Variable<ArrayList<Object>> decorators) { super(codegen); this.constructor = constructor; this.prototype = prototype; this.decorators = decorators; this.propgen = codegen.propertyGenerator(decorators); } static void ClassPropertyEvaluation(CodeGenerator codegen, List<? extends PropertyDefinition> properties, Variable<OrdinaryConstructorFunction> constructor, Variable<OrdinaryObject> prototype, Variable<ArrayList<Object>> decorators, CodeVisitor mv) { ClassPropertyGenerator classgen = new ClassPropertyGenerator(codegen, constructor, prototype, decorators); for (PropertyDefinition property : properties) { property.accept(classgen, mv); } } private Value<ArrayList<Object>> decoratorsOrNull(CodeVisitor mv) { return this.decorators != null ? this.decorators : mv.anullValue(); } @Override protected Void visit(Node node, CodeVisitor mv) { throw new IllegalStateException(String.format("node-class: %s", node.getClass())); } @Override public Void visit(MethodDefinition node, CodeVisitor mv) { if (!(node.isClassConstructor() || node.isCallConstructor())) { Variable<? extends OrdinaryObject> obj = node.isStatic() ? constructor : prototype; if (!node.getDecorators().isEmpty()) { addDecoratorObject(decorators, obj, mv); } // stack: [] -> [] mv.load(obj); node.accept(propgen, mv); } return null; } @Override public Void visit(PropertyValueDefinition node, CodeVisitor mv) { // stack: [] -> [] mv.load(constructor); node.accept(propgen, mv); return null; } @Override public Void visit(MethodDefinitionsMethod node, CodeVisitor mv) { MethodName method = codegen.compile(node, decorators != null, mv); boolean hasResume = node.hasResumePoint(); // stack: [] -> [] mv.lineInfo(0); // 0 = hint for stacktraces to omit this frame if (hasResume) { mv.callWithSuspend(method, constructor, prototype, decoratorsOrNull(mv)); } else { mv.call(method, constructor, prototype, decoratorsOrNull(mv)); } return null; } }