mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-20 00:29:10 +00:00
Merge branch 'master' of https://gitlab.com/camelot/kickc
This commit is contained in:
commit
68a737cf0f
@ -1,14 +1,14 @@
|
||||
# Contributing
|
||||
|
||||
When contributing to this repository, please first discuss the change you wish to make via issue,
|
||||
email, or any other method with the owner of this repository before making a change.
|
||||
facebook, or any other method with the owner of this repository before making a change.
|
||||
|
||||
## Building KickC
|
||||
|
||||
The prerequisites for locally building KickC is Java JDK 8+ and Apache Maven 3+.
|
||||
The prerequisites for locally building KickC are the following
|
||||
|
||||
* https://www.oracle.com/technetwork/java/javase
|
||||
* https://maven.apache.org
|
||||
* [Java JDK 8+](https://www.oracle.com/technetwork/java/javase)
|
||||
* [Apache Maven 3+](https://maven.apache.org)
|
||||
|
||||
The steps to build KickC is
|
||||
|
||||
@ -16,4 +16,3 @@ The steps to build KickC is
|
||||
2. Build and package the KickC compiler by entering the source directory and executing `mvn package`
|
||||
|
||||
|
||||
|
||||
|
17
README.md
17
README.md
@ -4,13 +4,7 @@ KickC is a compiler for a C-family language creating optimized and readable 6502
|
||||
|
||||
The KickC language is classic C with some limitations, some modifications and some extensions to ensure an optimal fit for creating 6502 assembler code.
|
||||
|
||||
## BETA
|
||||
|
||||
KickC is currently in beta, and crashes quite often resulting in cryptic errors. Also it will some times create ASM code that does not work properly.
|
||||
Feel free to test it and report any problems or errors you encounter, but do not expect it to produce production quality code.
|
||||
Also, be prepared that major breaking changes (to syntax, to semantics, etc.) may be implemented in the next versions.
|
||||
|
||||
* [Download](https://gitlab.com/camelot/kickc/releases) the newest Releases
|
||||
* [Download](https://gitlab.com/camelot/kickc/releases) the newest Release
|
||||
|
||||
* [Read](https://docs.google.com/document/d/1JE-Lt5apM-g4tZN3LS4TDbPKYgXuBz294enS9Oc4HXM/edit?usp=sharing) the Reference Manual
|
||||
|
||||
@ -20,4 +14,11 @@ Also, be prepared that major breaking changes (to syntax, to semantics, etc.) ma
|
||||
|
||||
* [Discuss](https://www.facebook.com/groups/302286200587943/) the compiler and receive news on facebook
|
||||
|
||||
* [Contribute](https://gitlab.com/camelot/kickc/blob/master/CONTRIBUTING.md) to the development of KickC
|
||||
* [Contribute](https://gitlab.com/camelot/kickc/blob/master/CONTRIBUTING.md) to the development of KickC
|
||||
|
||||
## BETA
|
||||
|
||||
KickC is currently in beta, and crashes quite often resulting in cryptic errors.
|
||||
Also it will at times create ASM code that does not work properly.
|
||||
Feel free to test it and report any problems or errors you encounter, but do not expect it to produce production quality code.
|
||||
Also, be prepared that major breaking changes (to syntax, to semantics, etc.) may be implemented in the next versions.
|
4
src/main/fragment/_deref_pptc1=pbuc2.asm
Normal file
4
src/main/fragment/_deref_pptc1=pbuc2.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda #<{c2}
|
||||
sta {c1}
|
||||
lda #>{c2}
|
||||
sta {c1}+1
|
6
src/main/fragment/_deref_pptz1=pbuc1.asm
Normal file
6
src/main/fragment/_deref_pptz1=pbuc1.asm
Normal file
@ -0,0 +1,6 @@
|
||||
ldy #0
|
||||
lda #<{c1}
|
||||
sta ({z1}),y
|
||||
iny
|
||||
lda #>{c1}
|
||||
sta ({z1}),y
|
6
src/main/fragment/_deref_pptz1=pbuz2.asm
Normal file
6
src/main/fragment/_deref_pptz1=pbuz2.asm
Normal file
@ -0,0 +1,6 @@
|
||||
ldy #0
|
||||
lda {z2}
|
||||
sta ({z1}),y
|
||||
iny
|
||||
lda {z2}+1
|
||||
sta ({z1}),y
|
1
src/main/fragment/pbsz1=_ptr_pbuz1.asm
Normal file
1
src/main/fragment/pbsz1=_ptr_pbuz1.asm
Normal file
@ -0,0 +1 @@
|
||||
// No operation needed
|
4
src/main/fragment/pbsz1=_ptr_pbuz2.asm
Normal file
4
src/main/fragment/pbsz1=_ptr_pbuz2.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda {z2}
|
||||
sta {z1}
|
||||
lda {z2}+1
|
||||
sta {z1}+1
|
4
src/main/fragment/pbsz1=pbsz2.asm
Normal file
4
src/main/fragment/pbsz1=pbsz2.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda {z2}
|
||||
sta {z1}
|
||||
lda {z2}+1
|
||||
sta {z1}+1
|
1
src/main/fragment/pbuz1=_ptr_pbsz1.asm
Normal file
1
src/main/fragment/pbuz1=_ptr_pbsz1.asm
Normal file
@ -0,0 +1 @@
|
||||
// No operation needed
|
4
src/main/fragment/pbuz1=_ptr_pbsz2.asm
Normal file
4
src/main/fragment/pbuz1=_ptr_pbsz2.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda {z2}
|
||||
sta {z1}
|
||||
lda {z2}+1
|
||||
sta {z1}+1
|
4
src/main/fragment/pprz1=_deref_pptc1.asm
Normal file
4
src/main/fragment/pprz1=_deref_pptc1.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda {c1}
|
||||
sta {z1}
|
||||
lda {c1}+1
|
||||
sta {z1}+1
|
4
src/main/fragment/pprz1=pprc1.asm
Normal file
4
src/main/fragment/pprz1=pprc1.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda #<{c1}
|
||||
sta {z1}
|
||||
lda #>{c1}
|
||||
sta {z1}+1
|
4
src/main/fragment/pprz1=pprz2.asm
Normal file
4
src/main/fragment/pprz1=pprz2.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda {z2}
|
||||
sta {z1}
|
||||
lda {z2}+1
|
||||
sta {z1}+1
|
4
src/main/fragment/pprz1=pptc1_derefidx_vbuxx.asm
Normal file
4
src/main/fragment/pprz1=pptc1_derefidx_vbuxx.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda {c1},x
|
||||
sta {z1}
|
||||
lda {c1}+1,x
|
||||
sta {z1}+1
|
4
src/main/fragment/pprz1=pptc1_derefidx_vbuyy.asm
Normal file
4
src/main/fragment/pprz1=pptc1_derefidx_vbuyy.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda {c1},y
|
||||
sta {z1}
|
||||
lda {c1}+1,y
|
||||
sta {z1}+1
|
4
src/main/fragment/pptz1=pptc1.asm
Normal file
4
src/main/fragment/pptz1=pptc1.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda #<{c1}
|
||||
sta {z1}
|
||||
lda #>{c1}
|
||||
sta {z1}+1
|
@ -0,0 +1,4 @@
|
||||
clc
|
||||
lda ({z1}),y
|
||||
ldy #{c1}
|
||||
adc ({z1}),y
|
@ -0,0 +1,2 @@
|
||||
clc
|
||||
adc ({z1}),y
|
4
src/main/fragment/vbsaa=vbsaa_ror_4.asm
Normal file
4
src/main/fragment/vbsaa=vbsaa_ror_4.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
1
src/main/fragment/vbuaa=_byte_pprz1.asm
Normal file
1
src/main/fragment/vbuaa=_byte_pprz1.asm
Normal file
@ -0,0 +1 @@
|
||||
lda {z1}
|
2
src/main/fragment/vbuaa=_deref__deref_pptc1.asm
Normal file
2
src/main/fragment/vbuaa=_deref__deref_pptc1.asm
Normal file
@ -0,0 +1,2 @@
|
||||
ldy #0
|
||||
lda ({c1}),y
|
@ -0,0 +1,4 @@
|
||||
clc
|
||||
lda ({z1}),y
|
||||
ldy #{c1}
|
||||
adc ({z1}),y
|
1
src/main/fragment/vbuaa=vbuaa_bxor_vbuz1.asm
Normal file
1
src/main/fragment/vbuaa=vbuaa_bxor_vbuz1.asm
Normal file
@ -0,0 +1 @@
|
||||
eor {z1}
|
@ -0,0 +1,2 @@
|
||||
clc
|
||||
adc ({z1}),y
|
4
src/main/fragment/vwsz1=_sword_pbsz2_derefidx_vbuyy.asm
Normal file
4
src/main/fragment/vwsz1=_sword_pbsz2_derefidx_vbuyy.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda ({z2}),y
|
||||
sta {z1}
|
||||
lda #0
|
||||
sta {z1}+1
|
@ -103,6 +103,11 @@ public class CompileLog {
|
||||
this.verboseStatementSequence = verboseStatementSequence;
|
||||
}
|
||||
|
||||
public CompileLog verboseStatementSequence() {
|
||||
setVerboseStatementSequence(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setVerboseComments(boolean verboseComments) {
|
||||
this.verboseComments = verboseComments;
|
||||
}
|
||||
@ -123,10 +128,20 @@ public class CompileLog {
|
||||
this.verboseSequencePlan = verboseSequencePlan;
|
||||
}
|
||||
|
||||
public CompileLog verboseParse() {
|
||||
setVerboseParse(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setVerboseParse(boolean verboseParse) {
|
||||
this.verboseParse = verboseParse;
|
||||
}
|
||||
|
||||
public CompileLog verboseCreateSsa() {
|
||||
setVerboseCreateSsa(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setVerboseCreateSsa(boolean verboseCreateSsa) {
|
||||
this.verboseCreateSsa = verboseCreateSsa;
|
||||
}
|
||||
@ -135,6 +150,11 @@ public class CompileLog {
|
||||
return verboseUplift;
|
||||
}
|
||||
|
||||
public CompileLog verboseUplift() {
|
||||
setVerboseUplift(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setVerboseUplift(boolean verboseUplift) {
|
||||
this.verboseUplift = verboseUplift;
|
||||
}
|
||||
@ -155,6 +175,11 @@ public class CompileLog {
|
||||
this.verboseFragmentLog = verboseFragmentLog;
|
||||
}
|
||||
|
||||
public CompileLog verboseFragmentLog() {
|
||||
setVerboseFragmentLog(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isVerboseAsmOptimize() {
|
||||
return verboseAsmOptimize;
|
||||
}
|
||||
@ -167,6 +192,12 @@ public class CompileLog {
|
||||
return verboseSSAOptimize;
|
||||
}
|
||||
|
||||
public CompileLog setVerboseSSAOptimize() {
|
||||
setVerboseSSAOptimize(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public void setVerboseSSAOptimize(boolean verboseSSAOptimize) {
|
||||
this.verboseSSAOptimize = verboseSSAOptimize;
|
||||
}
|
||||
|
@ -249,6 +249,7 @@ public class Compiler {
|
||||
optimizations.add(new Pass2NopCastElimination(program));
|
||||
optimizations.add(new Pass2EliminateUnusedBlocks(program));
|
||||
optimizations.add(new Pass2RangeResolving(program));
|
||||
optimizations.add(new Pass2ConstantCallPointerIdentification(program));
|
||||
pass2Execute(optimizations);
|
||||
}
|
||||
|
||||
@ -487,6 +488,8 @@ public class Compiler {
|
||||
pass5Optimizations.add(new Pass5DoubleJumpElimination(program));
|
||||
pass5Optimizations.add(new Pass5UnreachableCodeElimination(program));
|
||||
pass5Optimizations.add(new Pass5RelabelLongLabels(program));
|
||||
pass5Optimizations.add(new Pass5SkipBegin(program));
|
||||
pass5Optimizations.add(new Pass5AddMainRts(program));
|
||||
boolean asmOptimized = true;
|
||||
while(asmOptimized) {
|
||||
asmOptimized = false;
|
||||
|
@ -229,7 +229,7 @@ public class AsmFormat {
|
||||
* @param boundVar The variable
|
||||
* @return The ASM parameter to use in the ASM code
|
||||
*/
|
||||
static String getAsmParamName(Variable boundVar, ScopeRef codeScopeRef) {
|
||||
public static String getAsmParamName(Variable boundVar, ScopeRef codeScopeRef) {
|
||||
ScopeRef varScopeRef = boundVar.getScope().getRef();
|
||||
String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
|
||||
return getAsmParamName(varScopeRef, asmName, codeScopeRef);
|
||||
@ -241,7 +241,7 @@ public class AsmFormat {
|
||||
* @param boundVar The constant
|
||||
* @return The ASM parameter to use in the ASM code
|
||||
*/
|
||||
private static String getAsmParamName(ConstantVar boundVar, ScopeRef codeScopeRef) {
|
||||
public static String getAsmParamName(ConstantVar boundVar, ScopeRef codeScopeRef) {
|
||||
ScopeRef varScopeRef = boundVar.getScope().getRef();
|
||||
String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
|
||||
return getAsmParamName(varScopeRef, asmName, codeScopeRef);
|
||||
|
@ -444,9 +444,9 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
// Rewrite Assignments to *C1 from A
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pb(.)c1=(.*)", null, null, "vb$1aa=$2", "sta {c1}", null));
|
||||
// Rewrite Assignments to *Z1 from A
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pbuz1=(.*)", twoZ1, null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y", mapZ));
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pb(.)z1=(.*)", twoZ1, null, "vb$1aa=$2", "ldy #0\n" + "sta ({z1}),y", mapZ));
|
||||
// Rewrite Assignments to *Z1 from A
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pbuz1=(.*z1.*)", null, null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y", null));
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("_deref_pb(.)z1=(.*z1.*)", null, null, "vb$1aa=$2", "ldy #0\n" + "sta ({z1}),y", null));
|
||||
|
||||
// Rewrite _deref_pb.z1_ to _vb.aa_ (if no other Z1s)
|
||||
synths.add(new AsmFragmentTemplateSynthesisRule("(.*)_deref_pb(.)z1(.*)", twoZ1+"|"+rvalAa+"|"+rvalYy+"|"+ lvalDerefZ1, "ldy #0\n"+"lda ({z1}),y", "$1vb$2aa$3", null, mapZ));
|
||||
|
@ -549,11 +549,11 @@ public class AsmFragmentTemplateSynthesizer {
|
||||
|
||||
}
|
||||
|
||||
public class UnknownFragmentException extends RuntimeException {
|
||||
public static class UnknownFragmentException extends RuntimeException {
|
||||
|
||||
private String signature;
|
||||
|
||||
UnknownFragmentException(String signature) {
|
||||
public UnknownFragmentException(String signature) {
|
||||
super("Fragment not found " + signature);
|
||||
this.signature = signature;
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ public class ControlFlowGraphBaseVisitor<T> {
|
||||
return visitJumpTarget((StatementLabel) statement);
|
||||
} else if(statement instanceof StatementCall) {
|
||||
return visitCall((StatementCall) statement);
|
||||
} else if(statement instanceof StatementCallPointer) {
|
||||
return visitCallPointer((StatementCallPointer) statement);
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
return visitPhiBlock((StatementPhiBlock) statement);
|
||||
} else if(statement instanceof StatementReturn) {
|
||||
@ -86,6 +88,10 @@ public class ControlFlowGraphBaseVisitor<T> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public T visitCallPointer(StatementCallPointer call) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public T visitAsm(StatementAsm asm) {
|
||||
return null;
|
||||
}
|
||||
|
@ -173,6 +173,14 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
|
||||
return new StatementCall(lValue, procedureName, parameters, orig.getSource(), orig.getComments());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitCallPointer(StatementCallPointer orig) {
|
||||
LValue lValue = orig.getlValue();
|
||||
RValue procedure = orig.getProcedure();
|
||||
List<RValue> parameters = orig.getParameters();
|
||||
return new StatementCallPointer(lValue, procedure, parameters, orig.getSource(), orig.getComments());
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatementProcedureBegin visitProcedureBegin(StatementProcedureBegin orig) {
|
||||
return new StatementProcedureBegin(orig.getProcedure(), orig.getSource(), orig.getComments());
|
||||
|
@ -542,6 +542,44 @@ public abstract class ProgramValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static class CallPointerProcedure extends ProgramValue {
|
||||
private final StatementCallPointer call;
|
||||
|
||||
CallPointerProcedure(StatementCallPointer call) {
|
||||
this.call = call;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value get() {
|
||||
return call.getProcedure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Value value) {
|
||||
call.setProcedure((RValue) value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CallPointerParameter extends ProgramValue {
|
||||
private final StatementCallPointer call;
|
||||
private final int i;
|
||||
|
||||
CallPointerParameter(StatementCallPointer call, int i) {
|
||||
this.call = call;
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value get() {
|
||||
return call.getParameters().get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Value value) {
|
||||
call.getParameters().set(i, (RValue) value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CondRValue1 extends ProgramValue {
|
||||
private final StatementConditionalJump statement;
|
||||
|
||||
@ -618,7 +656,7 @@ public abstract class ProgramValue {
|
||||
private final StatementPhiBlock.PhiVariable phiVariable;
|
||||
private final int i;
|
||||
|
||||
PhiValue(StatementPhiBlock.PhiVariable phiVariable, int i) {
|
||||
public PhiValue(StatementPhiBlock.PhiVariable phiVariable, int i) {
|
||||
this.phiVariable = phiVariable;
|
||||
this.i = i;
|
||||
}
|
||||
|
@ -108,6 +108,16 @@ public class ProgramValueIterator {
|
||||
}
|
||||
}
|
||||
execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
||||
} else if(statement instanceof StatementCallPointer) {
|
||||
StatementCallPointer call = (StatementCallPointer) statement;
|
||||
execute(new ProgramValue.CallPointerProcedure((StatementCallPointer) statement), handler, statement, statementsIt, block);
|
||||
if(call.getParameters() != null) {
|
||||
int size = call.getParameters().size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
execute(new ProgramValue.CallPointerParameter(call, i), handler, statement, statementsIt, block);
|
||||
}
|
||||
}
|
||||
execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
|
||||
} else if(statement instanceof StatementConditionalJump) {
|
||||
execute(new ProgramValue.CondRValue1((StatementConditionalJump) statement), handler, statement, statementsIt, block);
|
||||
execute(new ProgramValue.CondRValue2((StatementConditionalJump) statement), handler, statement, statementsIt, block);
|
||||
|
@ -22,6 +22,8 @@ public class OperatorCastPtr extends OperatorUnary {
|
||||
public ConstantLiteral calculateLiteral(ConstantLiteral value) {
|
||||
if(value instanceof ConstantInteger) {
|
||||
return new ConstantPointer(((ConstantInteger) value).getInteger(), elementType);
|
||||
} else if(value instanceof ConstantPointer) {
|
||||
return new ConstantPointer(((ConstantPointer) value).getLocation(), elementType);
|
||||
}
|
||||
throw new CompileError("Calculation not implemented " + getOperator() + " " + value);
|
||||
}
|
||||
|
@ -15,12 +15,13 @@ import java.util.List;
|
||||
*/
|
||||
public class StatementCall extends StatementBase implements StatementLValue {
|
||||
|
||||
/**
|
||||
* The variable being assigned a value by the call. Can be null.
|
||||
*/
|
||||
/** The variable being assigned a value by the call. Can be null. */
|
||||
private LValue lValue;
|
||||
/** The name of the procedure called */
|
||||
private String procedureName;
|
||||
/** The procedure called. */
|
||||
private ProcedureRef procedure;
|
||||
/** The parameter values passed to the procedure. */
|
||||
private List<RValue> parameters;
|
||||
|
||||
public StatementCall(LValue lValue, String procedureName, List<RValue> parameters, StatementSource source, List<Comment> comments) {
|
||||
|
@ -0,0 +1,103 @@
|
||||
package dk.camelot64.kickc.model.statements;
|
||||
|
||||
import dk.camelot64.kickc.model.Comment;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Call of a procedure where the called procedure is not directly named, but the result of an expression.
|
||||
*/
|
||||
public class StatementCallPointer extends StatementBase implements StatementLValue {
|
||||
|
||||
/** The variable being assigned a value by the call. Can be null. */
|
||||
private LValue lValue;
|
||||
/** The expression calculating the procedure being called. */
|
||||
private RValue procedure;
|
||||
/** The parameter values passed to the procedure. */
|
||||
private List<RValue> parameters;
|
||||
|
||||
public StatementCallPointer(LValue lValue, RValue procedure, List<RValue> parameters, StatementSource source, List<Comment> comments) {
|
||||
super(null, source, comments);
|
||||
this.lValue = lValue;
|
||||
this.procedure = procedure;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public RValue getProcedure() {
|
||||
return procedure;
|
||||
}
|
||||
|
||||
public void setProcedure(RValue procedure) {
|
||||
this.procedure = procedure;
|
||||
}
|
||||
|
||||
public LValue getlValue() {
|
||||
return lValue;
|
||||
}
|
||||
|
||||
public void setlValue(LValue lValue) {
|
||||
this.lValue = lValue;
|
||||
}
|
||||
|
||||
public List<RValue> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(List<RValue> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public int getNumParameters() {
|
||||
return parameters.size();
|
||||
}
|
||||
|
||||
public RValue getParameter(int idx) {
|
||||
return parameters.get(idx);
|
||||
}
|
||||
|
||||
public void clearParameters() {
|
||||
this.parameters = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Program program, boolean aliveInfo) {
|
||||
StringBuilder res = new StringBuilder();
|
||||
res.append(super.idxString());
|
||||
if(lValue != null) {
|
||||
res.append(lValue.toString(program));
|
||||
res.append(" ← ");
|
||||
}
|
||||
res.append("call ");
|
||||
res.append(procedure.toString(program) + " ");
|
||||
if(parameters != null) {
|
||||
for(RValue parameter : parameters) {
|
||||
res.append(parameter.toString(program) + " ");
|
||||
}
|
||||
}
|
||||
if(aliveInfo) {
|
||||
res.append(super.aliveString(program));
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(this == o) return true;
|
||||
if(o == null || getClass() != o.getClass()) return false;
|
||||
if(!super.equals(o)) return false;
|
||||
StatementCallPointer that = (StatementCallPointer) o;
|
||||
return Objects.equals(lValue, that.lValue) &&
|
||||
Objects.equals(procedure, that.procedure) &&
|
||||
Objects.equals(parameters, that.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), lValue, procedure, parameters);
|
||||
}
|
||||
}
|
@ -241,6 +241,19 @@ public abstract class Scope implements Symbol {
|
||||
return procedures;
|
||||
}
|
||||
|
||||
public Collection<Symbol> getAllSymbols(boolean includeSubscopes) {
|
||||
ArrayList<Symbol> allSymbols = new ArrayList<>();
|
||||
for(Symbol symbol : symbols.values()) {
|
||||
allSymbols.add(symbol);
|
||||
if(symbol instanceof Scope && includeSubscopes) {
|
||||
allSymbols.addAll(((Scope) symbol).getAllSymbols(true));
|
||||
}
|
||||
}
|
||||
return allSymbols;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Label addLabel(String name) {
|
||||
Label symbol = new Label(name, this, false);
|
||||
add(symbol);
|
||||
|
@ -43,16 +43,46 @@ public interface SymbolType {
|
||||
switch(name) {
|
||||
case "byte":
|
||||
return BYTE;
|
||||
case "unsigned byte":
|
||||
return BYTE;
|
||||
case "signed byte":
|
||||
return SBYTE;
|
||||
case "char":
|
||||
return SBYTE;
|
||||
case "unsigned char":
|
||||
return BYTE;
|
||||
case "signed char":
|
||||
return SBYTE;
|
||||
case "word":
|
||||
return WORD;
|
||||
case "unsigned word":
|
||||
return WORD;
|
||||
case "signed word":
|
||||
return SWORD;
|
||||
case "short":
|
||||
return SWORD;
|
||||
case "unsigned short":
|
||||
return WORD;
|
||||
case "signed short":
|
||||
return SWORD;
|
||||
case "int":
|
||||
return SWORD;
|
||||
case "unsigned int":
|
||||
return WORD;
|
||||
case "signed int":
|
||||
return SWORD;
|
||||
case "dword":
|
||||
return DWORD;
|
||||
case "unsigned dword":
|
||||
return DWORD;
|
||||
case "signed dword":
|
||||
return SDWORD;
|
||||
case "long":
|
||||
return SDWORD;
|
||||
case "unsigned long":
|
||||
return DWORD;
|
||||
case "signed long":
|
||||
return SDWORD;
|
||||
case "string":
|
||||
return STRING;
|
||||
case "bool":
|
||||
|
@ -6,9 +6,7 @@ import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.operators.Operator;
|
||||
import dk.camelot64.kickc.model.operators.OperatorBinary;
|
||||
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementLValue;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
@ -327,6 +325,47 @@ public class SymbolTypeInference {
|
||||
}
|
||||
}
|
||||
|
||||
public static void inferCallPointerLValue(Program program, StatementCallPointer call, boolean reinfer) {
|
||||
ProgramScope programScope = program.getScope();
|
||||
LValue lValue = call.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
Variable symbol = programScope.getVariable((VariableRef) lValue);
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
|
||||
SymbolType procedureType = inferType(programScope, call.getProcedure());
|
||||
if(procedureType instanceof SymbolTypeProcedure) {
|
||||
SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType();
|
||||
setInferedType(program, call, symbol, returnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable, boolean reinfer) {
|
||||
ProgramScope programScope = program.getScope();
|
||||
|
||||
Variable symbol = programScope.getVariable(phiVariable.getVariable());
|
||||
if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
|
||||
SymbolType type = null;
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
RValue rValue = phiRValue.getrValue();
|
||||
SymbolType valueType = inferType(programScope, rValue);
|
||||
if(type == null) {
|
||||
type = valueType;
|
||||
} else {
|
||||
SymbolType newType = intersectTypes(type, valueType);
|
||||
if(newType == null) {
|
||||
throw new CompileError("Types not compatible " + type + " and " + valueType);
|
||||
}
|
||||
type = newType;
|
||||
}
|
||||
}
|
||||
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
|
||||
program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program));
|
||||
}
|
||||
symbol.setTypeInferred(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void inferAssignmentLValue(Program program, StatementAssignment assignment, boolean reinfer) {
|
||||
ProgramScope programScope = program.getScope();
|
||||
LValue lValue = assignment.getlValue();
|
||||
@ -365,9 +404,9 @@ public class SymbolTypeInference {
|
||||
}
|
||||
}
|
||||
|
||||
private static void setInferedType(Program program, StatementLValue statementLValue, Variable symbol, SymbolType type) {
|
||||
private static void setInferedType(Program program, Statement statement, Variable symbol, SymbolType type) {
|
||||
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
|
||||
program.getLog().append("Inferred type updated to " + type + " in " + statementLValue.toString(program, false));
|
||||
program.getLog().append("Inferred type updated to " + type + " in " + statement.toString(program, false));
|
||||
}
|
||||
symbol.setTypeInferred(type);
|
||||
}
|
||||
@ -377,6 +416,8 @@ public class SymbolTypeInference {
|
||||
inferAssignmentLValue(program, (StatementAssignment) statementLValue, reinfer);
|
||||
} else if(statementLValue instanceof StatementCall) {
|
||||
inferCallLValue(program, (StatementCall) statementLValue, reinfer);
|
||||
} else if(statementLValue instanceof StatementCallPointer) {
|
||||
inferCallPointerLValue(program, (StatementCallPointer) statementLValue, reinfer);
|
||||
} else {
|
||||
throw new RuntimeException("LValue statement not implemented " + statementLValue);
|
||||
}
|
||||
|
@ -39,7 +39,9 @@ parameterListDecl
|
||||
: parameterDecl (',' parameterDecl)* ;
|
||||
|
||||
parameterDecl
|
||||
: directive* typeDecl directive* NAME ;
|
||||
: directive* typeDecl directive* NAME #parameterDeclType
|
||||
| SIMPLETYPE #parameterDeclVoid
|
||||
;
|
||||
|
||||
directive
|
||||
: 'const' #directiveConst
|
||||
@ -82,7 +84,7 @@ forIteration
|
||||
typeDecl
|
||||
: '(' typeDecl ')' #typePar
|
||||
| SIMPLETYPE #typeSimple
|
||||
| 'signed' SIMPLETYPE #typeSignedSimple
|
||||
| ('signed'|'unsigned') SIMPLETYPE #typeSignedSimple
|
||||
| typeDecl '*' #typePtr
|
||||
| typeDecl '[' (expr)? ']' #typeArray
|
||||
| typeDecl '(' ')' #typeProcedure
|
||||
@ -90,7 +92,7 @@ typeDecl
|
||||
|
||||
expr
|
||||
: '(' expr ')' #exprPar
|
||||
| NAME '(' parameterList? ')' #exprCall
|
||||
| expr '(' parameterList? ')' #exprCall
|
||||
| expr '[' expr ']' #exprArray
|
||||
| '(' typeDecl ')' expr #exprCast
|
||||
| ('--' | '++' ) expr #exprPreMod
|
||||
@ -107,6 +109,7 @@ expr
|
||||
| expr ( '|' ) expr #exprBinary
|
||||
| expr ( '&&' ) expr #exprBinary
|
||||
| expr ( '||' ) expr #exprBinary
|
||||
| expr '?' expr ':' expr #exprTernary
|
||||
| <assoc=right> expr '=' expr #exprAssignment
|
||||
| <assoc=right> expr ('+=' | '-=' | '*=' | '/=' | '%=' | '<<=' | '>>=' | '&=' | '|=' | '^=' ) expr #exprAssignmentCompound
|
||||
| '{' expr (',' expr )* '}' #initList
|
||||
@ -193,7 +196,7 @@ MNEMONIC:
|
||||
|
||||
|
||||
KICKASM: '{{' .*? '}}';
|
||||
SIMPLETYPE: 'byte' | 'word' | 'dword' | 'bool' | 'void' ;
|
||||
SIMPLETYPE: 'byte' | 'word' | 'dword' | 'bool' | 'char' | 'short' | 'int' | 'long' | 'void' ;
|
||||
STRING : '"' ('\\"' | ~'"')* '"';
|
||||
CHAR : '\'' ('\\\'' | ~'\'' ) '\'';
|
||||
BOOLEAN : 'true' | 'false';
|
||||
|
@ -69,26 +69,28 @@ T__67=68
|
||||
T__68=69
|
||||
T__69=70
|
||||
T__70=71
|
||||
MNEMONIC=72
|
||||
KICKASM=73
|
||||
SIMPLETYPE=74
|
||||
STRING=75
|
||||
CHAR=76
|
||||
BOOLEAN=77
|
||||
NUMBER=78
|
||||
NUMFLOAT=79
|
||||
BINFLOAT=80
|
||||
DECFLOAT=81
|
||||
HEXFLOAT=82
|
||||
NUMINT=83
|
||||
BININTEGER=84
|
||||
DECINTEGER=85
|
||||
HEXINTEGER=86
|
||||
NAME=87
|
||||
ASMREL=88
|
||||
WS=89
|
||||
COMMENT_LINE=90
|
||||
COMMENT_BLOCK=91
|
||||
T__71=72
|
||||
T__72=73
|
||||
MNEMONIC=74
|
||||
KICKASM=75
|
||||
SIMPLETYPE=76
|
||||
STRING=77
|
||||
CHAR=78
|
||||
BOOLEAN=79
|
||||
NUMBER=80
|
||||
NUMFLOAT=81
|
||||
BINFLOAT=82
|
||||
DECFLOAT=83
|
||||
HEXFLOAT=84
|
||||
NUMINT=85
|
||||
BININTEGER=86
|
||||
DECINTEGER=87
|
||||
HEXINTEGER=88
|
||||
NAME=89
|
||||
ASMREL=90
|
||||
WS=91
|
||||
COMMENT_LINE=92
|
||||
COMMENT_BLOCK=93
|
||||
'import'=1
|
||||
'='=2
|
||||
';'=3
|
||||
@ -116,47 +118,49 @@ COMMENT_BLOCK=91
|
||||
':'=25
|
||||
'..'=26
|
||||
'signed'=27
|
||||
'*'=28
|
||||
'['=29
|
||||
']'=30
|
||||
'--'=31
|
||||
'++'=32
|
||||
'+'=33
|
||||
'-'=34
|
||||
'!'=35
|
||||
'&'=36
|
||||
'~'=37
|
||||
'>>'=38
|
||||
'<<'=39
|
||||
'/'=40
|
||||
'%'=41
|
||||
'<'=42
|
||||
'>'=43
|
||||
'=='=44
|
||||
'!='=45
|
||||
'<='=46
|
||||
'>='=47
|
||||
'^'=48
|
||||
'|'=49
|
||||
'&&'=50
|
||||
'||'=51
|
||||
'+='=52
|
||||
'-='=53
|
||||
'*='=54
|
||||
'/='=55
|
||||
'%='=56
|
||||
'<<='=57
|
||||
'>>='=58
|
||||
'&='=59
|
||||
'|='=60
|
||||
'^='=61
|
||||
'kickasm'=62
|
||||
'resource'=63
|
||||
'uses'=64
|
||||
'clobbers'=65
|
||||
'bytes'=66
|
||||
'cycles'=67
|
||||
'pc'=68
|
||||
'.byte'=69
|
||||
'#'=70
|
||||
'.'=71
|
||||
'unsigned'=28
|
||||
'*'=29
|
||||
'['=30
|
||||
']'=31
|
||||
'--'=32
|
||||
'++'=33
|
||||
'+'=34
|
||||
'-'=35
|
||||
'!'=36
|
||||
'&'=37
|
||||
'~'=38
|
||||
'>>'=39
|
||||
'<<'=40
|
||||
'/'=41
|
||||
'%'=42
|
||||
'<'=43
|
||||
'>'=44
|
||||
'=='=45
|
||||
'!='=46
|
||||
'<='=47
|
||||
'>='=48
|
||||
'^'=49
|
||||
'|'=50
|
||||
'&&'=51
|
||||
'||'=52
|
||||
'?'=53
|
||||
'+='=54
|
||||
'-='=55
|
||||
'*='=56
|
||||
'/='=57
|
||||
'%='=58
|
||||
'<<='=59
|
||||
'>>='=60
|
||||
'&='=61
|
||||
'|='=62
|
||||
'^='=63
|
||||
'kickasm'=64
|
||||
'resource'=65
|
||||
'uses'=66
|
||||
'clobbers'=67
|
||||
'bytes'=68
|
||||
'cycles'=69
|
||||
'pc'=70
|
||||
'.byte'=71
|
||||
'#'=72
|
||||
'.'=73
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
@ -124,13 +124,25 @@ public class KickCBaseListener implements KickCListener {
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterParameterDecl(KickCParser.ParameterDeclContext ctx) { }
|
||||
@Override public void enterParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitParameterDecl(KickCParser.ParameterDeclContext ctx) { }
|
||||
@Override public void exitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -659,6 +671,18 @@ public class KickCBaseListener implements KickCListener {
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprId(KickCParser.ExprIdContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExprTernary(KickCParser.ExprTernaryContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExprTernary(KickCParser.ExprTernaryContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
|
||||
|
||||
@ -80,7 +80,14 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitParameterDecl(KickCParser.ParameterDeclContext ctx) { return visitChildren(ctx); }
|
||||
@Override public T visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
@ -389,6 +396,13 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprId(KickCParser.ExprIdContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExprTernary(KickCParser.ExprTernaryContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
@ -26,10 +26,11 @@ public class KickCLexer extends Lexer {
|
||||
T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52,
|
||||
T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59,
|
||||
T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66,
|
||||
T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, MNEMONIC=72, KICKASM=73,
|
||||
SIMPLETYPE=74, STRING=75, CHAR=76, BOOLEAN=77, NUMBER=78, NUMFLOAT=79,
|
||||
BINFLOAT=80, DECFLOAT=81, HEXFLOAT=82, NUMINT=83, BININTEGER=84, DECINTEGER=85,
|
||||
HEXINTEGER=86, NAME=87, ASMREL=88, WS=89, COMMENT_LINE=90, COMMENT_BLOCK=91;
|
||||
T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73,
|
||||
MNEMONIC=74, KICKASM=75, SIMPLETYPE=76, STRING=77, CHAR=78, BOOLEAN=79,
|
||||
NUMBER=80, NUMFLOAT=81, BINFLOAT=82, DECFLOAT=83, HEXFLOAT=84, NUMINT=85,
|
||||
BININTEGER=86, DECINTEGER=87, HEXINTEGER=88, NAME=89, ASMREL=90, WS=91,
|
||||
COMMENT_LINE=92, COMMENT_BLOCK=93;
|
||||
public static String[] channelNames = {
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
};
|
||||
@ -47,23 +48,23 @@ public class KickCLexer extends Lexer {
|
||||
"T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48",
|
||||
"T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56",
|
||||
"T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64",
|
||||
"T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "MNEMONIC", "KICKASM",
|
||||
"SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT",
|
||||
"DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER",
|
||||
"BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR",
|
||||
"ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK"
|
||||
"T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "T__72",
|
||||
"MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER",
|
||||
"NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER",
|
||||
"DECINTEGER", "HEXINTEGER", "BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME",
|
||||
"NAME_START", "NAME_CHAR", "ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK"
|
||||
};
|
||||
|
||||
private static final String[] _LITERAL_NAMES = {
|
||||
null, "'import'", "'='", "';'", "'('", "')'", "'{'", "'}'", "','", "'const'",
|
||||
"'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'",
|
||||
"'if'", "'else'", "'while'", "'do'", "'for'", "'return'", "'break'", "'continue'",
|
||||
"'asm'", "':'", "'..'", "'signed'", "'*'", "'['", "']'", "'--'", "'++'",
|
||||
"'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'",
|
||||
"'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'+='",
|
||||
"'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", "'^='",
|
||||
"'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'", "'cycles'",
|
||||
"'pc'", "'.byte'", "'#'", "'.'"
|
||||
"'asm'", "':'", "'..'", "'signed'", "'unsigned'", "'*'", "'['", "']'",
|
||||
"'--'", "'++'", "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'",
|
||||
"'%'", "'<'", "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'",
|
||||
"'||'", "'?'", "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='",
|
||||
"'&='", "'|='", "'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'",
|
||||
"'bytes'", "'cycles'", "'pc'", "'.byte'", "'#'", "'.'"
|
||||
};
|
||||
private static final String[] _SYMBOLIC_NAMES = {
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
@ -72,8 +73,8 @@ public class KickCLexer extends Lexer {
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
"MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER",
|
||||
"NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER",
|
||||
null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN",
|
||||
"NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER",
|
||||
"DECINTEGER", "HEXINTEGER", "NAME", "ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK"
|
||||
};
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
@ -134,7 +135,7 @@ public class KickCLexer extends Lexer {
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2]\u039a\b\1\4\2\t"+
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2_\u03b9\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\4\30\t\30\4\31\t\31"+
|
||||
@ -145,326 +146,338 @@ public class KickCLexer extends Lexer {
|
||||
"\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+
|
||||
"\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+
|
||||
"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
|
||||
"`\t`\4a\ta\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6"+
|
||||
"\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3"+
|
||||
"\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r"+
|
||||
"\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17"+
|
||||
"\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\21"+
|
||||
"\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24"+
|
||||
"\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27"+
|
||||
"\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
|
||||
"\3\31\3\31\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34"+
|
||||
"\3\34\3\34\3\35\3\35\3\36\3\36\3\37\3\37\3 \3 \3 \3!\3!\3!\3\"\3\"\3#"+
|
||||
"\3#\3$\3$\3%\3%\3&\3&\3\'\3\'\3\'\3(\3(\3(\3)\3)\3*\3*\3+\3+\3,\3,\3-"+
|
||||
"\3-\3-\3.\3.\3.\3/\3/\3/\3\60\3\60\3\60\3\61\3\61\3\62\3\62\3\63\3\63"+
|
||||
"\3\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\67\3\67\3\67\38\3"+
|
||||
"8\38\39\39\39\3:\3:\3:\3:\3;\3;\3;\3;\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3"+
|
||||
"?\3?\3?\3?\3?\3?\3?\3@\3@\3@\3@\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3B\3B\3"+
|
||||
"B\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3"+
|
||||
"F\3F\3F\3F\3F\3F\3G\3G\3H\3H\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
|
||||
"I\3I\5I\u02bb\nI\3J\3J\3J\3J\7J\u02c1\nJ\fJ\16J\u02c4\13J\3J\3J\3J\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\5K\u02de"+
|
||||
"\nK\3L\3L\3L\3L\7L\u02e4\nL\fL\16L\u02e7\13L\3L\3L\3M\3M\3M\3M\5M\u02ef"+
|
||||
"\nM\3M\3M\3N\3N\3N\3N\3N\3N\3N\3N\3N\5N\u02fc\nN\3O\3O\5O\u0300\nO\3P"+
|
||||
"\3P\3P\5P\u0305\nP\3Q\3Q\3Q\3Q\3Q\5Q\u030c\nQ\3Q\7Q\u030f\nQ\fQ\16Q\u0312"+
|
||||
"\13Q\3Q\3Q\6Q\u0316\nQ\rQ\16Q\u0317\3R\7R\u031b\nR\fR\16R\u031e\13R\3"+
|
||||
"R\3R\6R\u0322\nR\rR\16R\u0323\3S\3S\3S\3S\3S\5S\u032b\nS\3S\7S\u032e\n"+
|
||||
"S\fS\16S\u0331\13S\3S\3S\6S\u0335\nS\rS\16S\u0336\3T\3T\3T\5T\u033c\n"+
|
||||
"T\3U\3U\3U\6U\u0341\nU\rU\16U\u0342\3U\3U\6U\u0347\nU\rU\16U\u0348\5U"+
|
||||
"\u034b\nU\3V\6V\u034e\nV\rV\16V\u034f\3W\3W\3W\3W\3W\5W\u0357\nW\3W\6"+
|
||||
"W\u035a\nW\rW\16W\u035b\3X\3X\3Y\3Y\3Z\3Z\3[\3[\7[\u0366\n[\f[\16[\u0369"+
|
||||
"\13[\3\\\3\\\3]\3]\3^\3^\7^\u0371\n^\f^\16^\u0374\13^\3^\6^\u0377\n^\r"+
|
||||
"^\16^\u0378\3_\6_\u037c\n_\r_\16_\u037d\3_\3_\3`\3`\3`\3`\7`\u0386\n`"+
|
||||
"\f`\16`\u0389\13`\3`\3`\3a\3a\3a\3a\7a\u0391\na\fa\16a\u0394\13a\3a\3"+
|
||||
"a\3a\3a\3a\4\u02c2\u0392\2b\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-\30/\31\61\32"+
|
||||
"\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a"+
|
||||
"\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087"+
|
||||
"E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009b"+
|
||||
"O\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00af"+
|
||||
"\2\u00b1\2\u00b3\2\u00b5Y\u00b7\2\u00b9\2\u00bbZ\u00bd[\u00bf\\\u00c1"+
|
||||
"]\3\2\r\3\2$$\3\2))\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|\6"+
|
||||
"\2\62;C\\aac|\4\2--//\6\2\13\f\17\17\"\"\u00a2\u00a2\4\2\f\f\17\17\2\u0402"+
|
||||
"\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-\3\2\2\2\2/\3\2\2"+
|
||||
"\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3"+
|
||||
"\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2"+
|
||||
"\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2"+
|
||||
"U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3"+
|
||||
"\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2"+
|
||||
"\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2"+
|
||||
"{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085"+
|
||||
"\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2"+
|
||||
"\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097"+
|
||||
"\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2"+
|
||||
"\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9"+
|
||||
"\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00b5\3\2\2\2\2\u00bb\3\2\2"+
|
||||
"\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\3\u00c3\3\2\2\2\5\u00ca"+
|
||||
"\3\2\2\2\7\u00cc\3\2\2\2\t\u00ce\3\2\2\2\13\u00d0\3\2\2\2\r\u00d2\3\2"+
|
||||
"\2\2\17\u00d4\3\2\2\2\21\u00d6\3\2\2\2\23\u00d8\3\2\2\2\25\u00de\3\2\2"+
|
||||
"\2\27\u00e5\3\2\2\2\31\u00eb\3\2\2\2\33\u00f4\3\2\2\2\35\u00fb\3\2\2\2"+
|
||||
"\37\u0104\3\2\2\2!\u010e\3\2\2\2#\u0111\3\2\2\2%\u0116\3\2\2\2\'\u011c"+
|
||||
"\3\2\2\2)\u011f\3\2\2\2+\u0123\3\2\2\2-\u012a\3\2\2\2/\u0130\3\2\2\2\61"+
|
||||
"\u0139\3\2\2\2\63\u013d\3\2\2\2\65\u013f\3\2\2\2\67\u0142\3\2\2\29\u0149"+
|
||||
"\3\2\2\2;\u014b\3\2\2\2=\u014d\3\2\2\2?\u014f\3\2\2\2A\u0152\3\2\2\2C"+
|
||||
"\u0155\3\2\2\2E\u0157\3\2\2\2G\u0159\3\2\2\2I\u015b\3\2\2\2K\u015d\3\2"+
|
||||
"\2\2M\u015f\3\2\2\2O\u0162\3\2\2\2Q\u0165\3\2\2\2S\u0167\3\2\2\2U\u0169"+
|
||||
"\3\2\2\2W\u016b\3\2\2\2Y\u016d\3\2\2\2[\u0170\3\2\2\2]\u0173\3\2\2\2_"+
|
||||
"\u0176\3\2\2\2a\u0179\3\2\2\2c\u017b\3\2\2\2e\u017d\3\2\2\2g\u0180\3\2"+
|
||||
"\2\2i\u0183\3\2\2\2k\u0186\3\2\2\2m\u0189\3\2\2\2o\u018c\3\2\2\2q\u018f"+
|
||||
"\3\2\2\2s\u0192\3\2\2\2u\u0196\3\2\2\2w\u019a\3\2\2\2y\u019d\3\2\2\2{"+
|
||||
"\u01a0\3\2\2\2}\u01a3\3\2\2\2\177\u01ab\3\2\2\2\u0081\u01b4\3\2\2\2\u0083"+
|
||||
"\u01b9\3\2\2\2\u0085\u01c2\3\2\2\2\u0087\u01c8\3\2\2\2\u0089\u01cf\3\2"+
|
||||
"\2\2\u008b\u01d2\3\2\2\2\u008d\u01d8\3\2\2\2\u008f\u01da\3\2\2\2\u0091"+
|
||||
"\u02ba\3\2\2\2\u0093\u02bc\3\2\2\2\u0095\u02dd\3\2\2\2\u0097\u02df\3\2"+
|
||||
"\2\2\u0099\u02ea\3\2\2\2\u009b\u02fb\3\2\2\2\u009d\u02ff\3\2\2\2\u009f"+
|
||||
"\u0304\3\2\2\2\u00a1\u030b\3\2\2\2\u00a3\u031c\3\2\2\2\u00a5\u032a\3\2"+
|
||||
"\2\2\u00a7\u033b\3\2\2\2\u00a9\u034a\3\2\2\2\u00ab\u034d\3\2\2\2\u00ad"+
|
||||
"\u0356\3\2\2\2\u00af\u035d\3\2\2\2\u00b1\u035f\3\2\2\2\u00b3\u0361\3\2"+
|
||||
"\2\2\u00b5\u0363\3\2\2\2\u00b7\u036a\3\2\2\2\u00b9\u036c\3\2\2\2\u00bb"+
|
||||
"\u036e\3\2\2\2\u00bd\u037b\3\2\2\2\u00bf\u0381\3\2\2\2\u00c1\u038c\3\2"+
|
||||
"\2\2\u00c3\u00c4\7k\2\2\u00c4\u00c5\7o\2\2\u00c5\u00c6\7r\2\2\u00c6\u00c7"+
|
||||
"\7q\2\2\u00c7\u00c8\7t\2\2\u00c8\u00c9\7v\2\2\u00c9\4\3\2\2\2\u00ca\u00cb"+
|
||||
"\7?\2\2\u00cb\6\3\2\2\2\u00cc\u00cd\7=\2\2\u00cd\b\3\2\2\2\u00ce\u00cf"+
|
||||
"\7*\2\2\u00cf\n\3\2\2\2\u00d0\u00d1\7+\2\2\u00d1\f\3\2\2\2\u00d2\u00d3"+
|
||||
"\7}\2\2\u00d3\16\3\2\2\2\u00d4\u00d5\7\177\2\2\u00d5\20\3\2\2\2\u00d6"+
|
||||
"\u00d7\7.\2\2\u00d7\22\3\2\2\2\u00d8\u00d9\7e\2\2\u00d9\u00da\7q\2\2\u00da"+
|
||||
"\u00db\7p\2\2\u00db\u00dc\7u\2\2\u00dc\u00dd\7v\2\2\u00dd\24\3\2\2\2\u00de"+
|
||||
"\u00df\7g\2\2\u00df\u00e0\7z\2\2\u00e0\u00e1\7v\2\2\u00e1\u00e2\7g\2\2"+
|
||||
"\u00e2\u00e3\7t\2\2\u00e3\u00e4\7p\2\2\u00e4\26\3\2\2\2\u00e5\u00e6\7"+
|
||||
"c\2\2\u00e6\u00e7\7n\2\2\u00e7\u00e8\7k\2\2\u00e8\u00e9\7i\2\2\u00e9\u00ea"+
|
||||
"\7p\2\2\u00ea\30\3\2\2\2\u00eb\u00ec\7t\2\2\u00ec\u00ed\7g\2\2\u00ed\u00ee"+
|
||||
"\7i\2\2\u00ee\u00ef\7k\2\2\u00ef\u00f0\7u\2\2\u00f0\u00f1\7v\2\2\u00f1"+
|
||||
"\u00f2\7g\2\2\u00f2\u00f3\7t\2\2\u00f3\32\3\2\2\2\u00f4\u00f5\7k\2\2\u00f5"+
|
||||
"\u00f6\7p\2\2\u00f6\u00f7\7n\2\2\u00f7\u00f8\7k\2\2\u00f8\u00f9\7p\2\2"+
|
||||
"\u00f9\u00fa\7g\2\2\u00fa\34\3\2\2\2\u00fb\u00fc\7x\2\2\u00fc\u00fd\7"+
|
||||
"q\2\2\u00fd\u00fe\7n\2\2\u00fe\u00ff\7c\2\2\u00ff\u0100\7v\2\2\u0100\u0101"+
|
||||
"\7k\2\2\u0101\u0102\7n\2\2\u0102\u0103\7g\2\2\u0103\36\3\2\2\2\u0104\u0105"+
|
||||
"\7k\2\2\u0105\u0106\7p\2\2\u0106\u0107\7v\2\2\u0107\u0108\7g\2\2\u0108"+
|
||||
"\u0109\7t\2\2\u0109\u010a\7t\2\2\u010a\u010b\7w\2\2\u010b\u010c\7r\2\2"+
|
||||
"\u010c\u010d\7v\2\2\u010d \3\2\2\2\u010e\u010f\7k\2\2\u010f\u0110\7h\2"+
|
||||
"\2\u0110\"\3\2\2\2\u0111\u0112\7g\2\2\u0112\u0113\7n\2\2\u0113\u0114\7"+
|
||||
"u\2\2\u0114\u0115\7g\2\2\u0115$\3\2\2\2\u0116\u0117\7y\2\2\u0117\u0118"+
|
||||
"\7j\2\2\u0118\u0119\7k\2\2\u0119\u011a\7n\2\2\u011a\u011b\7g\2\2\u011b"+
|
||||
"&\3\2\2\2\u011c\u011d\7f\2\2\u011d\u011e\7q\2\2\u011e(\3\2\2\2\u011f\u0120"+
|
||||
"\7h\2\2\u0120\u0121\7q\2\2\u0121\u0122\7t\2\2\u0122*\3\2\2\2\u0123\u0124"+
|
||||
"\7t\2\2\u0124\u0125\7g\2\2\u0125\u0126\7v\2\2\u0126\u0127\7w\2\2\u0127"+
|
||||
"\u0128\7t\2\2\u0128\u0129\7p\2\2\u0129,\3\2\2\2\u012a\u012b\7d\2\2\u012b"+
|
||||
"\u012c\7t\2\2\u012c\u012d\7g\2\2\u012d\u012e\7c\2\2\u012e\u012f\7m\2\2"+
|
||||
"\u012f.\3\2\2\2\u0130\u0131\7e\2\2\u0131\u0132\7q\2\2\u0132\u0133\7p\2"+
|
||||
"\2\u0133\u0134\7v\2\2\u0134\u0135\7k\2\2\u0135\u0136\7p\2\2\u0136\u0137"+
|
||||
"\7w\2\2\u0137\u0138\7g\2\2\u0138\60\3\2\2\2\u0139\u013a\7c\2\2\u013a\u013b"+
|
||||
"\7u\2\2\u013b\u013c\7o\2\2\u013c\62\3\2\2\2\u013d\u013e\7<\2\2\u013e\64"+
|
||||
"\3\2\2\2\u013f\u0140\7\60\2\2\u0140\u0141\7\60\2\2\u0141\66\3\2\2\2\u0142"+
|
||||
"\u0143\7u\2\2\u0143\u0144\7k\2\2\u0144\u0145\7i\2\2\u0145\u0146\7p\2\2"+
|
||||
"\u0146\u0147\7g\2\2\u0147\u0148\7f\2\2\u01488\3\2\2\2\u0149\u014a\7,\2"+
|
||||
"\2\u014a:\3\2\2\2\u014b\u014c\7]\2\2\u014c<\3\2\2\2\u014d\u014e\7_\2\2"+
|
||||
"\u014e>\3\2\2\2\u014f\u0150\7/\2\2\u0150\u0151\7/\2\2\u0151@\3\2\2\2\u0152"+
|
||||
"\u0153\7-\2\2\u0153\u0154\7-\2\2\u0154B\3\2\2\2\u0155\u0156\7-\2\2\u0156"+
|
||||
"D\3\2\2\2\u0157\u0158\7/\2\2\u0158F\3\2\2\2\u0159\u015a\7#\2\2\u015aH"+
|
||||
"\3\2\2\2\u015b\u015c\7(\2\2\u015cJ\3\2\2\2\u015d\u015e\7\u0080\2\2\u015e"+
|
||||
"L\3\2\2\2\u015f\u0160\7@\2\2\u0160\u0161\7@\2\2\u0161N\3\2\2\2\u0162\u0163"+
|
||||
"\7>\2\2\u0163\u0164\7>\2\2\u0164P\3\2\2\2\u0165\u0166\7\61\2\2\u0166R"+
|
||||
"\3\2\2\2\u0167\u0168\7\'\2\2\u0168T\3\2\2\2\u0169\u016a\7>\2\2\u016aV"+
|
||||
"\3\2\2\2\u016b\u016c\7@\2\2\u016cX\3\2\2\2\u016d\u016e\7?\2\2\u016e\u016f"+
|
||||
"\7?\2\2\u016fZ\3\2\2\2\u0170\u0171\7#\2\2\u0171\u0172\7?\2\2\u0172\\\3"+
|
||||
"\2\2\2\u0173\u0174\7>\2\2\u0174\u0175\7?\2\2\u0175^\3\2\2\2\u0176\u0177"+
|
||||
"\7@\2\2\u0177\u0178\7?\2\2\u0178`\3\2\2\2\u0179\u017a\7`\2\2\u017ab\3"+
|
||||
"\2\2\2\u017b\u017c\7~\2\2\u017cd\3\2\2\2\u017d\u017e\7(\2\2\u017e\u017f"+
|
||||
"\7(\2\2\u017ff\3\2\2\2\u0180\u0181\7~\2\2\u0181\u0182\7~\2\2\u0182h\3"+
|
||||
"\2\2\2\u0183\u0184\7-\2\2\u0184\u0185\7?\2\2\u0185j\3\2\2\2\u0186\u0187"+
|
||||
"\7/\2\2\u0187\u0188\7?\2\2\u0188l\3\2\2\2\u0189\u018a\7,\2\2\u018a\u018b"+
|
||||
"\7?\2\2\u018bn\3\2\2\2\u018c\u018d\7\61\2\2\u018d\u018e\7?\2\2\u018ep"+
|
||||
"\3\2\2\2\u018f\u0190\7\'\2\2\u0190\u0191\7?\2\2\u0191r\3\2\2\2\u0192\u0193"+
|
||||
"\7>\2\2\u0193\u0194\7>\2\2\u0194\u0195\7?\2\2\u0195t\3\2\2\2\u0196\u0197"+
|
||||
"\7@\2\2\u0197\u0198\7@\2\2\u0198\u0199\7?\2\2\u0199v\3\2\2\2\u019a\u019b"+
|
||||
"\7(\2\2\u019b\u019c\7?\2\2\u019cx\3\2\2\2\u019d\u019e\7~\2\2\u019e\u019f"+
|
||||
"\7?\2\2\u019fz\3\2\2\2\u01a0\u01a1\7`\2\2\u01a1\u01a2\7?\2\2\u01a2|\3"+
|
||||
"\2\2\2\u01a3\u01a4\7m\2\2\u01a4\u01a5\7k\2\2\u01a5\u01a6\7e\2\2\u01a6"+
|
||||
"\u01a7\7m\2\2\u01a7\u01a8\7c\2\2\u01a8\u01a9\7u\2\2\u01a9\u01aa\7o\2\2"+
|
||||
"\u01aa~\3\2\2\2\u01ab\u01ac\7t\2\2\u01ac\u01ad\7g\2\2\u01ad\u01ae\7u\2"+
|
||||
"\2\u01ae\u01af\7q\2\2\u01af\u01b0\7w\2\2\u01b0\u01b1\7t\2\2\u01b1\u01b2"+
|
||||
"\7e\2\2\u01b2\u01b3\7g\2\2\u01b3\u0080\3\2\2\2\u01b4\u01b5\7w\2\2\u01b5"+
|
||||
"\u01b6\7u\2\2\u01b6\u01b7\7g\2\2\u01b7\u01b8\7u\2\2\u01b8\u0082\3\2\2"+
|
||||
"\2\u01b9\u01ba\7e\2\2\u01ba\u01bb\7n\2\2\u01bb\u01bc\7q\2\2\u01bc\u01bd"+
|
||||
"\7d\2\2\u01bd\u01be\7d\2\2\u01be\u01bf\7g\2\2\u01bf\u01c0\7t\2\2\u01c0"+
|
||||
"\u01c1\7u\2\2\u01c1\u0084\3\2\2\2\u01c2\u01c3\7d\2\2\u01c3\u01c4\7{\2"+
|
||||
"\2\u01c4\u01c5\7v\2\2\u01c5\u01c6\7g\2\2\u01c6\u01c7\7u\2\2\u01c7\u0086"+
|
||||
"\3\2\2\2\u01c8\u01c9\7e\2\2\u01c9\u01ca\7{\2\2\u01ca\u01cb\7e\2\2\u01cb"+
|
||||
"\u01cc\7n\2\2\u01cc\u01cd\7g\2\2\u01cd\u01ce\7u\2\2\u01ce\u0088\3\2\2"+
|
||||
"\2\u01cf\u01d0\7r\2\2\u01d0\u01d1\7e\2\2\u01d1\u008a\3\2\2\2\u01d2\u01d3"+
|
||||
"\7\60\2\2\u01d3\u01d4\7d\2\2\u01d4\u01d5\7{\2\2\u01d5\u01d6\7v\2\2\u01d6"+
|
||||
"\u01d7\7g\2\2\u01d7\u008c\3\2\2\2\u01d8\u01d9\7%\2\2\u01d9\u008e\3\2\2"+
|
||||
"\2\u01da\u01db\7\60\2\2\u01db\u0090\3\2\2\2\u01dc\u01dd\7d\2\2\u01dd\u01de"+
|
||||
"\7t\2\2\u01de\u02bb\7m\2\2\u01df\u01e0\7q\2\2\u01e0\u01e1\7t\2\2\u01e1"+
|
||||
"\u02bb\7c\2\2\u01e2\u01e3\7m\2\2\u01e3\u01e4\7k\2\2\u01e4\u02bb\7n\2\2"+
|
||||
"\u01e5\u01e6\7u\2\2\u01e6\u01e7\7n\2\2\u01e7\u02bb\7q\2\2\u01e8\u01e9"+
|
||||
"\7p\2\2\u01e9\u01ea\7q\2\2\u01ea\u02bb\7r\2\2\u01eb\u01ec\7c\2\2\u01ec"+
|
||||
"\u01ed\7u\2\2\u01ed\u02bb\7n\2\2\u01ee\u01ef\7r\2\2\u01ef\u01f0\7j\2\2"+
|
||||
"\u01f0\u02bb\7r\2\2\u01f1\u01f2\7c\2\2\u01f2\u01f3\7p\2\2\u01f3\u02bb"+
|
||||
"\7e\2\2\u01f4\u01f5\7d\2\2\u01f5\u01f6\7r\2\2\u01f6\u02bb\7n\2\2\u01f7"+
|
||||
"\u01f8\7e\2\2\u01f8\u01f9\7n\2\2\u01f9\u02bb\7e\2\2\u01fa\u01fb\7l\2\2"+
|
||||
"\u01fb\u01fc\7u\2\2\u01fc\u02bb\7t\2\2\u01fd\u01fe\7c\2\2\u01fe\u01ff"+
|
||||
"\7p\2\2\u01ff\u02bb\7f\2\2\u0200\u0201\7t\2\2\u0201\u0202\7n\2\2\u0202"+
|
||||
"\u02bb\7c\2\2\u0203\u0204\7d\2\2\u0204\u0205\7k\2\2\u0205\u02bb\7v\2\2"+
|
||||
"\u0206\u0207\7t\2\2\u0207\u0208\7q\2\2\u0208\u02bb\7n\2\2\u0209\u020a"+
|
||||
"\7r\2\2\u020a\u020b\7n\2\2\u020b\u02bb\7c\2\2\u020c\u020d\7r\2\2\u020d"+
|
||||
"\u020e\7n\2\2\u020e\u02bb\7r\2\2\u020f\u0210\7d\2\2\u0210\u0211\7o\2\2"+
|
||||
"\u0211\u02bb\7k\2\2\u0212\u0213\7u\2\2\u0213\u0214\7g\2\2\u0214\u02bb"+
|
||||
"\7e\2\2\u0215\u0216\7t\2\2\u0216\u0217\7v\2\2\u0217\u02bb\7k\2\2\u0218"+
|
||||
"\u0219\7g\2\2\u0219\u021a\7q\2\2\u021a\u02bb\7t\2\2\u021b\u021c\7u\2\2"+
|
||||
"\u021c\u021d\7t\2\2\u021d\u02bb\7g\2\2\u021e\u021f\7n\2\2\u021f\u0220"+
|
||||
"\7u\2\2\u0220\u02bb\7t\2\2\u0221\u0222\7r\2\2\u0222\u0223\7j\2\2\u0223"+
|
||||
"\u02bb\7c\2\2\u0224\u0225\7c\2\2\u0225\u0226\7n\2\2\u0226\u02bb\7t\2\2"+
|
||||
"\u0227\u0228\7l\2\2\u0228\u0229\7o\2\2\u0229\u02bb\7r\2\2\u022a\u022b"+
|
||||
"\7d\2\2\u022b\u022c\7x\2\2\u022c\u02bb\7e\2\2\u022d\u022e\7e\2\2\u022e"+
|
||||
"\u022f\7n\2\2\u022f\u02bb\7k\2\2\u0230\u0231\7t\2\2\u0231\u0232\7v\2\2"+
|
||||
"\u0232\u02bb\7u\2\2\u0233\u0234\7c\2\2\u0234\u0235\7f\2\2\u0235\u02bb"+
|
||||
"\7e\2\2\u0236\u0237\7t\2\2\u0237\u0238\7t\2\2\u0238\u02bb\7c\2\2\u0239"+
|
||||
"\u023a\7d\2\2\u023a\u023b\7x\2\2\u023b\u02bb\7u\2\2\u023c\u023d\7u\2\2"+
|
||||
"\u023d\u023e\7g\2\2\u023e\u02bb\7k\2\2\u023f\u0240\7u\2\2\u0240\u0241"+
|
||||
"\7c\2\2\u0241\u02bb\7z\2\2\u0242\u0243\7u\2\2\u0243\u0244\7v\2\2\u0244"+
|
||||
"\u02bb\7{\2\2\u0245\u0246\7u\2\2\u0246\u0247\7v\2\2\u0247\u02bb\7c\2\2"+
|
||||
"\u0248\u0249\7u\2\2\u0249\u024a\7v\2\2\u024a\u02bb\7z\2\2\u024b\u024c"+
|
||||
"\7f\2\2\u024c\u024d\7g\2\2\u024d\u02bb\7{\2\2\u024e\u024f\7v\2\2\u024f"+
|
||||
"\u0250\7z\2\2\u0250\u02bb\7c\2\2\u0251\u0252\7z\2\2\u0252\u0253\7c\2\2"+
|
||||
"\u0253\u02bb\7c\2\2\u0254\u0255\7d\2\2\u0255\u0256\7e\2\2\u0256\u02bb"+
|
||||
"\7e\2\2\u0257\u0258\7c\2\2\u0258\u0259\7j\2\2\u0259\u02bb\7z\2\2\u025a"+
|
||||
"\u025b\7v\2\2\u025b\u025c\7{\2\2\u025c\u02bb\7c\2\2\u025d\u025e\7v\2\2"+
|
||||
"\u025e\u025f\7z\2\2\u025f\u02bb\7u\2\2\u0260\u0261\7v\2\2\u0261\u0262"+
|
||||
"\7c\2\2\u0262\u02bb\7u\2\2\u0263\u0264\7u\2\2\u0264\u0265\7j\2\2\u0265"+
|
||||
"\u02bb\7{\2\2\u0266\u0267\7u\2\2\u0267\u0268\7j\2\2\u0268\u02bb\7z\2\2"+
|
||||
"\u0269\u026a\7n\2\2\u026a\u026b\7f\2\2\u026b\u02bb\7{\2\2\u026c\u026d"+
|
||||
"\7n\2\2\u026d\u026e\7f\2\2\u026e\u02bb\7c\2\2\u026f\u0270\7n\2\2\u0270"+
|
||||
"\u0271\7f\2\2\u0271\u02bb\7z\2\2\u0272\u0273\7n\2\2\u0273\u0274\7c\2\2"+
|
||||
"\u0274\u02bb\7z\2\2\u0275\u0276\7v\2\2\u0276\u0277\7c\2\2\u0277\u02bb"+
|
||||
"\7{\2\2\u0278\u0279\7v\2\2\u0279\u027a\7c\2\2\u027a\u02bb\7z\2\2\u027b"+
|
||||
"\u027c\7d\2\2\u027c\u027d\7e\2\2\u027d\u02bb\7u\2\2\u027e\u027f\7e\2\2"+
|
||||
"\u027f\u0280\7n\2\2\u0280\u02bb\7x\2\2\u0281\u0282\7v\2\2\u0282\u0283"+
|
||||
"\7u\2\2\u0283\u02bb\7z\2\2\u0284\u0285\7n\2\2\u0285\u0286\7c\2\2\u0286"+
|
||||
"\u02bb\7u\2\2\u0287\u0288\7e\2\2\u0288\u0289\7r\2\2\u0289\u02bb\7{\2\2"+
|
||||
"\u028a\u028b\7e\2\2\u028b\u028c\7o\2\2\u028c\u02bb\7r\2\2\u028d\u028e"+
|
||||
"\7e\2\2\u028e\u028f\7r\2\2\u028f\u02bb\7z\2\2\u0290\u0291\7f\2\2\u0291"+
|
||||
"\u0292\7e\2\2\u0292\u02bb\7r\2\2\u0293\u0294\7f\2\2\u0294\u0295\7g\2\2"+
|
||||
"\u0295\u02bb\7e\2\2\u0296\u0297\7k\2\2\u0297\u0298\7p\2\2\u0298\u02bb"+
|
||||
"\7e\2\2\u0299\u029a\7c\2\2\u029a\u029b\7z\2\2\u029b\u02bb\7u\2\2\u029c"+
|
||||
"\u029d\7d\2\2\u029d\u029e\7p\2\2\u029e\u02bb\7g\2\2\u029f\u02a0\7e\2\2"+
|
||||
"\u02a0\u02a1\7n\2\2\u02a1\u02bb\7f\2\2\u02a2\u02a3\7u\2\2\u02a3\u02a4"+
|
||||
"\7d\2\2\u02a4\u02bb\7e\2\2\u02a5\u02a6\7k\2\2\u02a6\u02a7\7u\2\2\u02a7"+
|
||||
"\u02bb\7e\2\2\u02a8\u02a9\7k\2\2\u02a9\u02aa\7p\2\2\u02aa\u02bb\7z\2\2"+
|
||||
"\u02ab\u02ac\7d\2\2\u02ac\u02ad\7g\2\2\u02ad\u02bb\7s\2\2\u02ae\u02af"+
|
||||
"\7u\2\2\u02af\u02b0\7g\2\2\u02b0\u02bb\7f\2\2\u02b1\u02b2\7f\2\2\u02b2"+
|
||||
"\u02b3\7g\2\2\u02b3\u02bb\7z\2\2\u02b4\u02b5\7k\2\2\u02b5\u02b6\7p\2\2"+
|
||||
"\u02b6\u02bb\7{\2\2\u02b7\u02b8\7t\2\2\u02b8\u02b9\7q\2\2\u02b9\u02bb"+
|
||||
"\7t\2\2\u02ba\u01dc\3\2\2\2\u02ba\u01df\3\2\2\2\u02ba\u01e2\3\2\2\2\u02ba"+
|
||||
"\u01e5\3\2\2\2\u02ba\u01e8\3\2\2\2\u02ba\u01eb\3\2\2\2\u02ba\u01ee\3\2"+
|
||||
"\2\2\u02ba\u01f1\3\2\2\2\u02ba\u01f4\3\2\2\2\u02ba\u01f7\3\2\2\2\u02ba"+
|
||||
"\u01fa\3\2\2\2\u02ba\u01fd\3\2\2\2\u02ba\u0200\3\2\2\2\u02ba\u0203\3\2"+
|
||||
"\2\2\u02ba\u0206\3\2\2\2\u02ba\u0209\3\2\2\2\u02ba\u020c\3\2\2\2\u02ba"+
|
||||
"\u020f\3\2\2\2\u02ba\u0212\3\2\2\2\u02ba\u0215\3\2\2\2\u02ba\u0218\3\2"+
|
||||
"\2\2\u02ba\u021b\3\2\2\2\u02ba\u021e\3\2\2\2\u02ba\u0221\3\2\2\2\u02ba"+
|
||||
"\u0224\3\2\2\2\u02ba\u0227\3\2\2\2\u02ba\u022a\3\2\2\2\u02ba\u022d\3\2"+
|
||||
"\2\2\u02ba\u0230\3\2\2\2\u02ba\u0233\3\2\2\2\u02ba\u0236\3\2\2\2\u02ba"+
|
||||
"\u0239\3\2\2\2\u02ba\u023c\3\2\2\2\u02ba\u023f\3\2\2\2\u02ba\u0242\3\2"+
|
||||
"\2\2\u02ba\u0245\3\2\2\2\u02ba\u0248\3\2\2\2\u02ba\u024b\3\2\2\2\u02ba"+
|
||||
"\u024e\3\2\2\2\u02ba\u0251\3\2\2\2\u02ba\u0254\3\2\2\2\u02ba\u0257\3\2"+
|
||||
"\2\2\u02ba\u025a\3\2\2\2\u02ba\u025d\3\2\2\2\u02ba\u0260\3\2\2\2\u02ba"+
|
||||
"\u0263\3\2\2\2\u02ba\u0266\3\2\2\2\u02ba\u0269\3\2\2\2\u02ba\u026c\3\2"+
|
||||
"\2\2\u02ba\u026f\3\2\2\2\u02ba\u0272\3\2\2\2\u02ba\u0275\3\2\2\2\u02ba"+
|
||||
"\u0278\3\2\2\2\u02ba\u027b\3\2\2\2\u02ba\u027e\3\2\2\2\u02ba\u0281\3\2"+
|
||||
"\2\2\u02ba\u0284\3\2\2\2\u02ba\u0287\3\2\2\2\u02ba\u028a\3\2\2\2\u02ba"+
|
||||
"\u028d\3\2\2\2\u02ba\u0290\3\2\2\2\u02ba\u0293\3\2\2\2\u02ba\u0296\3\2"+
|
||||
"\2\2\u02ba\u0299\3\2\2\2\u02ba\u029c\3\2\2\2\u02ba\u029f\3\2\2\2\u02ba"+
|
||||
"\u02a2\3\2\2\2\u02ba\u02a5\3\2\2\2\u02ba\u02a8\3\2\2\2\u02ba\u02ab\3\2"+
|
||||
"\2\2\u02ba\u02ae\3\2\2\2\u02ba\u02b1\3\2\2\2\u02ba\u02b4\3\2\2\2\u02ba"+
|
||||
"\u02b7\3\2\2\2\u02bb\u0092\3\2\2\2\u02bc\u02bd\7}\2\2\u02bd\u02be\7}\2"+
|
||||
"\2\u02be\u02c2\3\2\2\2\u02bf\u02c1\13\2\2\2\u02c0\u02bf\3\2\2\2\u02c1"+
|
||||
"\u02c4\3\2\2\2\u02c2\u02c3\3\2\2\2\u02c2\u02c0\3\2\2\2\u02c3\u02c5\3\2"+
|
||||
"\2\2\u02c4\u02c2\3\2\2\2\u02c5\u02c6\7\177\2\2\u02c6\u02c7\7\177\2\2\u02c7"+
|
||||
"\u0094\3\2\2\2\u02c8\u02c9\7d\2\2\u02c9\u02ca\7{\2\2\u02ca\u02cb\7v\2"+
|
||||
"\2\u02cb\u02de\7g\2\2\u02cc\u02cd\7y\2\2\u02cd\u02ce\7q\2\2\u02ce\u02cf"+
|
||||
"\7t\2\2\u02cf\u02de\7f\2\2\u02d0\u02d1\7f\2\2\u02d1\u02d2\7y\2\2\u02d2"+
|
||||
"\u02d3\7q\2\2\u02d3\u02d4\7t\2\2\u02d4\u02de\7f\2\2\u02d5\u02d6\7d\2\2"+
|
||||
"\u02d6\u02d7\7q\2\2\u02d7\u02d8\7q\2\2\u02d8\u02de\7n\2\2\u02d9\u02da"+
|
||||
"\7x\2\2\u02da\u02db\7q\2\2\u02db\u02dc\7k\2\2\u02dc\u02de\7f\2\2\u02dd"+
|
||||
"\u02c8\3\2\2\2\u02dd\u02cc\3\2\2\2\u02dd\u02d0\3\2\2\2\u02dd\u02d5\3\2"+
|
||||
"\2\2\u02dd\u02d9\3\2\2\2\u02de\u0096\3\2\2\2\u02df\u02e5\7$\2\2\u02e0"+
|
||||
"\u02e1\7^\2\2\u02e1\u02e4\7$\2\2\u02e2\u02e4\n\2\2\2\u02e3\u02e0\3\2\2"+
|
||||
"\2\u02e3\u02e2\3\2\2\2\u02e4\u02e7\3\2\2\2\u02e5\u02e3\3\2\2\2\u02e5\u02e6"+
|
||||
"\3\2\2\2\u02e6\u02e8\3\2\2\2\u02e7\u02e5\3\2\2\2\u02e8\u02e9\7$\2\2\u02e9"+
|
||||
"\u0098\3\2\2\2\u02ea\u02ee\7)\2\2\u02eb\u02ec\7^\2\2\u02ec\u02ef\7)\2"+
|
||||
"\2\u02ed\u02ef\n\3\2\2\u02ee\u02eb\3\2\2\2\u02ee\u02ed\3\2\2\2\u02ef\u02f0"+
|
||||
"\3\2\2\2\u02f0\u02f1\7)\2\2\u02f1\u009a\3\2\2\2\u02f2\u02f3\7v\2\2\u02f3"+
|
||||
"\u02f4\7t\2\2\u02f4\u02f5\7w\2\2\u02f5\u02fc\7g\2\2\u02f6\u02f7\7h\2\2"+
|
||||
"\u02f7\u02f8\7c\2\2\u02f8\u02f9\7n\2\2\u02f9\u02fa\7u\2\2\u02fa\u02fc"+
|
||||
"\7g\2\2\u02fb\u02f2\3\2\2\2\u02fb\u02f6\3\2\2\2\u02fc\u009c\3\2\2\2\u02fd"+
|
||||
"\u0300\5\u009fP\2\u02fe\u0300\5\u00a7T\2\u02ff\u02fd\3\2\2\2\u02ff\u02fe"+
|
||||
"\3\2\2\2\u0300\u009e\3\2\2\2\u0301\u0305\5\u00a1Q\2\u0302\u0305\5\u00a3"+
|
||||
"R\2\u0303\u0305\5\u00a5S\2\u0304\u0301\3\2\2\2\u0304\u0302\3\2\2\2\u0304"+
|
||||
"\u0303\3\2\2\2\u0305\u00a0\3\2\2\2\u0306\u030c\7\'\2\2\u0307\u0308\7\62"+
|
||||
"\2\2\u0308\u030c\7d\2\2\u0309\u030a\7\62\2\2\u030a\u030c\7D\2\2\u030b"+
|
||||
"\u0306\3\2\2\2\u030b\u0307\3\2\2\2\u030b\u0309\3\2\2\2\u030c\u0310\3\2"+
|
||||
"\2\2\u030d\u030f\5\u00afX\2\u030e\u030d\3\2\2\2\u030f\u0312\3\2\2\2\u0310"+
|
||||
"\u030e\3\2\2\2\u0310\u0311\3\2\2\2\u0311\u0313\3\2\2\2\u0312\u0310\3\2"+
|
||||
"\2\2\u0313\u0315\7\60\2\2\u0314\u0316\5\u00afX\2\u0315\u0314\3\2\2\2\u0316"+
|
||||
"\u0317\3\2\2\2\u0317\u0315\3\2\2\2\u0317\u0318\3\2\2\2\u0318\u00a2\3\2"+
|
||||
"\2\2\u0319\u031b\5\u00b1Y\2\u031a\u0319\3\2\2\2\u031b\u031e\3\2\2\2\u031c"+
|
||||
"\u031a\3\2\2\2\u031c\u031d\3\2\2\2\u031d\u031f\3\2\2\2\u031e\u031c\3\2"+
|
||||
"\2\2\u031f\u0321\7\60\2\2\u0320\u0322\5\u00b1Y\2\u0321\u0320\3\2\2\2\u0322"+
|
||||
"\u0323\3\2\2\2\u0323\u0321\3\2\2\2\u0323\u0324\3\2\2\2\u0324\u00a4\3\2"+
|
||||
"\2\2\u0325\u032b\7&\2\2\u0326\u0327\7\62\2\2\u0327\u032b\7z\2\2\u0328"+
|
||||
"\u0329\7\62\2\2\u0329\u032b\7Z\2\2\u032a\u0325\3\2\2\2\u032a\u0326\3\2"+
|
||||
"\2\2\u032a\u0328\3\2\2\2\u032b\u032f\3\2\2\2\u032c\u032e\5\u00b3Z\2\u032d"+
|
||||
"\u032c\3\2\2\2\u032e\u0331\3\2\2\2\u032f\u032d\3\2\2\2\u032f\u0330\3\2"+
|
||||
"\2\2\u0330\u0332\3\2\2\2\u0331\u032f\3\2\2\2\u0332\u0334\7\60\2\2\u0333"+
|
||||
"\u0335\5\u00b3Z\2\u0334\u0333\3\2\2\2\u0335\u0336\3\2\2\2\u0336\u0334"+
|
||||
"\3\2\2\2\u0336\u0337\3\2\2\2\u0337\u00a6\3\2\2\2\u0338\u033c\5\u00abV"+
|
||||
"\2\u0339\u033c\5\u00adW\2\u033a\u033c\5\u00a9U\2\u033b\u0338\3\2\2\2\u033b"+
|
||||
"\u0339\3\2\2\2\u033b\u033a\3\2\2\2\u033c\u00a8\3\2\2\2\u033d\u033e\7\62"+
|
||||
"\2\2\u033e\u0340\t\4\2\2\u033f\u0341\5\u00afX\2\u0340\u033f\3\2\2\2\u0341"+
|
||||
"\u0342\3\2\2\2\u0342\u0340\3\2\2\2\u0342\u0343\3\2\2\2\u0343\u034b\3\2"+
|
||||
"\2\2\u0344\u0346\7\'\2\2\u0345\u0347\5\u00afX\2\u0346\u0345\3\2\2\2\u0347"+
|
||||
"\u0348\3\2\2\2\u0348\u0346\3\2\2\2\u0348\u0349\3\2\2\2\u0349\u034b\3\2"+
|
||||
"\2\2\u034a\u033d\3\2\2\2\u034a\u0344\3\2\2\2\u034b\u00aa\3\2\2\2\u034c"+
|
||||
"\u034e\5\u00b1Y\2\u034d\u034c\3\2\2\2\u034e\u034f\3\2\2\2\u034f\u034d"+
|
||||
"\3\2\2\2\u034f\u0350\3\2\2\2\u0350\u00ac\3\2\2\2\u0351\u0357\7&\2\2\u0352"+
|
||||
"\u0353\7\62\2\2\u0353\u0357\7z\2\2\u0354\u0355\7\62\2\2\u0355\u0357\7"+
|
||||
"Z\2\2\u0356\u0351\3\2\2\2\u0356\u0352\3\2\2\2\u0356\u0354\3\2\2\2\u0357"+
|
||||
"\u0359\3\2\2\2\u0358\u035a\5\u00b3Z\2\u0359\u0358\3\2\2\2\u035a\u035b"+
|
||||
"\3\2\2\2\u035b\u0359\3\2\2\2\u035b\u035c\3\2\2\2\u035c\u00ae\3\2\2\2\u035d"+
|
||||
"\u035e\t\5\2\2\u035e\u00b0\3\2\2\2\u035f\u0360\t\6\2\2\u0360\u00b2\3\2"+
|
||||
"\2\2\u0361\u0362\t\7\2\2\u0362\u00b4\3\2\2\2\u0363\u0367\5\u00b7\\\2\u0364"+
|
||||
"\u0366\5\u00b9]\2\u0365\u0364\3\2\2\2\u0366\u0369\3\2\2\2\u0367\u0365"+
|
||||
"\3\2\2\2\u0367\u0368\3\2\2\2\u0368\u00b6\3\2\2\2\u0369\u0367\3\2\2\2\u036a"+
|
||||
"\u036b\t\b\2\2\u036b\u00b8\3\2\2\2\u036c\u036d\t\t\2\2\u036d\u00ba\3\2"+
|
||||
"\2\2\u036e\u0372\7#\2\2\u036f\u0371\5\u00b9]\2\u0370\u036f\3\2\2\2\u0371"+
|
||||
"\u0374\3\2\2\2\u0372\u0370\3\2\2\2\u0372\u0373\3\2\2\2\u0373\u0376\3\2"+
|
||||
"\2\2\u0374\u0372\3\2\2\2\u0375\u0377\t\n\2\2\u0376\u0375\3\2\2\2\u0377"+
|
||||
"\u0378\3\2\2\2\u0378\u0376\3\2\2\2\u0378\u0379\3\2\2\2\u0379\u00bc\3\2"+
|
||||
"\2\2\u037a\u037c\t\13\2\2\u037b\u037a\3\2\2\2\u037c\u037d\3\2\2\2\u037d"+
|
||||
"\u037b\3\2\2\2\u037d\u037e\3\2\2\2\u037e\u037f\3\2\2\2\u037f\u0380\b_"+
|
||||
"\2\2\u0380\u00be\3\2\2\2\u0381\u0382\7\61\2\2\u0382\u0383\7\61\2\2\u0383"+
|
||||
"\u0387\3\2\2\2\u0384\u0386\n\f\2\2\u0385\u0384\3\2\2\2\u0386\u0389\3\2"+
|
||||
"\2\2\u0387\u0385\3\2\2\2\u0387\u0388\3\2\2\2\u0388\u038a\3\2\2\2\u0389"+
|
||||
"\u0387\3\2\2\2\u038a\u038b\b`\3\2\u038b\u00c0\3\2\2\2\u038c\u038d\7\61"+
|
||||
"\2\2\u038d\u038e\7,\2\2\u038e\u0392\3\2\2\2\u038f\u0391\13\2\2\2\u0390"+
|
||||
"\u038f\3\2\2\2\u0391\u0394\3\2\2\2\u0392\u0393\3\2\2\2\u0392\u0390\3\2"+
|
||||
"\2\2\u0393\u0395\3\2\2\2\u0394\u0392\3\2\2\2\u0395\u0396\7,\2\2\u0396"+
|
||||
"\u0397\7\61\2\2\u0397\u0398\3\2\2\2\u0398\u0399\ba\3\2\u0399\u00c2\3\2"+
|
||||
"\2\2!\2\u02ba\u02c2\u02dd\u02e3\u02e5\u02ee\u02fb\u02ff\u0304\u030b\u0310"+
|
||||
"\u0317\u031c\u0323\u032a\u032f\u0336\u033b\u0342\u0348\u034a\u034f\u0356"+
|
||||
"\u035b\u0367\u0372\u0378\u037d\u0387\u0392\4\2\3\2\2\4\2";
|
||||
"`\t`\4a\ta\4b\tb\4c\tc\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5"+
|
||||
"\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13"+
|
||||
"\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r"+
|
||||
"\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17"+
|
||||
"\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
|
||||
"\3\20\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23"+
|
||||
"\3\23\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26"+
|
||||
"\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
|
||||
"\3\30\3\30\3\31\3\31\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34"+
|
||||
"\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\36"+
|
||||
"\3\36\3\37\3\37\3 \3 \3!\3!\3!\3\"\3\"\3\"\3#\3#\3$\3$\3%\3%\3&\3&\3\'"+
|
||||
"\3\'\3(\3(\3(\3)\3)\3)\3*\3*\3+\3+\3,\3,\3-\3-\3.\3.\3.\3/\3/\3/\3\60"+
|
||||
"\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\63\3\63\3\64\3\64\3\64\3\65\3\65"+
|
||||
"\3\65\3\66\3\66\3\67\3\67\3\67\38\38\38\39\39\39\3:\3:\3:\3;\3;\3;\3<"+
|
||||
"\3<\3<\3<\3=\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A"+
|
||||
"\3A\3B\3B\3B\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D"+
|
||||
"\3D\3E\3E\3E\3E\3E\3E\3F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3H\3H\3H\3H\3H\3H"+
|
||||
"\3I\3I\3J\3J\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K"+
|
||||
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\5K\u02ca\nK"+
|
||||
"\3L\3L\3L\3L\7L\u02d0\nL\fL\16L\u02d3\13L\3L\3L\3L\3M\3M\3M\3M\3M\3M\3"+
|
||||
"M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3M\3"+
|
||||
"M\3M\3M\3M\3M\3M\3M\3M\5M\u02fd\nM\3N\3N\3N\3N\7N\u0303\nN\fN\16N\u0306"+
|
||||
"\13N\3N\3N\3O\3O\3O\3O\5O\u030e\nO\3O\3O\3P\3P\3P\3P\3P\3P\3P\3P\3P\5"+
|
||||
"P\u031b\nP\3Q\3Q\5Q\u031f\nQ\3R\3R\3R\5R\u0324\nR\3S\3S\3S\3S\3S\5S\u032b"+
|
||||
"\nS\3S\7S\u032e\nS\fS\16S\u0331\13S\3S\3S\6S\u0335\nS\rS\16S\u0336\3T"+
|
||||
"\7T\u033a\nT\fT\16T\u033d\13T\3T\3T\6T\u0341\nT\rT\16T\u0342\3U\3U\3U"+
|
||||
"\3U\3U\5U\u034a\nU\3U\7U\u034d\nU\fU\16U\u0350\13U\3U\3U\6U\u0354\nU\r"+
|
||||
"U\16U\u0355\3V\3V\3V\5V\u035b\nV\3W\3W\3W\6W\u0360\nW\rW\16W\u0361\3W"+
|
||||
"\3W\6W\u0366\nW\rW\16W\u0367\5W\u036a\nW\3X\6X\u036d\nX\rX\16X\u036e\3"+
|
||||
"Y\3Y\3Y\3Y\3Y\5Y\u0376\nY\3Y\6Y\u0379\nY\rY\16Y\u037a\3Z\3Z\3[\3[\3\\"+
|
||||
"\3\\\3]\3]\7]\u0385\n]\f]\16]\u0388\13]\3^\3^\3_\3_\3`\3`\7`\u0390\n`"+
|
||||
"\f`\16`\u0393\13`\3`\6`\u0396\n`\r`\16`\u0397\3a\6a\u039b\na\ra\16a\u039c"+
|
||||
"\3a\3a\3b\3b\3b\3b\7b\u03a5\nb\fb\16b\u03a8\13b\3b\3b\3c\3c\3c\3c\7c\u03b0"+
|
||||
"\nc\fc\16c\u03b3\13c\3c\3c\3c\3c\3c\4\u02d1\u03b1\2d\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-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'"+
|
||||
"M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177"+
|
||||
"A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093"+
|
||||
"K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7"+
|
||||
"U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3\2\u00b5\2\u00b7\2\u00b9[\u00bb"+
|
||||
"\2\u00bd\2\u00bf\\\u00c1]\u00c3^\u00c5_\3\2\r\3\2$$\3\2))\4\2DDdd\3\2"+
|
||||
"\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|\6\2\62;C\\aac|\4\2--//\6\2\13\f"+
|
||||
"\17\17\"\"\u00a2\u00a2\4\2\f\f\17\17\2\u0425\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-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2"+
|
||||
"\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2"+
|
||||
"\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2"+
|
||||
"M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3"+
|
||||
"\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2"+
|
||||
"\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2"+
|
||||
"s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177"+
|
||||
"\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2"+
|
||||
"\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091"+
|
||||
"\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2"+
|
||||
"\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3"+
|
||||
"\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2"+
|
||||
"\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b9\3\2\2\2\2\u00bf"+
|
||||
"\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\3\u00c7\3\2\2"+
|
||||
"\2\5\u00ce\3\2\2\2\7\u00d0\3\2\2\2\t\u00d2\3\2\2\2\13\u00d4\3\2\2\2\r"+
|
||||
"\u00d6\3\2\2\2\17\u00d8\3\2\2\2\21\u00da\3\2\2\2\23\u00dc\3\2\2\2\25\u00e2"+
|
||||
"\3\2\2\2\27\u00e9\3\2\2\2\31\u00ef\3\2\2\2\33\u00f8\3\2\2\2\35\u00ff\3"+
|
||||
"\2\2\2\37\u0108\3\2\2\2!\u0112\3\2\2\2#\u0115\3\2\2\2%\u011a\3\2\2\2\'"+
|
||||
"\u0120\3\2\2\2)\u0123\3\2\2\2+\u0127\3\2\2\2-\u012e\3\2\2\2/\u0134\3\2"+
|
||||
"\2\2\61\u013d\3\2\2\2\63\u0141\3\2\2\2\65\u0143\3\2\2\2\67\u0146\3\2\2"+
|
||||
"\29\u014d\3\2\2\2;\u0156\3\2\2\2=\u0158\3\2\2\2?\u015a\3\2\2\2A\u015c"+
|
||||
"\3\2\2\2C\u015f\3\2\2\2E\u0162\3\2\2\2G\u0164\3\2\2\2I\u0166\3\2\2\2K"+
|
||||
"\u0168\3\2\2\2M\u016a\3\2\2\2O\u016c\3\2\2\2Q\u016f\3\2\2\2S\u0172\3\2"+
|
||||
"\2\2U\u0174\3\2\2\2W\u0176\3\2\2\2Y\u0178\3\2\2\2[\u017a\3\2\2\2]\u017d"+
|
||||
"\3\2\2\2_\u0180\3\2\2\2a\u0183\3\2\2\2c\u0186\3\2\2\2e\u0188\3\2\2\2g"+
|
||||
"\u018a\3\2\2\2i\u018d\3\2\2\2k\u0190\3\2\2\2m\u0192\3\2\2\2o\u0195\3\2"+
|
||||
"\2\2q\u0198\3\2\2\2s\u019b\3\2\2\2u\u019e\3\2\2\2w\u01a1\3\2\2\2y\u01a5"+
|
||||
"\3\2\2\2{\u01a9\3\2\2\2}\u01ac\3\2\2\2\177\u01af\3\2\2\2\u0081\u01b2\3"+
|
||||
"\2\2\2\u0083\u01ba\3\2\2\2\u0085\u01c3\3\2\2\2\u0087\u01c8\3\2\2\2\u0089"+
|
||||
"\u01d1\3\2\2\2\u008b\u01d7\3\2\2\2\u008d\u01de\3\2\2\2\u008f\u01e1\3\2"+
|
||||
"\2\2\u0091\u01e7\3\2\2\2\u0093\u01e9\3\2\2\2\u0095\u02c9\3\2\2\2\u0097"+
|
||||
"\u02cb\3\2\2\2\u0099\u02fc\3\2\2\2\u009b\u02fe\3\2\2\2\u009d\u0309\3\2"+
|
||||
"\2\2\u009f\u031a\3\2\2\2\u00a1\u031e\3\2\2\2\u00a3\u0323\3\2\2\2\u00a5"+
|
||||
"\u032a\3\2\2\2\u00a7\u033b\3\2\2\2\u00a9\u0349\3\2\2\2\u00ab\u035a\3\2"+
|
||||
"\2\2\u00ad\u0369\3\2\2\2\u00af\u036c\3\2\2\2\u00b1\u0375\3\2\2\2\u00b3"+
|
||||
"\u037c\3\2\2\2\u00b5\u037e\3\2\2\2\u00b7\u0380\3\2\2\2\u00b9\u0382\3\2"+
|
||||
"\2\2\u00bb\u0389\3\2\2\2\u00bd\u038b\3\2\2\2\u00bf\u038d\3\2\2\2\u00c1"+
|
||||
"\u039a\3\2\2\2\u00c3\u03a0\3\2\2\2\u00c5\u03ab\3\2\2\2\u00c7\u00c8\7k"+
|
||||
"\2\2\u00c8\u00c9\7o\2\2\u00c9\u00ca\7r\2\2\u00ca\u00cb\7q\2\2\u00cb\u00cc"+
|
||||
"\7t\2\2\u00cc\u00cd\7v\2\2\u00cd\4\3\2\2\2\u00ce\u00cf\7?\2\2\u00cf\6"+
|
||||
"\3\2\2\2\u00d0\u00d1\7=\2\2\u00d1\b\3\2\2\2\u00d2\u00d3\7*\2\2\u00d3\n"+
|
||||
"\3\2\2\2\u00d4\u00d5\7+\2\2\u00d5\f\3\2\2\2\u00d6\u00d7\7}\2\2\u00d7\16"+
|
||||
"\3\2\2\2\u00d8\u00d9\7\177\2\2\u00d9\20\3\2\2\2\u00da\u00db\7.\2\2\u00db"+
|
||||
"\22\3\2\2\2\u00dc\u00dd\7e\2\2\u00dd\u00de\7q\2\2\u00de\u00df\7p\2\2\u00df"+
|
||||
"\u00e0\7u\2\2\u00e0\u00e1\7v\2\2\u00e1\24\3\2\2\2\u00e2\u00e3\7g\2\2\u00e3"+
|
||||
"\u00e4\7z\2\2\u00e4\u00e5\7v\2\2\u00e5\u00e6\7g\2\2\u00e6\u00e7\7t\2\2"+
|
||||
"\u00e7\u00e8\7p\2\2\u00e8\26\3\2\2\2\u00e9\u00ea\7c\2\2\u00ea\u00eb\7"+
|
||||
"n\2\2\u00eb\u00ec\7k\2\2\u00ec\u00ed\7i\2\2\u00ed\u00ee\7p\2\2\u00ee\30"+
|
||||
"\3\2\2\2\u00ef\u00f0\7t\2\2\u00f0\u00f1\7g\2\2\u00f1\u00f2\7i\2\2\u00f2"+
|
||||
"\u00f3\7k\2\2\u00f3\u00f4\7u\2\2\u00f4\u00f5\7v\2\2\u00f5\u00f6\7g\2\2"+
|
||||
"\u00f6\u00f7\7t\2\2\u00f7\32\3\2\2\2\u00f8\u00f9\7k\2\2\u00f9\u00fa\7"+
|
||||
"p\2\2\u00fa\u00fb\7n\2\2\u00fb\u00fc\7k\2\2\u00fc\u00fd\7p\2\2\u00fd\u00fe"+
|
||||
"\7g\2\2\u00fe\34\3\2\2\2\u00ff\u0100\7x\2\2\u0100\u0101\7q\2\2\u0101\u0102"+
|
||||
"\7n\2\2\u0102\u0103\7c\2\2\u0103\u0104\7v\2\2\u0104\u0105\7k\2\2\u0105"+
|
||||
"\u0106\7n\2\2\u0106\u0107\7g\2\2\u0107\36\3\2\2\2\u0108\u0109\7k\2\2\u0109"+
|
||||
"\u010a\7p\2\2\u010a\u010b\7v\2\2\u010b\u010c\7g\2\2\u010c\u010d\7t\2\2"+
|
||||
"\u010d\u010e\7t\2\2\u010e\u010f\7w\2\2\u010f\u0110\7r\2\2\u0110\u0111"+
|
||||
"\7v\2\2\u0111 \3\2\2\2\u0112\u0113\7k\2\2\u0113\u0114\7h\2\2\u0114\"\3"+
|
||||
"\2\2\2\u0115\u0116\7g\2\2\u0116\u0117\7n\2\2\u0117\u0118\7u\2\2\u0118"+
|
||||
"\u0119\7g\2\2\u0119$\3\2\2\2\u011a\u011b\7y\2\2\u011b\u011c\7j\2\2\u011c"+
|
||||
"\u011d\7k\2\2\u011d\u011e\7n\2\2\u011e\u011f\7g\2\2\u011f&\3\2\2\2\u0120"+
|
||||
"\u0121\7f\2\2\u0121\u0122\7q\2\2\u0122(\3\2\2\2\u0123\u0124\7h\2\2\u0124"+
|
||||
"\u0125\7q\2\2\u0125\u0126\7t\2\2\u0126*\3\2\2\2\u0127\u0128\7t\2\2\u0128"+
|
||||
"\u0129\7g\2\2\u0129\u012a\7v\2\2\u012a\u012b\7w\2\2\u012b\u012c\7t\2\2"+
|
||||
"\u012c\u012d\7p\2\2\u012d,\3\2\2\2\u012e\u012f\7d\2\2\u012f\u0130\7t\2"+
|
||||
"\2\u0130\u0131\7g\2\2\u0131\u0132\7c\2\2\u0132\u0133\7m\2\2\u0133.\3\2"+
|
||||
"\2\2\u0134\u0135\7e\2\2\u0135\u0136\7q\2\2\u0136\u0137\7p\2\2\u0137\u0138"+
|
||||
"\7v\2\2\u0138\u0139\7k\2\2\u0139\u013a\7p\2\2\u013a\u013b\7w\2\2\u013b"+
|
||||
"\u013c\7g\2\2\u013c\60\3\2\2\2\u013d\u013e\7c\2\2\u013e\u013f\7u\2\2\u013f"+
|
||||
"\u0140\7o\2\2\u0140\62\3\2\2\2\u0141\u0142\7<\2\2\u0142\64\3\2\2\2\u0143"+
|
||||
"\u0144\7\60\2\2\u0144\u0145\7\60\2\2\u0145\66\3\2\2\2\u0146\u0147\7u\2"+
|
||||
"\2\u0147\u0148\7k\2\2\u0148\u0149\7i\2\2\u0149\u014a\7p\2\2\u014a\u014b"+
|
||||
"\7g\2\2\u014b\u014c\7f\2\2\u014c8\3\2\2\2\u014d\u014e\7w\2\2\u014e\u014f"+
|
||||
"\7p\2\2\u014f\u0150\7u\2\2\u0150\u0151\7k\2\2\u0151\u0152\7i\2\2\u0152"+
|
||||
"\u0153\7p\2\2\u0153\u0154\7g\2\2\u0154\u0155\7f\2\2\u0155:\3\2\2\2\u0156"+
|
||||
"\u0157\7,\2\2\u0157<\3\2\2\2\u0158\u0159\7]\2\2\u0159>\3\2\2\2\u015a\u015b"+
|
||||
"\7_\2\2\u015b@\3\2\2\2\u015c\u015d\7/\2\2\u015d\u015e\7/\2\2\u015eB\3"+
|
||||
"\2\2\2\u015f\u0160\7-\2\2\u0160\u0161\7-\2\2\u0161D\3\2\2\2\u0162\u0163"+
|
||||
"\7-\2\2\u0163F\3\2\2\2\u0164\u0165\7/\2\2\u0165H\3\2\2\2\u0166\u0167\7"+
|
||||
"#\2\2\u0167J\3\2\2\2\u0168\u0169\7(\2\2\u0169L\3\2\2\2\u016a\u016b\7\u0080"+
|
||||
"\2\2\u016bN\3\2\2\2\u016c\u016d\7@\2\2\u016d\u016e\7@\2\2\u016eP\3\2\2"+
|
||||
"\2\u016f\u0170\7>\2\2\u0170\u0171\7>\2\2\u0171R\3\2\2\2\u0172\u0173\7"+
|
||||
"\61\2\2\u0173T\3\2\2\2\u0174\u0175\7\'\2\2\u0175V\3\2\2\2\u0176\u0177"+
|
||||
"\7>\2\2\u0177X\3\2\2\2\u0178\u0179\7@\2\2\u0179Z\3\2\2\2\u017a\u017b\7"+
|
||||
"?\2\2\u017b\u017c\7?\2\2\u017c\\\3\2\2\2\u017d\u017e\7#\2\2\u017e\u017f"+
|
||||
"\7?\2\2\u017f^\3\2\2\2\u0180\u0181\7>\2\2\u0181\u0182\7?\2\2\u0182`\3"+
|
||||
"\2\2\2\u0183\u0184\7@\2\2\u0184\u0185\7?\2\2\u0185b\3\2\2\2\u0186\u0187"+
|
||||
"\7`\2\2\u0187d\3\2\2\2\u0188\u0189\7~\2\2\u0189f\3\2\2\2\u018a\u018b\7"+
|
||||
"(\2\2\u018b\u018c\7(\2\2\u018ch\3\2\2\2\u018d\u018e\7~\2\2\u018e\u018f"+
|
||||
"\7~\2\2\u018fj\3\2\2\2\u0190\u0191\7A\2\2\u0191l\3\2\2\2\u0192\u0193\7"+
|
||||
"-\2\2\u0193\u0194\7?\2\2\u0194n\3\2\2\2\u0195\u0196\7/\2\2\u0196\u0197"+
|
||||
"\7?\2\2\u0197p\3\2\2\2\u0198\u0199\7,\2\2\u0199\u019a\7?\2\2\u019ar\3"+
|
||||
"\2\2\2\u019b\u019c\7\61\2\2\u019c\u019d\7?\2\2\u019dt\3\2\2\2\u019e\u019f"+
|
||||
"\7\'\2\2\u019f\u01a0\7?\2\2\u01a0v\3\2\2\2\u01a1\u01a2\7>\2\2\u01a2\u01a3"+
|
||||
"\7>\2\2\u01a3\u01a4\7?\2\2\u01a4x\3\2\2\2\u01a5\u01a6\7@\2\2\u01a6\u01a7"+
|
||||
"\7@\2\2\u01a7\u01a8\7?\2\2\u01a8z\3\2\2\2\u01a9\u01aa\7(\2\2\u01aa\u01ab"+
|
||||
"\7?\2\2\u01ab|\3\2\2\2\u01ac\u01ad\7~\2\2\u01ad\u01ae\7?\2\2\u01ae~\3"+
|
||||
"\2\2\2\u01af\u01b0\7`\2\2\u01b0\u01b1\7?\2\2\u01b1\u0080\3\2\2\2\u01b2"+
|
||||
"\u01b3\7m\2\2\u01b3\u01b4\7k\2\2\u01b4\u01b5\7e\2\2\u01b5\u01b6\7m\2\2"+
|
||||
"\u01b6\u01b7\7c\2\2\u01b7\u01b8\7u\2\2\u01b8\u01b9\7o\2\2\u01b9\u0082"+
|
||||
"\3\2\2\2\u01ba\u01bb\7t\2\2\u01bb\u01bc\7g\2\2\u01bc\u01bd\7u\2\2\u01bd"+
|
||||
"\u01be\7q\2\2\u01be\u01bf\7w\2\2\u01bf\u01c0\7t\2\2\u01c0\u01c1\7e\2\2"+
|
||||
"\u01c1\u01c2\7g\2\2\u01c2\u0084\3\2\2\2\u01c3\u01c4\7w\2\2\u01c4\u01c5"+
|
||||
"\7u\2\2\u01c5\u01c6\7g\2\2\u01c6\u01c7\7u\2\2\u01c7\u0086\3\2\2\2\u01c8"+
|
||||
"\u01c9\7e\2\2\u01c9\u01ca\7n\2\2\u01ca\u01cb\7q\2\2\u01cb\u01cc\7d\2\2"+
|
||||
"\u01cc\u01cd\7d\2\2\u01cd\u01ce\7g\2\2\u01ce\u01cf\7t\2\2\u01cf\u01d0"+
|
||||
"\7u\2\2\u01d0\u0088\3\2\2\2\u01d1\u01d2\7d\2\2\u01d2\u01d3\7{\2\2\u01d3"+
|
||||
"\u01d4\7v\2\2\u01d4\u01d5\7g\2\2\u01d5\u01d6\7u\2\2\u01d6\u008a\3\2\2"+
|
||||
"\2\u01d7\u01d8\7e\2\2\u01d8\u01d9\7{\2\2\u01d9\u01da\7e\2\2\u01da\u01db"+
|
||||
"\7n\2\2\u01db\u01dc\7g\2\2\u01dc\u01dd\7u\2\2\u01dd\u008c\3\2\2\2\u01de"+
|
||||
"\u01df\7r\2\2\u01df\u01e0\7e\2\2\u01e0\u008e\3\2\2\2\u01e1\u01e2\7\60"+
|
||||
"\2\2\u01e2\u01e3\7d\2\2\u01e3\u01e4\7{\2\2\u01e4\u01e5\7v\2\2\u01e5\u01e6"+
|
||||
"\7g\2\2\u01e6\u0090\3\2\2\2\u01e7\u01e8\7%\2\2\u01e8\u0092\3\2\2\2\u01e9"+
|
||||
"\u01ea\7\60\2\2\u01ea\u0094\3\2\2\2\u01eb\u01ec\7d\2\2\u01ec\u01ed\7t"+
|
||||
"\2\2\u01ed\u02ca\7m\2\2\u01ee\u01ef\7q\2\2\u01ef\u01f0\7t\2\2\u01f0\u02ca"+
|
||||
"\7c\2\2\u01f1\u01f2\7m\2\2\u01f2\u01f3\7k\2\2\u01f3\u02ca\7n\2\2\u01f4"+
|
||||
"\u01f5\7u\2\2\u01f5\u01f6\7n\2\2\u01f6\u02ca\7q\2\2\u01f7\u01f8\7p\2\2"+
|
||||
"\u01f8\u01f9\7q\2\2\u01f9\u02ca\7r\2\2\u01fa\u01fb\7c\2\2\u01fb\u01fc"+
|
||||
"\7u\2\2\u01fc\u02ca\7n\2\2\u01fd\u01fe\7r\2\2\u01fe\u01ff\7j\2\2\u01ff"+
|
||||
"\u02ca\7r\2\2\u0200\u0201\7c\2\2\u0201\u0202\7p\2\2\u0202\u02ca\7e\2\2"+
|
||||
"\u0203\u0204\7d\2\2\u0204\u0205\7r\2\2\u0205\u02ca\7n\2\2\u0206\u0207"+
|
||||
"\7e\2\2\u0207\u0208\7n\2\2\u0208\u02ca\7e\2\2\u0209\u020a\7l\2\2\u020a"+
|
||||
"\u020b\7u\2\2\u020b\u02ca\7t\2\2\u020c\u020d\7c\2\2\u020d\u020e\7p\2\2"+
|
||||
"\u020e\u02ca\7f\2\2\u020f\u0210\7t\2\2\u0210\u0211\7n\2\2\u0211\u02ca"+
|
||||
"\7c\2\2\u0212\u0213\7d\2\2\u0213\u0214\7k\2\2\u0214\u02ca\7v\2\2\u0215"+
|
||||
"\u0216\7t\2\2\u0216\u0217\7q\2\2\u0217\u02ca\7n\2\2\u0218\u0219\7r\2\2"+
|
||||
"\u0219\u021a\7n\2\2\u021a\u02ca\7c\2\2\u021b\u021c\7r\2\2\u021c\u021d"+
|
||||
"\7n\2\2\u021d\u02ca\7r\2\2\u021e\u021f\7d\2\2\u021f\u0220\7o\2\2\u0220"+
|
||||
"\u02ca\7k\2\2\u0221\u0222\7u\2\2\u0222\u0223\7g\2\2\u0223\u02ca\7e\2\2"+
|
||||
"\u0224\u0225\7t\2\2\u0225\u0226\7v\2\2\u0226\u02ca\7k\2\2\u0227\u0228"+
|
||||
"\7g\2\2\u0228\u0229\7q\2\2\u0229\u02ca\7t\2\2\u022a\u022b\7u\2\2\u022b"+
|
||||
"\u022c\7t\2\2\u022c\u02ca\7g\2\2\u022d\u022e\7n\2\2\u022e\u022f\7u\2\2"+
|
||||
"\u022f\u02ca\7t\2\2\u0230\u0231\7r\2\2\u0231\u0232\7j\2\2\u0232\u02ca"+
|
||||
"\7c\2\2\u0233\u0234\7c\2\2\u0234\u0235\7n\2\2\u0235\u02ca\7t\2\2\u0236"+
|
||||
"\u0237\7l\2\2\u0237\u0238\7o\2\2\u0238\u02ca\7r\2\2\u0239\u023a\7d\2\2"+
|
||||
"\u023a\u023b\7x\2\2\u023b\u02ca\7e\2\2\u023c\u023d\7e\2\2\u023d\u023e"+
|
||||
"\7n\2\2\u023e\u02ca\7k\2\2\u023f\u0240\7t\2\2\u0240\u0241\7v\2\2\u0241"+
|
||||
"\u02ca\7u\2\2\u0242\u0243\7c\2\2\u0243\u0244\7f\2\2\u0244\u02ca\7e\2\2"+
|
||||
"\u0245\u0246\7t\2\2\u0246\u0247\7t\2\2\u0247\u02ca\7c\2\2\u0248\u0249"+
|
||||
"\7d\2\2\u0249\u024a\7x\2\2\u024a\u02ca\7u\2\2\u024b\u024c\7u\2\2\u024c"+
|
||||
"\u024d\7g\2\2\u024d\u02ca\7k\2\2\u024e\u024f\7u\2\2\u024f\u0250\7c\2\2"+
|
||||
"\u0250\u02ca\7z\2\2\u0251\u0252\7u\2\2\u0252\u0253\7v\2\2\u0253\u02ca"+
|
||||
"\7{\2\2\u0254\u0255\7u\2\2\u0255\u0256\7v\2\2\u0256\u02ca\7c\2\2\u0257"+
|
||||
"\u0258\7u\2\2\u0258\u0259\7v\2\2\u0259\u02ca\7z\2\2\u025a\u025b\7f\2\2"+
|
||||
"\u025b\u025c\7g\2\2\u025c\u02ca\7{\2\2\u025d\u025e\7v\2\2\u025e\u025f"+
|
||||
"\7z\2\2\u025f\u02ca\7c\2\2\u0260\u0261\7z\2\2\u0261\u0262\7c\2\2\u0262"+
|
||||
"\u02ca\7c\2\2\u0263\u0264\7d\2\2\u0264\u0265\7e\2\2\u0265\u02ca\7e\2\2"+
|
||||
"\u0266\u0267\7c\2\2\u0267\u0268\7j\2\2\u0268\u02ca\7z\2\2\u0269\u026a"+
|
||||
"\7v\2\2\u026a\u026b\7{\2\2\u026b\u02ca\7c\2\2\u026c\u026d\7v\2\2\u026d"+
|
||||
"\u026e\7z\2\2\u026e\u02ca\7u\2\2\u026f\u0270\7v\2\2\u0270\u0271\7c\2\2"+
|
||||
"\u0271\u02ca\7u\2\2\u0272\u0273\7u\2\2\u0273\u0274\7j\2\2\u0274\u02ca"+
|
||||
"\7{\2\2\u0275\u0276\7u\2\2\u0276\u0277\7j\2\2\u0277\u02ca\7z\2\2\u0278"+
|
||||
"\u0279\7n\2\2\u0279\u027a\7f\2\2\u027a\u02ca\7{\2\2\u027b\u027c\7n\2\2"+
|
||||
"\u027c\u027d\7f\2\2\u027d\u02ca\7c\2\2\u027e\u027f\7n\2\2\u027f\u0280"+
|
||||
"\7f\2\2\u0280\u02ca\7z\2\2\u0281\u0282\7n\2\2\u0282\u0283\7c\2\2\u0283"+
|
||||
"\u02ca\7z\2\2\u0284\u0285\7v\2\2\u0285\u0286\7c\2\2\u0286\u02ca\7{\2\2"+
|
||||
"\u0287\u0288\7v\2\2\u0288\u0289\7c\2\2\u0289\u02ca\7z\2\2\u028a\u028b"+
|
||||
"\7d\2\2\u028b\u028c\7e\2\2\u028c\u02ca\7u\2\2\u028d\u028e\7e\2\2\u028e"+
|
||||
"\u028f\7n\2\2\u028f\u02ca\7x\2\2\u0290\u0291\7v\2\2\u0291\u0292\7u\2\2"+
|
||||
"\u0292\u02ca\7z\2\2\u0293\u0294\7n\2\2\u0294\u0295\7c\2\2\u0295\u02ca"+
|
||||
"\7u\2\2\u0296\u0297\7e\2\2\u0297\u0298\7r\2\2\u0298\u02ca\7{\2\2\u0299"+
|
||||
"\u029a\7e\2\2\u029a\u029b\7o\2\2\u029b\u02ca\7r\2\2\u029c\u029d\7e\2\2"+
|
||||
"\u029d\u029e\7r\2\2\u029e\u02ca\7z\2\2\u029f\u02a0\7f\2\2\u02a0\u02a1"+
|
||||
"\7e\2\2\u02a1\u02ca\7r\2\2\u02a2\u02a3\7f\2\2\u02a3\u02a4\7g\2\2\u02a4"+
|
||||
"\u02ca\7e\2\2\u02a5\u02a6\7k\2\2\u02a6\u02a7\7p\2\2\u02a7\u02ca\7e\2\2"+
|
||||
"\u02a8\u02a9\7c\2\2\u02a9\u02aa\7z\2\2\u02aa\u02ca\7u\2\2\u02ab\u02ac"+
|
||||
"\7d\2\2\u02ac\u02ad\7p\2\2\u02ad\u02ca\7g\2\2\u02ae\u02af\7e\2\2\u02af"+
|
||||
"\u02b0\7n\2\2\u02b0\u02ca\7f\2\2\u02b1\u02b2\7u\2\2\u02b2\u02b3\7d\2\2"+
|
||||
"\u02b3\u02ca\7e\2\2\u02b4\u02b5\7k\2\2\u02b5\u02b6\7u\2\2\u02b6\u02ca"+
|
||||
"\7e\2\2\u02b7\u02b8\7k\2\2\u02b8\u02b9\7p\2\2\u02b9\u02ca\7z\2\2\u02ba"+
|
||||
"\u02bb\7d\2\2\u02bb\u02bc\7g\2\2\u02bc\u02ca\7s\2\2\u02bd\u02be\7u\2\2"+
|
||||
"\u02be\u02bf\7g\2\2\u02bf\u02ca\7f\2\2\u02c0\u02c1\7f\2\2\u02c1\u02c2"+
|
||||
"\7g\2\2\u02c2\u02ca\7z\2\2\u02c3\u02c4\7k\2\2\u02c4\u02c5\7p\2\2\u02c5"+
|
||||
"\u02ca\7{\2\2\u02c6\u02c7\7t\2\2\u02c7\u02c8\7q\2\2\u02c8\u02ca\7t\2\2"+
|
||||
"\u02c9\u01eb\3\2\2\2\u02c9\u01ee\3\2\2\2\u02c9\u01f1\3\2\2\2\u02c9\u01f4"+
|
||||
"\3\2\2\2\u02c9\u01f7\3\2\2\2\u02c9\u01fa\3\2\2\2\u02c9\u01fd\3\2\2\2\u02c9"+
|
||||
"\u0200\3\2\2\2\u02c9\u0203\3\2\2\2\u02c9\u0206\3\2\2\2\u02c9\u0209\3\2"+
|
||||
"\2\2\u02c9\u020c\3\2\2\2\u02c9\u020f\3\2\2\2\u02c9\u0212\3\2\2\2\u02c9"+
|
||||
"\u0215\3\2\2\2\u02c9\u0218\3\2\2\2\u02c9\u021b\3\2\2\2\u02c9\u021e\3\2"+
|
||||
"\2\2\u02c9\u0221\3\2\2\2\u02c9\u0224\3\2\2\2\u02c9\u0227\3\2\2\2\u02c9"+
|
||||
"\u022a\3\2\2\2\u02c9\u022d\3\2\2\2\u02c9\u0230\3\2\2\2\u02c9\u0233\3\2"+
|
||||
"\2\2\u02c9\u0236\3\2\2\2\u02c9\u0239\3\2\2\2\u02c9\u023c\3\2\2\2\u02c9"+
|
||||
"\u023f\3\2\2\2\u02c9\u0242\3\2\2\2\u02c9\u0245\3\2\2\2\u02c9\u0248\3\2"+
|
||||
"\2\2\u02c9\u024b\3\2\2\2\u02c9\u024e\3\2\2\2\u02c9\u0251\3\2\2\2\u02c9"+
|
||||
"\u0254\3\2\2\2\u02c9\u0257\3\2\2\2\u02c9\u025a\3\2\2\2\u02c9\u025d\3\2"+
|
||||
"\2\2\u02c9\u0260\3\2\2\2\u02c9\u0263\3\2\2\2\u02c9\u0266\3\2\2\2\u02c9"+
|
||||
"\u0269\3\2\2\2\u02c9\u026c\3\2\2\2\u02c9\u026f\3\2\2\2\u02c9\u0272\3\2"+
|
||||
"\2\2\u02c9\u0275\3\2\2\2\u02c9\u0278\3\2\2\2\u02c9\u027b\3\2\2\2\u02c9"+
|
||||
"\u027e\3\2\2\2\u02c9\u0281\3\2\2\2\u02c9\u0284\3\2\2\2\u02c9\u0287\3\2"+
|
||||
"\2\2\u02c9\u028a\3\2\2\2\u02c9\u028d\3\2\2\2\u02c9\u0290\3\2\2\2\u02c9"+
|
||||
"\u0293\3\2\2\2\u02c9\u0296\3\2\2\2\u02c9\u0299\3\2\2\2\u02c9\u029c\3\2"+
|
||||
"\2\2\u02c9\u029f\3\2\2\2\u02c9\u02a2\3\2\2\2\u02c9\u02a5\3\2\2\2\u02c9"+
|
||||
"\u02a8\3\2\2\2\u02c9\u02ab\3\2\2\2\u02c9\u02ae\3\2\2\2\u02c9\u02b1\3\2"+
|
||||
"\2\2\u02c9\u02b4\3\2\2\2\u02c9\u02b7\3\2\2\2\u02c9\u02ba\3\2\2\2\u02c9"+
|
||||
"\u02bd\3\2\2\2\u02c9\u02c0\3\2\2\2\u02c9\u02c3\3\2\2\2\u02c9\u02c6\3\2"+
|
||||
"\2\2\u02ca\u0096\3\2\2\2\u02cb\u02cc\7}\2\2\u02cc\u02cd\7}\2\2\u02cd\u02d1"+
|
||||
"\3\2\2\2\u02ce\u02d0\13\2\2\2\u02cf\u02ce\3\2\2\2\u02d0\u02d3\3\2\2\2"+
|
||||
"\u02d1\u02d2\3\2\2\2\u02d1\u02cf\3\2\2\2\u02d2\u02d4\3\2\2\2\u02d3\u02d1"+
|
||||
"\3\2\2\2\u02d4\u02d5\7\177\2\2\u02d5\u02d6\7\177\2\2\u02d6\u0098\3\2\2"+
|
||||
"\2\u02d7\u02d8\7d\2\2\u02d8\u02d9\7{\2\2\u02d9\u02da\7v\2\2\u02da\u02fd"+
|
||||
"\7g\2\2\u02db\u02dc\7y\2\2\u02dc\u02dd\7q\2\2\u02dd\u02de\7t\2\2\u02de"+
|
||||
"\u02fd\7f\2\2\u02df\u02e0\7f\2\2\u02e0\u02e1\7y\2\2\u02e1\u02e2\7q\2\2"+
|
||||
"\u02e2\u02e3\7t\2\2\u02e3\u02fd\7f\2\2\u02e4\u02e5\7d\2\2\u02e5\u02e6"+
|
||||
"\7q\2\2\u02e6\u02e7\7q\2\2\u02e7\u02fd\7n\2\2\u02e8\u02e9\7e\2\2\u02e9"+
|
||||
"\u02ea\7j\2\2\u02ea\u02eb\7c\2\2\u02eb\u02fd\7t\2\2\u02ec\u02ed\7u\2\2"+
|
||||
"\u02ed\u02ee\7j\2\2\u02ee\u02ef\7q\2\2\u02ef\u02f0\7t\2\2\u02f0\u02fd"+
|
||||
"\7v\2\2\u02f1\u02f2\7k\2\2\u02f2\u02f3\7p\2\2\u02f3\u02fd\7v\2\2\u02f4"+
|
||||
"\u02f5\7n\2\2\u02f5\u02f6\7q\2\2\u02f6\u02f7\7p\2\2\u02f7\u02fd\7i\2\2"+
|
||||
"\u02f8\u02f9\7x\2\2\u02f9\u02fa\7q\2\2\u02fa\u02fb\7k\2\2\u02fb\u02fd"+
|
||||
"\7f\2\2\u02fc\u02d7\3\2\2\2\u02fc\u02db\3\2\2\2\u02fc\u02df\3\2\2\2\u02fc"+
|
||||
"\u02e4\3\2\2\2\u02fc\u02e8\3\2\2\2\u02fc\u02ec\3\2\2\2\u02fc\u02f1\3\2"+
|
||||
"\2\2\u02fc\u02f4\3\2\2\2\u02fc\u02f8\3\2\2\2\u02fd\u009a\3\2\2\2\u02fe"+
|
||||
"\u0304\7$\2\2\u02ff\u0300\7^\2\2\u0300\u0303\7$\2\2\u0301\u0303\n\2\2"+
|
||||
"\2\u0302\u02ff\3\2\2\2\u0302\u0301\3\2\2\2\u0303\u0306\3\2\2\2\u0304\u0302"+
|
||||
"\3\2\2\2\u0304\u0305\3\2\2\2\u0305\u0307\3\2\2\2\u0306\u0304\3\2\2\2\u0307"+
|
||||
"\u0308\7$\2\2\u0308\u009c\3\2\2\2\u0309\u030d\7)\2\2\u030a\u030b\7^\2"+
|
||||
"\2\u030b\u030e\7)\2\2\u030c\u030e\n\3\2\2\u030d\u030a\3\2\2\2\u030d\u030c"+
|
||||
"\3\2\2\2\u030e\u030f\3\2\2\2\u030f\u0310\7)\2\2\u0310\u009e\3\2\2\2\u0311"+
|
||||
"\u0312\7v\2\2\u0312\u0313\7t\2\2\u0313\u0314\7w\2\2\u0314\u031b\7g\2\2"+
|
||||
"\u0315\u0316\7h\2\2\u0316\u0317\7c\2\2\u0317\u0318\7n\2\2\u0318\u0319"+
|
||||
"\7u\2\2\u0319\u031b\7g\2\2\u031a\u0311\3\2\2\2\u031a\u0315\3\2\2\2\u031b"+
|
||||
"\u00a0\3\2\2\2\u031c\u031f\5\u00a3R\2\u031d\u031f\5\u00abV\2\u031e\u031c"+
|
||||
"\3\2\2\2\u031e\u031d\3\2\2\2\u031f\u00a2\3\2\2\2\u0320\u0324\5\u00a5S"+
|
||||
"\2\u0321\u0324\5\u00a7T\2\u0322\u0324\5\u00a9U\2\u0323\u0320\3\2\2\2\u0323"+
|
||||
"\u0321\3\2\2\2\u0323\u0322\3\2\2\2\u0324\u00a4\3\2\2\2\u0325\u032b\7\'"+
|
||||
"\2\2\u0326\u0327\7\62\2\2\u0327\u032b\7d\2\2\u0328\u0329\7\62\2\2\u0329"+
|
||||
"\u032b\7D\2\2\u032a\u0325\3\2\2\2\u032a\u0326\3\2\2\2\u032a\u0328\3\2"+
|
||||
"\2\2\u032b\u032f\3\2\2\2\u032c\u032e\5\u00b3Z\2\u032d\u032c\3\2\2\2\u032e"+
|
||||
"\u0331\3\2\2\2\u032f\u032d\3\2\2\2\u032f\u0330\3\2\2\2\u0330\u0332\3\2"+
|
||||
"\2\2\u0331\u032f\3\2\2\2\u0332\u0334\7\60\2\2\u0333\u0335\5\u00b3Z\2\u0334"+
|
||||
"\u0333\3\2\2\2\u0335\u0336\3\2\2\2\u0336\u0334\3\2\2\2\u0336\u0337\3\2"+
|
||||
"\2\2\u0337\u00a6\3\2\2\2\u0338\u033a\5\u00b5[\2\u0339\u0338\3\2\2\2\u033a"+
|
||||
"\u033d\3\2\2\2\u033b\u0339\3\2\2\2\u033b\u033c\3\2\2\2\u033c\u033e\3\2"+
|
||||
"\2\2\u033d\u033b\3\2\2\2\u033e\u0340\7\60\2\2\u033f\u0341\5\u00b5[\2\u0340"+
|
||||
"\u033f\3\2\2\2\u0341\u0342\3\2\2\2\u0342\u0340\3\2\2\2\u0342\u0343\3\2"+
|
||||
"\2\2\u0343\u00a8\3\2\2\2\u0344\u034a\7&\2\2\u0345\u0346\7\62\2\2\u0346"+
|
||||
"\u034a\7z\2\2\u0347\u0348\7\62\2\2\u0348\u034a\7Z\2\2\u0349\u0344\3\2"+
|
||||
"\2\2\u0349\u0345\3\2\2\2\u0349\u0347\3\2\2\2\u034a\u034e\3\2\2\2\u034b"+
|
||||
"\u034d\5\u00b7\\\2\u034c\u034b\3\2\2\2\u034d\u0350\3\2\2\2\u034e\u034c"+
|
||||
"\3\2\2\2\u034e\u034f\3\2\2\2\u034f\u0351\3\2\2\2\u0350\u034e\3\2\2\2\u0351"+
|
||||
"\u0353\7\60\2\2\u0352\u0354\5\u00b7\\\2\u0353\u0352\3\2\2\2\u0354\u0355"+
|
||||
"\3\2\2\2\u0355\u0353\3\2\2\2\u0355\u0356\3\2\2\2\u0356\u00aa\3\2\2\2\u0357"+
|
||||
"\u035b\5\u00afX\2\u0358\u035b\5\u00b1Y\2\u0359\u035b\5\u00adW\2\u035a"+
|
||||
"\u0357\3\2\2\2\u035a\u0358\3\2\2\2\u035a\u0359\3\2\2\2\u035b\u00ac\3\2"+
|
||||
"\2\2\u035c\u035d\7\62\2\2\u035d\u035f\t\4\2\2\u035e\u0360\5\u00b3Z\2\u035f"+
|
||||
"\u035e\3\2\2\2\u0360\u0361\3\2\2\2\u0361\u035f\3\2\2\2\u0361\u0362\3\2"+
|
||||
"\2\2\u0362\u036a\3\2\2\2\u0363\u0365\7\'\2\2\u0364\u0366\5\u00b3Z\2\u0365"+
|
||||
"\u0364\3\2\2\2\u0366\u0367\3\2\2\2\u0367\u0365\3\2\2\2\u0367\u0368\3\2"+
|
||||
"\2\2\u0368\u036a\3\2\2\2\u0369\u035c\3\2\2\2\u0369\u0363\3\2\2\2\u036a"+
|
||||
"\u00ae\3\2\2\2\u036b\u036d\5\u00b5[\2\u036c\u036b\3\2\2\2\u036d\u036e"+
|
||||
"\3\2\2\2\u036e\u036c\3\2\2\2\u036e\u036f\3\2\2\2\u036f\u00b0\3\2\2\2\u0370"+
|
||||
"\u0376\7&\2\2\u0371\u0372\7\62\2\2\u0372\u0376\7z\2\2\u0373\u0374\7\62"+
|
||||
"\2\2\u0374\u0376\7Z\2\2\u0375\u0370\3\2\2\2\u0375\u0371\3\2\2\2\u0375"+
|
||||
"\u0373\3\2\2\2\u0376\u0378\3\2\2\2\u0377\u0379\5\u00b7\\\2\u0378\u0377"+
|
||||
"\3\2\2\2\u0379\u037a\3\2\2\2\u037a\u0378\3\2\2\2\u037a\u037b\3\2\2\2\u037b"+
|
||||
"\u00b2\3\2\2\2\u037c\u037d\t\5\2\2\u037d\u00b4\3\2\2\2\u037e\u037f\t\6"+
|
||||
"\2\2\u037f\u00b6\3\2\2\2\u0380\u0381\t\7\2\2\u0381\u00b8\3\2\2\2\u0382"+
|
||||
"\u0386\5\u00bb^\2\u0383\u0385\5\u00bd_\2\u0384\u0383\3\2\2\2\u0385\u0388"+
|
||||
"\3\2\2\2\u0386\u0384\3\2\2\2\u0386\u0387\3\2\2\2\u0387\u00ba\3\2\2\2\u0388"+
|
||||
"\u0386\3\2\2\2\u0389\u038a\t\b\2\2\u038a\u00bc\3\2\2\2\u038b\u038c\t\t"+
|
||||
"\2\2\u038c\u00be\3\2\2\2\u038d\u0391\7#\2\2\u038e\u0390\5\u00bd_\2\u038f"+
|
||||
"\u038e\3\2\2\2\u0390\u0393\3\2\2\2\u0391\u038f\3\2\2\2\u0391\u0392\3\2"+
|
||||
"\2\2\u0392\u0395\3\2\2\2\u0393\u0391\3\2\2\2\u0394\u0396\t\n\2\2\u0395"+
|
||||
"\u0394\3\2\2\2\u0396\u0397\3\2\2\2\u0397\u0395\3\2\2\2\u0397\u0398\3\2"+
|
||||
"\2\2\u0398\u00c0\3\2\2\2\u0399\u039b\t\13\2\2\u039a\u0399\3\2\2\2\u039b"+
|
||||
"\u039c\3\2\2\2\u039c\u039a\3\2\2\2\u039c\u039d\3\2\2\2\u039d\u039e\3\2"+
|
||||
"\2\2\u039e\u039f\ba\2\2\u039f\u00c2\3\2\2\2\u03a0\u03a1\7\61\2\2\u03a1"+
|
||||
"\u03a2\7\61\2\2\u03a2\u03a6\3\2\2\2\u03a3\u03a5\n\f\2\2\u03a4\u03a3\3"+
|
||||
"\2\2\2\u03a5\u03a8\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a6\u03a7\3\2\2\2\u03a7"+
|
||||
"\u03a9\3\2\2\2\u03a8\u03a6\3\2\2\2\u03a9\u03aa\bb\3\2\u03aa\u00c4\3\2"+
|
||||
"\2\2\u03ab\u03ac\7\61\2\2\u03ac\u03ad\7,\2\2\u03ad\u03b1\3\2\2\2\u03ae"+
|
||||
"\u03b0\13\2\2\2\u03af\u03ae\3\2\2\2\u03b0\u03b3\3\2\2\2\u03b1\u03b2\3"+
|
||||
"\2\2\2\u03b1\u03af\3\2\2\2\u03b2\u03b4\3\2\2\2\u03b3\u03b1\3\2\2\2\u03b4"+
|
||||
"\u03b5\7,\2\2\u03b5\u03b6\7\61\2\2\u03b6\u03b7\3\2\2\2\u03b7\u03b8\bc"+
|
||||
"\3\2\u03b8\u00c6\3\2\2\2!\2\u02c9\u02d1\u02fc\u0302\u0304\u030d\u031a"+
|
||||
"\u031e\u0323\u032a\u032f\u0336\u033b\u0342\u0349\u034e\u0355\u035a\u0361"+
|
||||
"\u0367\u0369\u036e\u0375\u037a\u0386\u0391\u0397\u039c\u03a6\u03b1\4\2"+
|
||||
"\3\2\2\4\2";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
|
@ -69,26 +69,28 @@ T__67=68
|
||||
T__68=69
|
||||
T__69=70
|
||||
T__70=71
|
||||
MNEMONIC=72
|
||||
KICKASM=73
|
||||
SIMPLETYPE=74
|
||||
STRING=75
|
||||
CHAR=76
|
||||
BOOLEAN=77
|
||||
NUMBER=78
|
||||
NUMFLOAT=79
|
||||
BINFLOAT=80
|
||||
DECFLOAT=81
|
||||
HEXFLOAT=82
|
||||
NUMINT=83
|
||||
BININTEGER=84
|
||||
DECINTEGER=85
|
||||
HEXINTEGER=86
|
||||
NAME=87
|
||||
ASMREL=88
|
||||
WS=89
|
||||
COMMENT_LINE=90
|
||||
COMMENT_BLOCK=91
|
||||
T__71=72
|
||||
T__72=73
|
||||
MNEMONIC=74
|
||||
KICKASM=75
|
||||
SIMPLETYPE=76
|
||||
STRING=77
|
||||
CHAR=78
|
||||
BOOLEAN=79
|
||||
NUMBER=80
|
||||
NUMFLOAT=81
|
||||
BINFLOAT=82
|
||||
DECFLOAT=83
|
||||
HEXFLOAT=84
|
||||
NUMINT=85
|
||||
BININTEGER=86
|
||||
DECINTEGER=87
|
||||
HEXINTEGER=88
|
||||
NAME=89
|
||||
ASMREL=90
|
||||
WS=91
|
||||
COMMENT_LINE=92
|
||||
COMMENT_BLOCK=93
|
||||
'import'=1
|
||||
'='=2
|
||||
';'=3
|
||||
@ -116,47 +118,49 @@ COMMENT_BLOCK=91
|
||||
':'=25
|
||||
'..'=26
|
||||
'signed'=27
|
||||
'*'=28
|
||||
'['=29
|
||||
']'=30
|
||||
'--'=31
|
||||
'++'=32
|
||||
'+'=33
|
||||
'-'=34
|
||||
'!'=35
|
||||
'&'=36
|
||||
'~'=37
|
||||
'>>'=38
|
||||
'<<'=39
|
||||
'/'=40
|
||||
'%'=41
|
||||
'<'=42
|
||||
'>'=43
|
||||
'=='=44
|
||||
'!='=45
|
||||
'<='=46
|
||||
'>='=47
|
||||
'^'=48
|
||||
'|'=49
|
||||
'&&'=50
|
||||
'||'=51
|
||||
'+='=52
|
||||
'-='=53
|
||||
'*='=54
|
||||
'/='=55
|
||||
'%='=56
|
||||
'<<='=57
|
||||
'>>='=58
|
||||
'&='=59
|
||||
'|='=60
|
||||
'^='=61
|
||||
'kickasm'=62
|
||||
'resource'=63
|
||||
'uses'=64
|
||||
'clobbers'=65
|
||||
'bytes'=66
|
||||
'cycles'=67
|
||||
'pc'=68
|
||||
'.byte'=69
|
||||
'#'=70
|
||||
'.'=71
|
||||
'unsigned'=28
|
||||
'*'=29
|
||||
'['=30
|
||||
']'=31
|
||||
'--'=32
|
||||
'++'=33
|
||||
'+'=34
|
||||
'-'=35
|
||||
'!'=36
|
||||
'&'=37
|
||||
'~'=38
|
||||
'>>'=39
|
||||
'<<'=40
|
||||
'/'=41
|
||||
'%'=42
|
||||
'<'=43
|
||||
'>'=44
|
||||
'=='=45
|
||||
'!='=46
|
||||
'<='=47
|
||||
'>='=48
|
||||
'^'=49
|
||||
'|'=50
|
||||
'&&'=51
|
||||
'||'=52
|
||||
'?'=53
|
||||
'+='=54
|
||||
'-='=55
|
||||
'*='=56
|
||||
'/='=57
|
||||
'%='=58
|
||||
'<<='=59
|
||||
'>>='=60
|
||||
'&='=61
|
||||
'|='=62
|
||||
'^='=63
|
||||
'kickasm'=64
|
||||
'resource'=65
|
||||
'uses'=66
|
||||
'clobbers'=67
|
||||
'bytes'=68
|
||||
'cycles'=69
|
||||
'pc'=70
|
||||
'.byte'=71
|
||||
'#'=72
|
||||
'.'=73
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
|
||||
@ -98,15 +98,29 @@ public interface KickCListener extends ParseTreeListener {
|
||||
*/
|
||||
void exitParameterListDecl(KickCParser.ParameterListDeclContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link KickCParser#parameterDecl}.
|
||||
* Enter a parse tree produced by the {@code parameterDeclType}
|
||||
* labeled alternative in {@link KickCParser#parameterDecl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterParameterDecl(KickCParser.ParameterDeclContext ctx);
|
||||
void enterParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link KickCParser#parameterDecl}.
|
||||
* Exit a parse tree produced by the {@code parameterDeclType}
|
||||
* labeled alternative in {@link KickCParser#parameterDecl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitParameterDecl(KickCParser.ParameterDeclContext ctx);
|
||||
void exitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code parameterDeclVoid}
|
||||
* labeled alternative in {@link KickCParser#parameterDecl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code parameterDeclVoid}
|
||||
* labeled alternative in {@link KickCParser#parameterDecl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code directiveConst}
|
||||
* labeled alternative in {@link KickCParser#directive}.
|
||||
@ -633,6 +647,18 @@ public interface KickCListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprId(KickCParser.ExprIdContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprTernary}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExprTernary(KickCParser.ExprTernaryContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code exprTernary}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExprTernary(KickCParser.ExprTernaryContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code exprAssignment}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
// Generated from C:/c64/kickc/src/main/java/dk/camelot64/kickc/parser\KickC.g4 by ANTLR 4.7
|
||||
// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
|
||||
package dk.camelot64.kickc.parser;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
|
||||
|
||||
@ -65,11 +65,19 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
|
||||
*/
|
||||
T visitParameterListDecl(KickCParser.ParameterListDeclContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by {@link KickCParser#parameterDecl}.
|
||||
* Visit a parse tree produced by the {@code parameterDeclType}
|
||||
* labeled alternative in {@link KickCParser#parameterDecl}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitParameterDecl(KickCParser.ParameterDeclContext ctx);
|
||||
T visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code parameterDeclVoid}
|
||||
* labeled alternative in {@link KickCParser#parameterDecl}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code directiveConst}
|
||||
* labeled alternative in {@link KickCParser#directive}.
|
||||
@ -377,6 +385,13 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprId(KickCParser.ExprIdContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprTernary}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
T visitExprTernary(KickCParser.ExprTernaryContext ctx);
|
||||
/**
|
||||
* Visit a parse tree produced by the {@code exprAssignment}
|
||||
* labeled alternative in {@link KickCParser#expr}.
|
||||
|
@ -150,14 +150,25 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
public List<Variable> visitParameterListDecl(KickCParser.ParameterListDeclContext ctx) {
|
||||
ArrayList<Variable> parameterDecls = new ArrayList<>();
|
||||
for(KickCParser.ParameterDeclContext parameterDeclCtx : ctx.parameterDecl()) {
|
||||
Variable parameterDecl = (Variable) this.visit(parameterDeclCtx);
|
||||
parameterDecls.add(parameterDecl);
|
||||
Object parameterDecl = this.visit(parameterDeclCtx);
|
||||
if(parameterDecl.equals(SymbolType.VOID)) {
|
||||
if(ctx.parameterDecl().size() == 1) {
|
||||
// A single void parameter decl - equals zero parameters
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
throw new CompileError("Illegal void parameter." , new StatementSource(ctx));
|
||||
}
|
||||
} else if(parameterDecl instanceof Variable) {
|
||||
parameterDecls.add((Variable) parameterDecl);
|
||||
} else {
|
||||
throw new CompileError("Unknown parameter " + ctx.getText(), new StatementSource(ctx));
|
||||
}
|
||||
}
|
||||
return parameterDecls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variable visitParameterDecl(KickCParser.ParameterDeclContext ctx) {
|
||||
public Object visitParameterDeclType(KickCParser.ParameterDeclTypeContext ctx) {
|
||||
SymbolType type = (SymbolType) this.visit(ctx.typeDecl());
|
||||
VariableUnversioned param = new VariableUnversioned(ctx.NAME().getText(), getCurrentScope(), type);
|
||||
// Add directives
|
||||
@ -165,6 +176,14 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
return param;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitParameterDeclVoid(KickCParser.ParameterDeclVoidContext ctx) {
|
||||
if(!SymbolType.VOID.getTypeName().equals(ctx.SIMPLETYPE().getText())) {
|
||||
throw new CompileError("Illegal unnamed parameter " + ctx.SIMPLETYPE().getText(), new StatementSource(ctx));
|
||||
}
|
||||
return SymbolType.VOID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitDeclKasm(KickCParser.DeclKasmContext ctx) {
|
||||
String kasm = ctx.KICKASM().getText();
|
||||
@ -594,10 +613,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
public Void visitStmtIfElse(KickCParser.StmtIfElseContext ctx) {
|
||||
KickCParser.StmtContext ifStmt = ctx.stmt(0);
|
||||
KickCParser.StmtContext elseStmt = ctx.stmt(1);
|
||||
|
||||
PrePostModifierHandler.addPreModifiers(this, ctx.expr());
|
||||
RValue rValue = (RValue) this.visit(ctx.expr());
|
||||
|
||||
List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx));
|
||||
|
||||
if(elseStmt == null) {
|
||||
@ -649,7 +666,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
}
|
||||
|
||||
public Label getOrCreateBreakLabel() {
|
||||
if(breakLabel==null) {
|
||||
if(breakLabel == null) {
|
||||
breakLabel = loopScope.addLabelIntermediate();
|
||||
}
|
||||
return breakLabel;
|
||||
@ -664,7 +681,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
}
|
||||
|
||||
public Label getOrCreateContinueLabel() {
|
||||
if(continueLabel==null) {
|
||||
if(continueLabel == null) {
|
||||
continueLabel = loopScope.addLabelIntermediate();
|
||||
}
|
||||
return continueLabel;
|
||||
@ -827,14 +844,14 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
}
|
||||
|
||||
private void addLoopBreakLabel(Loop loop, ParserRuleContext ctx) {
|
||||
if(loop.getBreakLabel()!=null) {
|
||||
if(loop.getBreakLabel() != null) {
|
||||
StatementLabel breakTarget = new StatementLabel(loop.getBreakLabel().getRef(), new StatementSource(ctx), Comment.NO_COMMENTS);
|
||||
sequence.addStatement(breakTarget);
|
||||
}
|
||||
}
|
||||
|
||||
private void addLoopContinueLabel(Loop loop, ParserRuleContext ctx) {
|
||||
if(loop.getContinueLabel()!=null) {
|
||||
if(loop.getContinueLabel() != null) {
|
||||
StatementLabel continueTarget = new StatementLabel(loop.getContinueLabel().getRef(), new StatementSource(ctx), Comment.NO_COMMENTS);
|
||||
sequence.addStatement(continueTarget);
|
||||
}
|
||||
@ -1035,7 +1052,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public SymbolType visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) {
|
||||
return SymbolType.get("signed " + ctx.SIMPLETYPE().getText());
|
||||
String signedness = ctx.getChild(0).getText();
|
||||
return SymbolType.get(signedness + " " + ctx.SIMPLETYPE().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1119,6 +1137,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public Object visitExprCall(KickCParser.ExprCallContext ctx) {
|
||||
|
||||
List<RValue> parameters;
|
||||
KickCParser.ParameterListContext parameterList = ctx.parameterList();
|
||||
if(parameterList != null) {
|
||||
@ -1128,7 +1147,15 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
}
|
||||
VariableIntermediate tmpVar = getCurrentScope().addVariableIntermediate();
|
||||
VariableRef tmpVarRef = tmpVar.getRef();
|
||||
sequence.addStatement(new StatementCall(tmpVarRef, ctx.NAME().getText(), parameters, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))));
|
||||
|
||||
String procedureName;
|
||||
if(ctx.expr() instanceof KickCParser.ExprIdContext) {
|
||||
procedureName = ctx.expr().getText();
|
||||
sequence.addStatement(new StatementCall(tmpVarRef, procedureName, parameters, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))));
|
||||
} else {
|
||||
RValue procedurePointer = (RValue) this.visit(ctx.expr());
|
||||
sequence.addStatement(new StatementCallPointer(tmpVarRef, procedurePointer, parameters, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx))));
|
||||
}
|
||||
return tmpVarRef;
|
||||
}
|
||||
|
||||
@ -1207,6 +1234,33 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
return tmpVarRef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RValue visitExprTernary(KickCParser.ExprTernaryContext ctx) {
|
||||
RValue condValue = (RValue) this.visit(ctx.expr(0));
|
||||
Label trueLabel = getCurrentScope().addLabelIntermediate();
|
||||
Label falseLabel = getCurrentScope().addLabelIntermediate();
|
||||
Label endJumpLabel = getCurrentScope().addLabelIntermediate();
|
||||
sequence.addStatement(new StatementConditionalJump(condValue, trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||
sequence.addStatement(new StatementLabel(falseLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||
RValue falseValue = (RValue) this.visit(ctx.expr(2));
|
||||
VariableRef falseVar = getCurrentScope().addVariableIntermediate().getRef();
|
||||
sequence.addStatement(new StatementAssignment(falseVar, null, null, falseValue, new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||
sequence.addStatement(new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||
sequence.addStatement(new StatementLabel(trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||
RValue trueValue = (RValue) this.visit(ctx.expr(1));
|
||||
VariableRef trueVar = getCurrentScope().addVariableIntermediate().getRef();
|
||||
sequence.addStatement(new StatementAssignment(trueVar, null, null, trueValue, new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||
sequence.addStatement(new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
|
||||
StatementPhiBlock phiBlock = new StatementPhiBlock(Comment.NO_COMMENTS);
|
||||
phiBlock.setSource(new StatementSource(ctx));
|
||||
VariableRef finalVar = getCurrentScope().addVariableIntermediate().getRef();
|
||||
StatementPhiBlock.PhiVariable phiVariable = phiBlock.addPhiVariable(finalVar);
|
||||
phiVariable.setrValue(trueLabel.getRef(), trueVar);
|
||||
phiVariable.setrValue(falseLabel.getRef(), falseVar);
|
||||
sequence.addStatement(phiBlock);
|
||||
return finalVar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitExprPreMod(KickCParser.ExprPreModContext ctx) {
|
||||
RValue child = (RValue) this.visit(ctx.expr());
|
||||
|
@ -1,14 +1,22 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.VariableReferenceInfos;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
import dk.camelot64.kickc.model.values.SymbolVariableRef;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
@ -29,7 +37,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
|
||||
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
|
||||
|
||||
ControlFlowBlock beginBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.BEGIN_BLOCK_NAME));
|
||||
assertUsedVars(beginBlock, referenceInfos, new LinkedHashSet<>(), new LinkedHashSet<>());
|
||||
assertUsedVars(beginBlock, null, referenceInfos, new LinkedHashSet<>(), new LinkedHashSet<>());
|
||||
getProgram().setVariableReferenceInfos(null);
|
||||
new PassNStatementIndices(getProgram()).clearStatementIndices();
|
||||
|
||||
@ -42,16 +50,23 @@ public class Pass1AssertUsedVars extends Pass1Base {
|
||||
* Follow the control flow of the graph recursively.
|
||||
*
|
||||
* @param block The block to examine
|
||||
* @param predecessor The block jumping into this block (used for phi analysis)
|
||||
* @param referenceInfos Information about assigned/used variables in statements
|
||||
* @param defined Variables already assigned a value at the point of the first execution of the block
|
||||
* @param visited Blocks already visited
|
||||
*/
|
||||
public void assertUsedVars(ControlFlowBlock block, VariableReferenceInfos referenceInfos, Collection<VariableRef> defined, Collection<LabelRef> visited) {
|
||||
public void assertUsedVars(ControlFlowBlock block, LabelRef predecessor, VariableReferenceInfos referenceInfos, Collection<VariableRef> defined, Collection<LabelRef> visited) {
|
||||
// If the block has a phi statement it is always examined (to not skip any of the predecessor checks)
|
||||
assertUsedVarsPhi(block, predecessor, referenceInfos, defined);
|
||||
// If we have already visited the block - skip it
|
||||
if(visited.contains(block.getLabel())) {
|
||||
return;
|
||||
}
|
||||
visited.add(block.getLabel());
|
||||
// Examine all statements (except the potential PHI)
|
||||
for(Statement statement : block.getStatements()) {
|
||||
// PHI block has already been examined
|
||||
if(statement instanceof StatementPhiBlock) continue;
|
||||
Collection<VariableRef> used = referenceInfos.getUsedVars(statement);
|
||||
for(VariableRef usedRef : used) {
|
||||
if(!defined.contains(usedRef)) {
|
||||
@ -70,16 +85,57 @@ public class Pass1AssertUsedVars extends Pass1Base {
|
||||
}
|
||||
ControlFlowBlock procedureStart = getProgram().getGraph().getBlock(call.getProcedure().getLabelRef());
|
||||
|
||||
assertUsedVars(procedureStart, referenceInfos, defined, visited);
|
||||
assertUsedVars(procedureStart, block.getLabel(), referenceInfos, defined, visited);
|
||||
} else if(statement instanceof StatementConditionalJump) {
|
||||
StatementConditionalJump cond = (StatementConditionalJump) statement;
|
||||
ControlFlowBlock jumpTo = getProgram().getGraph().getBlock(cond.getDestination());
|
||||
assertUsedVars(jumpTo, referenceInfos, defined, visited);
|
||||
assertUsedVars(jumpTo, block.getLabel(), referenceInfos, defined, visited);
|
||||
}
|
||||
}
|
||||
ControlFlowBlock successor = getProgram().getGraph().getBlock(block.getDefaultSuccessor());
|
||||
if(successor != null) {
|
||||
assertUsedVars(successor, referenceInfos, defined, visited);
|
||||
assertUsedVars(successor, block.getLabel(), referenceInfos, defined, visited);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that all used vars have been assigned values before the use - in a PHI block.
|
||||
*
|
||||
* @param block The block to examine
|
||||
* @param predecessor The block jumping into this block (used for phi analysis)
|
||||
* @param referenceInfos Information about assigned/used variables in statements
|
||||
* @param defined Variables already assigned a value at the point of the first execution of the block
|
||||
* @param visited Blocks already visited
|
||||
*/
|
||||
|
||||
private void assertUsedVarsPhi(ControlFlowBlock block, LabelRef predecessor, VariableReferenceInfos referenceInfos, Collection<VariableRef> defined) {
|
||||
if(predecessor != null && block.hasPhiBlock()) {
|
||||
StatementPhiBlock phiBlock = block.getPhiBlock();
|
||||
ArrayList<SymbolVariableRef> used = new ArrayList<>();
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
|
||||
int i = 0;
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
if(predecessor.equals(phiRValue.getPredecessor())) {
|
||||
ProgramValueIterator.execute(new ProgramValue.PhiValue(phiVariable, i), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
if(programValue.get() instanceof SymbolVariableRef) {
|
||||
if(!used.contains(programValue.get())) used.add((SymbolVariableRef) programValue.get());
|
||||
}
|
||||
}, phiBlock, null, block);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
// Found used variables - check that they are defined
|
||||
for(SymbolVariableRef usedRef : used) {
|
||||
if(!defined.contains(usedRef)) {
|
||||
throw new CompileError("Error! Variable used before being defined " + usedRef.toString(getProgram()) + " in " + phiBlock.toString(getProgram(), false), phiBlock.getSource());
|
||||
}
|
||||
}
|
||||
// Add all variables fefined by the PHI block
|
||||
Collection<VariableRef> defd = referenceInfos.getDefinedVars(phiBlock);
|
||||
for(VariableRef definedRef : defd) {
|
||||
defined.add(definedRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -249,7 +249,8 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
||||
List<ControlFlowBlock> predecessors = getGraph().getPredecessors(block);
|
||||
Symbol symbol = getScope().getSymbol(block.getLabel());
|
||||
if(symbol instanceof Procedure) {
|
||||
if(((Procedure) symbol).getInterruptType()!=null) {
|
||||
Procedure procedure = (Procedure) symbol;
|
||||
if(procedure.getInterruptType()!=null || Pass2ConstantIdentification.isAddressOfUsed(procedure.getRef(), getProgram())) {
|
||||
// Find all root-level predecessors to the main block
|
||||
ControlFlowBlock mainBlock = getGraph().getBlock(new LabelRef(SymbolRef.MAIN_PROC_NAME));
|
||||
List<ControlFlowBlock> mainPredecessors = getGraph().getPredecessors(mainBlock);
|
||||
|
@ -1,17 +1,17 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementReturn;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/** Pass that modifies a control flow graph to call procedures by passing parameters through registers */
|
||||
@ -23,8 +23,25 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
private Map<LabelRef, LabelRef> splitBlockMap = new LinkedHashMap<>();
|
||||
|
||||
public void generate() {
|
||||
ControlFlowGraph generated = visitGraph(program.getGraph());
|
||||
|
||||
// Fix phi predecessors for any blocks has a split block as predecessor
|
||||
for(ControlFlowBlock block : generated.getAllBlocks()) {
|
||||
if(block.hasPhiBlock()) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : block.getPhiBlock().getPhiVariables()) {
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
LabelRef splitBlockNew = splitBlockMap.get(phiRValue.getPredecessor());
|
||||
if(splitBlockNew !=null) {
|
||||
phiRValue.setPredecessor(splitBlockNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
program.setGraph(generated);
|
||||
}
|
||||
|
||||
@ -62,7 +79,9 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
|
||||
} else {
|
||||
currentBlockScope = currentBlockSymbol.getScope();
|
||||
}
|
||||
splitCurrentBlock(currentBlockScope.addLabelIntermediate().getRef());
|
||||
LabelRef splitBlockNewLabelRef = currentBlockScope.addLabelIntermediate().getRef();
|
||||
splitCurrentBlock(splitBlockNewLabelRef);
|
||||
splitBlockMap.put(this.getOrigBlock().getLabel(), splitBlockNewLabelRef);
|
||||
if(!SymbolType.VOID.equals(procedure.getReturnType()) && origCall.getlValue() != null) {
|
||||
addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef, origCall.getSource(), Comment.NO_COMMENTS));
|
||||
} else {
|
||||
|
@ -3,9 +3,7 @@ package dk.camelot64.kickc.passes;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||
import dk.camelot64.kickc.model.symbols.Scope;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
@ -31,6 +29,14 @@ public class Pass1TypeInference extends Pass1Base {
|
||||
} catch(CompileError e) {
|
||||
throw new CompileError(e.getMessage(), statement.getSource());
|
||||
}
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
try {
|
||||
SymbolTypeInference.inferPhiVariable(getProgram(), phiVariable, false);
|
||||
} catch(CompileError e) {
|
||||
throw new CompileError(e.getMessage(), statement.getSource());
|
||||
}
|
||||
}
|
||||
} else if(statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
String procedureName = call.getProcedureName();
|
||||
@ -44,7 +50,10 @@ public class Pass1TypeInference extends Pass1Base {
|
||||
throw new CompileError("Wrong number of parameters in call. Expected " + procedure.getParameters().size() + ". " + statement.toString(), statement.getSource());
|
||||
}
|
||||
SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, false);
|
||||
} else if(statement instanceof StatementCallPointer) {
|
||||
SymbolTypeInference.inferCallPointerLValue(getProgram(), (StatementCallPointer) statement, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -1,10 +1,13 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
||||
import dk.camelot64.kickc.model.symbols.VariableUnversioned;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/** Asserts that the symbols in the symbol table match exactly the symbols in the program */
|
||||
@ -16,10 +19,17 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
|
||||
|
||||
@Override
|
||||
public void check() throws AssertionFailed {
|
||||
SymbolFinder symbolFinder = new SymbolFinder(getScope());
|
||||
symbolFinder.visitGraph(getGraph());
|
||||
HashSet<Symbol> codeSymbols = symbolFinder.getSymbols();
|
||||
// Check that all symbols found in the code is also oin the symbol tabel
|
||||
|
||||
HashSet<Symbol> codeSymbols = new HashSet<>();
|
||||
ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
if(programValue.get() instanceof SymbolRef) {
|
||||
Symbol symbol = getScope().getSymbol((SymbolRef) programValue.get());
|
||||
if(symbol != null)
|
||||
codeSymbols.add(symbol);
|
||||
}
|
||||
});
|
||||
|
||||
// Check that all symbols found in the code is also in the symbol table
|
||||
for(Symbol codeSymbol : codeSymbols) {
|
||||
if(codeSymbol.getFullName().equals(SymbolRef.PROCEXIT_BLOCK_NAME)) continue;
|
||||
Symbol tableSymbol = getScope().getSymbol(codeSymbol.getFullName());
|
||||
@ -28,7 +38,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
|
||||
}
|
||||
}
|
||||
// Check that all symbols in the symbol table is also in the code
|
||||
HashSet<Symbol> tableSymbols = getAllSymbols(getScope());
|
||||
Collection<Symbol> tableSymbols = getScope().getAllSymbols(true);
|
||||
for(Symbol tableSymbol : tableSymbols) {
|
||||
if(tableSymbol instanceof VariableUnversioned) continue;
|
||||
if(tableSymbol instanceof ConstantVar) continue;
|
||||
@ -46,124 +56,4 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<Symbol> getAllSymbols(Scope symbols) {
|
||||
HashSet<Symbol> allSymbols = new HashSet<>();
|
||||
for(Symbol symbol : symbols.getAllSymbols()) {
|
||||
allSymbols.add(symbol);
|
||||
if(symbol instanceof Scope) {
|
||||
HashSet<Symbol> subSymbols = getAllSymbols((Scope) symbol);
|
||||
allSymbols.addAll(subSymbols);
|
||||
}
|
||||
}
|
||||
return allSymbols;
|
||||
}
|
||||
|
||||
private static class SymbolFinder extends ControlFlowGraphBaseVisitor<Void> {
|
||||
|
||||
private ProgramScope programScope;
|
||||
private HashSet<Symbol> symbols = new HashSet<>();
|
||||
|
||||
public SymbolFinder(ProgramScope programScope) {
|
||||
this.programScope = programScope;
|
||||
}
|
||||
|
||||
public HashSet<Symbol> getSymbols() {
|
||||
return symbols;
|
||||
}
|
||||
|
||||
private void addSymbol(Value symbol) {
|
||||
if(symbol instanceof Symbol) {
|
||||
symbols.add((Symbol) symbol);
|
||||
} else if(symbol instanceof SymbolRef) {
|
||||
addSymbol(programScope.getSymbol((SymbolRef) symbol));
|
||||
} else if(symbol instanceof PointerDereferenceIndexed) {
|
||||
addSymbol(((PointerDereferenceIndexed) symbol).getPointer());
|
||||
addSymbol(((PointerDereferenceIndexed) symbol).getIndex());
|
||||
} else if(symbol instanceof PointerDereferenceSimple) {
|
||||
addSymbol(((PointerDereference) symbol).getPointer());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitBlock(ControlFlowBlock block) {
|
||||
addSymbol(block.getLabel());
|
||||
addSymbol(block.getDefaultSuccessor());
|
||||
addSymbol(block.getConditionalSuccessor());
|
||||
addSymbol(block.getCallSuccessor());
|
||||
return super.visitBlock(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProcedureBegin(StatementProcedureBegin procedureBegin) {
|
||||
ProcedureRef procedureRef = procedureBegin.getProcedure();
|
||||
Procedure procedure = programScope.getProcedure(procedureRef);
|
||||
symbols.add(procedure);
|
||||
return super.visitProcedureBegin(procedureBegin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProcedureEnd(StatementProcedureEnd procedureEnd) {
|
||||
ProcedureRef procedureRef = procedureEnd.getProcedure();
|
||||
Procedure procedure = programScope.getProcedure(procedureRef);
|
||||
symbols.add(procedure);
|
||||
return super.visitProcedureEnd(procedureEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitReturn(StatementReturn aReturn) {
|
||||
addSymbol(aReturn.getValue());
|
||||
return super.visitReturn(aReturn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
||||
addSymbol(conditionalJump.getrValue1());
|
||||
addSymbol(conditionalJump.getrValue2());
|
||||
addSymbol(conditionalJump.getDestination());
|
||||
return super.visitConditionalJump(conditionalJump);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAssignment(StatementAssignment assignment) {
|
||||
addSymbol(assignment.getlValue());
|
||||
addSymbol(assignment.getrValue1());
|
||||
addSymbol(assignment.getrValue2());
|
||||
return super.visitAssignment(assignment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitJump(StatementJump jump) {
|
||||
addSymbol(jump.getDestination());
|
||||
return super.visitJump(jump);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitJumpTarget(StatementLabel jumpTarget) {
|
||||
addSymbol(jumpTarget.getLabel());
|
||||
return super.visitJumpTarget(jumpTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCall(StatementCall call) {
|
||||
addSymbol(call.getlValue());
|
||||
addSymbol(call.getProcedure());
|
||||
if(call.getParameters() != null) {
|
||||
for(RValue param : call.getParameters()) {
|
||||
addSymbol(param);
|
||||
}
|
||||
}
|
||||
return super.visitCall(call);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhiBlock(StatementPhiBlock phi) {
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
|
||||
addSymbol(phiVariable.getVariable());
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
addSymbol(phiRValue.getrValue());
|
||||
}
|
||||
}
|
||||
return super.visitPhiBlock(phi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.VariableReferenceInfos;
|
||||
@ -129,6 +130,18 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
assignment.setrValue1(new ConstantBinary(const1, Operators.PLUS, consolidated));
|
||||
getLog().append("Consolidated constant in assignment " + assignment.getlValue());
|
||||
return true;
|
||||
} else {
|
||||
// Check if the constant is zero
|
||||
try {
|
||||
ConstantLiteral constantLiteral = ((ConstantValue) assignment.getrValue1()).calculateLiteral(getScope());
|
||||
if(constantLiteral.getValue().equals(0L)) {
|
||||
getLog().append("Removed zero-constant in assignment " + assignment.getlValue());
|
||||
assignment.setrValue1(null);
|
||||
assignment.setOperator(null);
|
||||
}
|
||||
} catch(ConstantNotLiteral e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
} else if(assignment.getrValue1() instanceof VariableRef && assignment.getrValue2() instanceof ConstantValue) {
|
||||
VariableRef variable = (VariableRef) assignment.getrValue1();
|
||||
@ -140,6 +153,20 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
// Handling of negative consolidated numbers?
|
||||
getLog().append("Consolidated constant in assignment " + assignment.getlValue());
|
||||
return true;
|
||||
} else {
|
||||
// Check if the constant is zero
|
||||
try {
|
||||
ConstantLiteral constantLiteral = ((ConstantValue) assignment.getrValue2()).calculateLiteral(getScope());
|
||||
if(constantLiteral.getValue().equals(0L)) {
|
||||
getLog().append("Removed zero-constant in assignment " + assignment.getlValue());
|
||||
assignment.setrValue2(assignment.getrValue1());
|
||||
assignment.setOperator(null);
|
||||
assignment.setrValue1(null);
|
||||
}
|
||||
} catch(ConstantNotLiteral e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -0,0 +1,96 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementCallPointer;
|
||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
/** Pass that identified indirect calls to constant function pointers */
|
||||
public class Pass2ConstantCallPointerIdentification extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2ConstantCallPointerIdentification(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
boolean optimized = false;
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
|
||||
while(statementsIt.hasNext()) {
|
||||
Statement statement = statementsIt.next();
|
||||
if(statement instanceof StatementCallPointer) {
|
||||
StatementCallPointer callPointer = (StatementCallPointer) statement;
|
||||
RValue procedure = callPointer.getProcedure();
|
||||
if(procedure instanceof PointerDereferenceSimple) {
|
||||
RValue pointer = ((PointerDereferenceSimple) procedure).getPointer();
|
||||
ProcedureRef constProcedureRef = findConstProcedure(pointer);
|
||||
if(constProcedureRef != null) {
|
||||
replacePointerCall(callPointer, constProcedureRef, statementsIt, block);
|
||||
optimized = true;
|
||||
}
|
||||
} else if(procedure instanceof ConstantRef) {
|
||||
ConstantVar procedureVariable = getScope().getConstant((ConstantRef) procedure);
|
||||
SymbolType procedureVariableType = procedureVariable.getType();
|
||||
if(procedureVariableType instanceof SymbolTypePointer) {
|
||||
if(((SymbolTypePointer) procedureVariableType).getElementType() instanceof SymbolTypeProcedure) {
|
||||
ProcedureRef constProcedureRef = findConstProcedure(procedure);
|
||||
if(constProcedureRef != null) {
|
||||
replacePointerCall(callPointer, constProcedureRef, statementsIt, block);
|
||||
optimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return optimized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a pointer-based call to a constant procedure with a classic procedure call
|
||||
* @param callPointer The call to replace
|
||||
* @param constProcedureRef The constant procedure pointed to
|
||||
* @param statementsIt The statement iterator currently pointing to the pointer-based call
|
||||
* @param block The block containing the call
|
||||
*/
|
||||
private void replacePointerCall(StatementCallPointer callPointer, ProcedureRef constProcedureRef, ListIterator<Statement> statementsIt, ControlFlowBlock block) {
|
||||
statementsIt.remove();
|
||||
StatementCall call = new StatementCall(callPointer.getlValue(), constProcedureRef.getFullName(), callPointer.getParameters(), callPointer.getSource(), callPointer.getComments());
|
||||
call.setProcedure(constProcedureRef);
|
||||
call.setIndex(callPointer.getIndex());
|
||||
block.setCallSuccessor(constProcedureRef.getLabelRef());
|
||||
statementsIt.add(call);
|
||||
getLog().append("Replacing constant pointer function " + call.toString(getProgram(), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine whither the passed RValue represents a constant procedure pointer.
|
||||
* If it does returns the procedure pointed to
|
||||
*
|
||||
* @param procedurePointer The potential procedure pointer
|
||||
* @return The procedure pointed to
|
||||
*/
|
||||
private ProcedureRef findConstProcedure(RValue procedurePointer) {
|
||||
if(procedurePointer instanceof ConstantRef) {
|
||||
ConstantVar constant = getScope().getConstant((ConstantRef) procedurePointer);
|
||||
return findConstProcedure(constant.getValue());
|
||||
} else if(procedurePointer instanceof ConstantSymbolPointer) {
|
||||
ConstantSymbolPointer pointer = (ConstantSymbolPointer) procedurePointer;
|
||||
if(pointer.getToSymbol() instanceof ProcedureRef) {
|
||||
return (ProcedureRef) pointer.getToSymbol();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -45,13 +45,26 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
for(VariableRef constRef : constVars) {
|
||||
Variable variable = getProgram().getScope().getVariable(constRef);
|
||||
|
||||
ConstantVariableValue constVarVal = constants.get(constRef);
|
||||
|
||||
// Weed out all variables that are affected by the address-of operator
|
||||
if(isAddressOfUsed(constRef, getProgram())) {
|
||||
|
||||
// If the assignment has an operator then replace it with the single constant value
|
||||
if(constVarVal.getAssignment() instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) constVarVal.getAssignment();
|
||||
if(assignment.getOperator()!=null) {
|
||||
getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false));
|
||||
assignment.setOperator(null);
|
||||
assignment.setrValue1(null);
|
||||
assignment.setrValue2(constVarVal.getConstantValue());
|
||||
}
|
||||
}
|
||||
|
||||
// But do not remove the variable
|
||||
constants.remove(constRef);
|
||||
continue;
|
||||
}
|
||||
|
||||
ConstantVariableValue constVarVal = constants.get(constRef);
|
||||
Scope constScope = variable.getScope();
|
||||
|
||||
ConstantValue constVal = constVarVal.getConstantValue();
|
||||
@ -80,7 +93,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
constVal);
|
||||
constantVar.setDeclaredAlignment(variable.getDeclaredAlignment());
|
||||
constantVar.setDeclaredRegister(variable.getDeclaredRegister());
|
||||
if(variable.getComments().size()>0) {
|
||||
if(variable.getComments().size() > 0) {
|
||||
constantVar.setComments(variable.getComments());
|
||||
} else {
|
||||
constantVar.setComments(constVarVal.getAssignment().getComments());
|
||||
@ -111,7 +124,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
/**
|
||||
* The statement that assigns the variable its value (the assignment will be removed at the end).
|
||||
* Either a {@link StatementAssignment} or a {@link StatementPhiBlock}.
|
||||
* */
|
||||
*/
|
||||
private Statement assignment;
|
||||
|
||||
public ConstantVariableValue(VariableRef variableRef, ConstantValue constantValue, Statement assignment) {
|
||||
@ -182,83 +195,85 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
// Volatile variables cannot be constant
|
||||
return;
|
||||
}
|
||||
if(assignment.getrValue1() == null && getConstant(assignment.getrValue2()) != null) {
|
||||
if(assignment.getOperator() == null) {
|
||||
// Constant assignment
|
||||
ConstantValue constant = getConstant(assignment.getrValue2());
|
||||
if(constant != null) {
|
||||
constants.put(variable, new ConstantVariableValue(variable, constant, assignment));
|
||||
}
|
||||
} else {
|
||||
// Constant unary expression
|
||||
ConstantValue constant = createUnary(
|
||||
(OperatorUnary) assignment.getOperator(),
|
||||
getConstant(assignment.getrValue2())
|
||||
);
|
||||
if(constant != null) {
|
||||
constants.put(variable, new ConstantVariableValue(variable, constant, assignment));
|
||||
}
|
||||
}
|
||||
} else if(getConstant(assignment.getrValue1()) != null && getConstant(assignment.getrValue2()) != null) {
|
||||
// Constant binary expression
|
||||
ConstantValue constant = createBinary(
|
||||
getConstant(assignment.getrValue1()),
|
||||
(OperatorBinary) assignment.getOperator(),
|
||||
getConstant(assignment.getrValue2()),
|
||||
getScope());
|
||||
if(constant != null) {
|
||||
constants.put(variable, new ConstantVariableValue(variable, constant, assignment));
|
||||
}
|
||||
} else if(assignment.getrValue2() instanceof ValueList && assignment.getOperator() == null && assignment.getrValue1() == null) {
|
||||
// A candidate for a constant list - examine to confirm
|
||||
Variable lVariable = getScope().getVariable((VariableRef) lValue);
|
||||
if(lVariable.getType() instanceof SymbolTypeArray) {
|
||||
ValueList valueList = (ValueList) assignment.getrValue2();
|
||||
List<RValue> values = valueList.getList();
|
||||
boolean allConstant = true;
|
||||
// Type of the elements of the list (deducted from the type of all elements)
|
||||
SymbolType listType = null;
|
||||
List<ConstantValue> elements = new ArrayList<>();
|
||||
for(RValue elmValue : values) {
|
||||
if(elmValue instanceof ConstantValue) {
|
||||
ConstantValue constantValue = (ConstantValue) elmValue;
|
||||
SymbolType elmType = constantValue.getType(getScope());
|
||||
if(listType == null) {
|
||||
listType = elmType;
|
||||
} else {
|
||||
if(!SymbolTypeInference.typeMatch(listType, elmType)) {
|
||||
SymbolType intersectType = SymbolTypeInference.intersectTypes(listType, elmType);
|
||||
if(intersectType == null) {
|
||||
// No overlap between list type and element type
|
||||
throw new RuntimeException("Array type " + listType + " does not match element type" + elmType + ". Array: " + valueList.toString(getProgram()));
|
||||
} else {
|
||||
listType = intersectType;
|
||||
}
|
||||
}
|
||||
}
|
||||
elements.add(constantValue);
|
||||
} else {
|
||||
allConstant = false;
|
||||
listType = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(allConstant && listType != null) {
|
||||
// Constant list confirmed!
|
||||
ConstantValue constant = new ConstantArrayList(elements, listType);
|
||||
constants.put(variable, new ConstantVariableValue(variable, constant, assignment));
|
||||
}
|
||||
}
|
||||
} else if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && assignment.getrValue1() == null) {
|
||||
// Constant address-of variable
|
||||
if(assignment.getrValue2() instanceof SymbolRef) {
|
||||
ConstantSymbolPointer constantSymbolPointer = new ConstantSymbolPointer((SymbolRef) assignment.getrValue2());
|
||||
constants.put(variable, new ConstantVariableValue(variable, constantSymbolPointer, assignment));
|
||||
}
|
||||
ConstantValue constant = getConstantAssignmentValue(assignment, var.getType());
|
||||
if(constant != null) {
|
||||
constants.put(variable, new ConstantVariableValue(variable, constant, assignment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine the right side of an assignment and if it is constant then return the constant value.
|
||||
* @param assignment The assignment to examine
|
||||
* @param lValueType The type of the lvalue
|
||||
* @return The constant value if the right side is constant
|
||||
*/
|
||||
private ConstantValue getConstantAssignmentValue(StatementAssignment assignment, SymbolType lValueType) {
|
||||
if(assignment.getrValue1() == null && getConstant(assignment.getrValue2()) != null) {
|
||||
if(assignment.getOperator() == null) {
|
||||
// Constant assignment
|
||||
return getConstant(assignment.getrValue2());
|
||||
} else {
|
||||
// Constant unary expression
|
||||
return createUnary(
|
||||
(OperatorUnary) assignment.getOperator(),
|
||||
getConstant(assignment.getrValue2())
|
||||
);
|
||||
}
|
||||
} else if(getConstant(assignment.getrValue1()) != null && getConstant(assignment.getrValue2()) != null) {
|
||||
// Constant binary expression
|
||||
return createBinary(
|
||||
getConstant(assignment.getrValue1()),
|
||||
(OperatorBinary) assignment.getOperator(),
|
||||
getConstant(assignment.getrValue2()),
|
||||
getScope());
|
||||
} else if(assignment.getrValue2() instanceof ValueList && assignment.getOperator() == null && assignment.getrValue1() == null) {
|
||||
// A candidate for a constant list - examine to confirm
|
||||
if(lValueType instanceof SymbolTypeArray) {
|
||||
ValueList valueList = (ValueList) assignment.getrValue2();
|
||||
List<RValue> values = valueList.getList();
|
||||
boolean allConstant = true;
|
||||
// Type of the elements of the list (deducted from the type of all elements)
|
||||
SymbolType listType = null;
|
||||
List<ConstantValue> elements = new ArrayList<>();
|
||||
for(RValue elmValue : values) {
|
||||
if(elmValue instanceof ConstantValue) {
|
||||
ConstantValue constantValue = (ConstantValue) elmValue;
|
||||
SymbolType elmType = constantValue.getType(getScope());
|
||||
if(listType == null) {
|
||||
listType = elmType;
|
||||
} else {
|
||||
if(!SymbolTypeInference.typeMatch(listType, elmType)) {
|
||||
SymbolType intersectType = SymbolTypeInference.intersectTypes(listType, elmType);
|
||||
if(intersectType == null) {
|
||||
// No overlap between list type and element type
|
||||
throw new RuntimeException("Array type " + listType + " does not match element type" + elmType + ". Array: " + valueList.toString(getProgram()));
|
||||
} else {
|
||||
listType = intersectType;
|
||||
}
|
||||
}
|
||||
}
|
||||
elements.add(constantValue);
|
||||
} else {
|
||||
allConstant = false;
|
||||
listType = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(allConstant && listType != null) {
|
||||
// Constant list confirmed!
|
||||
return new ConstantArrayList(elements, listType);
|
||||
}
|
||||
}
|
||||
} else if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && assignment.getrValue1() == null) {
|
||||
// Constant address-of variable
|
||||
if(assignment.getrValue2() instanceof SymbolRef) {
|
||||
return new ConstantSymbolPointer((SymbolRef) assignment.getrValue2());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the rValue is a known constant return the constant value.
|
||||
*
|
||||
|
@ -61,7 +61,7 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
|
||||
if(callPaths == null) {
|
||||
callPaths = new LiveRangeVariablesEffective.CallPaths(procedureRef);
|
||||
|
||||
if(procedure.getInterruptType()!=null) {
|
||||
if(procedure.getInterruptType()!=null || Pass2ConstantIdentification.isAddressOfUsed(procedureRef, getProgram())) {
|
||||
// Interrupt is called outside procedure scope - create initial call-path.
|
||||
ArrayList<CallGraph.CallBlock.Call> rootPath = new ArrayList<>();
|
||||
ArrayList<VariableRef> rootAlive = new ArrayList<>();
|
||||
|
@ -51,7 +51,8 @@ public class Pass3PhiLifting {
|
||||
Variable lValVar = program.getScope().getVariable(phiVariable.getVariable());
|
||||
newVar = ((VariableVersion) lValVar).getVersionOf().createVersion();
|
||||
} else {
|
||||
throw new RuntimeException("Only versions! " + phiVariable.getVariable());
|
||||
Variable lValVar = program.getScope().getVariable(phiVariable.getVariable());
|
||||
newVar = lValVar.getScope().addVariableIntermediate();
|
||||
}
|
||||
Symbol phiLValue = programScope.getSymbol(phiVariable.getVariable());
|
||||
newVar.setType(phiLValue.getType());
|
||||
|
@ -9,6 +9,7 @@ import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeArray;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.*;
|
||||
@ -64,10 +65,7 @@ public class Pass4CodeGeneration {
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
if(!block.getScope().equals(currentScope)) {
|
||||
// The current block is in a different scope. End the old scope.
|
||||
if(!ScopeRef.ROOT.equals(currentScope)) {
|
||||
addData(asm, currentScope);
|
||||
asm.addScopeEnd();
|
||||
}
|
||||
generateScopeEnding(asm, currentScope);
|
||||
currentScope = block.getScope();
|
||||
asm.startSegment(currentScope, null, block.getLabel().getFullName());
|
||||
// Add any procedure comments
|
||||
@ -121,10 +119,7 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!ScopeRef.ROOT.equals(currentScope)) {
|
||||
addData(asm, currentScope);
|
||||
asm.addScopeEnd();
|
||||
}
|
||||
generateScopeEnding(asm, currentScope);
|
||||
addData(asm, ScopeRef.ROOT);
|
||||
// Add all absolutely placed inline KickAsm
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
@ -143,10 +138,47 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
program.setAsm(asm);
|
||||
}
|
||||
|
||||
/**
|
||||
* ASM names of variables being used for indirect calls in the current scope (procedure).
|
||||
* These will all be added as indirect JMP's at the end of the procedure scope.
|
||||
*/
|
||||
private List<String> indirectCallAsmNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Generate the end of a scope
|
||||
* @param asm The assembler program being generated
|
||||
* @param currentScope The current scope, which is ending here
|
||||
*/
|
||||
private void generateScopeEnding(AsmProgram asm, ScopeRef currentScope) {
|
||||
if(!ScopeRef.ROOT.equals(currentScope)) {
|
||||
// Generate any indirect calls pending
|
||||
for(String indirectCallAsmName : indirectCallAsmNames) {
|
||||
asm.addLabel("bi_"+indirectCallAsmName);
|
||||
asm.addInstruction("jmp", AsmAddressingMode.IND, indirectCallAsmName, false);
|
||||
}
|
||||
indirectCallAsmNames = new ArrayList<>();
|
||||
addData(asm, currentScope);
|
||||
asm.addScopeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an indirect call to the assembler program. Also queues ASM for the indirect jump to be added at the end of the block.
|
||||
* @param asm The ASM program being built
|
||||
* @param procedureVariable The variable containing the function pointer
|
||||
* @param codeScopeRef The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
|
||||
*/
|
||||
private void generateIndirectCall(AsmProgram asm, Variable procedureVariable, ScopeRef codeScopeRef) {
|
||||
String varAsmName = AsmFormat.getAsmParamName(procedureVariable, codeScopeRef);
|
||||
indirectCallAsmNames.add(varAsmName);
|
||||
asm.addInstruction("jsr", AsmAddressingMode.ABS, "bi_" + varAsmName, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate a comment that describes the procedure signature and parameter transfer
|
||||
* @param asm The assembler program being generated
|
||||
@ -362,6 +394,13 @@ public class Pass4CodeGeneration {
|
||||
} else if(SymbolType.isDWord(elementType) || SymbolType.isSDWord(elementType)) {
|
||||
asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.DWORD, asmElements);
|
||||
added.add(asmName);
|
||||
} else if(elementType instanceof SymbolTypePointer) {
|
||||
if(((SymbolTypePointer) elementType).getElementType() instanceof SymbolTypeProcedure) {
|
||||
asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmElements);
|
||||
added.add(asmName);
|
||||
} else {
|
||||
throw new RuntimeException("Unhandled constant array element type " + constantArrayList.toString(program));
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Unhandled constant array element type " + constantArrayList.toString(program));
|
||||
}
|
||||
@ -563,9 +602,49 @@ public class Pass4CodeGeneration {
|
||||
if(statementKasm.getLocation() == null) {
|
||||
addKickAsm(asm, statementKasm);
|
||||
}
|
||||
if(statementKasm.getDeclaredClobber()!=null) {
|
||||
if(statementKasm.getDeclaredClobber() != null) {
|
||||
asm.getCurrentSegment().setClobberOverwrite(statementKasm.getDeclaredClobber());
|
||||
}
|
||||
} else if(statement instanceof StatementCallPointer) {
|
||||
StatementCallPointer callPointer = (StatementCallPointer) statement;
|
||||
RValue procedure = callPointer.getProcedure();
|
||||
boolean supported = false;
|
||||
if(procedure instanceof PointerDereferenceSimple) {
|
||||
RValue pointer = ((PointerDereferenceSimple) procedure).getPointer();
|
||||
if(pointer instanceof ConstantValue) {
|
||||
asm.addInstruction("jsr", AsmAddressingMode.ABS, AsmFormat.getAsmConstant(program, (ConstantValue) pointer, 99, block.getScope()), false);
|
||||
supported = true;
|
||||
} else if(pointer instanceof VariableRef) {
|
||||
Variable variable = getScope().getVariable((VariableRef) pointer);
|
||||
generateIndirectCall(asm, variable, block.getScope());
|
||||
supported = true;
|
||||
}
|
||||
} else if(procedure instanceof VariableRef) {
|
||||
Variable procedureVariable = getScope().getVariable((VariableRef) procedure);
|
||||
SymbolType procedureVariableType = procedureVariable.getType();
|
||||
if(procedureVariableType instanceof SymbolTypePointer) {
|
||||
if(((SymbolTypePointer) procedureVariableType).getElementType() instanceof SymbolTypeProcedure) {
|
||||
generateIndirectCall(asm, procedureVariable, block.getScope());
|
||||
supported = true;
|
||||
}
|
||||
}
|
||||
} else if(procedure instanceof ConstantRef) {
|
||||
ConstantVar procedureVariable = getScope().getConstant((ConstantRef) procedure);
|
||||
SymbolType procedureVariableType = procedureVariable.getType();
|
||||
if(procedureVariableType instanceof SymbolTypePointer) {
|
||||
if(((SymbolTypePointer) procedureVariableType).getElementType() instanceof SymbolTypeProcedure) {
|
||||
String varAsmName = AsmFormat.getAsmParamName(procedureVariable, block.getScope());
|
||||
asm.addInstruction("jsr", AsmAddressingMode.ABS, varAsmName,false);
|
||||
supported = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(supported) {
|
||||
asm.getCurrentSegment().setClobberOverwrite(AsmClobber.CLOBBER_ALL);
|
||||
}
|
||||
if(!supported) {
|
||||
throw new RuntimeException("Call Pointer not supported " + statement);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Statement not supported " + statement);
|
||||
}
|
||||
@ -573,27 +652,30 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate ASM code for an ASM fragment instance ()
|
||||
* Generate ASM code for an ASM fragment instance
|
||||
* @param asm The ASM program to generate into
|
||||
* @param asmFragmentInstanceSpecFactory The ASM fragment instance specification factory
|
||||
*/
|
||||
private void generateAsm(AsmProgram asm, AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory) {
|
||||
String initialSignature = asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec().getSignature();
|
||||
AsmFragmentInstanceSpec asmFragmentInstanceSpec = asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec();
|
||||
AsmFragmentInstance asmFragmentInstance = null;
|
||||
StringBuffer fragmentVariationsTried = new StringBuffer();
|
||||
while(asmFragmentInstance==null) {
|
||||
try {
|
||||
asmFragmentInstance = AsmFragmentTemplateSynthesizer.getFragmentInstance(asmFragmentInstanceSpec, program.getLog());
|
||||
} catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
|
||||
// Unknown fragment - keep looking through alternative ASM fragment instance specs until we have tried them all
|
||||
String signature = asmFragmentInstanceSpec.getSignature();
|
||||
fragmentVariationsTried.append(signature).append(" ");
|
||||
if(asmFragmentInstanceSpec.hasNextVariation()) {
|
||||
String signature = asmFragmentInstanceSpec.getSignature();
|
||||
asmFragmentInstanceSpec.nextVariation();
|
||||
if(program.getLog().isVerboseFragmentLog()) {
|
||||
program.getLog().append("Fragment not found "+signature+". Attempting another variation "+asmFragmentInstanceSpec.getSignature());
|
||||
}
|
||||
} else {
|
||||
// No more variations available - fail with an error
|
||||
throw e;
|
||||
throw new AsmFragmentTemplateSynthesizer.UnknownFragmentException("Fragment not found "+initialSignature+". Attempted variations "+fragmentVariationsTried);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.symbols.VariableVersion;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
@ -28,6 +29,28 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
||||
getLog().append(liveRangeEquivalenceClass.toString());
|
||||
}
|
||||
|
||||
|
||||
// Add all versions of volatile variables to the same equivalence class
|
||||
for(Variable variable : getSymbols().getAllVariables(true)) {
|
||||
if(variable.isVersioned() && variable.isDeclaredVolatile()) {
|
||||
// Found a volatile non-versioned variable
|
||||
for(Variable otherVariable : variable.getScope().getAllVariables(false)) {
|
||||
if(otherVariable.isVersioned()) {
|
||||
if(((VariableVersion)otherVariable).getVersionOf().equals(((VariableVersion)variable).getVersionOf())) {
|
||||
// They share the same main variable
|
||||
LiveRangeEquivalenceClass varEC = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(variable.getRef());
|
||||
LiveRangeEquivalenceClass otherEC = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(otherVariable.getRef());
|
||||
if(!varEC.equals(otherEC)) {
|
||||
getLog().append("Coalescing volatile variable equivalence classes " + varEC.toString() + " and " + otherEC.toString());
|
||||
liveRangeEquivalenceClassSet.consolidate(varEC, otherEC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add all other variables one by one to an available equivalence class - or create a new one
|
||||
EquivalenceClassAdder equivalenceClassAdder = new EquivalenceClassAdder(liveRangeEquivalenceClassSet);
|
||||
equivalenceClassAdder.visitGraph(getGraph());
|
||||
|
@ -1,10 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.values.ConstantSymbolPointer;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -49,12 +46,12 @@ public class Pass4RegisterUpliftPotentialInitialize extends Pass2Base {
|
||||
Registers.RegisterType registerType = defaultRegister.getType();
|
||||
List<Registers.Register> potentials = new ArrayList<>();
|
||||
potentials.add(defaultRegister);
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BYTE) && !varRefExtracted(equivalenceClass) &&!varVolatile(equivalenceClass)) {
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BYTE) && !isAddressOfUsed(equivalenceClass) &&!varVolatile(equivalenceClass)) {
|
||||
potentials.add(Registers.getRegisterA());
|
||||
potentials.add(Registers.getRegisterX());
|
||||
potentials.add(Registers.getRegisterY());
|
||||
}
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BOOL) && !varRefExtracted(equivalenceClass) &&!varVolatile(equivalenceClass)) {
|
||||
if(registerType.equals(Registers.RegisterType.ZP_BOOL) && !isAddressOfUsed(equivalenceClass) &&!varVolatile(equivalenceClass)) {
|
||||
potentials.add(Registers.getRegisterA());
|
||||
}
|
||||
registerPotentials.setPotentialRegisters(equivalenceClass, potentials);
|
||||
@ -83,14 +80,10 @@ public class Pass4RegisterUpliftPotentialInitialize extends Pass2Base {
|
||||
* @param equivalenceClass The equivalence class
|
||||
* @return true if a variable reference is extracted
|
||||
*/
|
||||
private boolean varRefExtracted(LiveRangeEquivalenceClass equivalenceClass) {
|
||||
Collection<ConstantVar> allConstants = getProgram().getScope().getAllConstants(true);
|
||||
for(ConstantVar allConstant : allConstants) {
|
||||
if(allConstant.getValue() instanceof ConstantSymbolPointer) {
|
||||
SymbolRef toSym = ((ConstantSymbolPointer) allConstant.getValue()).getToSymbol();
|
||||
if(equivalenceClass.getVariables().contains(toSym)) {
|
||||
return true;
|
||||
}
|
||||
private boolean isAddressOfUsed(LiveRangeEquivalenceClass equivalenceClass) {
|
||||
for(VariableRef variableRef : equivalenceClass.getVariables()) {
|
||||
if(Pass2ConstantIdentification.isAddressOfUsed(variableRef, getProgram())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -26,7 +26,7 @@ public class Pass4ZeroPageCoalesce extends Pass2Base {
|
||||
public void coalesce() {
|
||||
LinkedHashSet<String> unknownFragments = new LinkedHashSet<>();
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = getProgram().getLiveRangeEquivalenceClassSet();
|
||||
Collection<ScopeRef> threads = getThreadHeads(getSymbols());
|
||||
Collection<ScopeRef> threads = getThreadHeads(getProgram());
|
||||
boolean change;
|
||||
do {
|
||||
change = coalesce(liveRangeEquivalenceClassSet, threads, unknownFragments);
|
||||
@ -47,15 +47,16 @@ public class Pass4ZeroPageCoalesce extends Pass2Base {
|
||||
*
|
||||
* @return The threads.
|
||||
*/
|
||||
public static Collection<ScopeRef> getThreadHeads(ProgramScope programScope) {
|
||||
public static Collection<ScopeRef> getThreadHeads(Program program) {
|
||||
ArrayList<ScopeRef> threadHeads = new ArrayList<>();
|
||||
Collection<Procedure> procedures = programScope.getAllProcedures(true);
|
||||
Collection<Procedure> procedures = program.getScope().getAllProcedures(true);
|
||||
for(Procedure procedure : procedures) {
|
||||
if(procedure.getInterruptType() != null) {
|
||||
threadHeads.add(procedure.getRef());
|
||||
}
|
||||
if(procedure.getFullName().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
threadHeads.add(procedure.getRef());
|
||||
continue;
|
||||
}
|
||||
if(Pass2ConstantIdentification.isAddressOfUsed(procedure.getRef(), program)) {
|
||||
threadHeads.add(procedure.getRef());
|
||||
}
|
||||
}
|
||||
return threadHeads;
|
||||
@ -109,7 +110,7 @@ public class Pass4ZeroPageCoalesce extends Pass2Base {
|
||||
* @return True if the two equivalence classes can be coalesced into one without problems.
|
||||
*/
|
||||
private static boolean canCoalesceThreads(LiveRangeEquivalenceClass ec1, LiveRangeEquivalenceClass ec2, Collection<ScopeRef> threadHeads, Program program) {
|
||||
if(threadHeads.size()>=1) {
|
||||
if(threadHeads.size()<=1) {
|
||||
return true;
|
||||
}
|
||||
CallGraph callGraph = program.getCallGraph();
|
||||
|
@ -20,7 +20,7 @@ public class Pass4ZeroPageCoalesceAssignment extends Pass2Base {
|
||||
public void coalesce() {
|
||||
CoalesceVarScores coalesceVarScores = new CoalesceVarScores(getProgram());
|
||||
LinkedHashSet<String> unknownFragments = new LinkedHashSet<>();
|
||||
Collection<ScopeRef> threadHeads = Pass4ZeroPageCoalesce.getThreadHeads(getSymbols());
|
||||
Collection<ScopeRef> threadHeads = Pass4ZeroPageCoalesce.getThreadHeads(getProgram());
|
||||
|
||||
boolean change;
|
||||
do {
|
||||
|
59
src/main/java/dk/camelot64/kickc/passes/Pass5AddMainRts.java
Normal file
59
src/main/java/dk/camelot64/kickc/passes/Pass5AddMainRts.java
Normal file
@ -0,0 +1,59 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* If the main method is called by JSR this adds an additional RTS
|
||||
*/
|
||||
public class Pass5AddMainRts extends Pass5AsmOptimization {
|
||||
|
||||
public Pass5AddMainRts(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public boolean optimize() {
|
||||
for(AsmSegment segment : getAsmProgram().getSegments()) {
|
||||
String scopeLabel = segment.getScopeLabel();
|
||||
if(scopeLabel.equals(ScopeRef.ROOT.getFullName())) {
|
||||
ListIterator<AsmLine> lineIterator = segment.getLines().listIterator();
|
||||
while(lineIterator.hasNext()) {
|
||||
AsmLine line = lineIterator.next();
|
||||
if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getType().getMnemnonic().equals("jsr")) {
|
||||
if(instruction.getParameter().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
// Add RTS if it is missing
|
||||
if(!lineIterator.hasNext()) {
|
||||
addRts(lineIterator);
|
||||
return true;
|
||||
}
|
||||
AsmLine nextLine = lineIterator.next();
|
||||
if(!(nextLine instanceof AsmInstruction)) {
|
||||
addRts(lineIterator);
|
||||
return true;
|
||||
}
|
||||
AsmInstruction nextInstruction = (AsmInstruction) nextLine;
|
||||
if(!nextInstruction.getType().getMnemnonic().equals("rts")) {
|
||||
addRts(lineIterator);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addRts(ListIterator<AsmLine> lineIterator) {
|
||||
lineIterator.add(new AsmInstruction(AsmInstructionSet.getInstructionType("rts", AsmAddressingMode.NON, false), null));
|
||||
getLog().append("Adding RTS to root block ");
|
||||
}
|
||||
|
||||
}
|
@ -3,10 +3,7 @@ package dk.camelot64.kickc.passes;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.VariableReferenceInfos;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
@ -64,6 +61,20 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization {
|
||||
call.setlValue(null);
|
||||
modified = true;
|
||||
}
|
||||
} else if(statement instanceof StatementCallPointer) {
|
||||
StatementCallPointer call = (StatementCallPointer) statement;
|
||||
LValue lValue = call.getlValue();
|
||||
if(lValue instanceof VariableRef && referenceInfos.isUnused((VariableRef) lValue) && !Pass2ConstantIdentification.isAddressOfUsed((VariableRef) lValue, getProgram())) {
|
||||
if(getLog().isVerbosePass1CreateSsa() || getLog().isVerboseSSAOptimize()) {
|
||||
getLog().append("Eliminating unused variable - keeping the call " + lValue.toString(getProgram()));
|
||||
}
|
||||
Variable variable = getScope().getVariable((VariableRef) lValue);
|
||||
if(variable != null) {
|
||||
variable.getScope().remove(variable);
|
||||
}
|
||||
call.setlValue(null);
|
||||
modified = true;
|
||||
}
|
||||
} else if(statement instanceof StatementPhiBlock) {
|
||||
StatementPhiBlock statementPhi = (StatementPhiBlock) statement;
|
||||
ListIterator<StatementPhiBlock.PhiVariable> phiVarIt = statementPhi.getPhiVariables().listIterator();
|
||||
|
@ -5,10 +5,7 @@ import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.VariableReferenceInfos;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.SymbolVariable;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
@ -210,6 +207,12 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
|
||||
defined.add((VariableRef) ((StatementCall) stmt).getlValue());
|
||||
}
|
||||
return defined;
|
||||
} else if(stmt instanceof StatementCallPointer) {
|
||||
List<VariableRef> defined = new ArrayList<>();
|
||||
if(((StatementCallPointer) stmt).getlValue() instanceof VariableRef) {
|
||||
defined.add((VariableRef) ((StatementCallPointer) stmt).getlValue());
|
||||
}
|
||||
return defined;
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
@ -32,6 +32,141 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIllegalVoidParameter() throws IOException, URISyntaxException {
|
||||
assertError("illegal-void-parameter", "Illegal void parameter");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIllegalUnnamedParameter() throws IOException, URISyntaxException {
|
||||
assertError("illegal-unnamed-parameter", "Illegal unnamed parameter");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFire() throws IOException, URISyntaxException {
|
||||
compileAndCompare("examples/fire/fire");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCTypes() throws IOException, URISyntaxException {
|
||||
compileAndCompare("c-types");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlus0() throws IOException, URISyntaxException {
|
||||
compileAndCompare("plus-0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlasma2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("examples/plasma/plasma-unroll");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlasma() throws IOException, URISyntaxException {
|
||||
compileAndCompare("examples/plasma/plasma");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTernary3() throws IOException, URISyntaxException {
|
||||
compileAndCompare("ternary-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTernary2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("ternary-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTernary1() throws IOException, URISyntaxException {
|
||||
compileAndCompare("ternary-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointerPointer3() throws IOException, URISyntaxException {
|
||||
compileAndCompare("pointer-pointer-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointerPointer2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("pointer-pointer-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointerPointer1() throws IOException, URISyntaxException {
|
||||
compileAndCompare("pointer-pointer-1" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall10() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-10");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall9() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-9");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall8() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall7() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-7");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall6() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-6");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall5() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall4() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall3() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerReturn() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-return");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoarg3() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoarg2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoarg() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoopBreakContinue() throws IOException, URISyntaxException {
|
||||
compileAndCompare("loop-break-continue");
|
||||
@ -59,7 +194,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testLocalScopeLoops() throws IOException, URISyntaxException {
|
||||
compileAndCompare("localscope-loops", getLogSysout());
|
||||
compileAndCompare("localscope-loops");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1420,11 +1555,11 @@ public class TestPrograms {
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
CompileLog log = getLogSysout();
|
||||
CompileLog log = log();
|
||||
AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false);
|
||||
}
|
||||
|
||||
private static CompileLog getLogSysout() {
|
||||
private static CompileLog log() {
|
||||
CompileLog log = new CompileLog();
|
||||
log.setSysOut(true);
|
||||
return log;
|
||||
|
71
src/test/kc/c-types.kc
Normal file
71
src/test/kc/c-types.kc
Normal file
@ -0,0 +1,71 @@
|
||||
// Tests the different standard C types
|
||||
|
||||
import "print"
|
||||
|
||||
void main() {
|
||||
print_cls();
|
||||
testChar();
|
||||
testShort();
|
||||
testInt();
|
||||
testLong();
|
||||
}
|
||||
|
||||
void testChar() {
|
||||
unsigned char u = 14;
|
||||
char n = -14;
|
||||
signed char s = -14;
|
||||
|
||||
print_str("char: @");
|
||||
print_byte(u);
|
||||
print_char(' ');
|
||||
print_sbyte(n);
|
||||
print_char(' ');
|
||||
print_sbyte(s);
|
||||
print_ln();
|
||||
|
||||
}
|
||||
|
||||
void testShort() {
|
||||
unsigned short u = 1400;
|
||||
short n = -1400;
|
||||
signed short s = -1400;
|
||||
|
||||
print_str("short: @");
|
||||
print_word(u);
|
||||
print_char(' ');
|
||||
print_sword(n);
|
||||
print_char(' ');
|
||||
print_sword(s);
|
||||
print_ln();
|
||||
|
||||
}
|
||||
|
||||
void testInt() {
|
||||
unsigned int u = 1400;
|
||||
int n = -1400;
|
||||
signed int s = -1400;
|
||||
|
||||
print_str("int: @");
|
||||
print_word(u);
|
||||
print_char(' ');
|
||||
print_sword(n);
|
||||
print_char(' ');
|
||||
print_sword(s);
|
||||
print_ln();
|
||||
|
||||
}
|
||||
|
||||
void testLong() {
|
||||
unsigned long u = 140000;
|
||||
long n = -140000;
|
||||
signed long s = -140000;
|
||||
|
||||
print_str("long: @");
|
||||
print_dword(u);
|
||||
print_char(' ');
|
||||
print_sdword(n);
|
||||
print_char(' ');
|
||||
print_sdword(s);
|
||||
print_ln();
|
||||
|
||||
}
|
@ -21,7 +21,7 @@ void sid_rnd_init() {
|
||||
|
||||
// Get a random number from the SID voice 3,
|
||||
// Must be initialized with sid_rnd_init()
|
||||
byte sid_rnd() {
|
||||
inline byte sid_rnd() {
|
||||
return *SID_VOICE3_OSC;
|
||||
}
|
||||
|
||||
|
85
src/test/kc/examples/fire/fire.kc
Normal file
85
src/test/kc/examples/fire/fire.kc
Normal file
@ -0,0 +1,85 @@
|
||||
// A KickC version of the fire routine from the CC65 samples
|
||||
// (w)2002 by groepaz/hitmen
|
||||
// Cleanup and porting to CC65 by Ullrich von Bassewitz and Greg King .
|
||||
// Ported to KickC by Jesper Gravgaard.
|
||||
// Original source https://github.com/cc65/cc65/blob/master/samples/fire.c
|
||||
|
||||
import "c64"
|
||||
import "sid"
|
||||
|
||||
unsigned char* SCREEN1 = 0x3800;
|
||||
unsigned char* SCREEN2 = 0x3c00;
|
||||
unsigned char* BUFFER = 0x4000;
|
||||
unsigned char* CHARSET = 0x3000;
|
||||
|
||||
void main() {
|
||||
asm { sei }
|
||||
*BORDERCOL = BLACK;
|
||||
*BGCOL = BLACK;
|
||||
fillscreen(BUFFER, 00);
|
||||
fillscreen(SCREEN1, 00);
|
||||
fillscreen(SCREEN2, 00);
|
||||
fillscreen(COLS, YELLOW);
|
||||
sid_rnd_init();
|
||||
makecharset(CHARSET);
|
||||
// Show double-buffered fire
|
||||
while(true) {
|
||||
fire(SCREEN1);
|
||||
*D018 = toD018(SCREEN1, CHARSET);
|
||||
fire(SCREEN2);
|
||||
*D018 = toD018(SCREEN2, CHARSET);
|
||||
}
|
||||
}
|
||||
|
||||
// Animate the fire on the passe screen. Uses BUFFER to store the current values.
|
||||
void fire(unsigned char* screenbase) {
|
||||
|
||||
// Average characters from below the current character (24 lines)
|
||||
unsigned char* screen = screenbase;
|
||||
unsigned char* buffer = BUFFER;
|
||||
while (buffer != (BUFFER + (24 * 40))) {
|
||||
unsigned char c = ( buffer[40-1] + buffer[40-1] + buffer[40] + buffer[41] ) >> 2;
|
||||
if (c > 2) {
|
||||
c -= 3;
|
||||
}
|
||||
*screen = *buffer = c;
|
||||
++screen;
|
||||
++buffer;
|
||||
}
|
||||
// Add one new random line at the bottom
|
||||
screen = (screenbase + (24 * 40));
|
||||
buffer = (BUFFER + (24 * 40));
|
||||
while(buffer != (BUFFER+(25*40))) {
|
||||
*screen++ = *buffer++ = 0x30 + (sid_rnd()) >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Make a fire-friendly charset in chars $00-$3f of the passed charset
|
||||
void makecharset(byte* charset) {
|
||||
const unsigned char[8] bittab = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
|
||||
for (unsigned char *font = charset; font != (charset+(1*8)); ++font)
|
||||
*font = 0x00;
|
||||
for (unsigned char *font = (charset+(64*8)); font != (charset+(256*8)); ++font)
|
||||
*font = 0xff;
|
||||
for (unsigned char c = 0; c < 0x40; ++c) {
|
||||
unsigned char bc = 0;
|
||||
for (unsigned char i = 0; i < 8; i++){
|
||||
unsigned char b = 0;
|
||||
for (unsigned char ii = 0; ii < 8; ii++) {
|
||||
bc += c;
|
||||
if (bc > 0x3f) {
|
||||
bc = bc - 0x40;
|
||||
b += bittab[(ii + (i & 1)) & 0x7];
|
||||
}
|
||||
}
|
||||
(charset + (1 * 8)) [(((unsigned short)c) << 3) + i] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill a screen (1000 bytes) with a specific byte
|
||||
void fillscreen(unsigned char* screen, unsigned char fill) {
|
||||
for( unsigned word i : 0..999) {
|
||||
*screen++ = fill;
|
||||
}
|
||||
}
|
27
src/test/kc/examples/fire/sid.kc
Normal file
27
src/test/kc/examples/fire/sid.kc
Normal file
@ -0,0 +1,27 @@
|
||||
// SID registers for random number generation
|
||||
const word* SID_VOICE3_FREQ = $d40e;
|
||||
const byte* SID_VOICE3_FREQ_LOW = $d40e;
|
||||
const byte* SID_VOICE3_FREQ_HIGH = $d40f;
|
||||
const byte* SID_VOICE3_CONTROL = $d412;
|
||||
const byte SID_CONTROL_NOISE = $80;
|
||||
const byte SID_CONTROL_PULSE = $40;
|
||||
const byte SID_CONTROL_SAWTOOTH = $20;
|
||||
const byte SID_CONTROL_TRIANGLE = $10;
|
||||
const byte SID_CONTROL_TEST = $08;
|
||||
const byte SID_CONTROL_RING = $04;
|
||||
const byte SID_CONTROL_SYNC = $02;
|
||||
const byte SID_CONTROL_GATE = $01;
|
||||
const byte* SID_VOICE3_OSC = $d41b;
|
||||
|
||||
// Initialize SID voice 3 for random number generation
|
||||
void sid_rnd_init() {
|
||||
*SID_VOICE3_FREQ = $ffff;
|
||||
*SID_VOICE3_CONTROL = SID_CONTROL_NOISE;
|
||||
}
|
||||
|
||||
// Get a random number from the SID voice 3,
|
||||
// Must be initialized with sid_rnd_init()
|
||||
byte sid_rnd() {
|
||||
return *SID_VOICE3_OSC;
|
||||
}
|
||||
|
91
src/test/kc/examples/plasma/plasma-unroll.kc
Normal file
91
src/test/kc/examples/plasma/plasma-unroll.kc
Normal file
@ -0,0 +1,91 @@
|
||||
// A KickC version of the plasma routine from the CC65 samples
|
||||
// This version has an unrolled inner loop to reach ~50FPS
|
||||
// (w)2001 by groepaz/hitmen
|
||||
// Cleanup and porting to CC65 by Ullrich von Bassewitz.
|
||||
// Ported to KickC by Jesper Gravgaard.
|
||||
// Original source https://github.com/cc65/cc65/blob/master/samples/plasma.c
|
||||
|
||||
import "c64"
|
||||
import "print"
|
||||
import "sid"
|
||||
|
||||
const unsigned char* SCREEN1 = $2800;
|
||||
const unsigned char* CHARSET = $2000;
|
||||
const unsigned char* SINTABLE = $1f00;
|
||||
|
||||
kickasm(pc SINTABLE) {{
|
||||
.for(var i=0;i<$100;i++)
|
||||
.byte round(127.5+127.5*sin(toRadians(360*i/256)))
|
||||
}}
|
||||
|
||||
void main() {
|
||||
asm { sei }
|
||||
*BORDERCOL = BLUE;
|
||||
*BGCOL = BLUE;
|
||||
for(unsigned char* col : COLS..COLS+1000) *col = BLACK;
|
||||
makecharset(CHARSET);
|
||||
*D018 = toD018(SCREEN1, CHARSET);
|
||||
while(true) {
|
||||
// Show single-buffered plasma
|
||||
doplasma(SCREEN1);
|
||||
}
|
||||
}
|
||||
|
||||
// Plasma state variables
|
||||
unsigned char c1A = 0;
|
||||
unsigned char c1B = 0;
|
||||
unsigned char c2A = 0;
|
||||
unsigned char c2B = 0;
|
||||
|
||||
// Render plasma to the passed screen
|
||||
void doplasma(unsigned char* screen) {
|
||||
|
||||
unsigned char[40] xbuf;
|
||||
unsigned char[25] ybuf;
|
||||
|
||||
unsigned char c1a = c1A;
|
||||
unsigned char c1b = c1B;
|
||||
for (unsigned char i = 0; i < 25; ++i) {
|
||||
ybuf[i] = (SINTABLE[c1a] + SINTABLE[c1b]);
|
||||
c1a += 4;
|
||||
c1b += 9;
|
||||
}
|
||||
c1A += 3;
|
||||
c1B -= 5;
|
||||
unsigned char c2a = c2A;
|
||||
unsigned char c2b = c2B;
|
||||
for (unsigned char i = 0; i < 40; ++i) {
|
||||
xbuf[i] = (SINTABLE[c2a] + SINTABLE[c2b]);
|
||||
c2a += 3;
|
||||
c2b += 7;
|
||||
}
|
||||
c2A += 2;
|
||||
c2B -= 3;
|
||||
for (unsigned char i = 0; i < 40; ++i) {
|
||||
inline for (unsigned char ii = 0; ii < 25; ++ii) {
|
||||
(screen+ii*40)[i] = (xbuf[i] + ybuf[ii]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make a plasma-friendly charset where the chars are randomly filled
|
||||
void makecharset(unsigned char* charset) {
|
||||
const unsigned char[8] bittab = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
|
||||
sid_rnd_init();
|
||||
print_cls();
|
||||
for (unsigned int c = 0; c < 0x100; ++c) {
|
||||
unsigned char s = SINTABLE[<c];
|
||||
for ( unsigned char i = 0; i < 8; ++i){
|
||||
unsigned char b = 0;
|
||||
for (unsigned char ii = 0; ii < 8; ++ii) {
|
||||
if ((sid_rnd() & 0xFF) > s) {
|
||||
b |= bittab[ii];
|
||||
}
|
||||
}
|
||||
charset[(c<<3) + i] = b;
|
||||
}
|
||||
if ((c & 0x07) == 0) {
|
||||
print_char('.');
|
||||
}
|
||||
}
|
||||
}
|
94
src/test/kc/examples/plasma/plasma.kc
Normal file
94
src/test/kc/examples/plasma/plasma.kc
Normal file
@ -0,0 +1,94 @@
|
||||
// A KickC version of the plasma routine from the CC65 samples
|
||||
// (w)2001 by groepaz/hitmen
|
||||
// Cleanup and porting to CC65 by Ullrich von Bassewitz.
|
||||
// Ported to KickC by Jesper Gravgaard.
|
||||
// Original source https://github.com/cc65/cc65/blob/master/samples/plasma.c
|
||||
|
||||
import "c64"
|
||||
import "print"
|
||||
import "sid"
|
||||
|
||||
const unsigned char* SCREEN1 = $2800;
|
||||
const unsigned char* SCREEN2 = $2c00;
|
||||
const unsigned char* CHARSET = $2000;
|
||||
const unsigned char* SINTABLE = $1f00;
|
||||
|
||||
kickasm(pc SINTABLE) {{
|
||||
.for(var i=0;i<$100;i++)
|
||||
.byte round(127.5+127.5*sin(toRadians(360*i/256)))
|
||||
}}
|
||||
|
||||
void main() {
|
||||
asm { sei }
|
||||
*BORDERCOL = BLUE;
|
||||
*BGCOL = BLUE;
|
||||
for(unsigned char* col : COLS..COLS+1000) *col = BLACK;
|
||||
makecharset(CHARSET);
|
||||
// Show double-buffered plasma
|
||||
while(true) {
|
||||
doplasma(SCREEN1);
|
||||
*D018 = toD018(SCREEN1, CHARSET);
|
||||
doplasma(SCREEN2);
|
||||
*D018 = toD018(SCREEN2, CHARSET);
|
||||
}
|
||||
}
|
||||
|
||||
// Plasma state variables
|
||||
unsigned char c1A = 0;
|
||||
unsigned char c1B = 0;
|
||||
unsigned char c2A = 0;
|
||||
unsigned char c2B = 0;
|
||||
|
||||
// Render plasma to the passed screen
|
||||
void doplasma (unsigned char* screen) {
|
||||
|
||||
unsigned char[40] xbuf;
|
||||
unsigned char[25] ybuf;
|
||||
|
||||
unsigned char c1a = c1A;
|
||||
unsigned char c1b = c1B;
|
||||
for (unsigned char i = 0; i < 25; ++i) {
|
||||
ybuf[i] = (SINTABLE[c1a] + SINTABLE[c1b]);
|
||||
c1a += 4;
|
||||
c1b += 9;
|
||||
}
|
||||
c1A += 3;
|
||||
c1B -= 5;
|
||||
unsigned char c2a = c2A;
|
||||
unsigned char c2b = c2B;
|
||||
for (unsigned char i = 0; i < 40; ++i) {
|
||||
xbuf[i] = (SINTABLE[c2a] + SINTABLE[c2b]);
|
||||
c2a += 3;
|
||||
c2b += 7;
|
||||
}
|
||||
c2A += 2;
|
||||
c2B -= 3;
|
||||
for (unsigned char ii = 0; ii < 25; ++ii) {
|
||||
for (unsigned char i = 0; i < 40; ++i) {
|
||||
screen[i] = (xbuf[i] + ybuf[ii]);
|
||||
}
|
||||
screen += 40;
|
||||
}
|
||||
}
|
||||
|
||||
// Make a plasma-friendly charset where the chars are randomly filled
|
||||
void makecharset(unsigned char* charset) {
|
||||
const unsigned char[8] bittab = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
|
||||
sid_rnd_init();
|
||||
print_cls();
|
||||
for (unsigned int c = 0; c < 0x100; ++c) {
|
||||
unsigned char s = SINTABLE[<c];
|
||||
for ( unsigned char i = 0; i < 8; ++i){
|
||||
unsigned char b = 0;
|
||||
for (unsigned char ii = 0; ii < 8; ++ii) {
|
||||
if ((sid_rnd() & 0xFF) > s) {
|
||||
b |= bittab[ii];
|
||||
}
|
||||
}
|
||||
charset[(c<<3) + i] = b;
|
||||
}
|
||||
if ((c & 0x07) == 0) {
|
||||
print_char('.');
|
||||
}
|
||||
}
|
||||
}
|
27
src/test/kc/examples/plasma/sid.kc
Normal file
27
src/test/kc/examples/plasma/sid.kc
Normal file
@ -0,0 +1,27 @@
|
||||
// SID registers for random number generation
|
||||
const word* SID_VOICE3_FREQ = $d40e;
|
||||
const byte* SID_VOICE3_FREQ_LOW = $d40e;
|
||||
const byte* SID_VOICE3_FREQ_HIGH = $d40f;
|
||||
const byte* SID_VOICE3_CONTROL = $d412;
|
||||
const byte SID_CONTROL_NOISE = $80;
|
||||
const byte SID_CONTROL_PULSE = $40;
|
||||
const byte SID_CONTROL_SAWTOOTH = $20;
|
||||
const byte SID_CONTROL_TRIANGLE = $10;
|
||||
const byte SID_CONTROL_TEST = $08;
|
||||
const byte SID_CONTROL_RING = $04;
|
||||
const byte SID_CONTROL_SYNC = $02;
|
||||
const byte SID_CONTROL_GATE = $01;
|
||||
const byte* SID_VOICE3_OSC = $d41b;
|
||||
|
||||
// Initialize SID voice 3 for random number generation
|
||||
void sid_rnd_init() {
|
||||
*SID_VOICE3_FREQ = $ffff;
|
||||
*SID_VOICE3_CONTROL = SID_CONTROL_NOISE;
|
||||
}
|
||||
|
||||
// Get a random number from the SID voice 3,
|
||||
// Must be initialized with sid_rnd_init()
|
||||
byte sid_rnd() {
|
||||
return *SID_VOICE3_OSC;
|
||||
}
|
||||
|
25
src/test/kc/function-pointer-noarg-2.kc
Normal file
25
src/test/kc/function-pointer-noarg-2.kc
Normal file
@ -0,0 +1,25 @@
|
||||
// Tests creating and assigning pointers to non-args no-return functions
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
void()* f;
|
||||
|
||||
for ( byte i: 0..100) {
|
||||
if((i&1)==0) {
|
||||
f = &fn1;
|
||||
} else {
|
||||
f = &fn2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
35
src/test/kc/function-pointer-noarg-3.kc
Normal file
35
src/test/kc/function-pointer-noarg-3.kc
Normal file
@ -0,0 +1,35 @@
|
||||
// Tests creating and assigning pointers to non-args no-return functions - plus inline kickasm-based calling
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
void()* f;
|
||||
|
||||
byte i = 0;
|
||||
while(true) {
|
||||
++i;
|
||||
if((i&1)==0) {
|
||||
f = &fn1;
|
||||
} else {
|
||||
f = &fn2;
|
||||
}
|
||||
kickasm(uses f) {{
|
||||
jsr ff
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
kickasm {{
|
||||
ff:
|
||||
jmp (main.f)
|
||||
}}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
30
src/test/kc/function-pointer-noarg-call-10.kc
Normal file
30
src/test/kc/function-pointer-noarg-call-10.kc
Normal file
@ -0,0 +1,30 @@
|
||||
// Tests calling into different function pointers which call a common sub-method
|
||||
|
||||
void main() {
|
||||
do10(&hello);
|
||||
do10(&world);
|
||||
}
|
||||
|
||||
void do10(void()* fn) {
|
||||
for( byte i: 0..9)
|
||||
(*fn)();
|
||||
}
|
||||
|
||||
void hello() {
|
||||
print("hello @");
|
||||
}
|
||||
|
||||
void world() {
|
||||
print("world @");
|
||||
}
|
||||
|
||||
const byte* SCREEN = $0400;
|
||||
volatile byte idx = 0;
|
||||
|
||||
void print(byte* msg) {
|
||||
byte i=0;
|
||||
do {
|
||||
SCREEN[idx++] = msg[i++];
|
||||
} while(msg[i]!='@');
|
||||
}
|
||||
|
28
src/test/kc/function-pointer-noarg-call-2.kc
Normal file
28
src/test/kc/function-pointer-noarg-call-2.kc
Normal file
@ -0,0 +1,28 @@
|
||||
// Tests creating, assigning and calling pointers to non-args no-return functions
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
void()* f;
|
||||
|
||||
byte i = 0;
|
||||
while(true) {
|
||||
++i;
|
||||
if((i&1)==0) {
|
||||
f = &fn1;
|
||||
} else {
|
||||
f = &fn2;
|
||||
}
|
||||
(*f)();
|
||||
}
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
26
src/test/kc/function-pointer-noarg-call-3.kc
Normal file
26
src/test/kc/function-pointer-noarg-call-3.kc
Normal file
@ -0,0 +1,26 @@
|
||||
// Tests creating, assigning returning and calling pointers to non-args no-return functions
|
||||
|
||||
void main() {
|
||||
byte i = 0;
|
||||
while(true) {
|
||||
*(getfn(++i))();
|
||||
}
|
||||
}
|
||||
|
||||
void()* getfn(byte b) {
|
||||
if((b&1)==0) {
|
||||
return &fn1;
|
||||
} else {
|
||||
return &fn2;
|
||||
}
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
18
src/test/kc/function-pointer-noarg-call-4.kc
Normal file
18
src/test/kc/function-pointer-noarg-call-4.kc
Normal file
@ -0,0 +1,18 @@
|
||||
// Tests creating, assigning returning and calling pointers to non-args no-return functions
|
||||
|
||||
void main() {
|
||||
byte i = 0;
|
||||
while(true) {
|
||||
*(getfn(++i))();
|
||||
}
|
||||
}
|
||||
|
||||
void()* getfn(byte b) {
|
||||
return &fn1;
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
23
src/test/kc/function-pointer-noarg-call-5.kc
Normal file
23
src/test/kc/function-pointer-noarg-call-5.kc
Normal file
@ -0,0 +1,23 @@
|
||||
// Tests calling into arrays of pointers to non-args no-return functions
|
||||
|
||||
|
||||
void()*[2] fns = { &fn1, &fn2};
|
||||
|
||||
void main() {
|
||||
byte i = 0;
|
||||
while(true) {
|
||||
void()* f = fns[(++i&1)<<1];
|
||||
(*f)();
|
||||
}
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
||||
|
16
src/test/kc/function-pointer-noarg-call-6.kc
Normal file
16
src/test/kc/function-pointer-noarg-call-6.kc
Normal file
@ -0,0 +1,16 @@
|
||||
// Tests calling into a function pointer with local variables
|
||||
|
||||
void main() {
|
||||
void()* cls = &fn1;
|
||||
for(byte* cols = $d800; cols<$d800+1000;cols++) {
|
||||
(*cls)();
|
||||
(*cols)++;
|
||||
}
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
for(byte* screen=$400;screen<$400+1000;screen++)
|
||||
(*screen)++;
|
||||
}
|
||||
|
||||
|
26
src/test/kc/function-pointer-noarg-call-7.kc
Normal file
26
src/test/kc/function-pointer-noarg-call-7.kc
Normal file
@ -0,0 +1,26 @@
|
||||
// Tests calling into a function pointer with local variables
|
||||
|
||||
|
||||
void main() {
|
||||
void()* f = &hello;
|
||||
do10(f);
|
||||
}
|
||||
|
||||
void do10(void()* fn) {
|
||||
for( byte i: 0..9)
|
||||
(*fn)();
|
||||
}
|
||||
|
||||
const byte* SCREEN = $0400;
|
||||
const byte[] msg = "hello @";
|
||||
|
||||
volatile byte idx = 0;
|
||||
|
||||
void hello() {
|
||||
byte i=0;
|
||||
do {
|
||||
SCREEN[idx++] = msg[i++];
|
||||
} while(msg[i]!='@');
|
||||
}
|
||||
|
||||
|
31
src/test/kc/function-pointer-noarg-call-8.kc
Normal file
31
src/test/kc/function-pointer-noarg-call-8.kc
Normal file
@ -0,0 +1,31 @@
|
||||
// Tests calling into a function pointer with local variables
|
||||
|
||||
|
||||
void main() {
|
||||
void()* f = &hello;
|
||||
msg = msg1;
|
||||
do10(f);
|
||||
msg = msg2;
|
||||
do10(f);
|
||||
}
|
||||
|
||||
void do10(void()* fn) {
|
||||
for( byte i: 0..9)
|
||||
(*fn)();
|
||||
}
|
||||
|
||||
const byte* SCREEN = $0400;
|
||||
|
||||
const byte[] msg1 = "hello @";
|
||||
const byte[] msg2 = "world @";
|
||||
volatile byte* msg;
|
||||
volatile byte idx = 0;
|
||||
|
||||
void hello() {
|
||||
byte i=0;
|
||||
do {
|
||||
SCREEN[idx++] = msg[i++];
|
||||
} while(msg[i]!='@');
|
||||
}
|
||||
|
||||
|
19
src/test/kc/function-pointer-noarg-call-9.kc
Normal file
19
src/test/kc/function-pointer-noarg-call-9.kc
Normal file
@ -0,0 +1,19 @@
|
||||
// Tests calling into a function pointer which modifies global volatile
|
||||
|
||||
const byte* SCREEN = $0400;
|
||||
|
||||
volatile byte idx = 0;
|
||||
|
||||
void main() {
|
||||
void()* f = &fn1;
|
||||
(*f)();
|
||||
SCREEN[idx] = 'a';
|
||||
(*f)();
|
||||
SCREEN[idx] = 'a';
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
idx++;
|
||||
}
|
||||
|
||||
|
11
src/test/kc/function-pointer-noarg-call.kc
Normal file
11
src/test/kc/function-pointer-noarg-call.kc
Normal file
@ -0,0 +1,11 @@
|
||||
// Tests creating, assigning and calling pointers to non-args no-return functions
|
||||
|
||||
void main() {
|
||||
void()* f = &fn1;
|
||||
(*f)();
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
24
src/test/kc/function-pointer-noarg.kc
Normal file
24
src/test/kc/function-pointer-noarg.kc
Normal file
@ -0,0 +1,24 @@
|
||||
// Tests creating pointers to non-args no-return functions
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
void()* f;
|
||||
f = &fn1;
|
||||
SCREEN[0] = <(word)f;
|
||||
SCREEN[1] = >(word)f;
|
||||
f = &fn2;
|
||||
SCREEN[2] = <(word)f;
|
||||
SCREEN[3] = >(word)f;
|
||||
|
||||
}
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
30
src/test/kc/function-pointer-return.kc
Normal file
30
src/test/kc/function-pointer-return.kc
Normal file
@ -0,0 +1,30 @@
|
||||
// Tests creating and assigning pointers to non-args return with function value
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
byte()* f;
|
||||
|
||||
byte i = 0;
|
||||
while(true) {
|
||||
++i;
|
||||
if((i&1)==0) {
|
||||
f = &fn1;
|
||||
} else {
|
||||
f = &fn2;
|
||||
}
|
||||
SCREEN[0] = (byte)f;
|
||||
}
|
||||
}
|
||||
|
||||
byte fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
return *BORDERCOL;
|
||||
}
|
||||
|
||||
byte fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
return *BGCOL;
|
||||
}
|
4
src/test/kc/illegal-unnamed-parameter.kc
Normal file
4
src/test/kc/illegal-unnamed-parameter.kc
Normal file
@ -0,0 +1,4 @@
|
||||
// Tests that the compiler complains if a non-void parameter has no name
|
||||
|
||||
void main(char) {
|
||||
}
|
4
src/test/kc/illegal-void-parameter.kc
Normal file
4
src/test/kc/illegal-void-parameter.kc
Normal file
@ -0,0 +1,4 @@
|
||||
// Tests that the compiler complains if a non-void parameter has no name
|
||||
|
||||
void main(char c, void) {
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
byte* SCREEN = $0400;
|
||||
|
||||
byte char = 'a';
|
||||
byte ch = 'a';
|
||||
byte num = 1;
|
||||
byte[] str = "bc"+"d"+'e';
|
||||
byte[] nums = { 2, 3, 4, 5};
|
||||
|
||||
void main() {
|
||||
SCREEN[0] = char;
|
||||
SCREEN[0] = ch;
|
||||
SCREEN[2] = num;
|
||||
for(byte i : 0..3) {
|
||||
SCREEN[4+i] = str[i];
|
||||
|
@ -74,12 +74,12 @@ interrupt(kernel_min) void plex_irq() {
|
||||
// The raster loop
|
||||
void loop() {
|
||||
// The current index into the y-sinus
|
||||
volatile byte sin_idx = 0; // without volatile gives wrong asm
|
||||
byte sin_idx = 0;
|
||||
while(true) {
|
||||
while(!framedone) { }
|
||||
*BORDERCOL = RED;
|
||||
// Assign sinus positions
|
||||
volatile byte y_idx = sin_idx; // without volatile gives wrong asm
|
||||
byte y_idx = sin_idx;
|
||||
for(byte sy: 0..PLEX_COUNT-1) {
|
||||
PLEX_YPOS[sy] = YSIN[y_idx];
|
||||
y_idx += 8;
|
||||
|
14
src/test/kc/plus-0.kc
Normal file
14
src/test/kc/plus-0.kc
Normal file
@ -0,0 +1,14 @@
|
||||
// Tests elimination of plus 0
|
||||
|
||||
void main() {
|
||||
fill((byte*)$400,'a');
|
||||
fill((byte*)$2000,'b');
|
||||
}
|
||||
|
||||
void fill(byte* screen, byte ch) {
|
||||
for(byte i: 0..39) {
|
||||
inline for( byte j: 0..2 ) {
|
||||
(screen+j*40)[i] = ch;
|
||||
}
|
||||
}
|
||||
}
|
11
src/test/kc/pointer-pointer-1.kc
Normal file
11
src/test/kc/pointer-pointer-1.kc
Normal file
@ -0,0 +1,11 @@
|
||||
// Tests a simple pointer to a pointer
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
|
||||
byte b = 'a';
|
||||
byte* pb = &b;
|
||||
byte** ppb = &pb;
|
||||
*SCREEN = **ppb;
|
||||
|
||||
}
|
30
src/test/kc/pointer-pointer-2.kc
Normal file
30
src/test/kc/pointer-pointer-2.kc
Normal file
@ -0,0 +1,30 @@
|
||||
// Tests pointer to pointer in a more complex setup
|
||||
|
||||
void main() {
|
||||
|
||||
byte* screen = $400;
|
||||
|
||||
byte* text;
|
||||
for(byte i: 0..20) {
|
||||
nexttext(&text);
|
||||
while(*text!='@') {
|
||||
*screen++ = *text++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
byte[] text1 = "camelot @";
|
||||
byte[] text2 = "rex @";
|
||||
|
||||
byte textid = 0;
|
||||
|
||||
// Choose the next text to show - by updating the text pointer pointed to by the passed pointer to a pointer
|
||||
void nexttext(byte** textp) {
|
||||
if((textid++&1)==0) {
|
||||
*textp = text1;
|
||||
} else {
|
||||
*textp = text2;
|
||||
}
|
||||
}
|
||||
|
18
src/test/kc/pointer-pointer-3.kc
Normal file
18
src/test/kc/pointer-pointer-3.kc
Normal file
@ -0,0 +1,18 @@
|
||||
// Tests pointer to pointer in a more complex setup
|
||||
|
||||
|
||||
byte* screen = $400;
|
||||
|
||||
byte* screen1 = $400;
|
||||
byte* screen2 = $400+40;
|
||||
|
||||
void main() {
|
||||
setscreen(&screen, screen1);
|
||||
screen[0] = 'a';
|
||||
setscreen(&screen, screen2);
|
||||
screen[0] = 'a';
|
||||
}
|
||||
|
||||
void setscreen(byte** screen, byte* val) {
|
||||
*screen = val;
|
||||
}
|
@ -1,19 +1,19 @@
|
||||
byte* SCREEN= $400;
|
||||
byte line = $40;
|
||||
byte char = line;
|
||||
byte ch = line;
|
||||
|
||||
void main() {
|
||||
ln();
|
||||
char++;
|
||||
ch++;
|
||||
ln();
|
||||
char++;
|
||||
ch++;
|
||||
ln();
|
||||
*SCREEN = char;
|
||||
*SCREEN = ch;
|
||||
}
|
||||
|
||||
void ln() {
|
||||
line = line + $2;
|
||||
char = line;
|
||||
ch = line;
|
||||
}
|
||||
|
||||
|
||||
|
8
src/test/kc/ternary-1.kc
Normal file
8
src/test/kc/ternary-1.kc
Normal file
@ -0,0 +1,8 @@
|
||||
// Tests the ternary operator
|
||||
|
||||
void main() {
|
||||
const byte* SCREEN = $400;
|
||||
for( byte i: 0..9) {
|
||||
SCREEN[i] = i<5?'a':'b';
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user