package slangc.model.expressions; import slangc.api.BytecodeInstructionWriter; import slangc.api.Reporter; import slangc.bytecode.TypeSignature; import slangc.model.ClauseModel; import slangc.model.ExpressionModel; import slangc.model.ExpressionOwner; import slangc.model.ExpressionResult; import slangc.model.FieldModel; import slangc.model.MethodModel; import slangc.model.StatementOwner; import slangc.model.TypeModel; import slangc.model.UserTypeModel; import slangc.model.clauses.Arguments; import slangc.parser.Branch; import slangc.parser.ErrorType; import slangc.parser.Node; public class NewClassExpression extends ExpressionModel implements StatementOwner { TypeModel declaredType; Arguments arguments; public NewClassExpression(ExpressionOwner owner, Node source) { super(owner, source); //type = owner.resolveType(((Branch)source).getSubnode(1)); declaredType = getOwner().getTypeScope().getInnerTypeForSource((Branch)source); if (declaredType == null) { source.annotate(ErrorType.INTERNAL_ERROR, "Unable to match expression to type declaration"); } if (declaredType instanceof UserTypeModel) { ((UserTypeModel)declaredType).statementOrExpression = this; } arguments = (Arguments)ClauseModel.construct(this, ((Branch)source).getSubnode(2)); } public TypeModel getType() { return declaredType; } public Arguments getArguments() { return arguments; } @Override public void dump(Reporter reporter, String indent, String incr) { reporter.note("DUMP", indent + "> New class expression of '" + declaredType + "'"); dumpResolved(reporter, indent + incr, incr); arguments.dump(reporter, indent + incr, incr); } @Override public ExpressionModel[] getSubexpressions() { // NOTE: Only the expressions in the arguments are considered subexpressions // (any expressions within the defined class are handled as portions of that type instead) return arguments.getSubexpressions(); } @Override protected ExpressionResult resolveResult() { targetMethod = bestTargetMethod(declaredType.simplify().getInstanceConstructors(), arguments); return new ExpressionResult.TypedValue(declaredType.simplify()); } private MethodModel targetMethod = null; @Override public boolean hasTargetMethod() { return true; } @Override public MethodModel getTargetMethod() { // TODO Auto-generated method stub return targetMethod; } public static TypeSignature[] generateUpvalueLoads(BytecodeInstructionWriter w, UserTypeModel type) { FieldModel[] upvalues = type.getUpvalues(); TypeSignature[] result = new TypeSignature[upvalues.length]; for (int i = 0; i < upvalues.length; i++) { w.genLoadLocalOrParam(upvalues[i].getStorageType().getTypeSignature(), upvalues[i].getUpvalueReference().getIndex()); result[i] = upvalues[i].getStorageType().getTypeSignature(); } return result; } @Override public TypeSignature innerGenerate(BytecodeInstructionWriter w) { UserTypeModel t = (UserTypeModel) getType().simplify(); UserTypeModel outer = (UserTypeModel) t.getOwner().getNearestType(); OuterThisExpression.generatePossibleOuterThis(w, (UserTypeModel)getMethodOrField().getOwner(), outer); TypeSignature[] upvs = generateUpvalueLoads(w, t); arguments.generate(w, getTargetMethod(), true); w.genNewInner(getTargetMethod().getMethodSignature(), upvs); return getType().simplify().getTypeSignature(); } public TypeModel resolveType(Node n) { return super.resolveType(n); // TODO: Better support for interfaces } }