slcom/slangc/model/expressions/LiteralExpression.sauce

199 lines
6.8 KiB
Plaintext

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.TypeModel;
import slangc.parser.Branch;
import slangc.parser.ErrorType;
import slangc.parser.Node;
import slangc.parser.NodeType;
import slangc.parser.Token;
public class LiteralExpression extends ExpressionModel {
public static enum SimpleType {
INT32,
INT64,
UINT32,
UINT64,
FLOAT32,
FLOAT64,
STRING,
NULL,
BOOLEAN,
OTHER
}
private SimpleType simpleType = null;
private boolean negated = false;
public LiteralExpression(ExpressionOwner owner, Node source) {
super(owner, source);
//sourceFile.annotate(ErrorType.INTERNAL_ERROR, "Unrecognised expression (Internal error/TODO)");
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Literal expression (" + getSource().getNodeType() + ")");
dumpResolved(reporter, indent + incr, incr);
}
@Override
public ExpressionModel[] getSubexpressions() {
return NO_SUBEXPRESSIONS;
}
@Override
protected ExpressionResult resolveResult() {
if (getSource().getNodeType() == NodeType.STRING_LITERAL_EXPRESSION) {
simpleType = SimpleType.STRING;
return new ExpressionResult.TypedValue(getSystem().getDefaultStringType());//(TypeModel) lookupSimpleName("String")); // TODO: Better lookup
} else if (getSource().getNodeType() == NodeType.INTEGER_LITERAL_EXPRESSION || getSource().getNodeType() == NodeType.FLOAT_LITERAL_EXPRESSION) {
String lit = ((Token)((Branch)getSource()).getSubnode(0)).getSnippet().getSource();
if (getSource().getNodeType() == NodeType.FLOAT_LITERAL_EXPRESSION) {
// TODO: Translations for d/D
if (lit.search("f") || lit.search("F")) {
simpleType = SimpleType.FLOAT32;
return new ExpressionResult.TypedValue(getSystem().getDefaultFloat32Type());
} else {
simpleType = SimpleType.FLOAT64;
return new ExpressionResult.TypedValue(getSystem().getDefaultFloat64Type());
}
} else {
// TODO: Translations for l/L
if (lit.search("l") || lit.search("L")) {
// TODO: Translations for u/U
if (lit.search("u") || lit.search("U")) {
simpleType = SimpleType.UINT64;
} else {
simpleType = SimpleType.INT64;
}
return new ExpressionResult.TypedValue(
simpleType == SimpleType.UINT64
? getSystem().getDefaultUint64Type()
: getSystem().getDefaultInt64Type());
} else {
// Integer literals need some special handling for when they're assigning a field
// or variable with a known type. This applies to all of the types smaller than
// ints (otherwise they'd need casts everywhere they're used).
// TODO: Translations for u/U
if (lit.search("u") || lit.search("U")) {
simpleType = SimpleType.UINT32;
} else {
simpleType = SimpleType.INT32;
}
TypeModel expected = getOwner().getExpectedResult(this);
TypeModel byteType = (TypeModel) lookupSimpleName("byte");
TypeModel shortType = (TypeModel) lookupSimpleName("short");
TypeModel charType = (TypeModel) lookupSimpleName("char");
if (expected != null) {
if (expected.simplify() == byteType.simplify()) {
// TODO: Check that literal typeName actually fits in the expected type
return new ExpressionResult.TypedValue(byteType);
} else if (expected.simplify() == shortType.simplify()) {
return new ExpressionResult.TypedValue(shortType);
} else if (expected.simplify() == charType.simplify()) {
return new ExpressionResult.TypedValue(charType);
}
}
return new ExpressionResult.TypedValue(simpleType == SimpleType.UINT32 ?
getSystem().getDefaultUint32Type()
: getSystem().getDefaultInt32Type());
}
}
} else if (getSource().getNodeType() == NodeType.CHAR_LITERAL_EXPRESSION) {
simpleType = SimpleType.INT32;
return new ExpressionResult.TypedValue((TypeModel) lookupSimpleName("int"/*"char"*/));
} else if (getSource().getNodeType() == NodeType.NULL_LITERAL_EXPRESSION) {
simpleType = SimpleType.NULL;
return ExpressionResult.NULL;
} else if (getSource().getNodeType() == NodeType.BOOLEAN_LITERAL_EXPRESSION) {
simpleType = SimpleType.BOOLEAN;
return new ExpressionResult.TypedValue(getSystem().getDefaultBooleanType());
} else {
simpleType = null;
getSource().annotate(ErrorType.INTERNAL_ERROR, "Unrecognised expression type " + getSource().getNodeType());
return ExpressionResult.INVALID;
}
}
public SimpleType getSimpleType() {
return simpleType;
}
public String getRawSource() {
return ((Token)((Branch)getSource()).getSubnode(0)).getSnippet().getSource();
}
public String getProcessedString() {
String start = getRawSource();
return start.sub(1, start.ints().length-1);
}
public boolean canNegate() {
switch (getSimpleType()) {
case SimpleType.INT32:
case SimpleType.INT64:
case SimpleType.FLOAT32:
case SimpleType.FLOAT64:
return true;
default:
return false;
}
}
public void negate() {
if (!canNegate()) {
throw new Error("Internal error, this literal can't be negated");
}
negated = true;
}
@Override
public TypeSignature innerGenerate(BytecodeInstructionWriter w) {
switch (getSimpleType()) {
case SimpleType.BOOLEAN:
if (getRawSource().equals("true")) {
w.genBoolean(true);
} else { // false
w.genBoolean(false);
}
break;
case SimpleType.INT32:
w.genConst(w.getTarget().getHeap().getConstInt32((negated ? "-" : "") + getRawSource()));
break;
case SimpleType.INT64:
w.genConst(w.getTarget().getHeap().getConstInt64((negated ? "-" : "") + getRawSource()));
break;
case SimpleType.UINT32:
w.genConst(w.getTarget().getHeap().getConstUint32(getRawSource()));
break;
case SimpleType.UINT64:
w.genConst(w.getTarget().getHeap().getConstUint64(getRawSource()));
break;
case SimpleType.FLOAT32:
w.genConst(w.getTarget().getHeap().getConstFloat32(getRawSource()));
break;
case SimpleType.FLOAT64:
w.genConst(w.getTarget().getHeap().getConstFloat64(getRawSource()));
break;
case SimpleType.STRING:
w.genConst(w.getTarget().getHeap().getConstStringLiteral(getRawSource()));
break;
case SimpleType.NULL:
w.genConst(w.getTarget().getHeap().getNull());
break;
default:
w.genError("TODO: innerGenerate for " + Type.of(this));
return null;
}
return getResult().getValueTypeWithNullType(getSystem().getDefaultBaseType()).getTypeSignature();
}
public TypeModel resolveType(Node n) {
return super.resolveType(n); // TODO: Better support for interfaces
}
}