199 lines
6.8 KiB
Plaintext
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
|
||
|
}
|
||
|
}
|