package slangc.model.expressions; import slangc.api.BytecodeInstructionWriter; import slangc.api.Reporter; import slangc.bytecode.TypeSignature; import slangc.model.ExpressionModel; import slangc.model.ExpressionOwner; import slangc.model.ExpressionResult; import slangc.model.InnerTypeScope; import slangc.model.MemberModel; import slangc.model.TypeModel; import slangc.parser.Branch; import slangc.parser.Node; public class UnaryExpression extends ExpressionModel implements ExpressionOwner { String operator; ExpressionModel rightHandSide; public UnaryExpression(ExpressionOwner owner, Node source) { super(owner, source); operator = BinaryExpression.getOpName(((Branch)source).getSubnode(0)); rightHandSide = ExpressionModel.construct(this, ((Branch)source).getSubnode(1)); } @Override public void dump(Reporter reporter, String indent, String incr) { reporter.note("DUMP", indent + "> Unary expression (" + getSource().getNodeType() + ")"); dumpResolved(reporter, indent + incr, incr); rightHandSide.dump(reporter, indent + incr, incr); } @Override public ExpressionModel[] getSubexpressions() { return new ExpressionModel[] {rightHandSide}; } @Override public TypeModel getExpectedResult(ExpressionModel e) { // TODO not sure if relevant here return null; } @Override public InnerTypeScope getTypeScope() { return getOwner().getTypeScope(); } @Override public TypeModel resolveType(Node subnode) { return getOwner().resolveType(subnode); } @Override public MemberModel getMethodOrField() { return getOwner().getMethodOrField(); } @Override protected ExpressionResult resolveResult() { if (rightHandSide.getResult().resolvesToValueOrNull() && rightHandSide.getResult().getKind() != ExpressionResult.Kind.NULL) { return new ExpressionResult.TypedValue(rightHandSide.getResult().getValueType()); } else { return ExpressionResult.INVALID; } } public String getOperator() { return operator; } @Override public TypeSignature innerGenerate(BytecodeInstructionWriter w) { String op = getOperator(); if (op.equals("+")) { w.genConst(w.getTarget().getHeap().getConstInt32("0")); rightHandSide.generate(w); return BinaryExpression.generateALUOp(w, getSystem().getDefaultInt32Type(), "+", rightHandSide.getResult().getValueType()).getTypeSignature(); } else if (op.equals("-")) { if (rightHandSide instanceof LiteralExpression && ((LiteralExpression)rightHandSide).canNegate()) { LiteralExpression lrhs = (LiteralExpression) rightHandSide; lrhs.negate(); return lrhs.generate(w); } else { w.genConst(w.getTarget().getHeap().getConstInt32("0")); rightHandSide.generate(w); return BinaryExpression.generateALUOp(w, getSystem().getDefaultInt32Type(), "-", rightHandSide.getResult().getValueType()).getTypeSignature(); } } else if (op.equals("~")) { // TODO: Make sure this works for non-int types w.genConst(w.getTarget().getHeap().getConstInt32("-1")); rightHandSide.generate(w); return BinaryExpression.generateALUOp(w, getSystem().getDefaultInt32Type(), "^", rightHandSide.getResult().getValueType()).getTypeSignature(); } else if (op.equals("!")) { rightHandSide.generate(w); w.genNot(); return getSystem().getDefaultBooleanType().getTypeSignature(); } else if (op.equals("++")) { TypeSignature rhsType = rightHandSide.generate(w); w.genConst(w.getTarget().getHeap().getConstInt32("1")); TypeModel rt = BinaryExpression.generateALUOp(w, rightHandSide.getResult().getValueType(), "+", getSystem().getDefaultInt32Type()); if (!rt.getTypeSignature().mappableEquals(rightHandSide.getResult().getValueType().getTypeSignature())) { w.genConvert(rt.getTypeSignature(), rightHandSide.getResult().getValueType().getTypeSignature()); } rightHandSide.generateStore(w, rightHandSide.getResult().getValueType().getTypeSignature()); return rightHandSide.generate(w); } else if (op.equals("--")) { TypeSignature rhsType = rightHandSide.generate(w); w.genConst(w.getTarget().getHeap().getConstInt32("1")); TypeModel rt = BinaryExpression.generateALUOp(w, rightHandSide.getResult().getValueType(), "-", getSystem().getDefaultInt32Type()); if (!rt.getTypeSignature().mappableEquals(rightHandSide.getResult().getValueType().getTypeSignature())) { w.genConvert(rt.getTypeSignature(), rightHandSide.getResult().getValueType().getTypeSignature()); } rightHandSide.generateStore(w, rightHandSide.getResult().getValueType().getTypeSignature()); return rightHandSide.generate(w); } else { w.genError("TODO: innerGenerate for " + Type.of(this) + " with '" + getOperator() + "'"); return null; } } }