diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index 40d57a792..17e5f5635 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -51,8 +51,8 @@ public class AsmFragment { Label destination = conditionalJump.getDestination(); ControlFlowBlock destinationBlock = graph.getBlock(destination); String destinationLabel = destination.getName(); - if(destinationBlock.hasPhiStatements()) { - destinationLabel = destination.getName()+"_from_"+block.getLabel().getName(); + if (destinationBlock.hasPhiStatements()) { + destinationLabel = destination.getName() + "_from_" + block.getLabel().getName(); } signature.append(bind(new Label(destinationLabel, false))); setSignature(signature.toString()); @@ -86,6 +86,12 @@ public class AsmFragment { operator != null && (operator.getOperator().equals("-") || operator.getOperator().equals("+"))) { signature.append("1"); + } else if ( + rValue2 instanceof ConstantInteger && + ((ConstantInteger) rValue2).getNumber() == 0 && + operator != null && + (operator.getOperator().equals("-") || operator.getOperator().equals("+"))) { + signature.append("0"); } else { signature.append(bind(rValue2)); } @@ -141,6 +147,11 @@ public class AsmFragment { */ private int nextZpBoolIdx = 1; + /** + * Zero page ptr register name indexing. + */ + private int nextZpPtrIdx = 1; + /** * Constant byte indexing. */ @@ -182,8 +193,19 @@ public class AsmFragment { String name = "yby"; bindings.put(name, value); return name; - } else { - throw new RuntimeException("Binding of register type not supported " + register.getType()); + } else if (RegisterAllocation.RegisterType.ZP_PTR_BYTE.equals(register.getType())) { + String name = "zpptrby" + nextZpPtrIdx++; + bindings.put(name, value); + return name; + } + } else if (value instanceof PointerDereference) { + PointerDereference deref = (PointerDereference) value; + Variable pointer = deref.getPointer(); + RegisterAllocation.Register register = symbols.getRegister(pointer); + if (RegisterAllocation.RegisterType.ZP_PTR_BYTE.equals(register.getType())) { + String name = "zpiby"+ nextZpPtrIdx++; + bindings.put(name, value); + return name; } } else if (value instanceof ConstantInteger) { ConstantInteger intValue = (ConstantInteger) value; @@ -191,16 +213,17 @@ public class AsmFragment { String name = "coby" + nextConstByteIdx++; bindings.put(name, value); return name; - } else { - throw new RuntimeException("Binding of word integers not supported " + intValue); + } else if (intValue.getType().equals(SymbolTypeBasic.WORD)) { + String name = "cowo" + nextConstByteIdx++; + bindings.put(name, value); + return name; } } else if (value instanceof Label) { String name = "la" + nextLabelIdx++; bindings.put(name, value); return name; - } else { - throw new RuntimeException("Binding of value type not supported " + value); } + throw new RuntimeException("Binding of value type not supported " + value); } /** @@ -218,15 +241,26 @@ public class AsmFragment { bound = Integer.toString(((RegisterAllocation.RegisterZpByte) register).getZp()); } else if (register instanceof RegisterAllocation.RegisterZpBool) { bound = Integer.toString(((RegisterAllocation.RegisterZpBool) register).getZp()); + } else if (register instanceof RegisterAllocation.RegisterZpPointerByte) { + bound = Integer.toString(((RegisterAllocation.RegisterZpPointerByte) register).getZp()); } else { throw new RuntimeException("Register Type not implemented " + register); } + } else if(boundValue instanceof PointerDereference) { + PointerDereference deref = (PointerDereference) boundValue; + Variable pointer = deref.getPointer(); + RegisterAllocation.Register register = symbols.getRegister(pointer); + if(register instanceof RegisterAllocation.RegisterZpPointerByte) { + bound = Integer.toString(((RegisterAllocation.RegisterZpPointerByte) register).getZp()); + } else { + throw new RuntimeException("Bound Value Type not implemented " + boundValue); + } } else if (boundValue instanceof ConstantInteger) { ConstantInteger boundInt = (ConstantInteger) boundValue; if (boundInt.getType().equals(SymbolTypeBasic.BYTE)) { bound = Integer.toString(boundInt.getNumber()); } else { - throw new RuntimeException("Bound Value Type not implemented " + boundValue); + bound = Integer.toString(boundInt.getNumber()); } } else if (boundValue instanceof Label) { bound = ((Label) boundValue).getName().replace('@', 'B'); @@ -258,7 +292,7 @@ public class AsmFragment { parser.addErrorListener(new BaseErrorListener() { @Override public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { - throw new RuntimeException("Error parsing fragment file "+fragmentResource+"\n - Line: "+line+"\n - Message: "+msg); + throw new RuntimeException("Error parsing fragment file " + fragmentResource + "\n - Line: " + line + "\n - Message: " + msg); } }); parser.setBuildParseTree(true); @@ -312,75 +346,89 @@ public class AsmFragment { public Object visitInstruction(Asm6502Parser.InstructionContext ctx) { Asm6502Parser.ParamModeContext paramModeCtx = ctx.paramMode(); AsmInstruction instruction; - if(paramModeCtx==null) { + if (paramModeCtx == null) { AsmInstructionType type = AsmInstuctionSet.getInstructionType(ctx.MNEMONIC().getText(), AsmAddressingMode.NON, null); instruction = new AsmInstruction(type, null, 1); } else { instruction = (AsmInstruction) this.visit(paramModeCtx); } - if(instruction!=null) { + if (instruction != null) { program.addLine(instruction); } else { - throw new RuntimeException("Error parsing ASM fragment line in "+fragmentResource.toString()+"\n - Line: "+ctx.getText()); + throw new RuntimeException("Error parsing ASM fragment line in " + fragmentResource.toString() + "\n - Line: " + ctx.getText()); } return null; } @Override public Object visitModeAbs(Asm6502Parser.ModeAbsContext ctx) { - return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABS); + return createAsmInstruction(ctx, ctx.expr(), AsmAddressingMode.ABS); } @Override public Object visitModeImm(Asm6502Parser.ModeImmContext ctx) { - return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IMM); + return createAsmInstruction(ctx, ctx.expr(), AsmAddressingMode.IMM); } @Override public Object visitModeAbsX(Asm6502Parser.ModeAbsXContext ctx) { - return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABX); + return createAsmInstruction(ctx, ctx.expr(), AsmAddressingMode.ABX); } @Override public Object visitModeAbsY(Asm6502Parser.ModeAbsYContext ctx) { - return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABY); + return createAsmInstruction(ctx, ctx.expr(), AsmAddressingMode.ABY); } @Override public Object visitModeIndY(Asm6502Parser.ModeIndYContext ctx) { - return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IZY); + return createAsmInstruction(ctx, ctx.expr(), AsmAddressingMode.IZY); } @Override public Object visitModeIndX(Asm6502Parser.ModeIndXContext ctx) { - return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IZX); + return createAsmInstruction(ctx, ctx.expr(), AsmAddressingMode.IZX); } @Override public Object visitModeInd(Asm6502Parser.ModeIndContext ctx) { - return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IND); + return createAsmInstruction(ctx, ctx.expr(), AsmAddressingMode.IND); } - private AsmInstruction createAsmInstruction(Asm6502Parser.ParamModeContext ctx, Asm6502Parser.ParamContext paramCtx, AsmAddressingMode addressingMode) { + private AsmInstruction createAsmInstruction(Asm6502Parser.ParamModeContext ctx, Asm6502Parser.ExprContext exprCtx, AsmAddressingMode addressingMode) { Asm6502Parser.InstructionContext instructionCtx = (Asm6502Parser.InstructionContext) ctx.getParent(); String mnemonic = instructionCtx.MNEMONIC().getSymbol().getText(); - String parameter = (String) this.visit(paramCtx); + String parameter = (String) this.visit(exprCtx); AsmInstructionType type = AsmInstuctionSet.getInstructionType(mnemonic, addressingMode, parameter); return new AsmInstruction(type, parameter, 1); } + @Override - public Object visitParamInt(Asm6502Parser.ParamIntContext ctx) { + public Object visitExprBinary(Asm6502Parser.ExprBinaryContext ctx) { + Object left = this.visit(ctx.expr(0)); + Object right = this.visit(ctx.expr(1)); + return ""+left+ctx.getChild(1).getText()+right; + } + + @Override + public Object visitExprUnary(Asm6502Parser.ExprUnaryContext ctx) { + Object sub = this.visit(ctx.expr()); + return ctx.getChild(0).getText()+sub; + } + + @Override + public Object visitExprInt(Asm6502Parser.ExprIntContext ctx) { return NumberParser.parseLiteral(ctx.NUMINT().getText()).toString(); } @Override - public Object visitParamLabel(Asm6502Parser.ParamLabelContext ctx) { + public Object visitExprLabel(Asm6502Parser.ExprLabelContext ctx) { return ctx.NAME().getSymbol().getText(); } @Override - public Object visitParamReplace(Asm6502Parser.ParamReplaceContext ctx) { + public Object visitExprReplace(Asm6502Parser.ExprReplaceContext ctx) { String replaceName = ctx.NAME().getSymbol().getText(); return AsmFragment.this.getBoundValue(replaceName); } diff --git a/src/dk/camelot64/kickc/asm/fragment/xby=xby_plus_1.asm b/src/dk/camelot64/kickc/asm/fragment/xby=xby_plus_1.asm new file mode 100644 index 000000000..40e44366e --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/xby=xby_plus_1.asm @@ -0,0 +1 @@ +inx \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/xby=zpby1.asm b/src/dk/camelot64/kickc/asm/fragment/xby=zpby1.asm new file mode 100644 index 000000000..269f3a259 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/xby=zpby1.asm @@ -0,0 +1 @@ +ldx {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=zpiby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpiby1.asm new file mode 100644 index 000000000..a39f6b795 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpiby1.asm @@ -0,0 +1,3 @@ +ldy #0 +lda ({zpiby1}),y +sta {zpby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpiby1=coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpiby1=coby1.asm new file mode 100644 index 000000000..ff43e9fe8 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpiby1=coby1.asm @@ -0,0 +1,3 @@ +ldy #0 +lda #{coby1} +sta ({zpiby1}),y \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpiby1=xby.asm b/src/dk/camelot64/kickc/asm/fragment/zpiby1=xby.asm new file mode 100644 index 000000000..ca9c4dc4e --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpiby1=xby.asm @@ -0,0 +1,3 @@ +txa +ldy #0 +sta ({zpiby1}),y \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpptrby1=cowo1.asm b/src/dk/camelot64/kickc/asm/fragment/zpptrby1=cowo1.asm new file mode 100644 index 000000000..9aeba27ad --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpptrby1=cowo1.asm @@ -0,0 +1,4 @@ +lda #<{cowo1} +sta {zpptrby1} +lda #>{cowo1} +sta {zpptrby1}+1 diff --git a/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_0.asm b/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_0.asm new file mode 100644 index 000000000..ada638b0b --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_0.asm @@ -0,0 +1,4 @@ +lda {zpptrby2} +sta {zpptrby1} +lda {zpptrby2}+1 +sta {zpptrby1}+1 \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_coby1.asm new file mode 100644 index 000000000..b62b06e12 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_coby1.asm @@ -0,0 +1,7 @@ +lda #{coby1} +clc +adc {zpptrby2} +sta {zpptrby1} +lda #0 +adc {zpptrby2}+1 +sta {zpptrby1}+1 \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_xby.asm b/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_xby.asm new file mode 100644 index 000000000..4aa5df61c --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpptrby1=zpptrby2_plus_xby.asm @@ -0,0 +1,7 @@ +txa +clc +adc {zpptrby2} +sta {zpptrby1} +lda #0 +adc {zpptrby2}+1 +sta {zpptrby1}+1 diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 b/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 index 1ed978118..57e5028c2 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 @@ -22,19 +22,22 @@ instruction ; paramMode - : param #modeAbs - | '#' param #modeImm - | param ',x' #modeAbsX - | param ',y' #modeAbsY - | '(' param ')' ',y' #modeIndY - | '(' param ',x' ')' #modeIndX - | '(' param ')' #modeInd + : expr #modeAbs + | '#' expr #modeImm + | expr ',x' #modeAbsX + | expr ',y' #modeAbsY + | '(' expr ')' ',y' #modeIndY + | '(' expr ',x' ')' #modeIndX + | '(' expr ')' #modeInd ; -param - : NAME #paramLabel - | '{' NAME '}' #paramReplace - | NUMINT #paramInt +expr + : ('+' | '-' | '<' | '>') expr #exprUnary + | expr ('*' | '/' ) expr #exprBinary + | expr ( '+' | '-') expr #exprBinary + | NAME #exprLabel + | '{' NAME '}' #exprReplace + | NUMINT #exprInt ; MNEMONIC: [A-Za-z][A-Za-z][A-Za-z]; diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502.tokens b/src/dk/camelot64/kickc/asm/parser/Asm6502.tokens index b5a7d749b..84da0d5f2 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502.tokens +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502.tokens @@ -8,13 +8,19 @@ T__6=7 T__7=8 T__8=9 T__9=10 -MNEMONIC=11 -NUMINT=12 -BININTEGER=13 -DECINTEGER=14 -HEXINTEGER=15 -NAME=16 -WS=17 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +MNEMONIC=17 +NUMINT=18 +BININTEGER=19 +DECINTEGER=20 +HEXINTEGER=21 +NAME=22 +WS=23 '\n'=1 ':'=2 '//'=3 @@ -23,5 +29,11 @@ WS=17 ',y'=6 '('=7 ')'=8 -'{'=9 -'}'=10 +'+'=9 +'-'=10 +'<'=11 +'>'=12 +'*'=13 +'/'=14 +'{'=15 +'}'=16 diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502BaseListener.java b/src/dk/camelot64/kickc/asm/parser/Asm6502BaseListener.java index 85bad152b..f0a591faa 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502BaseListener.java +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502BaseListener.java @@ -160,37 +160,61 @@ public class Asm6502BaseListener implements Asm6502Listener { * *

The default implementation does nothing.

*/ - @Override public void enterParamLabel(Asm6502Parser.ParamLabelContext ctx) { } + @Override public void enterExprInt(Asm6502Parser.ExprIntContext ctx) { } /** * {@inheritDoc} * *

The default implementation does nothing.

*/ - @Override public void exitParamLabel(Asm6502Parser.ParamLabelContext ctx) { } + @Override public void exitExprInt(Asm6502Parser.ExprIntContext ctx) { } /** * {@inheritDoc} * *

The default implementation does nothing.

*/ - @Override public void enterParamReplace(Asm6502Parser.ParamReplaceContext ctx) { } + @Override public void enterExprLabel(Asm6502Parser.ExprLabelContext ctx) { } /** * {@inheritDoc} * *

The default implementation does nothing.

*/ - @Override public void exitParamReplace(Asm6502Parser.ParamReplaceContext ctx) { } + @Override public void exitExprLabel(Asm6502Parser.ExprLabelContext ctx) { } /** * {@inheritDoc} * *

The default implementation does nothing.

*/ - @Override public void enterParamInt(Asm6502Parser.ParamIntContext ctx) { } + @Override public void enterExprBinary(Asm6502Parser.ExprBinaryContext ctx) { } /** * {@inheritDoc} * *

The default implementation does nothing.

*/ - @Override public void exitParamInt(Asm6502Parser.ParamIntContext ctx) { } + @Override public void exitExprBinary(Asm6502Parser.ExprBinaryContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterExprUnary(Asm6502Parser.ExprUnaryContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitExprUnary(Asm6502Parser.ExprUnaryContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterExprReplace(Asm6502Parser.ExprReplaceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitExprReplace(Asm6502Parser.ExprReplaceContext ctx) { } /** * {@inheritDoc} diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502BaseVisitor.java b/src/dk/camelot64/kickc/asm/parser/Asm6502BaseVisitor.java index af3c09194..bb9474278 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502BaseVisitor.java +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502BaseVisitor.java @@ -101,19 +101,33 @@ public class Asm6502BaseVisitor extends AbstractParseTreeVisitor implement *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitParamLabel(Asm6502Parser.ParamLabelContext ctx) { return visitChildren(ctx); } + @Override public T visitExprInt(Asm6502Parser.ExprIntContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitParamReplace(Asm6502Parser.ParamReplaceContext ctx) { return visitChildren(ctx); } + @Override public T visitExprLabel(Asm6502Parser.ExprLabelContext ctx) { return visitChildren(ctx); } /** * {@inheritDoc} * *

The default implementation returns the result of calling * {@link #visitChildren} on {@code ctx}.

*/ - @Override public T visitParamInt(Asm6502Parser.ParamIntContext ctx) { return visitChildren(ctx); } + @Override public T visitExprBinary(Asm6502Parser.ExprBinaryContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitExprUnary(Asm6502Parser.ExprUnaryContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitExprReplace(Asm6502Parser.ExprReplaceContext ctx) { return visitChildren(ctx); } } \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.java b/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.java index 84d53e17d..22bed699d 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.java +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.java @@ -18,8 +18,8 @@ public class Asm6502Lexer extends Lexer { new PredictionContextCache(); public static final int T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, - T__9=10, MNEMONIC=11, NUMINT=12, BININTEGER=13, DECINTEGER=14, HEXINTEGER=15, - NAME=16, WS=17; + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, MNEMONIC=17, + NUMINT=18, BININTEGER=19, DECINTEGER=20, HEXINTEGER=21, NAME=22, WS=23; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -30,18 +30,19 @@ public class Asm6502Lexer extends Lexer { public static final String[] ruleNames = { "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", - "T__9", "MNEMONIC", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", - "BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR", - "WS" + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "MNEMONIC", + "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "BINDIGIT", "DECDIGIT", + "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR", "WS" }; private static final String[] _LITERAL_NAMES = { - null, "'\n'", "':'", "'//'", "'#'", "',x'", "',y'", "'('", "')'", "'{'", - "'}'" + null, "'\n'", "':'", "'//'", "'#'", "',x'", "',y'", "'('", "')'", "'+'", + "'-'", "'<'", "'>'", "'*'", "'/'", "'{'", "'}'" }; private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, null, null, null, null, null, "MNEMONIC", - "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "WS" + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, "MNEMONIC", "NUMINT", "BININTEGER", "DECINTEGER", + "HEXINTEGER", "NAME", "WS" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -101,46 +102,56 @@ public class Asm6502Lexer extends Lexer { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\23\u008d\b\1\4\2"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\31\u00a5\b\1\4\2"+ "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+ "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ - "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\3\2\3\2\3\3\3"+ - "\3\3\4\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\7\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n"+ - "\3\13\3\13\3\f\3\f\3\f\3\f\3\r\3\r\3\r\5\rN\n\r\3\16\3\16\3\16\6\16S\n"+ - "\16\r\16\16\16T\3\16\3\16\6\16Y\n\16\r\16\16\16Z\5\16]\n\16\3\17\6\17"+ - "`\n\17\r\17\16\17a\3\20\3\20\3\20\3\20\3\20\5\20i\n\20\3\20\6\20l\n\20"+ - "\r\20\16\20m\3\21\3\21\3\22\3\22\3\23\3\23\3\24\3\24\7\24x\n\24\f\24\16"+ - "\24{\13\24\3\24\7\24~\n\24\f\24\16\24\u0081\13\24\3\25\3\25\3\26\3\26"+ - "\3\27\6\27\u0088\n\27\r\27\16\27\u0089\3\27\3\27\2\2\30\3\3\5\4\7\5\t"+ - "\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\2#\2%\2"+ - "\'\22)\2+\2-\23\3\2\13\4\2C\\c|\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch"+ - "\4\2--//\6\2##C\\aac|\6\2\62;C\\aac|\5\2\13\13\17\17\"\"\2\u0093\2\3\3"+ - "\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2"+ - "\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3"+ - "\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2\'\3\2\2\2\2-\3\2\2\2\3"+ - "/\3\2\2\2\5\61\3\2\2\2\7\63\3\2\2\2\t\66\3\2\2\2\138\3\2\2\2\r;\3\2\2"+ - "\2\17>\3\2\2\2\21@\3\2\2\2\23B\3\2\2\2\25D\3\2\2\2\27F\3\2\2\2\31M\3\2"+ - "\2\2\33\\\3\2\2\2\35_\3\2\2\2\37h\3\2\2\2!o\3\2\2\2#q\3\2\2\2%s\3\2\2"+ - "\2\'u\3\2\2\2)\u0082\3\2\2\2+\u0084\3\2\2\2-\u0087\3\2\2\2/\60\7\f\2\2"+ - "\60\4\3\2\2\2\61\62\7<\2\2\62\6\3\2\2\2\63\64\7\61\2\2\64\65\7\61\2\2"+ - "\65\b\3\2\2\2\66\67\7%\2\2\67\n\3\2\2\289\7.\2\29:\7z\2\2:\f\3\2\2\2;"+ - "<\7.\2\2<=\7{\2\2=\16\3\2\2\2>?\7*\2\2?\20\3\2\2\2@A\7+\2\2A\22\3\2\2"+ - "\2BC\7}\2\2C\24\3\2\2\2DE\7\177\2\2E\26\3\2\2\2FG\t\2\2\2GH\t\2\2\2HI"+ - "\t\2\2\2I\30\3\2\2\2JN\5\35\17\2KN\5\37\20\2LN\5\33\16\2MJ\3\2\2\2MK\3"+ - "\2\2\2ML\3\2\2\2N\32\3\2\2\2OP\7\62\2\2PR\t\3\2\2QS\5!\21\2RQ\3\2\2\2"+ - "ST\3\2\2\2TR\3\2\2\2TU\3\2\2\2U]\3\2\2\2VX\7\'\2\2WY\5!\21\2XW\3\2\2\2"+ - "YZ\3\2\2\2ZX\3\2\2\2Z[\3\2\2\2[]\3\2\2\2\\O\3\2\2\2\\V\3\2\2\2]\34\3\2"+ - "\2\2^`\5#\22\2_^\3\2\2\2`a\3\2\2\2a_\3\2\2\2ab\3\2\2\2b\36\3\2\2\2ci\7"+ - "&\2\2de\7\62\2\2ei\7z\2\2fg\7\62\2\2gi\7Z\2\2hc\3\2\2\2hd\3\2\2\2hf\3"+ - "\2\2\2ik\3\2\2\2jl\5%\23\2kj\3\2\2\2lm\3\2\2\2mk\3\2\2\2mn\3\2\2\2n \3"+ - "\2\2\2op\t\4\2\2p\"\3\2\2\2qr\t\5\2\2r$\3\2\2\2st\t\6\2\2t&\3\2\2\2uy"+ - "\5)\25\2vx\5+\26\2wv\3\2\2\2x{\3\2\2\2yw\3\2\2\2yz\3\2\2\2z\177\3\2\2"+ - "\2{y\3\2\2\2|~\t\7\2\2}|\3\2\2\2~\u0081\3\2\2\2\177}\3\2\2\2\177\u0080"+ - "\3\2\2\2\u0080(\3\2\2\2\u0081\177\3\2\2\2\u0082\u0083\t\b\2\2\u0083*\3"+ - "\2\2\2\u0084\u0085\t\t\2\2\u0085,\3\2\2\2\u0086\u0088\t\n\2\2\u0087\u0086"+ - "\3\2\2\2\u0088\u0089\3\2\2\2\u0089\u0087\3\2\2\2\u0089\u008a\3\2\2\2\u008a"+ - "\u008b\3\2\2\2\u008b\u008c\b\27\2\2\u008c.\3\2\2\2\r\2MTZ\\ahmy\177\u0089"+ - "\3\b\2\2"; + "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+ + "\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\3\2\3\2\3\3\3\3\3\4\3\4"+ + "\3\4\3\5\3\5\3\6\3\6\3\6\3\7\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13"+ + "\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21\3\22\3\22\3\22"+ + "\3\22\3\23\3\23\3\23\5\23f\n\23\3\24\3\24\3\24\6\24k\n\24\r\24\16\24l"+ + "\3\24\3\24\6\24q\n\24\r\24\16\24r\5\24u\n\24\3\25\6\25x\n\25\r\25\16\25"+ + "y\3\26\3\26\3\26\3\26\3\26\5\26\u0081\n\26\3\26\6\26\u0084\n\26\r\26\16"+ + "\26\u0085\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32\7\32\u0090\n\32\f\32"+ + "\16\32\u0093\13\32\3\32\7\32\u0096\n\32\f\32\16\32\u0099\13\32\3\33\3"+ + "\33\3\34\3\34\3\35\6\35\u00a0\n\35\r\35\16\35\u00a1\3\35\3\35\2\2\36\3"+ + "\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37"+ + "\21!\22#\23%\24\'\25)\26+\27-\2/\2\61\2\63\30\65\2\67\29\31\3\2\13\4\2"+ + "C\\c|\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch\4\2--//\6\2##C\\aac|\6\2\62"+ + ";C\\aac|\5\2\13\13\17\17\"\"\2\u00ab\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2"+ + "\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23"+ + "\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2"+ + "\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2"+ + "\2\2\2+\3\2\2\2\2\63\3\2\2\2\29\3\2\2\2\3;\3\2\2\2\5=\3\2\2\2\7?\3\2\2"+ + "\2\tB\3\2\2\2\13D\3\2\2\2\rG\3\2\2\2\17J\3\2\2\2\21L\3\2\2\2\23N\3\2\2"+ + "\2\25P\3\2\2\2\27R\3\2\2\2\31T\3\2\2\2\33V\3\2\2\2\35X\3\2\2\2\37Z\3\2"+ + "\2\2!\\\3\2\2\2#^\3\2\2\2%e\3\2\2\2\'t\3\2\2\2)w\3\2\2\2+\u0080\3\2\2"+ + "\2-\u0087\3\2\2\2/\u0089\3\2\2\2\61\u008b\3\2\2\2\63\u008d\3\2\2\2\65"+ + "\u009a\3\2\2\2\67\u009c\3\2\2\29\u009f\3\2\2\2;<\7\f\2\2<\4\3\2\2\2=>"+ + "\7<\2\2>\6\3\2\2\2?@\7\61\2\2@A\7\61\2\2A\b\3\2\2\2BC\7%\2\2C\n\3\2\2"+ + "\2DE\7.\2\2EF\7z\2\2F\f\3\2\2\2GH\7.\2\2HI\7{\2\2I\16\3\2\2\2JK\7*\2\2"+ + "K\20\3\2\2\2LM\7+\2\2M\22\3\2\2\2NO\7-\2\2O\24\3\2\2\2PQ\7/\2\2Q\26\3"+ + "\2\2\2RS\7>\2\2S\30\3\2\2\2TU\7@\2\2U\32\3\2\2\2VW\7,\2\2W\34\3\2\2\2"+ + "XY\7\61\2\2Y\36\3\2\2\2Z[\7}\2\2[ \3\2\2\2\\]\7\177\2\2]\"\3\2\2\2^_\t"+ + "\2\2\2_`\t\2\2\2`a\t\2\2\2a$\3\2\2\2bf\5)\25\2cf\5+\26\2df\5\'\24\2eb"+ + "\3\2\2\2ec\3\2\2\2ed\3\2\2\2f&\3\2\2\2gh\7\62\2\2hj\t\3\2\2ik\5-\27\2"+ + "ji\3\2\2\2kl\3\2\2\2lj\3\2\2\2lm\3\2\2\2mu\3\2\2\2np\7\'\2\2oq\5-\27\2"+ + "po\3\2\2\2qr\3\2\2\2rp\3\2\2\2rs\3\2\2\2su\3\2\2\2tg\3\2\2\2tn\3\2\2\2"+ + "u(\3\2\2\2vx\5/\30\2wv\3\2\2\2xy\3\2\2\2yw\3\2\2\2yz\3\2\2\2z*\3\2\2\2"+ + "{\u0081\7&\2\2|}\7\62\2\2}\u0081\7z\2\2~\177\7\62\2\2\177\u0081\7Z\2\2"+ + "\u0080{\3\2\2\2\u0080|\3\2\2\2\u0080~\3\2\2\2\u0081\u0083\3\2\2\2\u0082"+ + "\u0084\5\61\31\2\u0083\u0082\3\2\2\2\u0084\u0085\3\2\2\2\u0085\u0083\3"+ + "\2\2\2\u0085\u0086\3\2\2\2\u0086,\3\2\2\2\u0087\u0088\t\4\2\2\u0088.\3"+ + "\2\2\2\u0089\u008a\t\5\2\2\u008a\60\3\2\2\2\u008b\u008c\t\6\2\2\u008c"+ + "\62\3\2\2\2\u008d\u0091\5\65\33\2\u008e\u0090\5\67\34\2\u008f\u008e\3"+ + "\2\2\2\u0090\u0093\3\2\2\2\u0091\u008f\3\2\2\2\u0091\u0092\3\2\2\2\u0092"+ + "\u0097\3\2\2\2\u0093\u0091\3\2\2\2\u0094\u0096\t\7\2\2\u0095\u0094\3\2"+ + "\2\2\u0096\u0099\3\2\2\2\u0097\u0095\3\2\2\2\u0097\u0098\3\2\2\2\u0098"+ + "\64\3\2\2\2\u0099\u0097\3\2\2\2\u009a\u009b\t\b\2\2\u009b\66\3\2\2\2\u009c"+ + "\u009d\t\t\2\2\u009d8\3\2\2\2\u009e\u00a0\t\n\2\2\u009f\u009e\3\2\2\2"+ + "\u00a0\u00a1\3\2\2\2\u00a1\u009f\3\2\2\2\u00a1\u00a2\3\2\2\2\u00a2\u00a3"+ + "\3\2\2\2\u00a3\u00a4\b\35\2\2\u00a4:\3\2\2\2\r\2elrty\u0080\u0085\u0091"+ + "\u0097\u00a1\3\b\2\2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.tokens b/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.tokens index b5a7d749b..84da0d5f2 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.tokens +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.tokens @@ -8,13 +8,19 @@ T__6=7 T__7=8 T__8=9 T__9=10 -MNEMONIC=11 -NUMINT=12 -BININTEGER=13 -DECINTEGER=14 -HEXINTEGER=15 -NAME=16 -WS=17 +T__10=11 +T__11=12 +T__12=13 +T__13=14 +T__14=15 +T__15=16 +MNEMONIC=17 +NUMINT=18 +BININTEGER=19 +DECINTEGER=20 +HEXINTEGER=21 +NAME=22 +WS=23 '\n'=1 ':'=2 '//'=3 @@ -23,5 +29,11 @@ WS=17 ',y'=6 '('=7 ')'=8 -'{'=9 -'}'=10 +'+'=9 +'-'=10 +'<'=11 +'>'=12 +'*'=13 +'/'=14 +'{'=15 +'}'=16 diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Listener.java b/src/dk/camelot64/kickc/asm/parser/Asm6502Listener.java index 83e5eb9cd..f6dc1d868 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502Listener.java +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Listener.java @@ -142,39 +142,63 @@ public interface Asm6502Listener extends ParseTreeListener { */ void exitModeInd(Asm6502Parser.ModeIndContext ctx); /** - * Enter a parse tree produced by the {@code paramLabel} - * labeled alternative in {@link Asm6502Parser#param}. + * Enter a parse tree produced by the {@code exprInt} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree */ - void enterParamLabel(Asm6502Parser.ParamLabelContext ctx); + void enterExprInt(Asm6502Parser.ExprIntContext ctx); /** - * Exit a parse tree produced by the {@code paramLabel} - * labeled alternative in {@link Asm6502Parser#param}. + * Exit a parse tree produced by the {@code exprInt} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree */ - void exitParamLabel(Asm6502Parser.ParamLabelContext ctx); + void exitExprInt(Asm6502Parser.ExprIntContext ctx); /** - * Enter a parse tree produced by the {@code paramReplace} - * labeled alternative in {@link Asm6502Parser#param}. + * Enter a parse tree produced by the {@code exprLabel} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree */ - void enterParamReplace(Asm6502Parser.ParamReplaceContext ctx); + void enterExprLabel(Asm6502Parser.ExprLabelContext ctx); /** - * Exit a parse tree produced by the {@code paramReplace} - * labeled alternative in {@link Asm6502Parser#param}. + * Exit a parse tree produced by the {@code exprLabel} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree */ - void exitParamReplace(Asm6502Parser.ParamReplaceContext ctx); + void exitExprLabel(Asm6502Parser.ExprLabelContext ctx); /** - * Enter a parse tree produced by the {@code paramInt} - * labeled alternative in {@link Asm6502Parser#param}. + * Enter a parse tree produced by the {@code exprBinary} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree */ - void enterParamInt(Asm6502Parser.ParamIntContext ctx); + void enterExprBinary(Asm6502Parser.ExprBinaryContext ctx); /** - * Exit a parse tree produced by the {@code paramInt} - * labeled alternative in {@link Asm6502Parser#param}. + * Exit a parse tree produced by the {@code exprBinary} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree */ - void exitParamInt(Asm6502Parser.ParamIntContext ctx); + void exitExprBinary(Asm6502Parser.ExprBinaryContext ctx); + /** + * Enter a parse tree produced by the {@code exprUnary} + * labeled alternative in {@link Asm6502Parser#expr}. + * @param ctx the parse tree + */ + void enterExprUnary(Asm6502Parser.ExprUnaryContext ctx); + /** + * Exit a parse tree produced by the {@code exprUnary} + * labeled alternative in {@link Asm6502Parser#expr}. + * @param ctx the parse tree + */ + void exitExprUnary(Asm6502Parser.ExprUnaryContext ctx); + /** + * Enter a parse tree produced by the {@code exprReplace} + * labeled alternative in {@link Asm6502Parser#expr}. + * @param ctx the parse tree + */ + void enterExprReplace(Asm6502Parser.ExprReplaceContext ctx); + /** + * Exit a parse tree produced by the {@code exprReplace} + * labeled alternative in {@link Asm6502Parser#expr}. + * @param ctx the parse tree + */ + void exitExprReplace(Asm6502Parser.ExprReplaceContext ctx); } \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Parser.java b/src/dk/camelot64/kickc/asm/parser/Asm6502Parser.java index 7c998d777..22a2e0708 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502Parser.java +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Parser.java @@ -18,22 +18,23 @@ public class Asm6502Parser extends Parser { new PredictionContextCache(); public static final int T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, - T__9=10, MNEMONIC=11, NUMINT=12, BININTEGER=13, DECINTEGER=14, HEXINTEGER=15, - NAME=16, WS=17; + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, MNEMONIC=17, + NUMINT=18, BININTEGER=19, DECINTEGER=20, HEXINTEGER=21, NAME=22, WS=23; public static final int RULE_file = 0, RULE_line = 1, RULE_label = 2, RULE_comment = 3, RULE_instruction = 4, - RULE_paramMode = 5, RULE_param = 6; + RULE_paramMode = 5, RULE_expr = 6; public static final String[] ruleNames = { - "file", "line", "label", "comment", "instruction", "paramMode", "param" + "file", "line", "label", "comment", "instruction", "paramMode", "expr" }; private static final String[] _LITERAL_NAMES = { - null, "'\n'", "':'", "'//'", "'#'", "',x'", "',y'", "'('", "')'", "'{'", - "'}'" + null, "'\n'", "':'", "'//'", "'#'", "',x'", "',y'", "'('", "')'", "'+'", + "'-'", "'<'", "'>'", "'*'", "'/'", "'{'", "'}'" }; private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, null, null, null, null, null, "MNEMONIC", - "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "WS" + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, "MNEMONIC", "NUMINT", "BININTEGER", "DECINTEGER", + "HEXINTEGER", "NAME", "WS" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -368,7 +369,7 @@ public class Asm6502Parser extends Parser { setState(45); _errHandler.sync(this); _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__6) | (1L << T__8) | (1L << NUMINT) | (1L << NAME))) != 0)) { + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__14) | (1L << NUMINT) | (1L << NAME))) != 0)) { { setState(44); paramMode(); @@ -400,8 +401,8 @@ public class Asm6502Parser extends Parser { } } public static class ModeIndXContext extends ParamModeContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); } public ModeIndXContext(ParamModeContext ctx) { copyFrom(ctx); } @Override @@ -419,8 +420,8 @@ public class Asm6502Parser extends Parser { } } public static class ModeImmContext extends ParamModeContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); } public ModeImmContext(ParamModeContext ctx) { copyFrom(ctx); } @Override @@ -438,8 +439,8 @@ public class Asm6502Parser extends Parser { } } public static class ModeIndYContext extends ParamModeContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); } public ModeIndYContext(ParamModeContext ctx) { copyFrom(ctx); } @Override @@ -457,8 +458,8 @@ public class Asm6502Parser extends Parser { } } public static class ModeAbsYContext extends ParamModeContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); } public ModeAbsYContext(ParamModeContext ctx) { copyFrom(ctx); } @Override @@ -476,8 +477,8 @@ public class Asm6502Parser extends Parser { } } public static class ModeIndContext extends ParamModeContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); } public ModeIndContext(ParamModeContext ctx) { copyFrom(ctx); } @Override @@ -495,8 +496,8 @@ public class Asm6502Parser extends Parser { } } public static class ModeAbsContext extends ParamModeContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); } public ModeAbsContext(ParamModeContext ctx) { copyFrom(ctx); } @Override @@ -514,8 +515,8 @@ public class Asm6502Parser extends Parser { } } public static class ModeAbsXContext extends ParamModeContext { - public ParamContext param() { - return getRuleContext(ParamContext.class,0); + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); } public ModeAbsXContext(ParamModeContext ctx) { copyFrom(ctx); } @Override @@ -545,7 +546,7 @@ public class Asm6502Parser extends Parser { enterOuterAlt(_localctx, 1); { setState(47); - param(); + expr(0); } break; case 2: @@ -555,7 +556,7 @@ public class Asm6502Parser extends Parser { setState(48); match(T__3); setState(49); - param(); + expr(0); } break; case 3: @@ -563,7 +564,7 @@ public class Asm6502Parser extends Parser { enterOuterAlt(_localctx, 3); { setState(50); - param(); + expr(0); setState(51); match(T__4); } @@ -573,7 +574,7 @@ public class Asm6502Parser extends Parser { enterOuterAlt(_localctx, 4); { setState(53); - param(); + expr(0); setState(54); match(T__5); } @@ -585,7 +586,7 @@ public class Asm6502Parser extends Parser { setState(56); match(T__6); setState(57); - param(); + expr(0); setState(58); match(T__7); setState(59); @@ -599,7 +600,7 @@ public class Asm6502Parser extends Parser { setState(61); match(T__6); setState(62); - param(); + expr(0); setState(63); match(T__4); setState(64); @@ -613,7 +614,7 @@ public class Asm6502Parser extends Parser { setState(66); match(T__6); setState(67); - param(); + expr(0); setState(68); match(T__7); } @@ -631,107 +632,246 @@ public class Asm6502Parser extends Parser { return _localctx; } - public static class ParamContext extends ParserRuleContext { - public ParamContext(ParserRuleContext parent, int invokingState) { + public static class ExprContext extends ParserRuleContext { + public ExprContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } - @Override public int getRuleIndex() { return RULE_param; } + @Override public int getRuleIndex() { return RULE_expr; } - public ParamContext() { } - public void copyFrom(ParamContext ctx) { + public ExprContext() { } + public void copyFrom(ExprContext ctx) { super.copyFrom(ctx); } } - public static class ParamReplaceContext extends ParamContext { - public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); } - public ParamReplaceContext(ParamContext ctx) { copyFrom(ctx); } - @Override - public void enterRule(ParseTreeListener listener) { - if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamReplace(this); - } - @Override - public void exitRule(ParseTreeListener listener) { - if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamReplace(this); - } - @Override - public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitParamReplace(this); - else return visitor.visitChildren(this); - } - } - public static class ParamIntContext extends ParamContext { + public static class ExprIntContext extends ExprContext { public TerminalNode NUMINT() { return getToken(Asm6502Parser.NUMINT, 0); } - public ParamIntContext(ParamContext ctx) { copyFrom(ctx); } + public ExprIntContext(ExprContext ctx) { copyFrom(ctx); } @Override public void enterRule(ParseTreeListener listener) { - if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamInt(this); + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterExprInt(this); } @Override public void exitRule(ParseTreeListener listener) { - if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamInt(this); + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitExprInt(this); } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitParamInt(this); + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitExprInt(this); else return visitor.visitChildren(this); } } - public static class ParamLabelContext extends ParamContext { + public static class ExprLabelContext extends ExprContext { public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); } - public ParamLabelContext(ParamContext ctx) { copyFrom(ctx); } + public ExprLabelContext(ExprContext ctx) { copyFrom(ctx); } @Override public void enterRule(ParseTreeListener listener) { - if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamLabel(this); + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterExprLabel(this); } @Override public void exitRule(ParseTreeListener listener) { - if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamLabel(this); + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitExprLabel(this); } @Override public T accept(ParseTreeVisitor visitor) { - if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitParamLabel(this); + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitExprLabel(this); + else return visitor.visitChildren(this); + } + } + public static class ExprBinaryContext extends ExprContext { + public List expr() { + return getRuleContexts(ExprContext.class); + } + public ExprContext expr(int i) { + return getRuleContext(ExprContext.class,i); + } + public ExprBinaryContext(ExprContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterExprBinary(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitExprBinary(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitExprBinary(this); + else return visitor.visitChildren(this); + } + } + public static class ExprUnaryContext extends ExprContext { + public ExprContext expr() { + return getRuleContext(ExprContext.class,0); + } + public ExprUnaryContext(ExprContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterExprUnary(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitExprUnary(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitExprUnary(this); + else return visitor.visitChildren(this); + } + } + public static class ExprReplaceContext extends ExprContext { + public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); } + public ExprReplaceContext(ExprContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterExprReplace(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitExprReplace(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitExprReplace(this); else return visitor.visitChildren(this); } } - public final ParamContext param() throws RecognitionException { - ParamContext _localctx = new ParamContext(_ctx, getState()); - enterRule(_localctx, 12, RULE_param); + public final ExprContext expr() throws RecognitionException { + return expr(0); + } + + private ExprContext expr(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + ExprContext _localctx = new ExprContext(_ctx, _parentState); + ExprContext _prevctx = _localctx; + int _startState = 12; + enterRecursionRule(_localctx, 12, RULE_expr, _p); + int _la; try { - setState(77); + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(80); _errHandler.sync(this); switch (_input.LA(1)) { - case NAME: - _localctx = new ParamLabelContext(_localctx); - enterOuterAlt(_localctx, 1); + case T__8: + case T__9: + case T__10: + case T__11: { - setState(72); + _localctx = new ExprUnaryContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(73); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11))) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(74); + expr(6); + } + break; + case NAME: + { + _localctx = new ExprLabelContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(75); match(NAME); } break; - case T__8: - _localctx = new ParamReplaceContext(_localctx); - enterOuterAlt(_localctx, 2); + case T__14: { - setState(73); - match(T__8); - setState(74); + _localctx = new ExprReplaceContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(76); + match(T__14); + setState(77); match(NAME); - setState(75); - match(T__9); + setState(78); + match(T__15); } break; case NUMINT: - _localctx = new ParamIntContext(_localctx); - enterOuterAlt(_localctx, 3); { - setState(76); + _localctx = new ExprIntContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(79); match(NUMINT); } break; default: throw new NoViableAltException(this); } + _ctx.stop = _input.LT(-1); + setState(90); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,9,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(88); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { + case 1: + { + _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); + pushNewRecursionContext(_localctx, _startState, RULE_expr); + setState(82); + if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); + setState(83); + _la = _input.LA(1); + if ( !(_la==T__12 || _la==T__13) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(84); + expr(6); + } + break; + case 2: + { + _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); + pushNewRecursionContext(_localctx, _startState, RULE_expr); + setState(85); + if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)"); + setState(86); + _la = _input.LA(1); + if ( !(_la==T__8 || _la==T__9) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(87); + expr(5); + } + break; + } + } + } + setState(92); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,9,_ctx); + } + } } catch (RecognitionException re) { _localctx.exception = re; @@ -739,33 +879,54 @@ public class Asm6502Parser extends Parser { _errHandler.recover(this, re); } finally { - exitRule(); + unrollRecursionContexts(_parentctx); } return _localctx; } + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 6: + return expr_sempred((ExprContext)_localctx, predIndex); + } + return true; + } + private boolean expr_sempred(ExprContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return precpred(_ctx, 5); + case 1: + return precpred(_ctx, 4); + } + return true; + } + public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\23R\4\2\t\2\4\3\t"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\31`\4\2\t\2\4\3\t"+ "\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\3\2\3\2\3\2\7\2\24\n\2\f\2"+ "\16\2\27\13\2\3\2\3\2\3\3\5\3\34\n\3\3\3\5\3\37\n\3\3\3\5\3\"\n\3\3\4"+ "\3\4\3\4\3\5\3\5\7\5)\n\5\f\5\16\5,\13\5\3\6\3\6\5\6\60\n\6\3\7\3\7\3"+ "\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7"+ - "\3\7\3\7\3\7\5\7I\n\7\3\b\3\b\3\b\3\b\3\b\5\bP\n\b\3\b\3*\2\t\2\4\6\b"+ - "\n\f\16\2\2\2X\2\20\3\2\2\2\4\33\3\2\2\2\6#\3\2\2\2\b&\3\2\2\2\n-\3\2"+ - "\2\2\fH\3\2\2\2\16O\3\2\2\2\20\25\5\4\3\2\21\22\7\3\2\2\22\24\5\4\3\2"+ - "\23\21\3\2\2\2\24\27\3\2\2\2\25\23\3\2\2\2\25\26\3\2\2\2\26\30\3\2\2\2"+ - "\27\25\3\2\2\2\30\31\7\2\2\3\31\3\3\2\2\2\32\34\5\6\4\2\33\32\3\2\2\2"+ - "\33\34\3\2\2\2\34\36\3\2\2\2\35\37\5\n\6\2\36\35\3\2\2\2\36\37\3\2\2\2"+ - "\37!\3\2\2\2 \"\5\b\5\2! \3\2\2\2!\"\3\2\2\2\"\5\3\2\2\2#$\7\22\2\2$%"+ - "\7\4\2\2%\7\3\2\2\2&*\7\5\2\2\')\13\2\2\2(\'\3\2\2\2),\3\2\2\2*+\3\2\2"+ - "\2*(\3\2\2\2+\t\3\2\2\2,*\3\2\2\2-/\7\r\2\2.\60\5\f\7\2/.\3\2\2\2/\60"+ - "\3\2\2\2\60\13\3\2\2\2\61I\5\16\b\2\62\63\7\6\2\2\63I\5\16\b\2\64\65\5"+ - "\16\b\2\65\66\7\7\2\2\66I\3\2\2\2\678\5\16\b\289\7\b\2\29I\3\2\2\2:;\7"+ - "\t\2\2;<\5\16\b\2<=\7\n\2\2=>\7\b\2\2>I\3\2\2\2?@\7\t\2\2@A\5\16\b\2A"+ - "B\7\7\2\2BC\7\n\2\2CI\3\2\2\2DE\7\t\2\2EF\5\16\b\2FG\7\n\2\2GI\3\2\2\2"+ - "H\61\3\2\2\2H\62\3\2\2\2H\64\3\2\2\2H\67\3\2\2\2H:\3\2\2\2H?\3\2\2\2H"+ - "D\3\2\2\2I\r\3\2\2\2JP\7\22\2\2KL\7\13\2\2LM\7\22\2\2MP\7\f\2\2NP\7\16"+ - "\2\2OJ\3\2\2\2OK\3\2\2\2ON\3\2\2\2P\17\3\2\2\2\n\25\33\36!*/HO"; + "\3\7\3\7\3\7\5\7I\n\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\5\bS\n\b\3\b\3\b"+ + "\3\b\3\b\3\b\3\b\7\b[\n\b\f\b\16\b^\13\b\3\b\3*\3\16\t\2\4\6\b\n\f\16"+ + "\2\5\3\2\13\16\3\2\17\20\3\2\13\f\2i\2\20\3\2\2\2\4\33\3\2\2\2\6#\3\2"+ + "\2\2\b&\3\2\2\2\n-\3\2\2\2\fH\3\2\2\2\16R\3\2\2\2\20\25\5\4\3\2\21\22"+ + "\7\3\2\2\22\24\5\4\3\2\23\21\3\2\2\2\24\27\3\2\2\2\25\23\3\2\2\2\25\26"+ + "\3\2\2\2\26\30\3\2\2\2\27\25\3\2\2\2\30\31\7\2\2\3\31\3\3\2\2\2\32\34"+ + "\5\6\4\2\33\32\3\2\2\2\33\34\3\2\2\2\34\36\3\2\2\2\35\37\5\n\6\2\36\35"+ + "\3\2\2\2\36\37\3\2\2\2\37!\3\2\2\2 \"\5\b\5\2! \3\2\2\2!\"\3\2\2\2\"\5"+ + "\3\2\2\2#$\7\30\2\2$%\7\4\2\2%\7\3\2\2\2&*\7\5\2\2\')\13\2\2\2(\'\3\2"+ + "\2\2),\3\2\2\2*+\3\2\2\2*(\3\2\2\2+\t\3\2\2\2,*\3\2\2\2-/\7\23\2\2.\60"+ + "\5\f\7\2/.\3\2\2\2/\60\3\2\2\2\60\13\3\2\2\2\61I\5\16\b\2\62\63\7\6\2"+ + "\2\63I\5\16\b\2\64\65\5\16\b\2\65\66\7\7\2\2\66I\3\2\2\2\678\5\16\b\2"+ + "89\7\b\2\29I\3\2\2\2:;\7\t\2\2;<\5\16\b\2<=\7\n\2\2=>\7\b\2\2>I\3\2\2"+ + "\2?@\7\t\2\2@A\5\16\b\2AB\7\7\2\2BC\7\n\2\2CI\3\2\2\2DE\7\t\2\2EF\5\16"+ + "\b\2FG\7\n\2\2GI\3\2\2\2H\61\3\2\2\2H\62\3\2\2\2H\64\3\2\2\2H\67\3\2\2"+ + "\2H:\3\2\2\2H?\3\2\2\2HD\3\2\2\2I\r\3\2\2\2JK\b\b\1\2KL\t\2\2\2LS\5\16"+ + "\b\bMS\7\30\2\2NO\7\21\2\2OP\7\30\2\2PS\7\22\2\2QS\7\24\2\2RJ\3\2\2\2"+ + "RM\3\2\2\2RN\3\2\2\2RQ\3\2\2\2S\\\3\2\2\2TU\f\7\2\2UV\t\3\2\2V[\5\16\b"+ + "\bWX\f\6\2\2XY\t\4\2\2Y[\5\16\b\7ZT\3\2\2\2ZW\3\2\2\2[^\3\2\2\2\\Z\3\2"+ + "\2\2\\]\3\2\2\2]\17\3\2\2\2^\\\3\2\2\2\f\25\33\36!*/HRZ\\"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Visitor.java b/src/dk/camelot64/kickc/asm/parser/Asm6502Visitor.java index d7950dd72..8ffe07068 100644 --- a/src/dk/camelot64/kickc/asm/parser/Asm6502Visitor.java +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Visitor.java @@ -90,24 +90,38 @@ public interface Asm6502Visitor extends ParseTreeVisitor { */ T visitModeInd(Asm6502Parser.ModeIndContext ctx); /** - * Visit a parse tree produced by the {@code paramLabel} - * labeled alternative in {@link Asm6502Parser#param}. + * Visit a parse tree produced by the {@code exprInt} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree * @return the visitor result */ - T visitParamLabel(Asm6502Parser.ParamLabelContext ctx); + T visitExprInt(Asm6502Parser.ExprIntContext ctx); /** - * Visit a parse tree produced by the {@code paramReplace} - * labeled alternative in {@link Asm6502Parser#param}. + * Visit a parse tree produced by the {@code exprLabel} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree * @return the visitor result */ - T visitParamReplace(Asm6502Parser.ParamReplaceContext ctx); + T visitExprLabel(Asm6502Parser.ExprLabelContext ctx); /** - * Visit a parse tree produced by the {@code paramInt} - * labeled alternative in {@link Asm6502Parser#param}. + * Visit a parse tree produced by the {@code exprBinary} + * labeled alternative in {@link Asm6502Parser#expr}. * @param ctx the parse tree * @return the visitor result */ - T visitParamInt(Asm6502Parser.ParamIntContext ctx); + T visitExprBinary(Asm6502Parser.ExprBinaryContext ctx); + /** + * Visit a parse tree produced by the {@code exprUnary} + * labeled alternative in {@link Asm6502Parser#expr}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitExprUnary(Asm6502Parser.ExprUnaryContext ctx); + /** + * Visit a parse tree produced by the {@code exprReplace} + * labeled alternative in {@link Asm6502Parser#expr}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitExprReplace(Asm6502Parser.ExprReplaceContext ctx); } \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java index 7e46a3d7d..4da7ecc60 100644 --- a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java +++ b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java @@ -159,7 +159,13 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public LValue visitLvalueArray(KickCParser.LvalueArrayContext ctx) { - throw new RuntimeException("Not implemented"); + LValue lval = (LValue) visit(ctx.lvalue()); + RValue index = (RValue) visit(ctx.expr()); + Operator operator = new Operator("+"); + VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment(); + Statement stmt = new StatementAssignment(tmpVar, lval, operator, index); + sequence.addStatement(stmt); + return new PointerDereference(tmpVar); } @Override @@ -205,8 +211,14 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { } @Override - public Object visitExprArray(KickCParser.ExprArrayContext ctx) { - throw new RuntimeException("Not implemented"); + public RValue visitExprArray(KickCParser.ExprArrayContext ctx) { + RValue array = (LValue) visit(ctx.expr(0)); + RValue index = (RValue) visit(ctx.expr(1)); + Operator operator = new Operator("+"); + VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment(); + Statement stmt = new StatementAssignment(tmpVar, array, operator, index); + sequence.addStatement(stmt); + return new PointerDereference(tmpVar); } @Override diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java index 37bfc9315..72a0b0fdb 100644 --- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java @@ -20,8 +20,12 @@ public class Pass3RegisterAllocation { allocation.allocate(var, new RegisterAllocation.RegisterZpByte(currentZp++)); } else if(var.getType().equals(SymbolTypeBasic.BOOLEAN)) { allocation.allocate(var, new RegisterAllocation.RegisterZpBool(currentZp++)); + } else if(var.getType() instanceof SymbolTypePointer) { + allocation.allocate(var, new RegisterAllocation.RegisterZpPointerByte(currentZp)); + currentZp = currentZp +2; } } + allocation.allocate(symbols.getVariable("i#0"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("i#2"), RegisterAllocation.getRegisterX()); allocation.allocate(symbols.getVariable("i#3"), RegisterAllocation.getRegisterX()); diff --git a/src/dk/camelot64/kickc/icl/PassTypeInference.java b/src/dk/camelot64/kickc/icl/PassTypeInference.java index 05bf4e871..edf1a5872 100644 --- a/src/dk/camelot64/kickc/icl/PassTypeInference.java +++ b/src/dk/camelot64/kickc/icl/PassTypeInference.java @@ -9,21 +9,24 @@ public class PassTypeInference { for (Statement statement : sequence.getStatements()) { if (statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; - Variable symbol = (Variable) assignment.getLValue(); - if (SymbolTypeBasic.VAR.equals(symbol.getType())) { - // Unresolved symbol - perform inference - Operator operator = assignment.getOperator(); - if (operator == null || assignment.getRValue1() == null) { - // Copy operation or Unary operation - RValue rValue = assignment.getRValue2(); - SymbolType type = inferType(rValue); - symbol.setInferredType(type); - } else { - // Binary operation - SymbolType type1 = inferType(assignment.getRValue1()); - SymbolType type2 = inferType(assignment.getRValue2()); - SymbolType type = inferType(type1, operator, type2); - symbol.setInferredType(type); + LValue lValue = assignment.getLValue(); + if (lValue instanceof Variable) { + Variable symbol = (Variable) lValue; + if (SymbolTypeBasic.VAR.equals(symbol.getType())) { + // Unresolved symbol - perform inference + Operator operator = assignment.getOperator(); + if (operator == null || assignment.getRValue1() == null) { + // Copy operation or Unary operation + RValue rValue = assignment.getRValue2(); + SymbolType type = inferType(rValue); + symbol.setInferredType(type); + } else { + // Binary operation + SymbolType type1 = inferType(assignment.getRValue1()); + SymbolType type2 = inferType(assignment.getRValue2()); + SymbolType type = inferType(type1, operator, type2); + symbol.setInferredType(type); + } } } } @@ -49,15 +52,18 @@ public class PassTypeInference { return SymbolTypeBasic.BOOLEAN; case "+": case "-": + if (type1 instanceof SymbolTypePointer && (type2.equals(SymbolTypeBasic.BYTE) || type2.equals(SymbolTypeBasic.WORD))) { + return new SymbolTypePointer(((SymbolTypePointer) type1).getElementType()); + } case "*": case "/": - if (type1.equals(SymbolTypeBasic.WORD) || type2.equals(SymbolTypeBasic.WORD)) { + if (SymbolTypeBasic.WORD.equals(type1) || SymbolTypeBasic.WORD.equals(type2)) { return SymbolTypeBasic.WORD; - } else { + } else if (SymbolTypeBasic.BYTE.equals(type1) && SymbolTypeBasic.BYTE.equals(type2)) { return SymbolTypeBasic.BYTE; } default: - throw new RuntimeException("Type inference case not handled "+type1+" "+operator+" "+type2); + throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2); } } @@ -78,8 +84,8 @@ public class PassTypeInference { } else if (rValue instanceof ConstantBool) { type = SymbolTypeBasic.BOOLEAN; } - if(type==null) { - throw new RuntimeException("Cannot infer type for "+rValue); + if (type == null) { + throw new RuntimeException("Cannot infer type for " + rValue); } return type; } diff --git a/src/dk/camelot64/kickc/icl/PointerDereference.java b/src/dk/camelot64/kickc/icl/PointerDereference.java new file mode 100644 index 000000000..1c34f946a --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PointerDereference.java @@ -0,0 +1,20 @@ +package dk.camelot64.kickc.icl; + +/** A dereferenced pointer */ +public class PointerDereference implements LValue { + + private Variable pointer; + + public PointerDereference(Variable pointer) { + this.pointer = pointer; + } + + public Variable getPointer() { + return pointer; + } + + @Override + public String toString() { + return "*(" + pointer + ')'; + } +} diff --git a/src/dk/camelot64/kickc/icl/RegisterAllocation.java b/src/dk/camelot64/kickc/icl/RegisterAllocation.java index 69b9069bd..3a9873a71 100644 --- a/src/dk/camelot64/kickc/icl/RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/RegisterAllocation.java @@ -36,8 +36,8 @@ public class RegisterAllocation { /** The register type. */ public enum RegisterType { - ZP_BYTE, ZP_BOOL, REG_Y_BYTE, REG_X_BYTE - }; + ZP_BYTE, ZP_BOOL, REG_Y_BYTE, REG_X_BYTE, ZP_PTR_BYTE + } /** A zero page address used as a register for a single byte variable. */ public static class RegisterZpByte implements Register { @@ -66,9 +66,7 @@ public class RegisterAllocation { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - RegisterZpByte that = (RegisterZpByte) o; - return zp == that.zp; } @@ -104,9 +102,7 @@ public class RegisterAllocation { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - RegisterZpBool that = (RegisterZpBool) o; - return zp == that.zp; } @@ -116,6 +112,43 @@ public class RegisterAllocation { } } + /** A zro page address pair used as a register containing a pointer to a byte. */ + public static class RegisterZpPointerByte implements Register { + private int zp; + + public RegisterZpPointerByte(int zp) { + this.zp = zp; + } + + @Override + public RegisterType getType() { + return RegisterType.ZP_PTR_BYTE; + } + + @Override + public String toString() { + return "zp ptrbyte:"+zp; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RegisterZpPointerByte that = (RegisterZpPointerByte) o; + return zp == that.zp; + } + + @Override + public int hashCode() { + return zp; + } + + public int getZp() { + return zp; + } + } + + /** The X register. */ public static class RegisterXByte implements Register { @Override diff --git a/src/dk/camelot64/kickc/icl/SymbolTypeArray.java b/src/dk/camelot64/kickc/icl/SymbolTypeArray.java index af8baedec..823c29fb7 100644 --- a/src/dk/camelot64/kickc/icl/SymbolTypeArray.java +++ b/src/dk/camelot64/kickc/icl/SymbolTypeArray.java @@ -1,26 +1,21 @@ package dk.camelot64.kickc.icl; /** A fixed size array of another type */ -public class SymbolTypeArray implements SymbolType { +public class SymbolTypeArray extends SymbolTypePointer { - private SymbolType elementType; private int size; public SymbolTypeArray(SymbolType elementType, int size) { - this.elementType = elementType; + super(elementType); this.size = size; } - public SymbolType getElementType() { - return elementType; - } - public int getSize() { return size; } @Override public String getTypeName() { - return elementType.getTypeName()+"["+size+"]"; + return getElementType().getTypeName()+"["+size+"]"; } } diff --git a/src/dk/camelot64/kickc/icl/SymbolTypePointer.java b/src/dk/camelot64/kickc/icl/SymbolTypePointer.java new file mode 100644 index 000000000..19e121533 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/SymbolTypePointer.java @@ -0,0 +1,22 @@ +package dk.camelot64.kickc.icl; + +/** A pointer */ +public class SymbolTypePointer implements SymbolType { + + private SymbolType elementType; + + public SymbolTypePointer(SymbolType elementType) { + this.elementType = elementType; + } + + public SymbolType getElementType() { + return elementType; + } + + @Override + public String getTypeName() { + return elementType.getTypeName()+"*"; + } + + +} diff --git a/src/dk/camelot64/kickc/icl/Variable.java b/src/dk/camelot64/kickc/icl/Variable.java index 210e2be32..af5131be3 100644 --- a/src/dk/camelot64/kickc/icl/Variable.java +++ b/src/dk/camelot64/kickc/icl/Variable.java @@ -41,7 +41,7 @@ public abstract class Variable implements Symbol, RValue, LValue { @Override public String toString() { - return "("+type.getTypeName() + (inferredType ?"*":"") + ") "+name; + return "("+type.getTypeName() + (inferredType ?"~":"") + ") "+name; } @Override diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java index f7e7f3f1e..a92a5dc70 100644 --- a/src/dk/camelot64/kickc/test/Main.java +++ b/src/dk/camelot64/kickc/test/Main.java @@ -50,6 +50,9 @@ public class Main { optimizations.add(new Pass2SelfPhiElimination(controlFlowGraph, symbolTable)); optimizations.add(new Pass2ConditionalJumpSimplification(controlFlowGraph, symbolTable)); + System.out.println("INITIAL CONTROL FLOW GRAPH"); + System.out.println(controlFlowGraph.toString()); + boolean optimized = true; while (optimized) { optimized = false; @@ -58,8 +61,8 @@ public class Main { if (stepOptimized) { System.out.println("Succesful optimization "+optimization); optimized = true; - //System.out.println("CONTROL FLOW GRAPH"); - //System.out.println(controlFlowGraph.toString()); + System.out.println("CONTROL FLOW GRAPH"); + System.out.println(controlFlowGraph.toString()); } } } diff --git a/src/dk/camelot64/kickc/test/mem.kc b/src/dk/camelot64/kickc/test/mem.kc index 4e589016e..7e0867451 100644 --- a/src/dk/camelot64/kickc/test/mem.kc +++ b/src/dk/camelot64/kickc/test/mem.kc @@ -1,10 +1,17 @@ // Array declaration & allocation (allocated in same memory space as the program) -byte[8*8] idtab; +byte[8*8] idtab = $1100; // Array assignment idtab[0] = 12; -// Using array indexing -//byte id6 = idtab[1]; +// Array assignment loop +byte i = 0; +do { + idtab[i] = i; + i = i+1; +} while (i!=0) + +// Using array indexing +byte id6 = idtab[14];