mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-03 12:07:26 +00:00
Now parsing array declarations
This commit is contained in:
parent
15b1dc60fe
commit
6376029dbf
@ -187,7 +187,7 @@ public class AsmFragment {
|
||||
}
|
||||
} else if (value instanceof ConstantInteger) {
|
||||
ConstantInteger intValue = (ConstantInteger) value;
|
||||
if (intValue.getType().equals(SymbolType.BYTE)) {
|
||||
if (intValue.getType().equals(SymbolTypeBasic.BYTE)) {
|
||||
String name = "coby" + nextConstByteIdx++;
|
||||
bindings.put(name, value);
|
||||
return name;
|
||||
@ -223,7 +223,7 @@ public class AsmFragment {
|
||||
}
|
||||
} else if (boundValue instanceof ConstantInteger) {
|
||||
ConstantInteger boundInt = (ConstantInteger) boundValue;
|
||||
if (boundInt.getType().equals(SymbolType.BYTE)) {
|
||||
if (boundInt.getType().equals(SymbolTypeBasic.BYTE)) {
|
||||
bound = Integer.toString(boundInt.getNumber());
|
||||
} else {
|
||||
throw new RuntimeException("Bound Value Type not implemented " + boundValue);
|
||||
|
@ -22,7 +22,7 @@ public class Label implements Symbol {
|
||||
}
|
||||
|
||||
public SymbolType getType() {
|
||||
return SymbolType.LABEL;
|
||||
return SymbolTypeBasic.LABEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
91
src/dk/camelot64/kickc/icl/ParseTreeConstantEvaluator.java
Normal file
91
src/dk/camelot64/kickc/icl/ParseTreeConstantEvaluator.java
Normal file
@ -0,0 +1,91 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import dk.camelot64.kickc.parser.KickCBaseVisitor;
|
||||
import dk.camelot64.kickc.parser.KickCParser;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/** Capable of evaluating constants directly on the parse tree. */
|
||||
public class ParseTreeConstantEvaluator extends KickCBaseVisitor<Constant> {
|
||||
|
||||
/**
|
||||
* Attempt to evaluate a constant expression.
|
||||
*
|
||||
* @param expr The expression to evaluate
|
||||
* @return The constant value of the expression. null if the expression is not constant.
|
||||
*/
|
||||
public static Constant evaluate(KickCParser.ExprContext expr) {
|
||||
return (new ParseTreeConstantEvaluator()).visit(expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprNumber(KickCParser.ExprNumberContext ctx) {
|
||||
Number number = NumberParser.parseLiteral(ctx.getText());
|
||||
if(number instanceof Integer) {
|
||||
return new ConstantInteger((Integer) number);
|
||||
} else {
|
||||
return new ConstantDouble((Double) number);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprString(KickCParser.ExprStringContext ctx) {
|
||||
return new ConstantString(ctx.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprBool(KickCParser.ExprBoolContext ctx) {
|
||||
return new ConstantBool(Boolean.getBoolean(ctx.getText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprPar(KickCParser.ExprParContext ctx) {
|
||||
return visit(ctx.expr());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprCast(KickCParser.ExprCastContext ctx) {
|
||||
return visit(ctx.expr());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprCall(KickCParser.ExprCallContext ctx) {
|
||||
throw new RuntimeException("Not implemented!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprArray(KickCParser.ExprArrayContext ctx) {
|
||||
throw new RuntimeException("Not implemented!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprId(KickCParser.ExprIdContext ctx) {
|
||||
throw new RuntimeException("Not implemented!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitInitExpr(KickCParser.InitExprContext ctx) {
|
||||
return visit(ctx.expr());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitInitList(KickCParser.InitListContext ctx) {
|
||||
throw new RuntimeException("Not implemented!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprUnary(KickCParser.ExprUnaryContext ctx) {
|
||||
Constant sub = visit(ctx.expr());
|
||||
String op = ((TerminalNode)ctx.getChild(0)).getSymbol().getText();
|
||||
Operator operator = new Operator(op);
|
||||
return Pass2ConstantPropagation.calculateUnary(operator, sub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Constant visitExprBinary(KickCParser.ExprBinaryContext ctx) {
|
||||
Constant left = this.visit(ctx.expr(0));
|
||||
Constant right = this.visit(ctx.expr(1));
|
||||
String op = ((TerminalNode)ctx.getChild(1)).getSymbol().getText();
|
||||
Operator operator = new Operator(op);
|
||||
return Pass2ConstantPropagation.calculateBinary(operator, left, right);
|
||||
}
|
||||
}
|
@ -174,7 +174,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public SymbolType visitTypeSimple(KickCParser.TypeSimpleContext ctx) {
|
||||
return SymbolType.get(ctx.getText());
|
||||
return SymbolTypeBasic.get(ctx.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -184,7 +184,13 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public SymbolType visitTypeArray(KickCParser.TypeArrayContext ctx) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
SymbolType elementType = (SymbolType) visit(ctx.typeDecl());
|
||||
Constant size = ParseTreeConstantEvaluator.evaluate(ctx.expr());
|
||||
if(size instanceof ConstantInteger) {
|
||||
return new SymbolTypeArray(elementType, ((ConstantInteger) size).getNumber());
|
||||
} else {
|
||||
throw new RuntimeException("Array size not a constant integer "+ctx.getText());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -95,6 +95,13 @@ public class Pass2ConstantPropagation extends Pass2Optimization {
|
||||
return new ConstantDouble(getDouble(c1) + getDouble(c2));
|
||||
}
|
||||
}
|
||||
case "*": {
|
||||
if (c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
|
||||
return new ConstantInteger(getInteger(c1) * getInteger(c2));
|
||||
} else {
|
||||
return new ConstantDouble(getDouble(c1) * getDouble(c2));
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new RuntimeException("Unhandled Binary Operator " + operator.getOperator());
|
||||
}
|
||||
|
@ -16,9 +16,9 @@ public class Pass3RegisterAllocation {
|
||||
int currentZp = 2;
|
||||
for (Variable var : symbols.getAllVariables()) {
|
||||
if(var instanceof VariableIntermediate || var instanceof VariableVersion)
|
||||
if(var.getType().equals(SymbolType.BYTE)) {
|
||||
if(var.getType().equals(SymbolTypeBasic.BYTE)) {
|
||||
allocation.allocate(var, new RegisterAllocation.RegisterZpByte(currentZp++));
|
||||
} else if(var.getType().equals(SymbolType.BOOLEAN)) {
|
||||
} else if(var.getType().equals(SymbolTypeBasic.BOOLEAN)) {
|
||||
allocation.allocate(var, new RegisterAllocation.RegisterZpBool(currentZp++));
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ public class PassTypeInference {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
Variable symbol = (Variable) assignment.getLValue();
|
||||
if (SymbolType.VAR.equals(symbol.getType())) {
|
||||
if (SymbolTypeBasic.VAR.equals(symbol.getType())) {
|
||||
// Unresolved symbol - perform inference
|
||||
Operator operator = assignment.getOperator();
|
||||
if (operator == null || assignment.getRValue1() == null) {
|
||||
@ -46,37 +46,40 @@ public class PassTypeInference {
|
||||
case "||":
|
||||
case "and":
|
||||
case "or":
|
||||
return SymbolType.BOOLEAN;
|
||||
return SymbolTypeBasic.BOOLEAN;
|
||||
case "+":
|
||||
case "-":
|
||||
case "*":
|
||||
case "/":
|
||||
if (type1.equals(SymbolType.WORD) || type2.equals(SymbolType.WORD)) {
|
||||
return SymbolType.WORD;
|
||||
if (type1.equals(SymbolTypeBasic.WORD) || type2.equals(SymbolTypeBasic.WORD)) {
|
||||
return SymbolTypeBasic.WORD;
|
||||
} else {
|
||||
return SymbolType.BYTE;
|
||||
return SymbolTypeBasic.BYTE;
|
||||
}
|
||||
default:
|
||||
return SymbolType.VAR;
|
||||
throw new RuntimeException("Type inference case not handled "+type1+" "+operator+" "+type2);
|
||||
}
|
||||
}
|
||||
|
||||
public static SymbolType inferType(RValue rValue) {
|
||||
SymbolType type = SymbolType.VAR;
|
||||
SymbolType type = null;
|
||||
if (rValue instanceof Symbol) {
|
||||
Symbol rSymbol = (Symbol) rValue;
|
||||
type = rSymbol.getType();
|
||||
} else if (rValue instanceof ConstantInteger) {
|
||||
ConstantInteger rInt = (ConstantInteger) rValue;
|
||||
if (rInt.getNumber() < 256) {
|
||||
type = SymbolType.BYTE;
|
||||
type = SymbolTypeBasic.BYTE;
|
||||
} else {
|
||||
type = SymbolType.WORD;
|
||||
type = SymbolTypeBasic.WORD;
|
||||
}
|
||||
} else if (rValue instanceof ConstantString) {
|
||||
type = SymbolType.STRING;
|
||||
type = SymbolTypeBasic.STRING;
|
||||
} else if (rValue instanceof ConstantBool) {
|
||||
type = SymbolType.BOOLEAN;
|
||||
type = SymbolTypeBasic.BOOLEAN;
|
||||
}
|
||||
if(type==null) {
|
||||
throw new RuntimeException("Cannot infer type for "+rValue);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class SymbolTable {
|
||||
}
|
||||
|
||||
public VariableUnversioned newVariableDeclaration(String name, String type) {
|
||||
SymbolType symbolType = SymbolType.get(type);
|
||||
SymbolType symbolType = SymbolTypeBasic.get(type);
|
||||
VariableUnversioned symbol = new VariableUnversioned(name, symbolType);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
@ -55,7 +55,7 @@ public class SymbolTable {
|
||||
|
||||
public VariableIntermediate newIntermediateAssignment() {
|
||||
String name = "$"+intermediateVarCount++;
|
||||
VariableIntermediate symbol = new VariableIntermediate(name, SymbolType.VAR);
|
||||
VariableIntermediate symbol = new VariableIntermediate(name, SymbolTypeBasic.VAR);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
@ -1,33 +1,8 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** Symbol Types */
|
||||
public enum SymbolType {
|
||||
BYTE("byte"),
|
||||
WORD("word"),
|
||||
STRING("string"),
|
||||
BOOLEAN("boolean"),
|
||||
LABEL("label"),
|
||||
VAR("var");
|
||||
|
||||
private String typeName;
|
||||
|
||||
SymbolType(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public static SymbolType get(String name) {
|
||||
switch (name) {
|
||||
case "byte": return BYTE;
|
||||
case "word": return WORD;
|
||||
case "string": return STRING;
|
||||
case "boolean": return BOOLEAN;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public interface SymbolType {
|
||||
|
||||
public String getTypeName();
|
||||
|
||||
}
|
||||
|
26
src/dk/camelot64/kickc/icl/SymbolTypeArray.java
Normal file
26
src/dk/camelot64/kickc/icl/SymbolTypeArray.java
Normal file
@ -0,0 +1,26 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A fixed size array of another type */
|
||||
public class SymbolTypeArray implements SymbolType {
|
||||
|
||||
private SymbolType elementType;
|
||||
private int size;
|
||||
|
||||
public SymbolTypeArray(SymbolType elementType, int size) {
|
||||
this.elementType = elementType;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public SymbolType getElementType() {
|
||||
return elementType;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return elementType.getTypeName()+"["+size+"]";
|
||||
}
|
||||
}
|
33
src/dk/camelot64/kickc/icl/SymbolTypeBasic.java
Normal file
33
src/dk/camelot64/kickc/icl/SymbolTypeBasic.java
Normal file
@ -0,0 +1,33 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** Basic Symbol Types */
|
||||
public enum SymbolTypeBasic implements SymbolType {
|
||||
BYTE("byte"),
|
||||
WORD("word"),
|
||||
STRING("string"),
|
||||
BOOLEAN("boolean"),
|
||||
LABEL("label"),
|
||||
VAR("var");
|
||||
|
||||
private String typeName;
|
||||
|
||||
SymbolTypeBasic(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public static SymbolTypeBasic get(String name) {
|
||||
switch (name) {
|
||||
case "byte": return BYTE;
|
||||
case "word": return WORD;
|
||||
case "string": return STRING;
|
||||
case "boolean": return BOOLEAN;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -13,7 +13,7 @@ import java.util.List;
|
||||
/** Test my KickC Grammar */
|
||||
public class Main {
|
||||
public static void main(String[] args) throws IOException {
|
||||
final String fileName = "src/dk/camelot64/kickc/test/fib.kc";
|
||||
final String fileName = "src/dk/camelot64/kickc/test/mem.kc";
|
||||
final CharStream input = CharStreams.fromFileName(fileName);
|
||||
System.out.println(input.toString());
|
||||
KickCLexer lexer = new KickCLexer(input);
|
||||
|
@ -1,12 +1,10 @@
|
||||
|
||||
// Array declaration & allocation (allocated in same memory space as the program)
|
||||
byte[64] idtab;
|
||||
byte[8*8] idtab;
|
||||
|
||||
// Array assignment
|
||||
idtab[0] = 12;
|
||||
|
||||
// Using array indexing
|
||||
byte id6 = idtab[1];
|
||||
|
||||
|
||||
//byte id6 = idtab[1];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user