synths = new ArrayList<>();
@@ -162,6 +173,11 @@ public class AsmFragmentManager {
synths.add(new FragmentSynthesis("(.*)_eq_(xs?by)_then_(.*)", ".*[ax]s?by.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
synths.add(new FragmentSynthesis("(.*)_eq_(ys?by)_then_(.*)", ".*[axy]s?by.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
+ synths.add(new FragmentSynthesis("zpptrby1=(coby.|cowo.)_(sethi|setlo|plus|minus)_(.*)", ".*zpwo.*|.*=zpptr.*", null, "zpwo1=$1_$2_$3", null, mapZpptrToWord));
+ synths.add(new FragmentSynthesis("zpptrby1=zpptrby([12])_(sethi|setlo|plus|minus)_(.*)", ".*zpwo.*", null, "zpwo1=zpwo$1_$2_$3", null, mapZpptrToWord));
+ synths.add(new FragmentSynthesis("zpptrby1=zpptrby1_(sethi|setlo|plus|minus)_zpwo1", null, null, "zpptrby1=zpptrby1_$1_zpwo1", null, mapZpptrToWord2));
+ synths.add(new FragmentSynthesis("zpptrby1=zpptrby2_(sethi|setlo|plus|minus)_zpwo1", null, null, "zpptrby1=zpptrby2_$1_zpwo1", null, mapZpptrToWord3));
+
for (FragmentSynthesis synth : synths) {
CharStream synthesized = synth.synthesize(signature, log);
if (synthesized != null) {
@@ -176,6 +192,26 @@ public class AsmFragmentManager {
}
+ /**
+ * Bindings/mappings used when synthesizing one fragment from another fragment.
+ * Eg. when synthesizing zpby1=zpby2_plus_zpby3 from aby=zpby1_plus_zpby2 the bindings (zpby2->zpby1, zpby3->zpby2) are used.
+ *
+ * Often the same bindings are used in the signature-name and in the asm-code, but the bindings can be different.
+ * Eg. when synthesizing zpptrby1=zpptrby2_plus_zpwo1 from zpwo1=zpwo2_plus_zpwo3 the bindings (zpptrby1->zpwo1, zpptrby2->zpwo2, zpwo1->zpwo3)
+ * are used in the asm, but not in the signature.
+ */
+ private static class FragmentBindings {
+
+ /** Bindings used for renaming in the sub-signature. */
+ private Map sigBindings;
+ /** Bindings used for renaming in the assembler-code. */
+ private Map asmBindings;
+
+
+ }
+
+
+
/**
* AsmFragment synthesis based on matching fragment signature and reusing another fragment with added prefix/postfix and some bind-mappings
*/
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java
index 55f2d3698..aa0a9682f 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java
@@ -283,52 +283,37 @@ public class AsmFragmentSignature {
} else if (Registers.RegisterType.REG_ALU.equals(register.getType())) {
throw new AsmFragment.AluNotApplicableException();
}
- } else if (value instanceof ConstantVar) {
- ConstantVar constantVar = (ConstantVar) value;
- SymbolType constType = constantVar.getType();
-
- if (SymbolTypeBasic.BYTE.equals(constType)) {
- String name = "coby" + nextConstByteIdx++;
- bindings.put(name, constantVar);
- return name;
- } else if (SymbolTypeBasic.WORD.equals(constType)) {
- String name = "cowo" + nextConstByteIdx++;
- bindings.put(name, constantVar);
- return name;
- } else if (constType instanceof SymbolTypePointer && SymbolTypeBasic.BYTE.equals(((SymbolTypePointer) constType).getElementType())) {
- String name = "cowo" + nextConstByteIdx++;
- bindings.put(name, constantVar);
- return name;
+ } else if (value instanceof ConstantVar || value instanceof ConstantValue) {
+ SymbolType constType;
+ if (value instanceof ConstantVar) {
+ constType = ((ConstantVar) value).getType();
+ } else if(value instanceof ConstantValue) {
+ constType = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value);
} else {
- throw new RuntimeException("Unhandled constant type " + constType);
+ throw new RuntimeException("Unhandled constant type " + value);
}
- } else if (value instanceof ConstantInteger) {
- ConstantInteger intValue = (ConstantInteger) value;
- if (SymbolTypeBasic.BYTE.equals(intValue.getType(program.getScope()))) {
+ if (SymbolType.BYTE.equals(constType) || (constType instanceof SymbolTypeInline && ((SymbolTypeInline) constType).isByte())) {
String name = "coby" + nextConstByteIdx++;
bindings.put(name, value);
return name;
- } else if (SymbolTypeBasic.WORD.equals(intValue.getType(program.getScope()))) {
+ } else if (SymbolType.WORD.equals(constType) || (constType instanceof SymbolTypeInline && ((SymbolTypeInline) constType).isWord())) {
String name = "cowo" + nextConstByteIdx++;
bindings.put(name, value);
return name;
- }
- } else if (value instanceof ConstantValue) {
- SymbolType type = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value);
- if (SymbolTypeBasic.BYTE.equals(type)) {
- String name = "coby" + nextConstByteIdx++;
+ } else if (SymbolType.SBYTE.equals(constType) || (constType instanceof SymbolTypeInline && ((SymbolTypeInline) constType).isSByte())) {
+ String name = "cosby" + nextConstByteIdx++;
bindings.put(name, value);
return name;
- } else if (SymbolTypeBasic.WORD.equals(type)) {
- String name = "cowo" + nextConstByteIdx++;
+ } else if (SymbolType.SWORD.equals(constType) || (constType instanceof SymbolTypeInline && ((SymbolTypeInline) constType).isSWord())) {
+ String name = "coswo" + nextConstByteIdx++;
bindings.put(name, value);
return name;
- } else if (type instanceof SymbolTypePointer) {
+ } else if (constType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) constType).getElementType())) {
String name = "cowo" + nextConstByteIdx++;
bindings.put(name, value);
return name;
} else {
- throw new RuntimeException("Unhandled constant type " + type);
+ throw new RuntimeException("Unhandled constant type " + constType);
}
} else if (value instanceof Label) {
String name = "la" + nextLabelIdx++;
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/aby=_byte_zpwo1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=_byte_zpwo1.asm
new file mode 100644
index 000000000..27e95a67c
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/aby=_byte_zpwo1.asm
@@ -0,0 +1 @@
+lda {zpwo1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_aby.asm
deleted file mode 100644
index f28330037..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_aby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sta {zpptrby1}+1
-lda #<{coby1}
-sta {zpptrby1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_xby.asm
deleted file mode 100644
index eabe69882..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_xby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-stx {zpptrby1}+1
-ldx #<{coby1}
-stx {zpptrby1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_yby.asm
deleted file mode 100644
index 083f61c66..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_yby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sty {zpptrby1}+1
-ldy #<{coby1}
-sty {zpptrby1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_zpby1.asm
deleted file mode 100644
index cd0a7337b..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=coby1_sethi_zpby1.asm
+++ /dev/null
@@ -1,4 +0,0 @@
-lda #<{coby1}
-sta {zpptrby1}
-lda {zpby1}
-sta {zpptrby1}+1
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_aby.asm
deleted file mode 100644
index dd3384948..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_aby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sta {zpptrby1}+1
-lda #<{cowo1}
-sta {zpptrby1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_xby.asm
deleted file mode 100644
index 6845b2a5b..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_xby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-stx {zpptrby1}+1
-ldx #<{cowo1}
-stx {zpptrby1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_yby.asm
deleted file mode 100644
index f46aea4be..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_yby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sty {zpptrby1}+1
-ldy #<{cowo1}
-sty {zpptrby1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_zpby1.asm
deleted file mode 100644
index 1ed6840c8..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_sethi_zpby1.asm
+++ /dev/null
@@ -1,4 +0,0 @@
-lda #<{cowo1}
-sta {zpptrby1}
-lda {zpby1}
-sta {zpptrby1}+1
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_aby.asm
deleted file mode 100644
index 62af073fb..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_aby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sta {zpptrby1}
-lda #>{cowo1}
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_xby.asm
deleted file mode 100644
index 2609c7363..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_xby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-stx {zpptrby1}
-lda #>{cowo1}
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_yby.asm
deleted file mode 100644
index 615dfbdac..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_yby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sty {zpptrby1}
-lda #>{cowo1}
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_zpby1.asm
deleted file mode 100644
index 6f5c986c8..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=cowo1_setlo_zpby1.asm
+++ /dev/null
@@ -1,4 +0,0 @@
-lda {zpby1}
-sta {zpptrby1}
-lda #>{cowo1}
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_aby.asm
deleted file mode 100644
index c98a20581..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_aby.asm
+++ /dev/null
@@ -1 +0,0 @@
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_xby.asm
deleted file mode 100644
index 564a51284..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_xby.asm
+++ /dev/null
@@ -1 +0,0 @@
-stx {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_yby.asm
deleted file mode 100644
index 3121ec5d9..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_sethi_yby.asm
+++ /dev/null
@@ -1 +0,0 @@
-sty {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_aby.asm
deleted file mode 100644
index 0dbfa369b..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_aby.asm
+++ /dev/null
@@ -1 +0,0 @@
-sta {zpptrby1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_xby.asm
deleted file mode 100644
index 8920b7d5c..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_xby.asm
+++ /dev/null
@@ -1 +0,0 @@
-stx {zpptrby1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_yby.asm
deleted file mode 100644
index b44e35ec0..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby1_setlo_yby.asm
+++ /dev/null
@@ -1 +0,0 @@
-sty {zpptrby1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_aby.asm
deleted file mode 100644
index c95ef856b..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_aby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sta {zpptrby1}+1
-lda {zpptrby2}
-sta {zpptrby1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_xby.asm
deleted file mode 100644
index ce21a5acf..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_xby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-stx {zpptrby1}+1
-lda {zpptrby2}
-sta {zpptrby1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_yby.asm
deleted file mode 100644
index d580d3076..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_yby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sty {zpptrby1}+1
-lda {zpptrby2}
-sta {zpptrby1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_zpby1.asm
deleted file mode 100644
index e10cc1bfe..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_sethi_zpby1.asm
+++ /dev/null
@@ -1,4 +0,0 @@
-lda {zpptrby2}
-sta {zpptrby1}
-lda {zpby1}
-sta {zpptrby1}+1
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_aby.asm
deleted file mode 100644
index 537c868aa..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_aby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sta {zpptrby1}
-lda {zpptrby2}+1
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_xby.asm
deleted file mode 100644
index bbfefa560..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_xby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-stx {zpptrby1}
-lda {zpptrby2}+1
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_yby.asm
deleted file mode 100644
index 22e10ea9f..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_yby.asm
+++ /dev/null
@@ -1,3 +0,0 @@
-sty {zpptrby1}
-lda {zpptrby2}+1
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_zpby1.asm
deleted file mode 100644
index c0d9b6952..000000000
--- a/src/main/java/dk/camelot64/kickc/fragment/asm/zpptrby1=zpptrby2_setlo_zpby1.asm
+++ /dev/null
@@ -1,4 +0,0 @@
-lda {zpby1}
-sta {zpptrby1}
-lda {zpptrby2}+1
-sta {zpptrby1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=_word_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=_word_aby.asm
new file mode 100644
index 000000000..704b0857d
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=_word_aby.asm
@@ -0,0 +1,3 @@
+sta {zpwo1}
+lda #0
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_aby.asm
new file mode 100644
index 000000000..64a2c9749
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_aby.asm
@@ -0,0 +1,3 @@
+sta {zpwo1}+1
+lda #<{coby1}
+sta {zpwo1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_xby.asm
new file mode 100644
index 000000000..82775d4e3
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_xby.asm
@@ -0,0 +1,3 @@
+stx {zpwo1}+1
+ldx #<{coby1}
+stx {zpwo1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_yby.asm
new file mode 100644
index 000000000..3bf602078
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_yby.asm
@@ -0,0 +1,3 @@
+sty {zpwo1}+1
+ldy #<{coby1}
+sty {zpwo1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_zpby1.asm
new file mode 100644
index 000000000..fea54a544
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=coby1_sethi_zpby1.asm
@@ -0,0 +1,4 @@
+lda #<{coby1}
+sta {zpwo1}
+lda {zpby1}
+sta {zpwo1}+1
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_plus_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_plus_aby.asm
new file mode 100644
index 000000000..b4791d1de
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_plus_aby.asm
@@ -0,0 +1,7 @@
+clc
+adc #<{cowo1}
+sta {zpwo1}
+lda #>{cowo1}
+adc #0
+sta {zpwo1}+1
+
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_aby.asm
new file mode 100644
index 000000000..3037fb5e3
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_aby.asm
@@ -0,0 +1,3 @@
+sta {zpwo1}+1
+lda #<{cowo1}
+sta {zpwo1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_xby.asm
new file mode 100644
index 000000000..47d8195a9
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_xby.asm
@@ -0,0 +1,3 @@
+stx {zpwo1}+1
+ldx #<{cowo1}
+stx {zpwo1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_yby.asm
new file mode 100644
index 000000000..ff9e3fb1c
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_yby.asm
@@ -0,0 +1,3 @@
+sty {zpwo1}+1
+ldy #<{cowo1}
+sty {zpwo1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_zpby1.asm
new file mode 100644
index 000000000..8bc013250
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_sethi_zpby1.asm
@@ -0,0 +1,4 @@
+lda #<{cowo1}
+sta {zpwo1}
+lda {zpby1}
+sta {zpwo1}+1
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_aby.asm
new file mode 100644
index 000000000..80cadad7b
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_aby.asm
@@ -0,0 +1,3 @@
+sta {zpwo1}
+lda #>{cowo1}
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_xby.asm
new file mode 100644
index 000000000..b72b2066b
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_xby.asm
@@ -0,0 +1,3 @@
+stx {zpwo1}
+lda #>{cowo1}
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_yby.asm
new file mode 100644
index 000000000..a2bcca793
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_yby.asm
@@ -0,0 +1,3 @@
+sty {zpwo1}
+lda #>{cowo1}
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_zpby1.asm
new file mode 100644
index 000000000..f8313dff1
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=cowo1_setlo_zpby1.asm
@@ -0,0 +1,4 @@
+lda {zpby1}
+sta {zpwo1}
+lda #>{cowo1}
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_minus_zpwo2.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_minus_zpwo2.asm
new file mode 100644
index 000000000..db5057bb4
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_minus_zpwo2.asm
@@ -0,0 +1,7 @@
+lda {zpwo1}
+sec
+sbc {zpwo2}
+sta {zpwo1}
+lda {zpwo1}+1
+sbc {zpwo2}+1
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_plus_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_plus_aby.asm
new file mode 100644
index 000000000..22d455809
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_plus_aby.asm
@@ -0,0 +1,6 @@
+clc
+adc {zpwo1}
+sta {zpwo1}
+bcc !+
+inc {zpwo1}+1
+!:
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_plus_zpwo2.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_plus_zpwo2.asm
new file mode 100644
index 000000000..96c99fd22
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_plus_zpwo2.asm
@@ -0,0 +1,8 @@
+lda {zpwo1}
+clc
+adc {zpwo2}
+sta {zpwo1}
+lda {zpwo1}+1
+adc {zpwo2}+1
+sta {zpwo1}+1
+
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_aby.asm
new file mode 100644
index 000000000..1d11defcc
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_aby.asm
@@ -0,0 +1 @@
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_xby.asm
new file mode 100644
index 000000000..7a6bb99d0
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_xby.asm
@@ -0,0 +1 @@
+stx {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_yby.asm
new file mode 100644
index 000000000..c427c54d7
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_sethi_yby.asm
@@ -0,0 +1 @@
+sty {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_aby.asm
new file mode 100644
index 000000000..10c42cdf0
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_aby.asm
@@ -0,0 +1 @@
+sta {zpwo1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_xby.asm
new file mode 100644
index 000000000..3ca36930a
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_xby.asm
@@ -0,0 +1 @@
+stx {zpwo1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_yby.asm
new file mode 100644
index 000000000..17d3d6fde
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo1_setlo_yby.asm
@@ -0,0 +1 @@
+sty {zpwo1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_minus_zpwo3.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_minus_zpwo3.asm
new file mode 100644
index 000000000..d7195edd4
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_minus_zpwo3.asm
@@ -0,0 +1,7 @@
+lda {zpwo2}
+sec
+sbc {zpwo3}
+sta {zpwo1}
+lda {zpwo2}+1
+sbc {zpwo3}+1
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_plus_zpwo3.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_plus_zpwo3.asm
new file mode 100644
index 000000000..bdf7f4206
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_plus_zpwo3.asm
@@ -0,0 +1,8 @@
+lda {zpwo1}
+clc
+adc {zpwo2}
+sta {zpwo3}
+lda {zpwo1}+1
+adc {zpwo2}+1
+sta {zpwo3}+1
+
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_aby.asm
new file mode 100644
index 000000000..24285d5d6
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_aby.asm
@@ -0,0 +1,3 @@
+sta {zpwo1}+1
+lda {zpwo2}
+sta {zpwo1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_xby.asm
new file mode 100644
index 000000000..67f7deac0
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_xby.asm
@@ -0,0 +1,3 @@
+stx {zpwo1}+1
+lda {zpwo2}
+sta {zpwo1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_yby.asm
new file mode 100644
index 000000000..8c9475e93
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_yby.asm
@@ -0,0 +1,3 @@
+sty {zpwo1}+1
+lda {zpwo2}
+sta {zpwo1}
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_zpby1.asm
new file mode 100644
index 000000000..61ae36338
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_sethi_zpby1.asm
@@ -0,0 +1,4 @@
+lda {zpwo2}
+sta {zpwo1}
+lda {zpby1}
+sta {zpwo1}+1
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_aby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_aby.asm
new file mode 100644
index 000000000..4b32f1ce9
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_aby.asm
@@ -0,0 +1,3 @@
+sta {zpwo1}
+lda {zpwo2}+1
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_xby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_xby.asm
new file mode 100644
index 000000000..e62731835
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_xby.asm
@@ -0,0 +1,3 @@
+stx {zpwo1}
+lda {zpwo2}+1
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_yby.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_yby.asm
new file mode 100644
index 000000000..daeb65b18
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_yby.asm
@@ -0,0 +1,3 @@
+sty {zpwo1}
+lda {zpwo2}+1
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_zpby1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_zpby1.asm
new file mode 100644
index 000000000..17bedfe74
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/fragment/asm/zpwo1=zpwo2_setlo_zpby1.asm
@@ -0,0 +1,4 @@
+lda {zpby1}
+sta {zpwo1}
+lda {zpwo2}+1
+sta {zpwo1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantBool.java b/src/main/java/dk/camelot64/kickc/model/ConstantBool.java
index 20a461393..d90b5e6b0 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantBool.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantBool.java
@@ -13,7 +13,7 @@ public class ConstantBool implements ConstantValue {
@Override
public SymbolType getType(ProgramScope scope) {
- return SymbolTypeBasic.BOOLEAN;
+ return SymbolType.BOOLEAN;
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantChar.java b/src/main/java/dk/camelot64/kickc/model/ConstantChar.java
index 8b957a8fc..db33fc0b4 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantChar.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantChar.java
@@ -13,7 +13,7 @@ public class ConstantChar implements ConstantValue {
@Override
public SymbolType getType(ProgramScope scope) {
- return SymbolTypeBasic.BYTE;
+ return SymbolType.BYTE;
}
public Character getValue() {
@@ -30,7 +30,7 @@ public class ConstantChar implements ConstantValue {
if (program == null) {
return "'" + value + "'";
} else {
- return "(" + SymbolTypeBasic.BYTE.getTypeName() + ") " + "'" + value + "'";
+ return "(" + SymbolType.BYTE.getTypeName() + ") " + "'" + value + "'";
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantDouble.java b/src/main/java/dk/camelot64/kickc/model/ConstantDouble.java
index faf935883..2a91c3dd7 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantDouble.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantDouble.java
@@ -13,7 +13,7 @@ public class ConstantDouble implements ConstantValue {
@Override
public SymbolType getType(ProgramScope scope) {
- return SymbolTypeBasic.DOUBLE;
+ return SymbolType.DOUBLE;
}
public Double getNumber() {
@@ -30,7 +30,7 @@ public class ConstantDouble implements ConstantValue {
if(program ==null) {
return Double.toString(number);
} else {
- return "(" + SymbolTypeBasic.VOID.getTypeName() + ") " + Double.toString(number);
+ return "(" + SymbolType.VOID.getTypeName() + ") " + Double.toString(number);
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/model/ConstantInteger.java
index ef7f345f0..53e0223ea 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantInteger.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantInteger.java
@@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+
/** SSA form constant integer value */
public class ConstantInteger implements ConstantValue {
@@ -25,13 +27,14 @@ public class ConstantInteger implements ConstantValue {
}
public SymbolType getType() {
- SymbolType type;
- if (getNumber() < 256) {
- type = SymbolTypeBasic.BYTE;
- } else {
- type = SymbolTypeBasic.WORD;
+ ArrayList potentialTypes = new ArrayList<>();
+ Integer number = getNumber();
+ for (SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) {
+ if(number>=typeInteger.getMinValue() && number<= typeInteger.getMaxValue()) {
+ potentialTypes.add(typeInteger);
+ }
}
- return type;
+ return new SymbolTypeInline(potentialTypes);
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantString.java b/src/main/java/dk/camelot64/kickc/model/ConstantString.java
index cfe33038c..4dae792e6 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantString.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantString.java
@@ -13,7 +13,7 @@ public class ConstantString implements ConstantValue {
@Override
public SymbolType getType(ProgramScope scope) {
- return SymbolTypeBasic.STRING;
+ return SymbolType.STRING;
}
public String getValue() {
@@ -30,7 +30,7 @@ public class ConstantString implements ConstantValue {
if (program == null) {
return "\"" + value + "\"";
} else {
- return "(" + SymbolTypeBasic.STRING.getTypeName() + ") " + "\"" + value + "\"";
+ return "(" + SymbolType.STRING.getTypeName() + ") " + "\"" + value + "\"";
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantValueCalculator.java b/src/main/java/dk/camelot64/kickc/model/ConstantValueCalculator.java
new file mode 100644
index 000000000..7b62dd4cb
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantValueCalculator.java
@@ -0,0 +1,95 @@
+package dk.camelot64.kickc.model;
+
+/** Can calculate the exact value for constants (used for type inference).*/
+public class ConstantValueCalculator {
+
+
+ private static ConstantValue calcValue(ProgramScope programScope, ConstantValue value) {
+ if(value instanceof ConstantInteger) {
+ return value;
+ } else if(value instanceof ConstantString) {
+ return value;
+ } else if(value instanceof ConstantChar) {
+ ConstantChar charValue = (ConstantChar) value;
+ return new ConstantInteger((int)charValue.getValue());
+ } else if(value instanceof ConstantRef) {
+ ConstantVar constantVar = programScope.getConstant((ConstantRef) value);
+ ConstantValue constantVarValue = constantVar.getValue();
+ return calcValue(programScope, constantVarValue);
+ } else if(value instanceof ConstantUnary) {
+ ConstantUnary unary = (ConstantUnary) value;
+ return calcValue(programScope, unary.getOperator(), unary.getOperand());
+ } else if(value instanceof ConstantBinary) {
+ ConstantBinary binary = (ConstantBinary) value;
+ return calcValue(programScope, binary.getLeft(), binary.getOperator(), binary.getRight());
+ } else {
+ throw new RuntimeException("Unknown constant value "+value);
+ }
+ }
+
+
+ public static ConstantValue calcValue(ProgramScope programScope, Operator operator, ConstantValue value) {
+ if(operator.equals(Operator.NEG)) {
+ return neg(calcValue(programScope, value));
+ } else if(operator.equals(Operator.POS)) {
+ return pos(calcValue(programScope, value));
+ }
+ return null;
+ }
+
+ public static ConstantValue calcValue(ProgramScope programScope, ConstantValue value1, Operator operator, ConstantValue value2) {
+ if(operator.equals(Operator.MULTIPLY)) {
+ return multiply(calcValue(programScope, value1), calcValue(programScope, value2));
+ } else if(operator.equals(Operator.PLUS)) {
+ return plus(calcValue(programScope, value1), calcValue(programScope, value2));
+ } else if(operator.equals(Operator.MINUS)) {
+ return minus(calcValue(programScope, value1), calcValue(programScope, value2));
+ } else if(operator.equals(Operator.DIVIDE)) {
+ return div(calcValue(programScope, value1), calcValue(programScope, value2));
+ }
+ return null;
+ }
+
+ private static ConstantValue neg(ConstantValue value) {
+ if(value instanceof ConstantInteger) {
+ return new ConstantInteger(-((ConstantInteger) value).getNumber());
+ }
+ return null;
+ }
+
+ private static ConstantValue pos(ConstantValue value) {
+ if(value instanceof ConstantInteger) {
+ return new ConstantInteger(+((ConstantInteger) value).getNumber());
+ }
+ return null;
+ }
+
+ private static ConstantValue multiply(ConstantValue value1, ConstantValue value2) {
+ if(value1 instanceof ConstantInteger && value2 instanceof ConstantInteger) {
+ return new ConstantInteger(((ConstantInteger) value1).getNumber()*((ConstantInteger) value2).getNumber());
+ }
+ return null;
+ }
+
+ private static ConstantValue plus(ConstantValue value1, ConstantValue value2) {
+ if(value1 instanceof ConstantInteger && value2 instanceof ConstantInteger) {
+ return new ConstantInteger(((ConstantInteger) value1).getNumber()+((ConstantInteger) value2).getNumber());
+ }
+ return null;
+ }
+
+ private static ConstantValue minus(ConstantValue value1, ConstantValue value2) {
+ if(value1 instanceof ConstantInteger && value2 instanceof ConstantInteger) {
+ return new ConstantInteger(((ConstantInteger) value1).getNumber()-((ConstantInteger) value2).getNumber());
+ }
+ return null;
+ }
+
+ private static ConstantValue div(ConstantValue value1, ConstantValue value2) {
+ if(value1 instanceof ConstantInteger && value2 instanceof ConstantInteger) {
+ return new ConstantInteger(((ConstantInteger) value1).getNumber()/((ConstantInteger) value2).getNumber());
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/Label.java b/src/main/java/dk/camelot64/kickc/model/Label.java
index 1d7828b53..29756c032 100644
--- a/src/main/java/dk/camelot64/kickc/model/Label.java
+++ b/src/main/java/dk/camelot64/kickc/model/Label.java
@@ -65,7 +65,7 @@ public class Label implements Symbol {
@JsonIgnore
public SymbolType getType() {
- return SymbolTypeBasic.LABEL;
+ return SymbolType.LABEL;
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/model/Operator.java b/src/main/java/dk/camelot64/kickc/model/Operator.java
index b985ffe72..dd6ddd0fe 100644
--- a/src/main/java/dk/camelot64/kickc/model/Operator.java
+++ b/src/main/java/dk/camelot64/kickc/model/Operator.java
@@ -70,9 +70,9 @@ public class Operator {
public static Operator getUnary(String op) {
switch (op) {
case "+":
- return UNARY_PLUS;
+ return POS;
case "-":
- return UNARY_MINUS;
+ return NEG;
case "++":
return INCREMENT;
case "--":
@@ -93,13 +93,13 @@ public class Operator {
}
public static Operator getCastUnary(SymbolType castType) {
- if (SymbolTypeBasic.BYTE.equals(castType)) {
+ if (SymbolType.BYTE.equals(castType)) {
return CAST_BYTE;
- } else if (SymbolTypeBasic.SBYTE.equals(castType)) {
+ } else if (SymbolType.SBYTE.equals(castType)) {
return CAST_SBYTE;
- } else if (SymbolTypeBasic.WORD.equals(castType)) {
+ } else if (SymbolType.WORD.equals(castType)) {
return CAST_WORD;
- } else if (SymbolTypeBasic.SWORD.equals(castType)) {
+ } else if (SymbolType.SWORD.equals(castType)) {
return CAST_SWORD;
} else {
throw new RuntimeException("Unknown cast type " + castType);
@@ -113,8 +113,8 @@ public class Operator {
public static final Operator INCREMENT = new Operator("++", "_inc_", Type.UNARY, 1);
public static final Operator DECREMENT = new Operator("--", "_dec_", Type.UNARY, 1);
- public static final Operator UNARY_PLUS = new Operator("+", "_pos_", Type.UNARY, 2);
- public static final Operator UNARY_MINUS = new Operator("-", "_neg_", Type.UNARY, 2);
+ public static final Operator POS = new Operator("+", "_pos_", Type.UNARY, 2);
+ public static final Operator NEG = new Operator("-", "_neg_", Type.UNARY, 2);
public static final Operator BOOL_NOT = new Operator("~", "_not_", Type.UNARY, 2);
public static final Operator NOT = new Operator("!", "_not_", Type.UNARY, 2);
public static final Operator DEREF = new Operator("*", "_deref_", Type.UNARY, 2);
diff --git a/src/main/java/dk/camelot64/kickc/model/Registers.java b/src/main/java/dk/camelot64/kickc/model/Registers.java
index 9ade365d6..a8d931a17 100644
--- a/src/main/java/dk/camelot64/kickc/model/Registers.java
+++ b/src/main/java/dk/camelot64/kickc/model/Registers.java
@@ -41,6 +41,7 @@ public class Registers {
ZP_BYTE, ZP_SBYTE,
ZP_PTR_BYTE,
ZP_WORD,
+ ZP_SWORD,
ZP_BOOL,
CONSTANT
}
@@ -147,6 +148,21 @@ public class Registers {
}
+ /** Two zero page addresses used as a register for a single signed word variable. */
+ public static class RegisterZpSWord extends RegisterZp {
+
+ public RegisterZpSWord(int zp) {
+ super(zp);
+ }
+
+ @Override
+ public RegisterType getType() {
+ return RegisterType.ZP_SWORD;
+ }
+
+ }
+
+
/** A zero page address used as a register for a boolean variable. */
public static class RegisterZpBool extends RegisterZp {
diff --git a/src/main/java/dk/camelot64/kickc/model/Scope.java b/src/main/java/dk/camelot64/kickc/model/Scope.java
index 9143a6b77..e6e08c88a 100644
--- a/src/main/java/dk/camelot64/kickc/model/Scope.java
+++ b/src/main/java/dk/camelot64/kickc/model/Scope.java
@@ -113,7 +113,7 @@ public abstract class Scope implements Symbol {
public VariableIntermediate addVariableIntermediate() {
String name = "$" + intermediateVarCount++;
- VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolTypeBasic.VAR);
+ VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolType.VAR);
add(symbol);
return symbol;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/SymbolType.java
index 24c758430..0c887062d 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolType.java
@@ -1,18 +1,127 @@
package dk.camelot64.kickc.model;
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import java.util.ArrayList;
+import java.util.Collection;
/** Symbol Types */
-@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
-@JsonSubTypes({
- @JsonSubTypes.Type(value = SymbolTypeProgram.class, name = "program"),
- @JsonSubTypes.Type(value = SymbolTypeBasic.class, name = "basic"),
- @JsonSubTypes.Type(value = SymbolTypeArray.class, name = "array"),
- @JsonSubTypes.Type(value = SymbolTypePointer.class, name = "pointer"),
- @JsonSubTypes.Type(value = SymbolTypeProcedure.class, name = "procedure")
-})
public interface SymbolType {
- public String getTypeName();
+
+ /** Unsigned byte (8 bits)). */
+ SymbolTypeInteger BYTE = new SymbolTypeInteger("byte", 0, 255);
+ /** Signed byte (8 bits). */
+ SymbolTypeInteger SBYTE = new SymbolTypeInteger("signed byte", -128, 127);
+ /** Unsigned word (2 bytes, 16 bits). */
+ SymbolTypeInteger WORD = new SymbolTypeInteger("word", 0, 65_535);
+ /** Signed word (2 bytes, 16 bits). */
+ SymbolTypeInteger SWORD = new SymbolTypeInteger("signed word", -32_768, 32_767);
+ /** String value (treated like byte* ). */
+ SymbolTypeBasic STRING = new SymbolTypeBasic("string");
+ /** Boolean value. */
+ SymbolTypeBasic BOOLEAN = new SymbolTypeBasic("boolean");
+ /** Numeric floating point value. */
+ SymbolTypeBasic DOUBLE = new SymbolTypeBasic("double");
+ /** A label. Name of functions of jump-targets. */
+ SymbolTypeBasic LABEL = new SymbolTypeBasic("label");
+ /** Void type representing no value. */
+ SymbolTypeBasic VOID = new SymbolTypeBasic("void");
+ /** An unresolved type. Will be infered later. */
+ SymbolTypeBasic VAR = new SymbolTypeBasic("var");
+
+ /**
+ * Get the name of the type
+ * @return The type name
+ */
+ String getTypeName();
+
+ /**
+ * Get a simple symbol type from the type name.
+ * @param name The type name.
+ * @return The simple symbol type
+ */
+ static SymbolType get(String name) {
+ switch (name) {
+ case "byte": return BYTE;
+ case "signed byte": return SBYTE;
+ case "word": return WORD;
+ case "signed word": return SWORD;
+ case "string": return STRING;
+ case "boolean": return BOOLEAN;
+ case "void": return VOID;
+ }
+ return null;
+ }
+
+ /**
+ * Get all integer types.
+ * @return All integeer types
+ */
+ static Collection getIntegerTypes() {
+ ArrayList types = new ArrayList<>();
+ types.add(BYTE);
+ types.add(SBYTE);
+ types.add(WORD);
+ types.add(SWORD);
+ return types;
+ }
+
+ /**
+ * Is the type {@link #BYTE} or compatible {@link SymbolTypeInline}
+ * @param type The type to examine
+ * @return true if the type is BYTE compatible
+ */
+ static boolean isByte(SymbolType type) {
+ if(BYTE.equals(type)) {
+ return true;
+ } else if(type instanceof SymbolTypeInline) {
+ return ((SymbolTypeInline) type).isByte();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Is the type {@link #SBYTE} or compatible {@link SymbolTypeInline}
+ * @param type The type to examine
+ * @return true if the type is SBYTE compatible
+ */
+ static boolean isSByte(SymbolType type) {
+ if(SBYTE.equals(type)) {
+ return true;
+ } else if(type instanceof SymbolTypeInline) {
+ return ((SymbolTypeInline) type).isSByte();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Is the type {@link #WORD} or compatible {@link SymbolTypeInline}
+ * @param type The type to examine
+ * @return true if the type is WORD compatible
+ */
+ static boolean isWord(SymbolType type) {
+ if(WORD.equals(type)) {
+ return true;
+ } else if(type instanceof SymbolTypeInline) {
+ return ((SymbolTypeInline) type).isWord();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Is the type {@link #SWORD} or compatible {@link SymbolTypeInline}
+ * @param type The type to examine
+ * @return true if the type is SWORD compatible
+ */
+ static boolean isSWord(SymbolType type) {
+ if(SWORD.equals(type)) {
+ return true;
+ } else if(type instanceof SymbolTypeInline) {
+ return ((SymbolTypeInline) type).isSWord();
+ } else {
+ return false;
+ }
+ }
}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java
index f1d1a5c39..c31d4245d 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java
@@ -1,32 +1,11 @@
package dk.camelot64.kickc.model;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
/** Basic Symbol Types */
public class SymbolTypeBasic implements SymbolType {
- public static final SymbolTypeBasic BYTE = new SymbolTypeBasic("byte");
- public static final SymbolTypeBasic SBYTE = new SymbolTypeBasic("signed byte");
-
- public static final SymbolTypeBasic WORD = new SymbolTypeBasic("word");
- public static final SymbolTypeBasic SWORD = new SymbolTypeBasic("signed word");
-
- public static final SymbolTypeBasic STRING = new SymbolTypeBasic("string");
- public static final SymbolTypeBasic BOOLEAN = new SymbolTypeBasic("boolean");
- public static final SymbolTypeBasic DOUBLE = new SymbolTypeBasic("double");
- // A label
- public static final SymbolTypeBasic LABEL = new SymbolTypeBasic("label");
- // Void type.
- public static final SymbolTypeBasic VOID = new SymbolTypeBasic("void");
- // Unresolved type. Will be infered later
- public static final SymbolTypeBasic VAR = new SymbolTypeBasic("var");
-
private String typeName;
- @JsonCreator
- SymbolTypeBasic(
- @JsonProperty("typeName") String typeName) {
+ SymbolTypeBasic(String typeName) {
this.typeName = typeName;
}
@@ -34,19 +13,6 @@ public class SymbolTypeBasic implements SymbolType {
return typeName;
}
- public static SymbolTypeBasic get(String name) {
- switch (name) {
- case "byte": return BYTE;
- case "signed byte": return SBYTE;
- case "word": return WORD;
- case "signed word": return SWORD;
- case "string": return STRING;
- case "boolean": return BOOLEAN;
- case "void": return VOID;
- }
- return null;
- }
-
@Override
public boolean equals(Object o) {
if (this == o) {
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java
index 7cab9c4eb..6c6b4ad8a 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java
@@ -5,6 +5,39 @@ package dk.camelot64.kickc.model;
*/
public class SymbolTypeInference {
+
+ /**
+ * Infer the type of a unary operator on a value
+ *
+ * @param programScope The program scope usable for accessing the symbol table
+ * @param operator The unary operator
+ * @param rValue The value
+ * @return The type of the resulting value
+ */
+ public static SymbolType inferType(ProgramScope programScope, Operator operator, RValue rValue) {
+ if (rValue instanceof ConstantValue) {
+ ConstantValue value = ConstantValueCalculator.calcValue(programScope, operator, (ConstantValue) rValue);
+ if (value != null) {
+ return value.getType(programScope);
+ }
+ }
+ SymbolType valueType = inferType(programScope, rValue);
+ return inferType(operator, valueType);
+ }
+
+ public static SymbolType inferType(ProgramScope programScope, RValue rValue1, Operator operator, RValue rValue2) {
+ if (rValue1 instanceof ConstantValue && rValue2 instanceof ConstantValue) {
+ ConstantValue value = ConstantValueCalculator.calcValue(programScope, (ConstantValue) rValue1, operator, (ConstantValue) rValue2);
+ if (value != null) {
+ return value.getType(programScope);
+ }
+ }
+ SymbolType valueType1 = inferType(programScope, rValue1);
+ SymbolType valueType2 = inferType(programScope, rValue2);
+ return inferType(valueType1, operator, valueType2);
+ }
+
+
public static SymbolType inferType(Operator operator, SymbolType subType) {
if (operator == null) {
return subType;
@@ -16,21 +49,21 @@ public class SymbolTypeInference {
throw new RuntimeException("Type error: Dereferencing a non-pointer " + subType);
}
} else if (Operator.LOWBYTE.equals(operator)) {
- if (subType instanceof SymbolTypePointer || SymbolTypeBasic.WORD.equals(subType)) {
- return SymbolTypeBasic.BYTE;
+ if (subType instanceof SymbolTypePointer || SymbolType.WORD.equals(subType)) {
+ return SymbolType.BYTE;
}
} else if (Operator.HIBYTE.equals(operator)) {
- if (subType instanceof SymbolTypePointer || SymbolTypeBasic.WORD.equals(subType)) {
- return SymbolTypeBasic.BYTE;
+ if (subType instanceof SymbolTypePointer || SymbolType.WORD.equals(subType)) {
+ return SymbolType.BYTE;
}
} else if (Operator.CAST_BYTE.equals(operator)) {
- return SymbolTypeBasic.BYTE;
+ return SymbolType.BYTE;
} else if (Operator.CAST_SBYTE.equals(operator)) {
- return SymbolTypeBasic.SBYTE;
+ return SymbolType.SBYTE;
} else if (Operator.CAST_WORD.equals(operator)) {
- return SymbolTypeBasic.WORD;
+ return SymbolType.WORD;
} else if (Operator.CAST_SWORD.equals(operator)) {
- return SymbolTypeBasic.SWORD;
+ return SymbolType.SWORD;
} else {
return subType;
}
@@ -38,6 +71,14 @@ public class SymbolTypeInference {
}
public static SymbolType inferType(SymbolType type1, Operator operator, SymbolType type2) {
+
+ if (operator.equals(Operator.PLUS)) {
+ return inferPlus(type1, type2);
+ } else if (operator.equals(Operator.MINUS)) {
+ return inferMinus(type1, type2);
+ }
+
+
String op = operator.getOperator();
switch (op) {
case "==":
@@ -53,41 +94,17 @@ public class SymbolTypeInference {
case "||":
case "and":
case "or":
- return SymbolTypeBasic.BOOLEAN;
- case "+":
- if (type1.equals(SymbolTypeBasic.STRING) && SymbolTypeBasic.BYTE.equals(type2)) {
- return SymbolTypeBasic.STRING;
- } else if (type1.equals(SymbolTypeBasic.STRING) && SymbolTypeBasic.STRING.equals(type2)) {
- return SymbolTypeBasic.STRING;
- }
- case "-":
- // Also continues "+"
- if (type1 instanceof SymbolTypePointer && (type2.equals(SymbolTypeBasic.BYTE) || type2.equals(SymbolTypeBasic.WORD))) {
- return new SymbolTypePointer(((SymbolTypePointer) type1).getElementType());
- }
- if (type1 instanceof SymbolTypePointer && type2 instanceof SymbolTypePointer) {
- SymbolType elmType1 = ((SymbolTypePointer) type1).getElementType();
- SymbolType elmType2 = ((SymbolTypePointer) type2).getElementType();
- return inferType(elmType1, operator, elmType2);
- }
- if (SymbolTypeBasic.WORD.equals(type1) || SymbolTypeBasic.WORD.equals(type2)) {
- return SymbolTypeBasic.WORD;
- } else if (SymbolTypeBasic.BYTE.equals(type1) && SymbolTypeBasic.BYTE.equals(type2)) {
- return SymbolTypeBasic.BYTE;
- } else if (SymbolTypeBasic.SBYTE.equals(type1) && SymbolTypeBasic.SBYTE.equals(type2)) {
- return SymbolTypeBasic.SBYTE;
- }
- throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2);
+ return SymbolType.BOOLEAN;
case "*":
if (type1 == null && type2 instanceof SymbolTypePointer) {
return ((SymbolTypePointer) type2).getElementType();
}
- if (SymbolTypeBasic.WORD.equals(type1) || SymbolTypeBasic.WORD.equals(type2)) {
- return SymbolTypeBasic.WORD;
- } else if (SymbolTypeBasic.BYTE.equals(type1) && SymbolTypeBasic.BYTE.equals(type2)) {
- return SymbolTypeBasic.BYTE;
- } else if (SymbolTypeBasic.SBYTE.equals(type1) && SymbolTypeBasic.SBYTE.equals(type2)) {
- return SymbolTypeBasic.SBYTE;
+ if (SymbolType.WORD.equals(type1) || SymbolType.WORD.equals(type2)) {
+ return SymbolType.WORD;
+ } else if (isByte(type1) && isByte(type2)) {
+ return SymbolType.BYTE;
+ } else if (SymbolType.SBYTE.equals(type1) && SymbolType.SBYTE.equals(type2)) {
+ return SymbolType.SBYTE;
}
throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2);
case "*idx":
@@ -96,25 +113,25 @@ public class SymbolTypeInference {
}
throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2);
case "/":
- if (type1 instanceof SymbolTypePointer && SymbolTypeBasic.BYTE.equals(type2)) {
+ if (type1 instanceof SymbolTypePointer && isByte(type2)) {
return type1;
}
case "&":
case "|":
case "^":
- if (SymbolTypeBasic.WORD.equals(type1) || SymbolTypeBasic.WORD.equals(type2)) {
- return SymbolTypeBasic.WORD;
- } else if (SymbolTypeBasic.BYTE.equals(type1) && SymbolTypeBasic.BYTE.equals(type2)) {
- return SymbolTypeBasic.BYTE;
+ if (SymbolType.WORD.equals(type1) || SymbolType.WORD.equals(type2)) {
+ return SymbolType.WORD;
+ } else if (isByte(type1) && isByte(type2)) {
+ return SymbolType.BYTE;
}
throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2);
case "<<":
case ">>":
- if (SymbolTypeBasic.WORD.equals(type1)) {
- return SymbolTypeBasic.WORD;
- } else if (SymbolTypeBasic.BYTE.equals(type1)) {
- return SymbolTypeBasic.BYTE;
+ if (SymbolType.WORD.equals(type1)) {
+ return SymbolType.WORD;
+ } else if (isByte(type1)) {
+ return SymbolType.BYTE;
}
throw new RuntimeException("Type inference case not handled " + type1 + " " + operator + " " + type2);
default:
@@ -122,6 +139,110 @@ public class SymbolTypeInference {
}
}
+ private static SymbolType inferPlus(SymbolType type1, SymbolType type2) {
+ if (type1.equals(SymbolType.STRING) && isByte(type2)) {
+ return SymbolType.STRING;
+ } else if (type1.equals(SymbolType.STRING) && SymbolType.STRING.equals(type2)) {
+ return SymbolType.STRING;
+ }
+ if (type1 instanceof SymbolTypePointer && isInteger(type2)) {
+ return new SymbolTypePointer(((SymbolTypePointer) type1).getElementType());
+ }
+ if (isByte(type1) && isByte(type2)) {
+ return SymbolType.BYTE;
+ }
+ if (isSByte(type1) && isSByte(type2)) {
+ return SymbolType.SBYTE;
+ }
+ if (isWord(type1) && isWord(type2)) {
+ return SymbolType.WORD;
+ }
+ if (isSWord(type1) && isSWord(type2)) {
+ return SymbolType.SWORD;
+ }
+ throw new RuntimeException("Type inference case not handled " + type1 + " " + "+" + " " + type2);
+ }
+
+ private static SymbolType inferMinus(SymbolType type1, SymbolType type2) {
+ if (type1 instanceof SymbolTypePointer && isInteger(type2)) {
+ return new SymbolTypePointer(((SymbolTypePointer) type1).getElementType());
+ }
+ if (type1 instanceof SymbolTypePointer && type2 instanceof SymbolTypePointer) {
+ return SymbolType.WORD;
+ }
+ if (isByte(type1) && isByte(type2)) {
+ return SymbolType.BYTE;
+ }
+ if (isSByte(type1) && isSByte(type2)) {
+ return SymbolType.SBYTE;
+ }
+ if (isWord(type1) && isWord(type2)) {
+ return SymbolType.WORD;
+ }
+ if (isSWord(type1) && isSWord(type2)) {
+ return SymbolType.SWORD;
+ }
+ throw new RuntimeException("Type inference case not handled " + type1 + " " + "+" + " " + type2);
+ }
+
+
+ private static boolean isInteger(SymbolType type) {
+ if (SymbolType.BYTE.equals(type)) {
+ return true;
+ } else if (SymbolType.WORD.equals(type)) {
+ return true;
+ } else if (SymbolType.SBYTE.equals(type)) {
+ return true;
+ } else if (SymbolType.SWORD.equals(type)) {
+ return true;
+ } else if (type instanceof SymbolTypeInline) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private static boolean isByte(SymbolType type) {
+ if (SymbolType.BYTE.equals(type)) {
+ return true;
+ } else if (type instanceof SymbolTypeInline) {
+ return ((SymbolTypeInline) type).isByte();
+ } else {
+ return false;
+ }
+ }
+
+ private static boolean isSByte(SymbolType type) {
+ if (SymbolType.SBYTE.equals(type)) {
+ return true;
+ } else if (type instanceof SymbolTypeInline) {
+ return ((SymbolTypeInline) type).isSByte();
+ } else {
+ return false;
+ }
+ }
+
+ private static boolean isWord(SymbolType type) {
+ if (SymbolType.WORD.equals(type)) {
+ return true;
+ } else if (type instanceof SymbolTypeInline) {
+ return ((SymbolTypeInline) type).isWord();
+ } else {
+ return false;
+ }
+ }
+
+ private static boolean isSWord(SymbolType type) {
+ if (SymbolType.SWORD.equals(type)) {
+ return true;
+ } else if (type instanceof SymbolTypeInline) {
+ return ((SymbolTypeInline) type).isSWord();
+ } else {
+ return false;
+ }
+ }
+
+
public static SymbolType inferType(ProgramScope programScope, RValue rValue) {
SymbolType type = null;
if (rValue instanceof VariableRef) {
@@ -137,11 +258,11 @@ public class SymbolTypeInference {
ConstantInteger rInt = (ConstantInteger) rValue;
return rInt.getType(programScope);
} else if (rValue instanceof ConstantString) {
- type = SymbolTypeBasic.STRING;
+ type = SymbolType.STRING;
} else if (rValue instanceof ConstantChar) {
- type = SymbolTypeBasic.BYTE;
+ type = SymbolType.BYTE;
} else if (rValue instanceof ConstantBool) {
- type = SymbolTypeBasic.BOOLEAN;
+ type = SymbolType.BOOLEAN;
} else if (rValue instanceof ConstantUnary) {
ConstantUnary constUnary = (ConstantUnary) rValue;
SymbolType subType = inferType(programScope, constUnary.getOperand());
@@ -164,4 +285,5 @@ public class SymbolTypeInference {
}
return type;
}
+
}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInline.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInline.java
new file mode 100644
index 000000000..27ac8bb6d
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInline.java
@@ -0,0 +1,76 @@
+package dk.camelot64.kickc.model;
+
+import java.util.Collection;
+
+/**
+ * Symbol Type of an inline numeric expression. Inline expressions can match multiple types depending on the actual value,
+ * eg. the value 27 matches both byte and signed byte (which can in turn be promoted to word/signed word) , while the value -252 only matches signed word.
+ */
+public class SymbolTypeInline implements SymbolType {
+
+ /**
+ * All potential types for the inline constant.
+ */
+ private Collection types;
+
+ public SymbolTypeInline(Collection types) {
+ this.types = types;
+ }
+
+ public Collection getTypes() {
+ return types;
+ }
+
+ @Override
+ public String getTypeName() {
+ StringBuilder name = new StringBuilder();
+ boolean first = true;
+ for (SymbolTypeInteger type : types) {
+ if(first) {
+ first = false;
+ } else {
+ name.append("/");
+ }
+ name.append(type);
+ }
+ return name.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SymbolTypeInline that = (SymbolTypeInline) o;
+ return types != null ? types.equals(that.types) : that.types == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return types != null ? types.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return getTypeName();
+ }
+
+ /**
+ * Is unsigned byte one of the potential types
+ * @return true if unsigned byte is a potential type
+ */
+ public boolean isByte() {
+ return types.contains(BYTE);
+ }
+
+ public boolean isSByte() {
+ return types.contains(SBYTE);
+ }
+
+ public boolean isWord() {
+ return types.contains(WORD);
+ }
+
+ public boolean isSWord() {
+ return types.contains(SWORD);
+ }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInteger.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInteger.java
new file mode 100644
index 000000000..34abe30fb
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInteger.java
@@ -0,0 +1,33 @@
+package dk.camelot64.kickc.model;
+
+/** Integer symbol types (byte, signed byte, word, ...). */
+public class SymbolTypeInteger implements SymbolType {
+
+ private final String typeName;
+ private final int minValue;
+ private final int maxValue;
+
+ SymbolTypeInteger(String typeName, int minValue, int maxValue) {
+ this.typeName = typeName;
+ this.minValue = minValue;
+ this.maxValue = maxValue;
+ }
+
+ @Override
+ public String getTypeName() {
+ return typeName;
+ }
+
+ public int getMinValue() {
+ return minValue;
+ }
+
+ public int getMaxValue() {
+ return maxValue;
+ }
+
+ @Override
+ public String toString() {
+ return getTypeName();
+ }
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java
index 486eebd3e..32a5405fc 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java
@@ -273,7 +273,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor