mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-17 10:30:43 +00:00
Merged with master.
This commit is contained in:
commit
15acdc3752
1
.idea/encodings.xml
generated
1
.idea/encodings.xml
generated
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$" charset="UTF-8" />
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
@ -5,10 +5,10 @@ facebook, or any other method with the owner of this repository before making a
|
||||
|
||||
## 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`
|
||||
|
||||
|
||||
|
||||
|
2
pom.xml
2
pom.xml
@ -82,6 +82,8 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<parallel>all</parallel>
|
||||
<threadCount>5</threadCount>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
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
|
4
src/main/fragment/_deref_pwsc1=vwsc2.asm
Normal file
4
src/main/fragment/_deref_pwsc1=vwsc2.asm
Normal file
@ -0,0 +1,4 @@
|
||||
lda #<{c2}
|
||||
sta {c1}
|
||||
lda #>{c2}
|
||||
sta {c1}+1
|
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;
|
||||
}
|
||||
|
@ -250,6 +250,7 @@ public class Compiler {
|
||||
optimizations.add(new Pass2EliminateUnusedBlocks(program));
|
||||
optimizations.add(new Pass2RangeResolving(program));
|
||||
optimizations.add(new Pass2ComparisonOptimization(program));
|
||||
optimizations.add(new Pass2ConstantCallPointerIdentification(program));
|
||||
pass2Execute(optimizations);
|
||||
}
|
||||
|
||||
@ -485,6 +486,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);
|
||||
|
@ -11,9 +11,15 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
* Contains matching groups (parenthesis) that are used in sigReplace to build the signature of the sub-fragment to synthesize from. */
|
||||
final String sigMatch;
|
||||
|
||||
/** Compiled regex for sigMatch */
|
||||
Pattern sigMatchPattern = null;
|
||||
|
||||
/** Regular expression that limits which fragments the synthesize rule can handle. */
|
||||
final String sigAvoid;
|
||||
|
||||
/** Compiled regex for sigAvoid */
|
||||
Pattern sigAvoidPattern = null;
|
||||
|
||||
/** ASM code prefixed to the sub-fragment when synthesizing. */
|
||||
final private String asmPrefix;
|
||||
|
||||
@ -62,7 +68,20 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
* @return true if the rule matches the signature
|
||||
*/
|
||||
public boolean matches(String signature) {
|
||||
return signature.matches(sigMatch) && (sigAvoid == null || !signature.matches(sigAvoid));
|
||||
if (sigMatchPattern == null)
|
||||
sigMatchPattern = Pattern.compile(sigMatch);
|
||||
Matcher m = sigMatchPattern.matcher(signature);
|
||||
if (m.matches()) {
|
||||
if (sigAvoid == null)
|
||||
return true;
|
||||
else {
|
||||
if (sigAvoidPattern == null)
|
||||
sigAvoidPattern = Pattern.compile(sigAvoid);
|
||||
Matcher ma = sigAvoidPattern.matcher(signature);
|
||||
return !ma.matches();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,12 +106,12 @@ class AsmFragmentTemplateSynthesisRule {
|
||||
}
|
||||
|
||||
public AsmFragmentTemplate synthesize(String signature, AsmFragmentTemplate subTemplate) {
|
||||
if(!matches(signature)) {
|
||||
throw new RuntimeException("Synthesis error! Attempting to synthesize on non-matching signature signature:"+signature+" match:"+sigMatch+" avoid:"+sigAvoid);
|
||||
}
|
||||
if(!subTemplate.getSignature().equals(getSubSignature(signature))) {
|
||||
throw new RuntimeException("Synthesis error! Attempting to synthesize on non-matching sub template sub-signature:"+subTemplate.getSignature()+" expecting:"+getSubSignature(signature));
|
||||
}
|
||||
// if(!matches(signature)) {
|
||||
// throw new RuntimeException("Synthesis error! Attempting to synthesize on non-matching signature signature:"+signature+" match:"+sigMatch+" avoid:"+sigAvoid);
|
||||
// }
|
||||
// if(!subTemplate.getSignature().equals(getSubSignature(signature))) {
|
||||
// throw new RuntimeException("Synthesis error! Attempting to synthesize on non-matching sub template sub-signature:"+subTemplate.getSignature()+" expecting:"+getSubSignature(signature));
|
||||
// }
|
||||
if(subDontClobber!=null) {
|
||||
if(subDontClobber.contains("aa") && subTemplate.getClobber().isClobberA()) return null;
|
||||
if(subDontClobber.contains("xx") && subTemplate.getClobber().isClobberX()) return null;
|
||||
@ -425,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;
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ public class ControlFlowBlock {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = label.hashCode();
|
||||
result = 31 * result + (statements != null ? statements.hashCode() : 0);
|
||||
result = 31 * result + statements.size();
|
||||
result = 31 * result + (defaultSuccessor != null ? defaultSuccessor.hashCode() : 0);
|
||||
result = 31 * result + (conditionalSuccessor != null ? conditionalSuccessor.hashCode() : 0);
|
||||
result = 31 * result + (callSuccessor != null ? callSuccessor.hashCode() : 0);
|
||||
|
@ -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);
|
||||
}
|
||||
if(value instanceof ConstantPointer) {
|
||||
return new ConstantPointer(((ConstantPointer) value).getLocation(), elementType);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -13,12 +13,21 @@ public class Label implements Symbol {
|
||||
/** The containing scope */
|
||||
private Scope scope;
|
||||
|
||||
/** Full name of label (scope::name or name) */
|
||||
private String fullName;
|
||||
|
||||
private boolean intermediate;
|
||||
|
||||
public Label(String name, Scope scope, boolean intermediate) {
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
this.intermediate = intermediate;
|
||||
setFullName();
|
||||
}
|
||||
|
||||
private void setFullName() {
|
||||
String scopeName = (scope == null) ? "" : scope.getFullName();
|
||||
fullName = (scopeName.length() > 0) ? scopeName + "::" + name : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -47,7 +56,7 @@ public class Label implements Symbol {
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return Scope.getFullName(this);
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public boolean isIntermediate() {
|
||||
|
@ -20,27 +20,25 @@ public abstract class Scope implements Symbol {
|
||||
private int intermediateLabelCount = 1;
|
||||
private int blockCount = 1;
|
||||
private Scope parentScope;
|
||||
private String fullName;
|
||||
|
||||
public Scope(String name, Scope parentScope) {
|
||||
this.name = name;
|
||||
this.parentScope = parentScope;
|
||||
this.symbols = new LinkedHashMap<>();
|
||||
setFullName();
|
||||
}
|
||||
|
||||
public Scope() {
|
||||
this.name = "";
|
||||
this.parentScope = null;
|
||||
this.symbols = new LinkedHashMap<>();
|
||||
setFullName();
|
||||
}
|
||||
|
||||
public static String getFullName(Symbol symbol) {
|
||||
if(symbol.getScope() != null) {
|
||||
String scopeName = symbol.getScope().getFullName();
|
||||
if(scopeName.length() > 0) {
|
||||
return scopeName + "::" + symbol.getLocalName();
|
||||
}
|
||||
}
|
||||
return symbol.getLocalName();
|
||||
private void setFullName() {
|
||||
String scopeName = (parentScope == null) ? "" : parentScope.getFullName();
|
||||
fullName = (scopeName.length() > 0) ? scopeName + "::" + name : name;
|
||||
}
|
||||
|
||||
public HashMap<String, Symbol> getSymbols() {
|
||||
@ -54,7 +52,7 @@ public abstract class Scope implements Symbol {
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return getFullName(this);
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public ScopeRef getRef() {
|
||||
@ -69,6 +67,7 @@ public abstract class Scope implements Symbol {
|
||||
@Override
|
||||
public void setScope(Scope scope) {
|
||||
this.parentScope = scope;
|
||||
setFullName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -241,6 +240,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);
|
||||
|
@ -41,12 +41,21 @@ public abstract class SymbolVariable implements Symbol {
|
||||
/** Comments preceding the procedure in the source code. */
|
||||
private List<Comment> comments;
|
||||
|
||||
/** Full name of variable (scope::name or name) */
|
||||
private String fullName;
|
||||
|
||||
public SymbolVariable(String name, Scope scope, SymbolType type) {
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
this.type = type;
|
||||
this.inferredType = false;
|
||||
this.comments = new ArrayList<>();
|
||||
setFullName();
|
||||
}
|
||||
|
||||
private void setFullName() {
|
||||
String scopeName = (scope == null) ? "" : scope.getFullName();
|
||||
fullName = (scopeName.length() > 0) ? scopeName + "::" + name : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -56,7 +65,7 @@ public abstract class SymbolVariable implements Symbol {
|
||||
|
||||
@Override
|
||||
public String getFullName() {
|
||||
return Scope.getFullName(this);
|
||||
return this.fullName;
|
||||
}
|
||||
|
||||
public SymbolType getType() {
|
||||
@ -86,6 +95,7 @@ public abstract class SymbolVariable implements Symbol {
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
setFullName();
|
||||
}
|
||||
|
||||
public String getAsmName() {
|
||||
@ -102,6 +112,7 @@ public abstract class SymbolVariable implements Symbol {
|
||||
|
||||
public void setScope(Scope scope) {
|
||||
this.scope = scope;
|
||||
setFullName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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,8 +196,8 @@ MNEMONIC:
|
||||
|
||||
|
||||
KICKASM: '{{' .*? '}}';
|
||||
SIMPLETYPE: 'byte' | 'word' | 'dword' | 'bool' | 'void' ;
|
||||
STRING : '"' ('\\"' | ~'"')* '"';
|
||||
SIMPLETYPE: 'byte' | 'word' | 'dword' | 'bool' | 'char' | 'short' | 'int' | 'long' | 'void' ;
|
||||
STRING : '"' ('\\"' | ~'"')* '"' 'z'?;
|
||||
CHAR : '\'' ('\\\'' | ~'\'' ) '\'';
|
||||
BOOLEAN : 'true' | 'false';
|
||||
NUMBER : NUMFLOAT | NUMINT ;
|
||||
|
@ -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_\u03bb\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,339 @@ 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"+
|
||||
"`\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\5N\u030a\nN\3O\3O\3O\3O\5O\u0310\nO\3O\3O\3P\3P\3P\3P\3P\3"+
|
||||
"P\3P\3P\3P\5P\u031d\nP\3Q\3Q\5Q\u0321\nQ\3R\3R\3R\5R\u0326\nR\3S\3S\3"+
|
||||
"S\3S\3S\5S\u032d\nS\3S\7S\u0330\nS\fS\16S\u0333\13S\3S\3S\6S\u0337\nS"+
|
||||
"\rS\16S\u0338\3T\7T\u033c\nT\fT\16T\u033f\13T\3T\3T\6T\u0343\nT\rT\16"+
|
||||
"T\u0344\3U\3U\3U\3U\3U\5U\u034c\nU\3U\7U\u034f\nU\fU\16U\u0352\13U\3U"+
|
||||
"\3U\6U\u0356\nU\rU\16U\u0357\3V\3V\3V\5V\u035d\nV\3W\3W\3W\6W\u0362\n"+
|
||||
"W\rW\16W\u0363\3W\3W\6W\u0368\nW\rW\16W\u0369\5W\u036c\nW\3X\6X\u036f"+
|
||||
"\nX\rX\16X\u0370\3Y\3Y\3Y\3Y\3Y\5Y\u0378\nY\3Y\6Y\u037b\nY\rY\16Y\u037c"+
|
||||
"\3Z\3Z\3[\3[\3\\\3\\\3]\3]\7]\u0387\n]\f]\16]\u038a\13]\3^\3^\3_\3_\3"+
|
||||
"`\3`\7`\u0392\n`\f`\16`\u0395\13`\3`\6`\u0398\n`\r`\16`\u0399\3a\6a\u039d"+
|
||||
"\na\ra\16a\u039e\3a\3a\3b\3b\3b\3b\7b\u03a7\nb\fb\16b\u03aa\13b\3b\3b"+
|
||||
"\3c\3c\3c\3c\7c\u03b2\nc\fc\16c\u03b5\13c\3c\3c\3c\3c\3c\4\u02d1\u03b3"+
|
||||
"\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\67"+
|
||||
"m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008d"+
|
||||
"H\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1"+
|
||||
"R\u00a3S\u00a5T\u00a7U\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\u0428\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\2"+
|
||||
"I\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_\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\2"+
|
||||
"o\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";
|
||||
"\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\u030b\3\2\2\2\u009f\u031c\3\2\2\2\u00a1\u0320\3\2\2\2\u00a3"+
|
||||
"\u0325\3\2\2\2\u00a5\u032c\3\2\2\2\u00a7\u033d\3\2\2\2\u00a9\u034b\3\2"+
|
||||
"\2\2\u00ab\u035c\3\2\2\2\u00ad\u036b\3\2\2\2\u00af\u036e\3\2\2\2\u00b1"+
|
||||
"\u0377\3\2\2\2\u00b3\u037e\3\2\2\2\u00b5\u0380\3\2\2\2\u00b7\u0382\3\2"+
|
||||
"\2\2\u00b9\u0384\3\2\2\2\u00bb\u038b\3\2\2\2\u00bd\u038d\3\2\2\2\u00bf"+
|
||||
"\u038f\3\2\2\2\u00c1\u039c\3\2\2\2\u00c3\u03a2\3\2\2\2\u00c5\u03ad\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\7"+
|
||||
"c\2\2\u00ea\u00eb\7n\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\7p\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\7"+
|
||||
"q\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\7"+
|
||||
"u\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\u0309\7$\2\2\u0308\u030a\7|\2\2\u0309\u0308\3\2\2"+
|
||||
"\2\u0309\u030a\3\2\2\2\u030a\u009c\3\2\2\2\u030b\u030f\7)\2\2\u030c\u030d"+
|
||||
"\7^\2\2\u030d\u0310\7)\2\2\u030e\u0310\n\3\2\2\u030f\u030c\3\2\2\2\u030f"+
|
||||
"\u030e\3\2\2\2\u0310\u0311\3\2\2\2\u0311\u0312\7)\2\2\u0312\u009e\3\2"+
|
||||
"\2\2\u0313\u0314\7v\2\2\u0314\u0315\7t\2\2\u0315\u0316\7w\2\2\u0316\u031d"+
|
||||
"\7g\2\2\u0317\u0318\7h\2\2\u0318\u0319\7c\2\2\u0319\u031a\7n\2\2\u031a"+
|
||||
"\u031b\7u\2\2\u031b\u031d\7g\2\2\u031c\u0313\3\2\2\2\u031c\u0317\3\2\2"+
|
||||
"\2\u031d\u00a0\3\2\2\2\u031e\u0321\5\u00a3R\2\u031f\u0321\5\u00abV\2\u0320"+
|
||||
"\u031e\3\2\2\2\u0320\u031f\3\2\2\2\u0321\u00a2\3\2\2\2\u0322\u0326\5\u00a5"+
|
||||
"S\2\u0323\u0326\5\u00a7T\2\u0324\u0326\5\u00a9U\2\u0325\u0322\3\2\2\2"+
|
||||
"\u0325\u0323\3\2\2\2\u0325\u0324\3\2\2\2\u0326\u00a4\3\2\2\2\u0327\u032d"+
|
||||
"\7\'\2\2\u0328\u0329\7\62\2\2\u0329\u032d\7d\2\2\u032a\u032b\7\62\2\2"+
|
||||
"\u032b\u032d\7D\2\2\u032c\u0327\3\2\2\2\u032c\u0328\3\2\2\2\u032c\u032a"+
|
||||
"\3\2\2\2\u032d\u0331\3\2\2\2\u032e\u0330\5\u00b3Z\2\u032f\u032e\3\2\2"+
|
||||
"\2\u0330\u0333\3\2\2\2\u0331\u032f\3\2\2\2\u0331\u0332\3\2\2\2\u0332\u0334"+
|
||||
"\3\2\2\2\u0333\u0331\3\2\2\2\u0334\u0336\7\60\2\2\u0335\u0337\5\u00b3"+
|
||||
"Z\2\u0336\u0335\3\2\2\2\u0337\u0338\3\2\2\2\u0338\u0336\3\2\2\2\u0338"+
|
||||
"\u0339\3\2\2\2\u0339\u00a6\3\2\2\2\u033a\u033c\5\u00b5[\2\u033b\u033a"+
|
||||
"\3\2\2\2\u033c\u033f\3\2\2\2\u033d\u033b\3\2\2\2\u033d\u033e\3\2\2\2\u033e"+
|
||||
"\u0340\3\2\2\2\u033f\u033d\3\2\2\2\u0340\u0342\7\60\2\2\u0341\u0343\5"+
|
||||
"\u00b5[\2\u0342\u0341\3\2\2\2\u0343\u0344\3\2\2\2\u0344\u0342\3\2\2\2"+
|
||||
"\u0344\u0345\3\2\2\2\u0345\u00a8\3\2\2\2\u0346\u034c\7&\2\2\u0347\u0348"+
|
||||
"\7\62\2\2\u0348\u034c\7z\2\2\u0349\u034a\7\62\2\2\u034a\u034c\7Z\2\2\u034b"+
|
||||
"\u0346\3\2\2\2\u034b\u0347\3\2\2\2\u034b\u0349\3\2\2\2\u034c\u0350\3\2"+
|
||||
"\2\2\u034d\u034f\5\u00b7\\\2\u034e\u034d\3\2\2\2\u034f\u0352\3\2\2\2\u0350"+
|
||||
"\u034e\3\2\2\2\u0350\u0351\3\2\2\2\u0351\u0353\3\2\2\2\u0352\u0350\3\2"+
|
||||
"\2\2\u0353\u0355\7\60\2\2\u0354\u0356\5\u00b7\\\2\u0355\u0354\3\2\2\2"+
|
||||
"\u0356\u0357\3\2\2\2\u0357\u0355\3\2\2\2\u0357\u0358\3\2\2\2\u0358\u00aa"+
|
||||
"\3\2\2\2\u0359\u035d\5\u00afX\2\u035a\u035d\5\u00b1Y\2\u035b\u035d\5\u00ad"+
|
||||
"W\2\u035c\u0359\3\2\2\2\u035c\u035a\3\2\2\2\u035c\u035b\3\2\2\2\u035d"+
|
||||
"\u00ac\3\2\2\2\u035e\u035f\7\62\2\2\u035f\u0361\t\4\2\2\u0360\u0362\5"+
|
||||
"\u00b3Z\2\u0361\u0360\3\2\2\2\u0362\u0363\3\2\2\2\u0363\u0361\3\2\2\2"+
|
||||
"\u0363\u0364\3\2\2\2\u0364\u036c\3\2\2\2\u0365\u0367\7\'\2\2\u0366\u0368"+
|
||||
"\5\u00b3Z\2\u0367\u0366\3\2\2\2\u0368\u0369\3\2\2\2\u0369\u0367\3\2\2"+
|
||||
"\2\u0369\u036a\3\2\2\2\u036a\u036c\3\2\2\2\u036b\u035e\3\2\2\2\u036b\u0365"+
|
||||
"\3\2\2\2\u036c\u00ae\3\2\2\2\u036d\u036f\5\u00b5[\2\u036e\u036d\3\2\2"+
|
||||
"\2\u036f\u0370\3\2\2\2\u0370\u036e\3\2\2\2\u0370\u0371\3\2\2\2\u0371\u00b0"+
|
||||
"\3\2\2\2\u0372\u0378\7&\2\2\u0373\u0374\7\62\2\2\u0374\u0378\7z\2\2\u0375"+
|
||||
"\u0376\7\62\2\2\u0376\u0378\7Z\2\2\u0377\u0372\3\2\2\2\u0377\u0373\3\2"+
|
||||
"\2\2\u0377\u0375\3\2\2\2\u0378\u037a\3\2\2\2\u0379\u037b\5\u00b7\\\2\u037a"+
|
||||
"\u0379\3\2\2\2\u037b\u037c\3\2\2\2\u037c\u037a\3\2\2\2\u037c\u037d\3\2"+
|
||||
"\2\2\u037d\u00b2\3\2\2\2\u037e\u037f\t\5\2\2\u037f\u00b4\3\2\2\2\u0380"+
|
||||
"\u0381\t\6\2\2\u0381\u00b6\3\2\2\2\u0382\u0383\t\7\2\2\u0383\u00b8\3\2"+
|
||||
"\2\2\u0384\u0388\5\u00bb^\2\u0385\u0387\5\u00bd_\2\u0386\u0385\3\2\2\2"+
|
||||
"\u0387\u038a\3\2\2\2\u0388\u0386\3\2\2\2\u0388\u0389\3\2\2\2\u0389\u00ba"+
|
||||
"\3\2\2\2\u038a\u0388\3\2\2\2\u038b\u038c\t\b\2\2\u038c\u00bc\3\2\2\2\u038d"+
|
||||
"\u038e\t\t\2\2\u038e\u00be\3\2\2\2\u038f\u0393\7#\2\2\u0390\u0392\5\u00bd"+
|
||||
"_\2\u0391\u0390\3\2\2\2\u0392\u0395\3\2\2\2\u0393\u0391\3\2\2\2\u0393"+
|
||||
"\u0394\3\2\2\2\u0394\u0397\3\2\2\2\u0395\u0393\3\2\2\2\u0396\u0398\t\n"+
|
||||
"\2\2\u0397\u0396\3\2\2\2\u0398\u0399\3\2\2\2\u0399\u0397\3\2\2\2\u0399"+
|
||||
"\u039a\3\2\2\2\u039a\u00c0\3\2\2\2\u039b\u039d\t\13\2\2\u039c\u039b\3"+
|
||||
"\2\2\2\u039d\u039e\3\2\2\2\u039e\u039c\3\2\2\2\u039e\u039f\3\2\2\2\u039f"+
|
||||
"\u03a0\3\2\2\2\u03a0\u03a1\ba\2\2\u03a1\u00c2\3\2\2\2\u03a2\u03a3\7\61"+
|
||||
"\2\2\u03a3\u03a4\7\61\2\2\u03a4\u03a8\3\2\2\2\u03a5\u03a7\n\f\2\2\u03a6"+
|
||||
"\u03a5\3\2\2\2\u03a7\u03aa\3\2\2\2\u03a8\u03a6\3\2\2\2\u03a8\u03a9\3\2"+
|
||||
"\2\2\u03a9\u03ab\3\2\2\2\u03aa\u03a8\3\2\2\2\u03ab\u03ac\bb\3\2\u03ac"+
|
||||
"\u00c4\3\2\2\2\u03ad\u03ae\7\61\2\2\u03ae\u03af\7,\2\2\u03af\u03b3\3\2"+
|
||||
"\2\2\u03b0\u03b2\13\2\2\2\u03b1\u03b0\3\2\2\2\u03b2\u03b5\3\2\2\2\u03b3"+
|
||||
"\u03b4\3\2\2\2\u03b3\u03b1\3\2\2\2\u03b4\u03b6\3\2\2\2\u03b5\u03b3\3\2"+
|
||||
"\2\2\u03b6\u03b7\7,\2\2\u03b7\u03b8\7\61\2\2\u03b8\u03b9\3\2\2\2\u03b9"+
|
||||
"\u03ba\bc\3\2\u03ba\u00c6\3\2\2\2\"\2\u02c9\u02d1\u02fc\u0302\u0304\u0309"+
|
||||
"\u030f\u031c\u0320\u0325\u032c\u0331\u0338\u033d\u0344\u034b\u0350\u0357"+
|
||||
"\u035c\u0363\u0369\u036b\u0370\u0377\u037c\u0388\u0393\u0399\u039e\u03a8"+
|
||||
"\u03b3\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;
|
||||
}
|
||||
|
||||
@ -1162,7 +1189,13 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
@Override
|
||||
public RValue visitExprString(KickCParser.ExprStringContext ctx) {
|
||||
String text = ctx.getText();
|
||||
return new ConstantString(text.substring(1, text.length() - 1));
|
||||
String stringValue;
|
||||
if(text.endsWith("z")) {
|
||||
stringValue = text.substring(1, text.length() - 2);
|
||||
} else {
|
||||
stringValue = text.substring(1, text.length() - 1)+"@";
|
||||
}
|
||||
return new ConstantString(stringValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1207,6 +1240,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,16 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
||||
|
||||
ControlFlowBlock conditionalDestBlock = getGraph().getBlock(conditional.getDestination());
|
||||
if(conditionalDestBlock.hasPhiBlock()) {
|
||||
throw new RuntimeException("TODO: Fix phi-values inside the conditional destination phi-block!");
|
||||
StatementPhiBlock conditionalDestPhiBlock = conditionalDestBlock.getPhiBlock();
|
||||
for(StatementPhiBlock.PhiVariable phiVariable : conditionalDestPhiBlock.getPhiVariables()) {
|
||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
if(phiRValue.getPredecessor().equals(block.getLabel())) {
|
||||
// Found phi-variable with current block as predecessor - copy the phivalue for the new block
|
||||
phiVariable.setrValue(newBlockLabel.getRef(), phiRValue.getrValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 ");
|
||||
}
|
||||
|
||||
}
|
@ -40,9 +40,13 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
if(currentLabel != null) {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) line;
|
||||
AsmInstructionType jmpType = AsmInstructionSet.getInstructionType("jmp", AsmAddressingMode.ABS, false);
|
||||
AsmInstructionType rtsType = AsmInstructionSet.getInstructionType("rts", AsmAddressingMode.NON, false);
|
||||
if(asmInstruction.getType().equals(jmpType)) {
|
||||
immediateJumps.put(currentScope + "::" + currentLabel, asmInstruction.getParameter());
|
||||
}
|
||||
if(asmInstruction.getType().equals(rtsType)) {
|
||||
immediateJumps.put(currentScope + "::" + currentLabel, "rts");
|
||||
}
|
||||
}
|
||||
currentLabel = null;
|
||||
} else {
|
||||
@ -62,7 +66,12 @@ public class Pass5DoubleJumpElimination extends Pass5AsmOptimization {
|
||||
AsmInstruction asmInstruction = (AsmInstruction) line;
|
||||
if(asmInstruction.getType().isJump()) {
|
||||
String immediateJmpTarget = immediateJumps.get(currentScope + "::" + asmInstruction.getParameter());
|
||||
if(immediateJmpTarget != null && !immediateJmpTarget.equals(asmInstruction.getParameter())) {
|
||||
if(immediateJmpTarget == "rts" && asmInstruction.getType().getMnemnonic() == "jmp") {
|
||||
getLog().append("Replacing jump to rts with rts in " + asmInstruction.toString());
|
||||
AsmInstructionType rtsType = AsmInstructionSet.getInstructionType("rts", AsmAddressingMode.NON, false);
|
||||
asmInstruction.setType(rtsType);
|
||||
optimized = true;
|
||||
} else if(immediateJmpTarget != null && immediateJmpTarget != "rts" && !immediateJmpTarget.equals(asmInstruction.getParameter())) {
|
||||
getLog().append("Skipping double jump to " + immediateJmpTarget + " in " + asmInstruction.toString());
|
||||
asmInstruction.setParameter(immediateJmpTarget);
|
||||
optimized = true;
|
||||
|
@ -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.*;
|
||||
|
||||
@ -23,6 +20,9 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
|
||||
super(program);
|
||||
}
|
||||
|
||||
private LinkedHashMap<LabelRef, Collection<VariableRef>> blockDirectVarRefsMap = null;
|
||||
private LinkedHashMap<LabelRef, Collection<VariableRef>> blockDirectUsedVarsMap = null;
|
||||
|
||||
/** Create defined/referenced maps */
|
||||
@Override
|
||||
public boolean step() {
|
||||
@ -31,28 +31,40 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
|
||||
LinkedHashMap<Integer, Collection<VariableRef>> stmtReferenced = new LinkedHashMap<>();
|
||||
LinkedHashMap<Integer, Collection<VariableRef>> stmtDefined = new LinkedHashMap<>();
|
||||
Map<SymbolVariableRef, Collection<VariableReferenceInfos.ReferenceToSymbolVar>> symbolVarReferences = new LinkedHashMap<>();
|
||||
blockDirectVarRefsMap = new LinkedHashMap<>();
|
||||
blockDirectUsedVarsMap = new LinkedHashMap<>();
|
||||
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
LabelRef blockLabel = block.getLabel();
|
||||
blockReferencedVars.put(blockLabel, getReferencedVars(blockLabel, new ArrayList<>()));
|
||||
blockUsedVars.put(blockLabel, getUsedVars(blockLabel, new ArrayList<>()));
|
||||
LinkedHashSet<VariableRef> blockDirectVarRefs = new LinkedHashSet<>();;
|
||||
LinkedHashSet<VariableRef> blockDirectUsedVars = new LinkedHashSet<>();;
|
||||
for(Statement statement : block.getStatements()) {
|
||||
Collection<SymbolVariableRef> referenced = getReferenced(statement);
|
||||
Collection<VariableRef> defined = getDefinedVars(statement);
|
||||
LinkedHashSet<SymbolVariableRef> stmtSymbolVarRefs = new LinkedHashSet<>();
|
||||
LinkedHashSet<VariableRef> stmtVarRefs = new LinkedHashSet<>();
|
||||
LinkedHashSet<VariableRef> stmtUsedVars = new LinkedHashSet<>();
|
||||
ProgramValueIterator.execute(statement,
|
||||
(programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
if(programValue.get() instanceof SymbolVariableRef)
|
||||
stmtSymbolVarRefs.add((SymbolVariableRef) programValue.get());
|
||||
if(programValue.get() instanceof VariableRef)
|
||||
stmtVarRefs.add((VariableRef) programValue.get());
|
||||
}
|
||||
, null, null);
|
||||
Collection<VariableRef> stmtDefinedVars = getDefinedVars(statement);
|
||||
stmtUsedVars.addAll(stmtVarRefs);
|
||||
stmtUsedVars.removeAll(stmtDefinedVars);
|
||||
blockDirectVarRefs.addAll(stmtVarRefs);
|
||||
blockDirectUsedVars.addAll(stmtUsedVars);
|
||||
|
||||
// Add variable definitions to the statement
|
||||
stmtDefined.put(statement.getIndex(), defined);
|
||||
stmtDefined.put(statement.getIndex(), stmtDefinedVars);
|
||||
// Identify statement defining variables
|
||||
for(VariableRef variableRef : defined) {
|
||||
for(VariableRef variableRef : stmtDefinedVars) {
|
||||
symbolVarReferences.putIfAbsent(variableRef, new ArrayList<>());
|
||||
Collection<VariableReferenceInfos.ReferenceToSymbolVar> references = symbolVarReferences.get(variableRef);
|
||||
references.add(new VariableReferenceInfos.ReferenceInStatement(statement.getIndex(), VariableReferenceInfos.ReferenceToSymbolVar.ReferenceType.DEFINE, variableRef));
|
||||
}
|
||||
// Gather statements referencing variables/constants
|
||||
Collection<VariableRef> varRefs = new ArrayList<>();
|
||||
for(SymbolVariableRef referencedVarRef : referenced) {
|
||||
if(referencedVarRef instanceof VariableRef) {
|
||||
varRefs.add((VariableRef) referencedVarRef);
|
||||
}
|
||||
if(!defined.contains(referencedVarRef)) {
|
||||
for(SymbolVariableRef referencedVarRef : stmtSymbolVarRefs) {
|
||||
if(!stmtDefinedVars.contains(referencedVarRef)) {
|
||||
symbolVarReferences.putIfAbsent(referencedVarRef, new ArrayList<>());
|
||||
Collection<VariableReferenceInfos.ReferenceToSymbolVar> references = symbolVarReferences.get(referencedVarRef);
|
||||
references.add(
|
||||
@ -63,8 +75,19 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
|
||||
}
|
||||
}
|
||||
// Add variable reference to the statement
|
||||
stmtReferenced.put(statement.getIndex(), varRefs);
|
||||
stmtReferenced.put(statement.getIndex(), stmtVarRefs);
|
||||
}
|
||||
LabelRef blockLabel = block.getLabel();
|
||||
blockDirectVarRefsMap.put(blockLabel, blockDirectVarRefs);
|
||||
blockDirectUsedVarsMap.put(blockLabel, blockDirectUsedVars);
|
||||
}
|
||||
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
LabelRef blockLabel = block.getLabel();
|
||||
LinkedHashSet<VariableRef> blockRecursiveVarRefs = new LinkedHashSet<>();
|
||||
LinkedHashSet<VariableRef> blockRecursiveUsedVars = new LinkedHashSet<>();
|
||||
addReferencedVars(block.getLabel(), block, blockRecursiveVarRefs, blockRecursiveUsedVars, new ArrayList<>());
|
||||
blockReferencedVars.put(blockLabel, blockRecursiveVarRefs);
|
||||
blockUsedVars.put(blockLabel, blockRecursiveUsedVars);
|
||||
}
|
||||
// Gather symbols in the symbol table referencing other variables/constants
|
||||
Collection<SymbolVariable> allSymbolVariables = getProgram().getScope().getAllSymbolVariables(true);
|
||||
@ -84,7 +107,6 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all variables referenced in an rValue
|
||||
*
|
||||
@ -134,67 +156,29 @@ public class PassNVariableReferenceInfos extends Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all variables used inside a block and its successors (including any called method)
|
||||
* Recursively get all variables used or defined inside a block and its successors (including any called method)
|
||||
*
|
||||
* @param labelRef The block to examine
|
||||
* @param block The block to examine (optional, saves lookup)
|
||||
* @param referencedVars the set of referenced variables
|
||||
* @param usedVars the set of referenced variables
|
||||
* @param visited The blocks already visited during the search. Used to stop infinite recursion
|
||||
* @return All used variables
|
||||
*/
|
||||
private Collection<VariableRef> getUsedVars(LabelRef labelRef, Collection<LabelRef> visited) {
|
||||
if(labelRef == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
if(visited.contains(labelRef)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
private void addReferencedVars(LabelRef labelRef, ControlFlowBlock block, LinkedHashSet<VariableRef> referencedVars, LinkedHashSet<VariableRef> usedVars, Collection<LabelRef> visited) {
|
||||
if(labelRef == null || visited.contains(labelRef))
|
||||
return;
|
||||
visited.add(labelRef);
|
||||
ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef);
|
||||
if(block == null) {
|
||||
return new ArrayList<>();
|
||||
block = getProgram().getGraph().getBlock(labelRef);
|
||||
if(block == null)
|
||||
return;
|
||||
}
|
||||
LinkedHashSet<VariableRef> used = new LinkedHashSet<>();
|
||||
for(Statement statement : block.getStatements()) {
|
||||
used.addAll(getUsedVars(statement));
|
||||
if(statement instanceof StatementCall) {
|
||||
ProcedureRef procedure = ((StatementCall) statement).getProcedure();
|
||||
used.addAll(getUsedVars(procedure.getLabelRef(), visited));
|
||||
}
|
||||
}
|
||||
used.addAll(getUsedVars(block.getDefaultSuccessor(), visited));
|
||||
used.addAll(getUsedVars(block.getConditionalSuccessor(), visited));
|
||||
return used;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all variables used or defined inside a block and its successors (including any called method)
|
||||
*
|
||||
* @param labelRef The block to examine
|
||||
* @param visited The blocks already visited during the search. Used to stop infinite recursion
|
||||
* @return All used variables
|
||||
*/
|
||||
private Collection<VariableRef> getReferencedVars(LabelRef labelRef, Collection<LabelRef> visited) {
|
||||
if(labelRef == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
if(visited.contains(labelRef)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
visited.add(labelRef);
|
||||
ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef);
|
||||
if(block == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
LinkedHashSet<VariableRef> referenced = new LinkedHashSet<>();
|
||||
for(Statement statement : block.getStatements()) {
|
||||
referenced.addAll(getReferencedVars(statement));
|
||||
if(statement instanceof StatementCall) {
|
||||
ProcedureRef procedure = ((StatementCall) statement).getProcedure();
|
||||
referenced.addAll(getReferencedVars(procedure.getLabelRef(), visited));
|
||||
}
|
||||
}
|
||||
referenced.addAll(getReferencedVars(block.getDefaultSuccessor(), visited));
|
||||
referenced.addAll(getReferencedVars(block.getConditionalSuccessor(), visited));
|
||||
return referenced;
|
||||
referencedVars.addAll(blockDirectVarRefsMap.get(labelRef));
|
||||
usedVars.addAll(blockDirectUsedVarsMap.get(labelRef));
|
||||
addReferencedVars(block.getDefaultSuccessor(), null, referencedVars, usedVars, visited);
|
||||
addReferencedVars(block.getConditionalSuccessor(), null, referencedVars, usedVars, visited);
|
||||
addReferencedVars(block.getCallSuccessor(), null, referencedVars, usedVars, visited);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -223,54 +207,14 @@ 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<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables used, but not defined, in a statement
|
||||
*
|
||||
* @param statement The statement to examine
|
||||
* @return The used variables (not including defined variables)
|
||||
*/
|
||||
private Collection<VariableRef> getUsedVars(Statement statement) {
|
||||
LinkedHashSet<VariableRef> used = new LinkedHashSet<>();
|
||||
used.addAll(getReferencedVars(statement));
|
||||
used.removeAll(getDefinedVars(statement));
|
||||
return used;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables referenced (used or defined) in a statement
|
||||
*
|
||||
* @param statement The statement to examine
|
||||
* @return The referenced variables
|
||||
*/
|
||||
private Collection<VariableRef> getReferencedVars(Statement statement) {
|
||||
LinkedHashSet<VariableRef> referencedVars = new LinkedHashSet<>();
|
||||
getReferenced(statement)
|
||||
.stream()
|
||||
.filter(symbolVariableRef -> symbolVariableRef instanceof VariableRef)
|
||||
.forEach(symbolVariableRef -> referencedVars.add((VariableRef) symbolVariableRef));
|
||||
return referencedVars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables / constants referenced (used or defined) in a statement
|
||||
*
|
||||
* @param statement The statement to examine
|
||||
* @return The referenced variables / constants (VariableRef / ConstantRef)
|
||||
*/
|
||||
private Collection<SymbolVariableRef> getReferenced(Statement statement) {
|
||||
LinkedHashSet<SymbolVariableRef> referenced = new LinkedHashSet<>();
|
||||
ProgramValueIterator.execute(statement,
|
||||
(programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
if(programValue.get() instanceof SymbolVariableRef)
|
||||
referenced.add((SymbolVariableRef) programValue.get());
|
||||
}
|
||||
, null, null);
|
||||
return referenced;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ void print_sdword(signed dword dw) {
|
||||
print_dword((dword)dw);
|
||||
}
|
||||
|
||||
const byte[] print_hextab = "0123456789abcdef";
|
||||
const byte[] print_hextab = "0123456789abcdef"z;
|
||||
|
||||
// Print a byte as HEX
|
||||
void print_byte(byte b) {
|
||||
|
@ -32,6 +32,161 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
//@Test
|
||||
//public void testPointerCast3() throws IOException, URISyntaxException {
|
||||
// compileAndCompare("pointer-cast-3");
|
||||
//}
|
||||
|
||||
@Test
|
||||
public void testPointerCast2() throws IOException, URISyntaxException {
|
||||
compileAndCompare("pointer-cast-2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPointerCast() throws IOException, URISyntaxException {
|
||||
compileAndCompare("pointer-cast");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLiteralStrings() throws IOException, URISyntaxException {
|
||||
compileAndCompare("literal-strings");
|
||||
}
|
||||
|
||||
@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 testComparisonRewriting() throws IOException, URISyntaxException {
|
||||
compileAndCompare("comparison-rewriting", getLogSysout());
|
||||
@ -64,7 +219,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testLocalScopeLoops() throws IOException, URISyntaxException {
|
||||
compileAndCompare("localscope-loops", getLogSysout());
|
||||
compileAndCompare("localscope-loops");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -349,7 +504,7 @@ public class TestPrograms {
|
||||
|
||||
//@Test
|
||||
//public void testRobozzle64() throws IOException, URISyntaxException {
|
||||
// compileAndCompare("complex/robozzle64/robozzle64");
|
||||
// compileAndCompare("complex/robozzle_c64/robozzle64_1", log());
|
||||
//}
|
||||
|
||||
//@Test
|
||||
@ -658,6 +813,11 @@ public class TestPrograms {
|
||||
compileAndCompare("const-param");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeepNesting() throws IOException, URISyntaxException {
|
||||
compileAndCompare("deep-nesting");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHelloWorld() throws IOException, URISyntaxException {
|
||||
compileAndCompare("examples/helloworld/helloworld");
|
||||
@ -1425,11 +1585,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;
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
byte[3] b;
|
||||
byte[] c = {'c', 'm', 'l'};
|
||||
byte[] d = "cml";
|
||||
byte[] d = "cml"z;
|
||||
|
||||
byte* SCREEN = $400;
|
||||
|
||||
|
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();
|
||||
|
||||
}
|
@ -115,40 +115,40 @@ const byte* FORM_SCREEN = $0400;
|
||||
const byte* FORM_CHARSET = $1800; // Charset ROM
|
||||
|
||||
byte[] FORM_TEXT =
|
||||
" C64 DTV Graphics Mode Explorer @" +
|
||||
" @" +
|
||||
" PRESET 0 Standard Charset @" +
|
||||
" @" +
|
||||
" CONTROL PLANE A VIC II @" +
|
||||
" bmm 0 pattern p0 screen s0 @" +
|
||||
" mcm 0 start 00 gfx g0 @" +
|
||||
" ecm 0 step 00 colors c0 @" +
|
||||
" hicolor 0 modulo 00 @" +
|
||||
" linear 0 COLORS @" +
|
||||
" color off 0 PLANE B palet 0 @" +
|
||||
" chunky 0 pattern p0 bgcol0 00 @" +
|
||||
" border off 0 start 00 bgcol1 00 @" +
|
||||
" overscan 0 step 00 bgcol2 00 @" +
|
||||
" modulo 00 bgcol3 00 @" +
|
||||
"@" ;
|
||||
" C64 DTV Graphics Mode Explorer @"z +
|
||||
" @"z +
|
||||
" PRESET 0 Standard Charset @"z +
|
||||
" @"z +
|
||||
" CONTROL PLANE A VIC II @"z +
|
||||
" bmm 0 pattern p0 screen s0 @"z +
|
||||
" mcm 0 start 00 gfx g0 @"z +
|
||||
" ecm 0 step 00 colors c0 @"z +
|
||||
" hicolor 0 modulo 00 @"z +
|
||||
" linear 0 COLORS @"z +
|
||||
" color off 0 PLANE B palet 0 @"z +
|
||||
" chunky 0 pattern p0 bgcol0 00 @"z +
|
||||
" border off 0 start 00 bgcol1 00 @"z +
|
||||
" overscan 0 step 00 bgcol2 00 @"z +
|
||||
" modulo 00 bgcol3 00 @"z +
|
||||
"@"z ;
|
||||
byte[] FORM_COLS =
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@" +
|
||||
" @" +
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@" +
|
||||
" @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm @" +
|
||||
" nnnnnnnnnnnn jjjjjjjjj @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @" +
|
||||
"@" ;
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"z +
|
||||
" @"z +
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"z +
|
||||
" @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm @"z +
|
||||
" nnnnnnnnnnnn jjjjjjjjj @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
||||
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
||||
"@"z ;
|
||||
|
||||
// Number of form fields
|
||||
byte form_fields_cnt = 36;
|
||||
@ -224,29 +224,29 @@ void apply_preset(byte idx) {
|
||||
void render_preset_name(byte idx) {
|
||||
byte* name;
|
||||
if(idx==0) {
|
||||
name = "Standard Charset @";
|
||||
name = "Standard Charset ";
|
||||
} else if(idx==1){
|
||||
name = "Extended Color Charset @";
|
||||
name = "Extended Color Charset ";
|
||||
} else if(idx==2){
|
||||
name = "Standard Bitmap @";
|
||||
name = "Standard Bitmap ";
|
||||
} else if(idx==3){
|
||||
name = "Multicolor Bitmap @";
|
||||
name = "Multicolor Bitmap ";
|
||||
} else if(idx==4){
|
||||
name = "Hicolor Charset @";
|
||||
name = "Hicolor Charset ";
|
||||
} else if(idx==5){
|
||||
name = "Hicolor Extended Color Charset@";
|
||||
name = "Hicolor Extended Color Charset";
|
||||
} else if(idx==6){
|
||||
name = "Twoplane Bitmap @";
|
||||
name = "Twoplane Bitmap ";
|
||||
} else if(idx==7){
|
||||
name = "Chunky 8bpp @";
|
||||
name = "Chunky 8bpp ";
|
||||
} else if(idx==8){
|
||||
name = "Sixs Fred @";
|
||||
name = "Sixs Fred ";
|
||||
} else if(idx==9){
|
||||
name = "Sixs Fred 2 @";
|
||||
name = "Sixs Fred 2 ";
|
||||
} else if(idx==10){
|
||||
name = "8bpp Pixel Cell @";
|
||||
name = "8bpp Pixel Cell ";
|
||||
} else {
|
||||
name = "Standard Charset @";
|
||||
name = "Standard Charset ";
|
||||
}
|
||||
// Render it
|
||||
print_str_at(name, FORM_SCREEN+40*2+10);
|
||||
|
@ -18,27 +18,27 @@ void main() {
|
||||
}
|
||||
|
||||
byte[] MENU_TEXT =
|
||||
"C64DTV Graphics Modes CCLHBME@" +
|
||||
" OHIIMCC@" +
|
||||
" LUNCMMM@" +
|
||||
"----------------------------------------@" +
|
||||
"1. Standard Char (V) 0000000@" +
|
||||
"2. Extended Color Char (V) 0000001@" +
|
||||
"3. Multicolor Char (V) 0000010@" +
|
||||
"4. Standard Bitmap (V) 0000100@" +
|
||||
"5. Multicolor Bitmap (V) 0000110@" +
|
||||
"6. High Color Standard Char (H) 0001000@" +
|
||||
"7. High Extended Color Char (H) 0001001@" +
|
||||
"8. High Multicolor Char (H) 0001010@" +
|
||||
"9. High Multicolor Bitmap (H) 0001110@" +
|
||||
"a. Sixs Fred 2 (D) 0010111@" +
|
||||
"b. Two Plane Bitmap (D) 0011101@" +
|
||||
"c. Sixs Fred (2 Plane MC BM) (D) 0011111@" +
|
||||
"d. 8bpp Pixel Cell (D) 0111011@" +
|
||||
"e. Chunky 8bpp Bitmap (D) 1111011@" +
|
||||
"----------------------------------------@" +
|
||||
" (V) vicII (H) vicII+hicol (D) c64dtv@" +
|
||||
"@" ;
|
||||
"C64DTV Graphics Modes CCLHBME@"z +
|
||||
" OHIIMCC@"z +
|
||||
" LUNCMMM@"z +
|
||||
"----------------------------------------@"z +
|
||||
"1. Standard Char (V) 0000000@"z +
|
||||
"2. Extended Color Char (V) 0000001@"z +
|
||||
"3. Multicolor Char (V) 0000010@"z +
|
||||
"4. Standard Bitmap (V) 0000100@"z +
|
||||
"5. Multicolor Bitmap (V) 0000110@"z +
|
||||
"6. High Color Standard Char (H) 0001000@"z +
|
||||
"7. High Extended Color Char (H) 0001001@"z +
|
||||
"8. High Multicolor Char (H) 0001010@"z +
|
||||
"9. High Multicolor Bitmap (H) 0001110@"z +
|
||||
"a. Sixs Fred 2 (D) 0010111@"z +
|
||||
"b. Two Plane Bitmap (D) 0011101@"z +
|
||||
"c. Sixs Fred (2 Plane MC BM) (D) 0011111@"z +
|
||||
"d. 8bpp Pixel Cell (D) 0111011@"z +
|
||||
"e. Chunky 8bpp Bitmap (D) 1111011@"z +
|
||||
"----------------------------------------@"z +
|
||||
" (V) vicII (H) vicII+hicol (D) c64dtv@"z +
|
||||
"@"z ;
|
||||
|
||||
void menu() {
|
||||
const byte* SCREEN = $8000;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ main_state = GAME_FADE_IN;
|
||||
|
||||
byte fade_in_game() {
|
||||
fillscreen(SCREEN, $20);
|
||||
print_str("lone archer -- game@");
|
||||
print_str("lone archer -- game");
|
||||
print_ln();
|
||||
return 1;
|
||||
}
|
||||
@ -86,7 +86,7 @@ return 1;
|
||||
byte game_weapon_plus() {
|
||||
if (action_count == 0)
|
||||
action_count = WEAPON_SWITCH_FRAMES;
|
||||
print_str("weapon plus@");
|
||||
print_str("weapon plus");
|
||||
print_ln();
|
||||
action_count--;
|
||||
return (action_count==0);
|
||||
@ -95,7 +95,7 @@ return (action_count==0);
|
||||
byte game_weapon_minus() {
|
||||
if (action_count == 0)
|
||||
action_count = WEAPON_SWITCH_FRAMES;
|
||||
print_str("weapon minus@");
|
||||
print_str("weapon minus");
|
||||
print_ln();
|
||||
action_count--;
|
||||
return (action_count==0);
|
||||
@ -104,7 +104,7 @@ return (action_count==0);
|
||||
byte game_path_plus() {
|
||||
if (action_count == 0)
|
||||
action_count = PATH_SWITCH_FRAMES;
|
||||
print_str("path plus@");
|
||||
print_str("path plus");
|
||||
print_ln();
|
||||
action_count--;
|
||||
return (action_count==0);
|
||||
@ -113,7 +113,7 @@ return (action_count==0);
|
||||
byte game_path_minus() {
|
||||
if (action_count == 0)
|
||||
action_count = PATH_SWITCH_FRAMES;
|
||||
print_str("path minus@");
|
||||
print_str("path minus");
|
||||
print_ln();
|
||||
action_count--;
|
||||
return (action_count==0);
|
||||
@ -122,7 +122,7 @@ return (action_count==0);
|
||||
byte game_ready() {
|
||||
if (action_count == 0)
|
||||
action_count = READY_FRAMES;
|
||||
print_str("ready@");
|
||||
print_str("ready");
|
||||
print_ln();
|
||||
action_count--;
|
||||
return (action_count==0);
|
||||
@ -143,7 +143,7 @@ print_str("d");
|
||||
}
|
||||
|
||||
byte game_fire() {
|
||||
print_str("fire!@");
|
||||
print_str("fire!");
|
||||
print_ln();
|
||||
return 1;
|
||||
}
|
||||
@ -151,7 +151,7 @@ return 1;
|
||||
byte game_dead_fall() {
|
||||
if (action_count == 0)
|
||||
action_count = DEAD_FALL_FRAMES;
|
||||
print_str("dead fall...@");
|
||||
print_str("dead fall...");
|
||||
print_ln();
|
||||
action_count--;
|
||||
return (action_count==0);
|
||||
@ -160,7 +160,7 @@ return (action_count==0);
|
||||
byte game_dead_wait() {
|
||||
if (action_count == 0)
|
||||
action_count = DEAD_WAIT_FRAMES;
|
||||
print_str("dead wait...@");
|
||||
print_str("dead wait...");
|
||||
print_ln();
|
||||
action_count--;
|
||||
return (action_count==0);
|
||||
|
@ -3,7 +3,7 @@
|
||||
void main() {
|
||||
byte* screen = $400;
|
||||
byte l = 'l';
|
||||
byte[] msg = "cm"+l;
|
||||
byte[] msg = "cm"z+l;
|
||||
for( byte i: 0..2 ) {
|
||||
screen[i] = msg[i];
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Concatenates string constants in different ways
|
||||
void main() {
|
||||
byte[] s = "e"+"l";
|
||||
byte[] s = "e"z+"l"z;
|
||||
byte[] s2 = s+'o';
|
||||
byte[] s3 = "cam"+s2;
|
||||
byte[] s3 = "cam"z+s2;
|
||||
byte e = '!';
|
||||
byte[] s4 = ""+'t'+ e;
|
||||
byte[] s4 = ""z+'t'+ e;
|
||||
byte[] s5 = s3+s4;
|
||||
byte* SCREEN = $400;
|
||||
for( byte i: 0..7) {
|
||||
|
@ -13,21 +13,21 @@ void main() {
|
||||
// Test different byte constants
|
||||
void test_bytes() {
|
||||
byte bb=0;
|
||||
assert_byte("0=0@", bb, 0);
|
||||
assert_byte("0=0", bb, 0);
|
||||
byte bc=bb+2;
|
||||
assert_byte("0+2=2@", bc, 2);
|
||||
assert_byte("0+2=2", bc, 2);
|
||||
byte bd=(byte)((signed byte)bc-4);
|
||||
assert_byte("0+2-4=254@", bd, 254);
|
||||
assert_byte("0+2-4=254", bd, 254);
|
||||
}
|
||||
|
||||
void assert_byte(byte* msg, byte b, byte c) {
|
||||
print_str(msg);
|
||||
print_str(" @");
|
||||
print_str(" ");
|
||||
if(b!=c) {
|
||||
*BGCOL = RED;
|
||||
print_str("fail!@");
|
||||
print_str("fail!");
|
||||
} else {
|
||||
print_str("ok@");
|
||||
print_str("ok");
|
||||
}
|
||||
print_ln();
|
||||
}
|
||||
@ -35,25 +35,25 @@ void assert_byte(byte* msg, byte b, byte c) {
|
||||
// Test different signed byte constants
|
||||
void test_sbytes() {
|
||||
signed byte bb=0;
|
||||
assert_sbyte("0=0@", bb, 0);
|
||||
assert_sbyte("0=0", bb, 0);
|
||||
signed byte bc=bb+2;
|
||||
assert_sbyte("0+2=2@", bc, 2);
|
||||
assert_sbyte("0+2=2", bc, 2);
|
||||
signed byte bd=bc-4;
|
||||
assert_sbyte("0+2-4=-2@", bd, -2);
|
||||
assert_sbyte("0+2-4=-2", bd, -2);
|
||||
signed byte be=-bd;
|
||||
assert_sbyte("-(0+2-4)=2@", be, 2);
|
||||
assert_sbyte("-(0+2-4)=2", be, 2);
|
||||
signed byte bf=(signed byte)(-127-127);
|
||||
assert_sbyte("-127-127=2@", bf, 2);
|
||||
assert_sbyte("-127-127=2", bf, 2);
|
||||
}
|
||||
|
||||
void assert_sbyte(byte* msg, signed byte b, signed byte c) {
|
||||
print_str(msg);
|
||||
print_str(" @");
|
||||
print_str(" ");
|
||||
if(b!=c) {
|
||||
*BGCOL = RED;
|
||||
print_str("fail!@");
|
||||
print_str("fail!");
|
||||
} else {
|
||||
print_str("ok@");
|
||||
print_str("ok");
|
||||
}
|
||||
print_ln();
|
||||
}
|
||||
|
108
src/test/kc/deep-nesting.kc
Normal file
108
src/test/kc/deep-nesting.kc
Normal file
@ -0,0 +1,108 @@
|
||||
// Test that the compiler handles deep nesting well -- mainly a performance issue.
|
||||
|
||||
void main() {
|
||||
byte* screen = $400;
|
||||
const byte reverse = $80;
|
||||
screen[0] = f1(0);
|
||||
}
|
||||
|
||||
byte f1(byte x) { return f2(x) + 1; }
|
||||
byte f2(byte x) { return f3(x) + 1; }
|
||||
byte f3(byte x) { return f4(x) + 1; }
|
||||
byte f4(byte x) { return f5(x) + 1; }
|
||||
byte f5(byte x) { return f6(x) + 1; }
|
||||
byte f6(byte x) { return f7(x) + 1; }
|
||||
byte f7(byte x) { return f8(x) + 1; }
|
||||
byte f8(byte x) { return f9(x) + 1; }
|
||||
byte f9(byte x) { return f10(x) + 1; }
|
||||
byte f10(byte x) { return f11(x) + 1; }
|
||||
byte f11(byte x) { return f12(x) + 1; }
|
||||
byte f12(byte x) { return f13(x) + 1; }
|
||||
byte f13(byte x) { return f14(x) + 1; }
|
||||
byte f14(byte x) { return f15(x) + 1; }
|
||||
byte f15(byte x) { return f16(x) + 1; }
|
||||
byte f16(byte x) { return f17(x) + 1; }
|
||||
byte f17(byte x) { return f18(x) + 1; }
|
||||
byte f18(byte x) { return f19(x) + 1; }
|
||||
byte f19(byte x) { return f20(x) + 1; }
|
||||
byte f20(byte x) { return f21(x) + 1; }
|
||||
byte f21(byte x) { return f22(x) + 1; }
|
||||
byte f22(byte x) { return f23(x) + 1; }
|
||||
byte f23(byte x) { return f24(x) + 1; }
|
||||
byte f24(byte x) { return f25(x) + 1; }
|
||||
byte f25(byte x) { return f26(x) + 1; }
|
||||
byte f26(byte x) { return f27(x) + 1; }
|
||||
byte f27(byte x) { return f28(x) + 1; }
|
||||
byte f28(byte x) { return f29(x) + 1; }
|
||||
byte f29(byte x) { return f30(x) + 1; }
|
||||
byte f30(byte x) { return f31(x) + 1; }
|
||||
byte f31(byte x) { return f32(x) + 1; }
|
||||
byte f32(byte x) { return f33(x) + 1; }
|
||||
byte f33(byte x) { return f34(x) + 1; }
|
||||
byte f34(byte x) { return f35(x) + 1; }
|
||||
byte f35(byte x) { return f36(x) + 1; }
|
||||
byte f36(byte x) { return f37(x) + 1; }
|
||||
byte f37(byte x) { return f38(x) + 1; }
|
||||
byte f38(byte x) { return f39(x) + 1; }
|
||||
byte f39(byte x) { return f40(x) + 1; }
|
||||
byte f40(byte x) { return f41(x) + 1; }
|
||||
byte f41(byte x) { return f42(x) + 1; }
|
||||
byte f42(byte x) { return f43(x) + 1; }
|
||||
byte f43(byte x) { return f44(x) + 1; }
|
||||
byte f44(byte x) { return f45(x) + 1; }
|
||||
byte f45(byte x) { return f46(x) + 1; }
|
||||
byte f46(byte x) { return f47(x) + 1; }
|
||||
byte f47(byte x) { return f48(x) + 1; }
|
||||
byte f48(byte x) { return f49(x) + 1; }
|
||||
byte f49(byte x) { return f50(x) + 1; }
|
||||
byte f50(byte x) { return f51(x) + 1; }
|
||||
byte f51(byte x) { return f52(x) + 1; }
|
||||
byte f52(byte x) { return f53(x) + 1; }
|
||||
byte f53(byte x) { return f54(x) + 1; }
|
||||
byte f54(byte x) { return f55(x) + 1; }
|
||||
byte f55(byte x) { return f56(x) + 1; }
|
||||
byte f56(byte x) { return f57(x) + 1; }
|
||||
byte f57(byte x) { return f58(x) + 1; }
|
||||
byte f58(byte x) { return f59(x) + 1; }
|
||||
byte f59(byte x) { return f60(x) + 1; }
|
||||
byte f60(byte x) { return f61(x) + 1; }
|
||||
byte f61(byte x) { return f62(x) + 1; }
|
||||
byte f62(byte x) { return f63(x) + 1; }
|
||||
byte f63(byte x) { return f64(x) + 1; }
|
||||
byte f64(byte x) { return f65(x) + 1; }
|
||||
byte f65(byte x) { return f66(x) + 1; }
|
||||
byte f66(byte x) { return f67(x) + 1; }
|
||||
byte f67(byte x) { return f68(x) + 1; }
|
||||
byte f68(byte x) { return f69(x) + 1; }
|
||||
byte f69(byte x) { return f70(x) + 1; }
|
||||
byte f70(byte x) { return f71(x) + 1; }
|
||||
byte f71(byte x) { return f72(x) + 1; }
|
||||
byte f72(byte x) { return f73(x) + 1; }
|
||||
byte f73(byte x) { return f74(x) + 1; }
|
||||
byte f74(byte x) { return f75(x) + 1; }
|
||||
byte f75(byte x) { return f76(x) + 1; }
|
||||
byte f76(byte x) { return f77(x) + 1; }
|
||||
byte f77(byte x) { return f78(x) + 1; }
|
||||
byte f78(byte x) { return f79(x) + 1; }
|
||||
byte f79(byte x) { return f80(x) + 1; }
|
||||
byte f80(byte x) { return f81(x) + 1; }
|
||||
byte f81(byte x) { return f82(x) + 1; }
|
||||
byte f82(byte x) { return f83(x) + 1; }
|
||||
byte f83(byte x) { return f84(x) + 1; }
|
||||
byte f84(byte x) { return f85(x) + 1; }
|
||||
byte f85(byte x) { return f86(x) + 1; }
|
||||
byte f86(byte x) { return f87(x) + 1; }
|
||||
byte f87(byte x) { return f88(x) + 1; }
|
||||
byte f88(byte x) { return f89(x) + 1; }
|
||||
byte f89(byte x) { return f90(x) + 1; }
|
||||
byte f90(byte x) { return f91(x) + 1; }
|
||||
byte f91(byte x) { return f92(x) + 1; }
|
||||
byte f92(byte x) { return f93(x) + 1; }
|
||||
byte f93(byte x) { return f94(x) + 1; }
|
||||
byte f94(byte x) { return f95(x) + 1; }
|
||||
byte f95(byte x) { return f96(x) + 1; }
|
||||
byte f96(byte x) { return f97(x) + 1; }
|
||||
byte f97(byte x) { return f98(x) + 1; }
|
||||
byte f98(byte x) { return f99(x) + 1; }
|
||||
byte f99(byte x) { return f100(x) + 1; }
|
||||
byte f100(byte x) { return x;}
|
@ -91,18 +91,18 @@ void anim() {
|
||||
|
||||
void debug_print_init() {
|
||||
print_cls();
|
||||
print_str_at("sx@", SCREEN+40*0+34);
|
||||
print_str_at("sy@", SCREEN+40*1+34);
|
||||
print_str_at("sz@", SCREEN+40*2+34);
|
||||
print_str_at("x@", SCREEN+40*16);
|
||||
print_str_at("y@", SCREEN+40*17);
|
||||
print_str_at("z@", SCREEN+40*18);
|
||||
print_str_at("xr@", SCREEN+40*19);
|
||||
print_str_at("yr@", SCREEN+40*20);
|
||||
print_str_at("zr@", SCREEN+40*21);
|
||||
print_str_at("pp@", SCREEN+40*22);
|
||||
print_str_at("xp@", SCREEN+40*23);
|
||||
print_str_at("yp@", SCREEN+40*24);
|
||||
print_str_at("sx", SCREEN+40*0+34);
|
||||
print_str_at("sy", SCREEN+40*1+34);
|
||||
print_str_at("sz", SCREEN+40*2+34);
|
||||
print_str_at("x", SCREEN+40*16);
|
||||
print_str_at("y", SCREEN+40*17);
|
||||
print_str_at("z", SCREEN+40*18);
|
||||
print_str_at("xr", SCREEN+40*19);
|
||||
print_str_at("yr", SCREEN+40*20);
|
||||
print_str_at("zr", SCREEN+40*21);
|
||||
print_str_at("pp", SCREEN+40*22);
|
||||
print_str_at("xp", SCREEN+40*23);
|
||||
print_str_at("yp", SCREEN+40*24);
|
||||
|
||||
byte* at_line = SCREEN+16*40;
|
||||
byte c = 4;
|
||||
|
@ -37,18 +37,18 @@ void main() {
|
||||
|
||||
|
||||
void do_perspective(signed byte x, signed byte y, signed byte z) {
|
||||
print_str("(@");
|
||||
print_str("(");
|
||||
print_sbyte(x);
|
||||
print_str(",@");
|
||||
print_str(",");
|
||||
print_sbyte(y);
|
||||
print_str(",@");
|
||||
print_str(",");
|
||||
print_sbyte(z);
|
||||
print_str(") -> (@");
|
||||
print_str(") -> (");
|
||||
perspective(x, y, z);
|
||||
print_byte((byte)*xr);
|
||||
print_str(",@");
|
||||
print_str(",");
|
||||
print_byte((byte)*yr);
|
||||
print_str(")@");
|
||||
print_str(")");
|
||||
print_ln();
|
||||
}
|
||||
|
||||
|
@ -10,10 +10,10 @@ void main() {
|
||||
for( byte* sc=SCREEN;sc<SCREEN+1000;sc++) *sc = ' ';
|
||||
|
||||
// Plot 4 initial analysis chars
|
||||
print_str_at("f1@", SCREEN+1);
|
||||
print_str_at("f3@", SCREEN+1+10);
|
||||
print_str_at("f5@", SCREEN+1+20);
|
||||
print_str_at("f7@", SCREEN+1+30);
|
||||
print_str_at("f1", SCREEN+1);
|
||||
print_str_at("f3", SCREEN+1+10);
|
||||
print_str_at("f5", SCREEN+1+20);
|
||||
print_str_at("f7", SCREEN+1+30);
|
||||
for(byte i : 0..3 ) {
|
||||
plot_chargen(i, $20, 0);
|
||||
}
|
||||
|
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;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import "print"
|
||||
void main() {
|
||||
print_str("hello world!@");
|
||||
print_str("hello world!");
|
||||
print_ln();
|
||||
}
|
||||
|
93
src/test/kc/examples/plasma/plasma-unroll.kc
Normal file
93
src/test/kc/examples/plasma/plasma-unroll.kc
Normal file
@ -0,0 +1,93 @@
|
||||
// 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) {
|
||||
unsigned char xval = xbuf[i];
|
||||
// Use experimental loop unrolling to increase the speed
|
||||
inline for (unsigned char ii = 0; ii < 25; ++ii) {
|
||||
(screen+ii*40)[i] = xval + 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;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ byte* SCREEN = $0400;
|
||||
byte* RASTER = $d012;
|
||||
byte* BGCOL = $d020;
|
||||
byte* SCROLL = $d016;
|
||||
byte* TEXT = "-= this is rex of camelot testing a scroller created in kickc. kickc is an optimizing c-compiler for 6502 assembler. =- @";
|
||||
byte* TEXT = "-= this is rex of camelot testing a scroller created in kickc. kickc is an optimizing c-compiler for 6502 assembler. =- ";
|
||||
|
||||
void main() {
|
||||
fillscreen(SCREEN, $20);
|
||||
|
@ -6,7 +6,7 @@ byte* SCREEN = $0400;
|
||||
byte* RASTER = $d012;
|
||||
byte* BGCOL = $d020;
|
||||
byte* SCROLL = $d016;
|
||||
byte* TEXT = "-= this is rex of camelot testing a scroller created in kickc. kickc is an optimizing c-compiler for 6502 assembler. =- @";
|
||||
byte* TEXT = "-= this is rex of camelot testing a scroller created in kickc. kickc is an optimizing c-compiler for 6502 assembler. =- ";
|
||||
|
||||
void main() {
|
||||
fillscreen(SCREEN, $20);
|
||||
|
@ -121,7 +121,7 @@ void place_sprites() {
|
||||
}
|
||||
|
||||
void gen_sprites() {
|
||||
byte[] cml = "camelot";
|
||||
byte[] cml = "camelot"z;
|
||||
byte* spr = sprites;
|
||||
for( byte i : 0..6 ) {
|
||||
gen_chargen_sprite(cml[i], spr);
|
||||
|
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)++;
|
||||
}
|
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