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.MethodModel; 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 NormalMethodCallExpression extends ExpressionModel implements ExpressionOwner { private ExpressionModel leftHandSide; private String name; private Arguments arguments; public NormalMethodCallExpression(ExpressionOwner owner, Node source) { super(owner, source); leftHandSide = ExpressionModel.construct(this, ((Branch)source).getSubnode(0)); name = UserTypeModel.plainName(((Branch)source).getSubnode(2)); arguments = (Arguments)ClauseModel.construct(this, ((Branch)source).getSubnode(3)); //sourceFile.annotate(ErrorType.INTERNAL_ERROR, "Unrecognised expression (Internal error/TODO)"); } @Override public void dump(Reporter reporter, String indent, String incr) { reporter.note("DUMP", indent + "> Normal method call expression '" + name + "' of:"); dumpResolved(reporter, indent + incr, incr); leftHandSide.dump(reporter, indent + incr, incr); arguments.dump(reporter, indent + incr, incr); } @Override public ExpressionModel[] getSubexpressions() { ExpressionModel[] args = arguments.getSubexpressions(); ExpressionModel[] result = new ExpressionModel[args.length + 1]; for (int i = 0; i < result.length; i++) { if (i == 0) { result[i] = leftHandSide; } else { result[i] = args[i - 1]; } } return result; } public String getName() { return name; } @Override public TypeModel getExpectedResult(ExpressionModel e) { // TODO Auto-generated method stub return null; } public ExpressionModel getLeftHandSide() { return leftHandSide; } public Arguments getArguments() { return arguments; } @Override protected ExpressionResult resolveResult() { if (leftHandSide.getResult().resolvesToValueOrNull() && leftHandSide.getResult().getKind() != ExpressionResult.Kind.NULL) { TypeModel lhsType = leftHandSide.getResult().getValueType(); targetMethod = bestTargetMethod(lhsType.getMethods(name, true), arguments); return ExpressionResult.fromMethodResult(targetMethod); } else if (leftHandSide.getResult().getKind() == ExpressionResult.Kind.POINTS_TO_TYPE) { TypeModel staticType = ((ExpressionResult.PointsToType) leftHandSide.getResult()).getType(); targetMethod = bestTargetMethod(staticType.getMethods(name, true), arguments); return ExpressionResult.fromMethodResult(targetMethod); } else { leftHandSide.getSource().annotate(ErrorType.INTERNAL_ERROR, "Failed to resolve method target"); return ExpressionResult.INVALID; } } private MethodModel targetMethod = null; @Override public boolean hasTargetMethod() { return true; } @Override public MethodModel getTargetMethod() { // TODO Auto-generated method stub return targetMethod; } @Override public TypeSignature innerGenerate(BytecodeInstructionWriter w) { arguments.generate(w, getTargetMethod(), true); if (!getTargetMethod().isStatic()) { // TODO: Handle outer-this calls getLeftHandSide().generate(w); } w.genCall(getTargetMethod().getMethodSignature()); return getTargetMethod().getMethodSignature().returnType; } public TypeModel resolveType(Node n) { return super.resolveType(n); // TODO: Better support for interfaces } }