From 21d7c6849c2a07d72592afcbd88235eddc3b8e32 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Mon, 22 Apr 2019 13:47:22 +0200
Subject: [PATCH 01/93] Added tests failing due to constant type interference
 problems. Working on #181

---
 .../java/dk/camelot64/kickc/test/TestPrograms.java | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 8877be5d6..59d4212f9 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -37,15 +37,15 @@ public class TestPrograms {
    //   compileAndCompare("pointer-cast-3");
    //}
 
-   //@Test
-   //public void testTypeIdPlusByteProblem() throws IOException, URISyntaxException {
-   //   compileAndCompare("typeid-plus-byte-problem");
-   //}
+   @Test
+   public void testTypeIdPlusByteProblem() throws IOException, URISyntaxException {
+      compileAndCompare("typeid-plus-byte-problem");
+   }
 
    //@Test
-   //public void testTypeIdPlusBytes() throws IOException, URISyntaxException {
-   //   compileAndCompare("typeid-plus-bytes");
-   //}
+   public void testTypeIdPlusBytes() throws IOException, URISyntaxException {
+      compileAndCompare("typeid-plus-bytes");
+   }
 
    @Test
    public void testTypeIdSimple() throws IOException, URISyntaxException {

From 1fa41859b0663b4550406ebf1e900d30a0ca9c8d Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 23 Apr 2019 20:42:18 +0200
Subject: [PATCH 02/93] Starting work on type system.

---
 .../kickc/model/types/SymbolTypeMulti.java    | 18 ++++++++++
 .../kickc/model/values/ConstantInteger.java   | 25 +++++++------
 .../passes/Pass2ConstantIdentification.java   | 35 ++++++++++++-------
 .../dk/camelot64/kickc/test/TestPrograms.java |  2 +-
 src/test/kc/typeid-plus-byte-problem.kc       |  5 +--
 5 files changed, 56 insertions(+), 29 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
index 802810c7f..5b1ca45a5 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
@@ -1,5 +1,6 @@
 package dk.camelot64.kickc.model.types;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 
@@ -11,6 +12,7 @@ public class SymbolTypeMulti implements SymbolType {
 
    /** All numeric types. */
    public static final SymbolTypeMulti NUMERIC = new SymbolTypeMulti(Arrays.asList(BYTE, SBYTE, WORD, SWORD, DWORD, SDWORD));
+
    /**
     * All potential types for the inline constant.
     */
@@ -24,6 +26,22 @@ public class SymbolTypeMulti implements SymbolType {
       return types;
    }
 
+
+   /**
+    * Get the multi-type that can contain the passed number.
+    * @param number The number
+    * @return The multi-type
+    */
+   public static SymbolType getMultiType(Long number) {
+      ArrayList<SymbolType> potentialTypes = new ArrayList<>();
+      for(SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) {
+         if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) {
+            potentialTypes.add(typeInteger);
+         }
+      }
+      return new SymbolTypeMulti(potentialTypes);
+   }
+
    @Override
    public int getSizeBytes() {
       // Find the minimal sizeof - and return that
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
index c56e01657..b0131e99e 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
@@ -5,17 +5,23 @@ import dk.camelot64.kickc.model.*;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeMulti;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
 
-import java.util.ArrayList;
-
-/** SSA form constant integer value */
+/** Constant integer value */
 public class ConstantInteger implements ConstantEnumerable<Long> {
 
    private Long number;
 
-   public ConstantInteger( Long number) {
+   /** The type of the number. (Either specific or the multi-type)*/
+   private SymbolType type;
+
+   public ConstantInteger(Long number) {
       this.number = number;
+      this.type = SymbolTypeMulti.getMultiType(number);
+   }
+
+   public ConstantInteger(Long number, SymbolType type) {
+      this.number = number;
+      this.type = type;
    }
 
    @Override
@@ -32,14 +38,7 @@ public class ConstantInteger implements ConstantEnumerable<Long> {
    }
 
    public SymbolType getType() {
-      ArrayList<SymbolType> potentialTypes = new ArrayList<>();
-      Long number = getValue();
-      for(SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) {
-         if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) {
-            potentialTypes.add(typeInteger);
-         }
-      }
-      return new SymbolTypeMulti(potentialTypes);
+      return type;
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
index 7ae4366dd..f3c968da0 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
@@ -4,7 +4,9 @@ import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.ControlFlowBlock;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
-import dk.camelot64.kickc.model.operators.*;
+import dk.camelot64.kickc.model.operators.OperatorBinary;
+import dk.camelot64.kickc.model.operators.OperatorUnary;
+import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementPhiBlock;
@@ -50,7 +52,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
             // 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) {
+               if(assignment.getOperator() != null) {
                   getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false));
                   assignment.setOperator(null);
                   assignment.setrValue1(null);
@@ -201,6 +203,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
 
    /**
     * 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
@@ -259,7 +262,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
             }
             if(allConstant && listType != null) {
                // Constant list confirmed!
-               return  new ConstantArrayList(elements, listType);
+               return new ConstantArrayList(elements, listType);
             }
          }
       } else if(Operators.ADDRESS_OF.equals(assignment.getOperator()) && assignment.getrValue1() == null) {
@@ -307,18 +310,24 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
    }
 
    static ConstantValue createBinary(ConstantValue c1, OperatorBinary operator, ConstantValue c2, ProgramScope programScope) {
+
+      // Special handling of string append using +
+      if(Operators.PLUS.equals(operator) && SymbolType.STRING.equals(c1.getType(programScope))) {
+         if(c1 instanceof ConstantRef) {
+            c1 = programScope.getConstant((ConstantRef) c1).getValue();
+         }
+         if(c2 instanceof ConstantRef) {
+            c2 = programScope.getConstant((ConstantRef) c2).getValue();
+         }
+         return new ConstantBinary(c1, operator, c2);
+      }
+
+      if(Operators.PLUS.equals(operator)) {
+         return new ConstantBinary(c1, operator, c2);
+      }
+
       switch(operator.getOperator()) {
          case "-":
-         case "+":
-            if(SymbolType.STRING.equals(c1.getType(programScope))) {
-               if(c1 instanceof ConstantRef) {
-                  c1 = programScope.getConstant((ConstantRef) c1).getValue();
-               }
-               if(c2 instanceof ConstantRef) {
-                  c2 = programScope.getConstant((ConstantRef) c2).getValue();
-               }
-               return new ConstantBinary(c1, operator, c2);
-            }
          case "*":
          case "/":
          case "%":
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 59d4212f9..c47e892ae 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -39,7 +39,7 @@ public class TestPrograms {
 
    @Test
    public void testTypeIdPlusByteProblem() throws IOException, URISyntaxException {
-      compileAndCompare("typeid-plus-byte-problem");
+      compileAndCompare("typeid-plus-byte-problem", log());
    }
 
    //@Test
diff --git a/src/test/kc/typeid-plus-byte-problem.kc b/src/test/kc/typeid-plus-byte-problem.kc
index c4ddec78f..1b7cc98c6 100644
--- a/src/test/kc/typeid-plus-byte-problem.kc
+++ b/src/test/kc/typeid-plus-byte-problem.kc
@@ -3,7 +3,8 @@
 const byte* SCREEN = $400;
 
 void main() {
-    unsigned byte ubc1 = 250;
-    SCREEN[0] = ubc1+250;
+    unsigned byte ubc1 = 12+13+14;
+    unsigned byte ubc2 = 250;
+    SCREEN[0] = ubc1+ubc2;
 }
 

From fd72ecc0c746edcc1b47a9cb22c12742ca24dd29 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 27 Apr 2019 12:12:44 +0200
Subject: [PATCH 03/93] Added syntax for typed integer literal postfix
 (ub/sb/uc/sc/uw/sw/ui/si/us/ss/ud/sd/ul/sl and l)

---
 .../java/dk/camelot64/kickc/parser/KickC.g4   |   2 +-
 .../dk/camelot64/kickc/parser/KickCLexer.java | 614 +++++++++---------
 .../dk/camelot64/kickc/test/TestPrograms.java |   2 +-
 3 files changed, 310 insertions(+), 308 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4
index dbc6688a9..9c0cbfe03 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4
+++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4
@@ -236,7 +236,7 @@ NUMFLOAT : BINFLOAT | DECFLOAT | HEXFLOAT;
 BINFLOAT : ('%' | '0b' | '0B' ) (BINDIGIT)* '.' BINDIGIT+;
 DECFLOAT : (DECDIGIT)* '.' DECDIGIT+;
 HEXFLOAT : ('$' | '0x' | '0X' ) (HEXDIGIT)* '.' HEXDIGIT+;
-NUMINT : DECINTEGER | HEXINTEGER | BININTEGER ;
+NUMINT : (DECINTEGER | HEXINTEGER | BININTEGER ) ([us][bcwisdl] | 'l')? ;
 BININTEGER : '0' [bB] BINDIGIT+ | '%' BINDIGIT+ ;
 DECINTEGER : DECDIGIT+ ;
 HEXINTEGER : ( '$' | '0x' | '0X' ) HEXDIGIT+ ;
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
index c628f18ce..4b9fc4407 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
@@ -138,7 +138,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\2b\u03d7\b\1\4\2\t"+
+		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2b\u03dc\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"+
@@ -186,311 +186,313 @@ public class KickCLexer extends Lexer {
 		"\16V\u034f\13V\3V\3V\6V\u0353\nV\rV\16V\u0354\3W\7W\u0358\nW\fW\16W\u035b"+
 		"\13W\3W\3W\6W\u035f\nW\rW\16W\u0360\3X\3X\3X\3X\3X\5X\u0368\nX\3X\7X\u036b"+
 		"\nX\fX\16X\u036e\13X\3X\3X\6X\u0372\nX\rX\16X\u0373\3Y\3Y\3Y\5Y\u0379"+
-		"\nY\3Z\3Z\3Z\6Z\u037e\nZ\rZ\16Z\u037f\3Z\3Z\6Z\u0384\nZ\rZ\16Z\u0385\5"+
-		"Z\u0388\nZ\3[\6[\u038b\n[\r[\16[\u038c\3\\\3\\\3\\\3\\\3\\\5\\\u0394\n"+
-		"\\\3\\\6\\\u0397\n\\\r\\\16\\\u0398\3]\3]\3^\3^\3_\3_\3`\3`\7`\u03a3\n"+
-		"`\f`\16`\u03a6\13`\3a\3a\3b\3b\3c\3c\7c\u03ae\nc\fc\16c\u03b1\13c\3c\6"+
-		"c\u03b4\nc\rc\16c\u03b5\3d\6d\u03b9\nd\rd\16d\u03ba\3d\3d\3e\3e\3e\3e"+
-		"\7e\u03c3\ne\fe\16e\u03c6\13e\3e\3e\3f\3f\3f\3f\7f\u03ce\nf\ff\16f\u03d1"+
-		"\13f\3f\3f\3f\3f\3f\4\u02ed\u03cf\2g\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\u0083"+
-		"C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097"+
-		"M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00ab"+
-		"W\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9\2\u00bb\2\u00bd\2\u00bf"+
-		"^\u00c1\2\u00c3\2\u00c5_\u00c7`\u00c9a\u00cbb\3\2\r\3\2$$\3\2))\4\2DD"+
-		"dd\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\u0444\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\2U\3\2\2\2\2W\3\2\2\2\2"+
-		"Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3"+
-		"\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2"+
-		"\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2"+
-		"\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3"+
-		"\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2"+
-		"\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099"+
-		"\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2"+
-		"\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab"+
-		"\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2"+
-		"\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00bf\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7"+
-		"\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\3\u00cd\3\2\2\2\5\u00d4\3\2\2"+
-		"\2\7\u00d6\3\2\2\2\t\u00d8\3\2\2\2\13\u00da\3\2\2\2\r\u00dc\3\2\2\2\17"+
-		"\u00de\3\2\2\2\21\u00e0\3\2\2\2\23\u00e2\3\2\2\2\25\u00e8\3\2\2\2\27\u00ef"+
-		"\3\2\2\2\31\u00f5\3\2\2\2\33\u00fe\3\2\2\2\35\u0105\3\2\2\2\37\u010e\3"+
-		"\2\2\2!\u0118\3\2\2\2#\u0120\3\2\2\2%\u0123\3\2\2\2\'\u0128\3\2\2\2)\u012e"+
-		"\3\2\2\2+\u0131\3\2\2\2-\u0135\3\2\2\2/\u013c\3\2\2\2\61\u0142\3\2\2\2"+
-		"\63\u014b\3\2\2\2\65\u014f\3\2\2\2\67\u0151\3\2\2\29\u0154\3\2\2\2;\u015b"+
-		"\3\2\2\2=\u0164\3\2\2\2?\u0166\3\2\2\2A\u0168\3\2\2\2C\u016a\3\2\2\2E"+
-		"\u0171\3\2\2\2G\u0178\3\2\2\2I\u017b\3\2\2\2K\u017e\3\2\2\2M\u0180\3\2"+
-		"\2\2O\u0182\3\2\2\2Q\u0184\3\2\2\2S\u0186\3\2\2\2U\u0188\3\2\2\2W\u018b"+
-		"\3\2\2\2Y\u018e\3\2\2\2[\u0190\3\2\2\2]\u0192\3\2\2\2_\u0194\3\2\2\2a"+
-		"\u0196\3\2\2\2c\u0199\3\2\2\2e\u019c\3\2\2\2g\u019f\3\2\2\2i\u01a2\3\2"+
-		"\2\2k\u01a4\3\2\2\2m\u01a6\3\2\2\2o\u01a9\3\2\2\2q\u01ac\3\2\2\2s\u01ae"+
-		"\3\2\2\2u\u01b1\3\2\2\2w\u01b4\3\2\2\2y\u01b7\3\2\2\2{\u01ba\3\2\2\2}"+
-		"\u01bd\3\2\2\2\177\u01c1\3\2\2\2\u0081\u01c5\3\2\2\2\u0083\u01c8\3\2\2"+
-		"\2\u0085\u01cb\3\2\2\2\u0087\u01ce\3\2\2\2\u0089\u01d6\3\2\2\2\u008b\u01df"+
-		"\3\2\2\2\u008d\u01e4\3\2\2\2\u008f\u01ed\3\2\2\2\u0091\u01f3\3\2\2\2\u0093"+
-		"\u01fa\3\2\2\2\u0095\u01fd\3\2\2\2\u0097\u0203\3\2\2\2\u0099\u0205\3\2"+
-		"\2\2\u009b\u02e5\3\2\2\2\u009d\u02e7\3\2\2\2\u009f\u0318\3\2\2\2\u00a1"+
-		"\u031a\3\2\2\2\u00a3\u0327\3\2\2\2\u00a5\u0338\3\2\2\2\u00a7\u033c\3\2"+
-		"\2\2\u00a9\u0341\3\2\2\2\u00ab\u0348\3\2\2\2\u00ad\u0359\3\2\2\2\u00af"+
-		"\u0367\3\2\2\2\u00b1\u0378\3\2\2\2\u00b3\u0387\3\2\2\2\u00b5\u038a\3\2"+
-		"\2\2\u00b7\u0393\3\2\2\2\u00b9\u039a\3\2\2\2\u00bb\u039c\3\2\2\2\u00bd"+
-		"\u039e\3\2\2\2\u00bf\u03a0\3\2\2\2\u00c1\u03a7\3\2\2\2\u00c3\u03a9\3\2"+
-		"\2\2\u00c5\u03ab\3\2\2\2\u00c7\u03b8\3\2\2\2\u00c9\u03be\3\2\2\2\u00cb"+
-		"\u03c9\3\2\2\2\u00cd\u00ce\7k\2\2\u00ce\u00cf\7o\2\2\u00cf\u00d0\7r\2"+
-		"\2\u00d0\u00d1\7q\2\2\u00d1\u00d2\7t\2\2\u00d2\u00d3\7v\2\2\u00d3\4\3"+
-		"\2\2\2\u00d4\u00d5\7=\2\2\u00d5\6\3\2\2\2\u00d6\u00d7\7.\2\2\u00d7\b\3"+
-		"\2\2\2\u00d8\u00d9\7?\2\2\u00d9\n\3\2\2\2\u00da\u00db\7*\2\2\u00db\f\3"+
-		"\2\2\2\u00dc\u00dd\7+\2\2\u00dd\16\3\2\2\2\u00de\u00df\7}\2\2\u00df\20"+
-		"\3\2\2\2\u00e0\u00e1\7\177\2\2\u00e1\22\3\2\2\2\u00e2\u00e3\7e\2\2\u00e3"+
-		"\u00e4\7q\2\2\u00e4\u00e5\7p\2\2\u00e5\u00e6\7u\2\2\u00e6\u00e7\7v\2\2"+
-		"\u00e7\24\3\2\2\2\u00e8\u00e9\7g\2\2\u00e9\u00ea\7z\2\2\u00ea\u00eb\7"+
-		"v\2\2\u00eb\u00ec\7g\2\2\u00ec\u00ed\7t\2\2\u00ed\u00ee\7p\2\2\u00ee\26"+
-		"\3\2\2\2\u00ef\u00f0\7c\2\2\u00f0\u00f1\7n\2\2\u00f1\u00f2\7k\2\2\u00f2"+
-		"\u00f3\7i\2\2\u00f3\u00f4\7p\2\2\u00f4\30\3\2\2\2\u00f5\u00f6\7t\2\2\u00f6"+
-		"\u00f7\7g\2\2\u00f7\u00f8\7i\2\2\u00f8\u00f9\7k\2\2\u00f9\u00fa\7u\2\2"+
-		"\u00fa\u00fb\7v\2\2\u00fb\u00fc\7g\2\2\u00fc\u00fd\7t\2\2\u00fd\32\3\2"+
-		"\2\2\u00fe\u00ff\7k\2\2\u00ff\u0100\7p\2\2\u0100\u0101\7n\2\2\u0101\u0102"+
-		"\7k\2\2\u0102\u0103\7p\2\2\u0103\u0104\7g\2\2\u0104\34\3\2\2\2\u0105\u0106"+
-		"\7x\2\2\u0106\u0107\7q\2\2\u0107\u0108\7n\2\2\u0108\u0109\7c\2\2\u0109"+
-		"\u010a\7v\2\2\u010a\u010b\7k\2\2\u010b\u010c\7n\2\2\u010c\u010d\7g\2\2"+
-		"\u010d\36\3\2\2\2\u010e\u010f\7k\2\2\u010f\u0110\7p\2\2\u0110\u0111\7"+
-		"v\2\2\u0111\u0112\7g\2\2\u0112\u0113\7t\2\2\u0113\u0114\7t\2\2\u0114\u0115"+
-		"\7w\2\2\u0115\u0116\7r\2\2\u0116\u0117\7v\2\2\u0117 \3\2\2\2\u0118\u0119"+
-		"\7t\2\2\u0119\u011a\7g\2\2\u011a\u011b\7u\2\2\u011b\u011c\7g\2\2\u011c"+
-		"\u011d\7t\2\2\u011d\u011e\7x\2\2\u011e\u011f\7g\2\2\u011f\"\3\2\2\2\u0120"+
-		"\u0121\7k\2\2\u0121\u0122\7h\2\2\u0122$\3\2\2\2\u0123\u0124\7g\2\2\u0124"+
-		"\u0125\7n\2\2\u0125\u0126\7u\2\2\u0126\u0127\7g\2\2\u0127&\3\2\2\2\u0128"+
-		"\u0129\7y\2\2\u0129\u012a\7j\2\2\u012a\u012b\7k\2\2\u012b\u012c\7n\2\2"+
-		"\u012c\u012d\7g\2\2\u012d(\3\2\2\2\u012e\u012f\7f\2\2\u012f\u0130\7q\2"+
-		"\2\u0130*\3\2\2\2\u0131\u0132\7h\2\2\u0132\u0133\7q\2\2\u0133\u0134\7"+
-		"t\2\2\u0134,\3\2\2\2\u0135\u0136\7t\2\2\u0136\u0137\7g\2\2\u0137\u0138"+
-		"\7v\2\2\u0138\u0139\7w\2\2\u0139\u013a\7t\2\2\u013a\u013b\7p\2\2\u013b"+
-		".\3\2\2\2\u013c\u013d\7d\2\2\u013d\u013e\7t\2\2\u013e\u013f\7g\2\2\u013f"+
-		"\u0140\7c\2\2\u0140\u0141\7m\2\2\u0141\60\3\2\2\2\u0142\u0143\7e\2\2\u0143"+
-		"\u0144\7q\2\2\u0144\u0145\7p\2\2\u0145\u0146\7v\2\2\u0146\u0147\7k\2\2"+
-		"\u0147\u0148\7p\2\2\u0148\u0149\7w\2\2\u0149\u014a\7g\2\2\u014a\62\3\2"+
-		"\2\2\u014b\u014c\7c\2\2\u014c\u014d\7u\2\2\u014d\u014e\7o\2\2\u014e\64"+
-		"\3\2\2\2\u014f\u0150\7<\2\2\u0150\66\3\2\2\2\u0151\u0152\7\60\2\2\u0152"+
-		"\u0153\7\60\2\2\u01538\3\2\2\2\u0154\u0155\7u\2\2\u0155\u0156\7k\2\2\u0156"+
-		"\u0157\7i\2\2\u0157\u0158\7p\2\2\u0158\u0159\7g\2\2\u0159\u015a\7f\2\2"+
-		"\u015a:\3\2\2\2\u015b\u015c\7w\2\2\u015c\u015d\7p\2\2\u015d\u015e\7u\2"+
-		"\2\u015e\u015f\7k\2\2\u015f\u0160\7i\2\2\u0160\u0161\7p\2\2\u0161\u0162"+
-		"\7g\2\2\u0162\u0163\7f\2\2\u0163<\3\2\2\2\u0164\u0165\7,\2\2\u0165>\3"+
-		"\2\2\2\u0166\u0167\7]\2\2\u0167@\3\2\2\2\u0168\u0169\7_\2\2\u0169B\3\2"+
-		"\2\2\u016a\u016b\7u\2\2\u016b\u016c\7k\2\2\u016c\u016d\7|\2\2\u016d\u016e"+
-		"\7g\2\2\u016e\u016f\7q\2\2\u016f\u0170\7h\2\2\u0170D\3\2\2\2\u0171\u0172"+
-		"\7v\2\2\u0172\u0173\7{\2\2\u0173\u0174\7r\2\2\u0174\u0175\7g\2\2\u0175"+
-		"\u0176\7k\2\2\u0176\u0177\7f\2\2\u0177F\3\2\2\2\u0178\u0179\7/\2\2\u0179"+
-		"\u017a\7/\2\2\u017aH\3\2\2\2\u017b\u017c\7-\2\2\u017c\u017d\7-\2\2\u017d"+
-		"J\3\2\2\2\u017e\u017f\7-\2\2\u017fL\3\2\2\2\u0180\u0181\7/\2\2\u0181N"+
-		"\3\2\2\2\u0182\u0183\7#\2\2\u0183P\3\2\2\2\u0184\u0185\7(\2\2\u0185R\3"+
-		"\2\2\2\u0186\u0187\7\u0080\2\2\u0187T\3\2\2\2\u0188\u0189\7@\2\2\u0189"+
-		"\u018a\7@\2\2\u018aV\3\2\2\2\u018b\u018c\7>\2\2\u018c\u018d\7>\2\2\u018d"+
-		"X\3\2\2\2\u018e\u018f\7\61\2\2\u018fZ\3\2\2\2\u0190\u0191\7\'\2\2\u0191"+
-		"\\\3\2\2\2\u0192\u0193\7>\2\2\u0193^\3\2\2\2\u0194\u0195\7@\2\2\u0195"+
-		"`\3\2\2\2\u0196\u0197\7?\2\2\u0197\u0198\7?\2\2\u0198b\3\2\2\2\u0199\u019a"+
-		"\7#\2\2\u019a\u019b\7?\2\2\u019bd\3\2\2\2\u019c\u019d\7>\2\2\u019d\u019e"+
-		"\7?\2\2\u019ef\3\2\2\2\u019f\u01a0\7@\2\2\u01a0\u01a1\7?\2\2\u01a1h\3"+
-		"\2\2\2\u01a2\u01a3\7`\2\2\u01a3j\3\2\2\2\u01a4\u01a5\7~\2\2\u01a5l\3\2"+
-		"\2\2\u01a6\u01a7\7(\2\2\u01a7\u01a8\7(\2\2\u01a8n\3\2\2\2\u01a9\u01aa"+
-		"\7~\2\2\u01aa\u01ab\7~\2\2\u01abp\3\2\2\2\u01ac\u01ad\7A\2\2\u01adr\3"+
-		"\2\2\2\u01ae\u01af\7-\2\2\u01af\u01b0\7?\2\2\u01b0t\3\2\2\2\u01b1\u01b2"+
-		"\7/\2\2\u01b2\u01b3\7?\2\2\u01b3v\3\2\2\2\u01b4\u01b5\7,\2\2\u01b5\u01b6"+
-		"\7?\2\2\u01b6x\3\2\2\2\u01b7\u01b8\7\61\2\2\u01b8\u01b9\7?\2\2\u01b9z"+
-		"\3\2\2\2\u01ba\u01bb\7\'\2\2\u01bb\u01bc\7?\2\2\u01bc|\3\2\2\2\u01bd\u01be"+
-		"\7>\2\2\u01be\u01bf\7>\2\2\u01bf\u01c0\7?\2\2\u01c0~\3\2\2\2\u01c1\u01c2"+
-		"\7@\2\2\u01c2\u01c3\7@\2\2\u01c3\u01c4\7?\2\2\u01c4\u0080\3\2\2\2\u01c5"+
-		"\u01c6\7(\2\2\u01c6\u01c7\7?\2\2\u01c7\u0082\3\2\2\2\u01c8\u01c9\7~\2"+
-		"\2\u01c9\u01ca\7?\2\2\u01ca\u0084\3\2\2\2\u01cb\u01cc\7`\2\2\u01cc\u01cd"+
-		"\7?\2\2\u01cd\u0086\3\2\2\2\u01ce\u01cf\7m\2\2\u01cf\u01d0\7k\2\2\u01d0"+
-		"\u01d1\7e\2\2\u01d1\u01d2\7m\2\2\u01d2\u01d3\7c\2\2\u01d3\u01d4\7u\2\2"+
-		"\u01d4\u01d5\7o\2\2\u01d5\u0088\3\2\2\2\u01d6\u01d7\7t\2\2\u01d7\u01d8"+
-		"\7g\2\2\u01d8\u01d9\7u\2\2\u01d9\u01da\7q\2\2\u01da\u01db\7w\2\2\u01db"+
-		"\u01dc\7t\2\2\u01dc\u01dd\7e\2\2\u01dd\u01de\7g\2\2\u01de\u008a\3\2\2"+
-		"\2\u01df\u01e0\7w\2\2\u01e0\u01e1\7u\2\2\u01e1\u01e2\7g\2\2\u01e2\u01e3"+
-		"\7u\2\2\u01e3\u008c\3\2\2\2\u01e4\u01e5\7e\2\2\u01e5\u01e6\7n\2\2\u01e6"+
-		"\u01e7\7q\2\2\u01e7\u01e8\7d\2\2\u01e8\u01e9\7d\2\2\u01e9\u01ea\7g\2\2"+
-		"\u01ea\u01eb\7t\2\2\u01eb\u01ec\7u\2\2\u01ec\u008e\3\2\2\2\u01ed\u01ee"+
-		"\7d\2\2\u01ee\u01ef\7{\2\2\u01ef\u01f0\7v\2\2\u01f0\u01f1\7g\2\2\u01f1"+
-		"\u01f2\7u\2\2\u01f2\u0090\3\2\2\2\u01f3\u01f4\7e\2\2\u01f4\u01f5\7{\2"+
-		"\2\u01f5\u01f6\7e\2\2\u01f6\u01f7\7n\2\2\u01f7\u01f8\7g\2\2\u01f8\u01f9"+
-		"\7u\2\2\u01f9\u0092\3\2\2\2\u01fa\u01fb\7r\2\2\u01fb\u01fc\7e\2\2\u01fc"+
-		"\u0094\3\2\2\2\u01fd\u01fe\7\60\2\2\u01fe\u01ff\7d\2\2\u01ff\u0200\7{"+
-		"\2\2\u0200\u0201\7v\2\2\u0201\u0202\7g\2\2\u0202\u0096\3\2\2\2\u0203\u0204"+
-		"\7%\2\2\u0204\u0098\3\2\2\2\u0205\u0206\7\60\2\2\u0206\u009a\3\2\2\2\u0207"+
-		"\u0208\7d\2\2\u0208\u0209\7t\2\2\u0209\u02e6\7m\2\2\u020a\u020b\7q\2\2"+
-		"\u020b\u020c\7t\2\2\u020c\u02e6\7c\2\2\u020d\u020e\7m\2\2\u020e\u020f"+
-		"\7k\2\2\u020f\u02e6\7n\2\2\u0210\u0211\7u\2\2\u0211\u0212\7n\2\2\u0212"+
-		"\u02e6\7q\2\2\u0213\u0214\7p\2\2\u0214\u0215\7q\2\2\u0215\u02e6\7r\2\2"+
-		"\u0216\u0217\7c\2\2\u0217\u0218\7u\2\2\u0218\u02e6\7n\2\2\u0219\u021a"+
-		"\7r\2\2\u021a\u021b\7j\2\2\u021b\u02e6\7r\2\2\u021c\u021d\7c\2\2\u021d"+
-		"\u021e\7p\2\2\u021e\u02e6\7e\2\2\u021f\u0220\7d\2\2\u0220\u0221\7r\2\2"+
-		"\u0221\u02e6\7n\2\2\u0222\u0223\7e\2\2\u0223\u0224\7n\2\2\u0224\u02e6"+
-		"\7e\2\2\u0225\u0226\7l\2\2\u0226\u0227\7u\2\2\u0227\u02e6\7t\2\2\u0228"+
-		"\u0229\7c\2\2\u0229\u022a\7p\2\2\u022a\u02e6\7f\2\2\u022b\u022c\7t\2\2"+
-		"\u022c\u022d\7n\2\2\u022d\u02e6\7c\2\2\u022e\u022f\7d\2\2\u022f\u0230"+
-		"\7k\2\2\u0230\u02e6\7v\2\2\u0231\u0232\7t\2\2\u0232\u0233\7q\2\2\u0233"+
-		"\u02e6\7n\2\2\u0234\u0235\7r\2\2\u0235\u0236\7n\2\2\u0236\u02e6\7c\2\2"+
-		"\u0237\u0238\7r\2\2\u0238\u0239\7n\2\2\u0239\u02e6\7r\2\2\u023a\u023b"+
-		"\7d\2\2\u023b\u023c\7o\2\2\u023c\u02e6\7k\2\2\u023d\u023e\7u\2\2\u023e"+
-		"\u023f\7g\2\2\u023f\u02e6\7e\2\2\u0240\u0241\7t\2\2\u0241\u0242\7v\2\2"+
-		"\u0242\u02e6\7k\2\2\u0243\u0244\7g\2\2\u0244\u0245\7q\2\2\u0245\u02e6"+
-		"\7t\2\2\u0246\u0247\7u\2\2\u0247\u0248\7t\2\2\u0248\u02e6\7g\2\2\u0249"+
-		"\u024a\7n\2\2\u024a\u024b\7u\2\2\u024b\u02e6\7t\2\2\u024c\u024d\7r\2\2"+
-		"\u024d\u024e\7j\2\2\u024e\u02e6\7c\2\2\u024f\u0250\7c\2\2\u0250\u0251"+
-		"\7n\2\2\u0251\u02e6\7t\2\2\u0252\u0253\7l\2\2\u0253\u0254\7o\2\2\u0254"+
-		"\u02e6\7r\2\2\u0255\u0256\7d\2\2\u0256\u0257\7x\2\2\u0257\u02e6\7e\2\2"+
-		"\u0258\u0259\7e\2\2\u0259\u025a\7n\2\2\u025a\u02e6\7k\2\2\u025b\u025c"+
-		"\7t\2\2\u025c\u025d\7v\2\2\u025d\u02e6\7u\2\2\u025e\u025f\7c\2\2\u025f"+
-		"\u0260\7f\2\2\u0260\u02e6\7e\2\2\u0261\u0262\7t\2\2\u0262\u0263\7t\2\2"+
-		"\u0263\u02e6\7c\2\2\u0264\u0265\7d\2\2\u0265\u0266\7x\2\2\u0266\u02e6"+
-		"\7u\2\2\u0267\u0268\7u\2\2\u0268\u0269\7g\2\2\u0269\u02e6\7k\2\2\u026a"+
-		"\u026b\7u\2\2\u026b\u026c\7c\2\2\u026c\u02e6\7z\2\2\u026d\u026e\7u\2\2"+
-		"\u026e\u026f\7v\2\2\u026f\u02e6\7{\2\2\u0270\u0271\7u\2\2\u0271\u0272"+
-		"\7v\2\2\u0272\u02e6\7c\2\2\u0273\u0274\7u\2\2\u0274\u0275\7v\2\2\u0275"+
-		"\u02e6\7z\2\2\u0276\u0277\7f\2\2\u0277\u0278\7g\2\2\u0278\u02e6\7{\2\2"+
-		"\u0279\u027a\7v\2\2\u027a\u027b\7z\2\2\u027b\u02e6\7c\2\2\u027c\u027d"+
-		"\7z\2\2\u027d\u027e\7c\2\2\u027e\u02e6\7c\2\2\u027f\u0280\7d\2\2\u0280"+
-		"\u0281\7e\2\2\u0281\u02e6\7e\2\2\u0282\u0283\7c\2\2\u0283\u0284\7j\2\2"+
-		"\u0284\u02e6\7z\2\2\u0285\u0286\7v\2\2\u0286\u0287\7{\2\2\u0287\u02e6"+
-		"\7c\2\2\u0288\u0289\7v\2\2\u0289\u028a\7z\2\2\u028a\u02e6\7u\2\2\u028b"+
-		"\u028c\7v\2\2\u028c\u028d\7c\2\2\u028d\u02e6\7u\2\2\u028e\u028f\7u\2\2"+
-		"\u028f\u0290\7j\2\2\u0290\u02e6\7{\2\2\u0291\u0292\7u\2\2\u0292\u0293"+
-		"\7j\2\2\u0293\u02e6\7z\2\2\u0294\u0295\7n\2\2\u0295\u0296\7f\2\2\u0296"+
-		"\u02e6\7{\2\2\u0297\u0298\7n\2\2\u0298\u0299\7f\2\2\u0299\u02e6\7c\2\2"+
-		"\u029a\u029b\7n\2\2\u029b\u029c\7f\2\2\u029c\u02e6\7z\2\2\u029d\u029e"+
-		"\7n\2\2\u029e\u029f\7c\2\2\u029f\u02e6\7z\2\2\u02a0\u02a1\7v\2\2\u02a1"+
-		"\u02a2\7c\2\2\u02a2\u02e6\7{\2\2\u02a3\u02a4\7v\2\2\u02a4\u02a5\7c\2\2"+
-		"\u02a5\u02e6\7z\2\2\u02a6\u02a7\7d\2\2\u02a7\u02a8\7e\2\2\u02a8\u02e6"+
-		"\7u\2\2\u02a9\u02aa\7e\2\2\u02aa\u02ab\7n\2\2\u02ab\u02e6\7x\2\2\u02ac"+
-		"\u02ad\7v\2\2\u02ad\u02ae\7u\2\2\u02ae\u02e6\7z\2\2\u02af\u02b0\7n\2\2"+
-		"\u02b0\u02b1\7c\2\2\u02b1\u02e6\7u\2\2\u02b2\u02b3\7e\2\2\u02b3\u02b4"+
-		"\7r\2\2\u02b4\u02e6\7{\2\2\u02b5\u02b6\7e\2\2\u02b6\u02b7\7o\2\2\u02b7"+
-		"\u02e6\7r\2\2\u02b8\u02b9\7e\2\2\u02b9\u02ba\7r\2\2\u02ba\u02e6\7z\2\2"+
-		"\u02bb\u02bc\7f\2\2\u02bc\u02bd\7e\2\2\u02bd\u02e6\7r\2\2\u02be\u02bf"+
-		"\7f\2\2\u02bf\u02c0\7g\2\2\u02c0\u02e6\7e\2\2\u02c1\u02c2\7k\2\2\u02c2"+
-		"\u02c3\7p\2\2\u02c3\u02e6\7e\2\2\u02c4\u02c5\7c\2\2\u02c5\u02c6\7z\2\2"+
-		"\u02c6\u02e6\7u\2\2\u02c7\u02c8\7d\2\2\u02c8\u02c9\7p\2\2\u02c9\u02e6"+
-		"\7g\2\2\u02ca\u02cb\7e\2\2\u02cb\u02cc\7n\2\2\u02cc\u02e6\7f\2\2\u02cd"+
-		"\u02ce\7u\2\2\u02ce\u02cf\7d\2\2\u02cf\u02e6\7e\2\2\u02d0\u02d1\7k\2\2"+
-		"\u02d1\u02d2\7u\2\2\u02d2\u02e6\7e\2\2\u02d3\u02d4\7k\2\2\u02d4\u02d5"+
-		"\7p\2\2\u02d5\u02e6\7z\2\2\u02d6\u02d7\7d\2\2\u02d7\u02d8\7g\2\2\u02d8"+
-		"\u02e6\7s\2\2\u02d9\u02da\7u\2\2\u02da\u02db\7g\2\2\u02db\u02e6\7f\2\2"+
-		"\u02dc\u02dd\7f\2\2\u02dd\u02de\7g\2\2\u02de\u02e6\7z\2\2\u02df\u02e0"+
-		"\7k\2\2\u02e0\u02e1\7p\2\2\u02e1\u02e6\7{\2\2\u02e2\u02e3\7t\2\2\u02e3"+
-		"\u02e4\7q\2\2\u02e4\u02e6\7t\2\2\u02e5\u0207\3\2\2\2\u02e5\u020a\3\2\2"+
-		"\2\u02e5\u020d\3\2\2\2\u02e5\u0210\3\2\2\2\u02e5\u0213\3\2\2\2\u02e5\u0216"+
-		"\3\2\2\2\u02e5\u0219\3\2\2\2\u02e5\u021c\3\2\2\2\u02e5\u021f\3\2\2\2\u02e5"+
-		"\u0222\3\2\2\2\u02e5\u0225\3\2\2\2\u02e5\u0228\3\2\2\2\u02e5\u022b\3\2"+
-		"\2\2\u02e5\u022e\3\2\2\2\u02e5\u0231\3\2\2\2\u02e5\u0234\3\2\2\2\u02e5"+
-		"\u0237\3\2\2\2\u02e5\u023a\3\2\2\2\u02e5\u023d\3\2\2\2\u02e5\u0240\3\2"+
-		"\2\2\u02e5\u0243\3\2\2\2\u02e5\u0246\3\2\2\2\u02e5\u0249\3\2\2\2\u02e5"+
-		"\u024c\3\2\2\2\u02e5\u024f\3\2\2\2\u02e5\u0252\3\2\2\2\u02e5\u0255\3\2"+
-		"\2\2\u02e5\u0258\3\2\2\2\u02e5\u025b\3\2\2\2\u02e5\u025e\3\2\2\2\u02e5"+
-		"\u0261\3\2\2\2\u02e5\u0264\3\2\2\2\u02e5\u0267\3\2\2\2\u02e5\u026a\3\2"+
-		"\2\2\u02e5\u026d\3\2\2\2\u02e5\u0270\3\2\2\2\u02e5\u0273\3\2\2\2\u02e5"+
-		"\u0276\3\2\2\2\u02e5\u0279\3\2\2\2\u02e5\u027c\3\2\2\2\u02e5\u027f\3\2"+
-		"\2\2\u02e5\u0282\3\2\2\2\u02e5\u0285\3\2\2\2\u02e5\u0288\3\2\2\2\u02e5"+
-		"\u028b\3\2\2\2\u02e5\u028e\3\2\2\2\u02e5\u0291\3\2\2\2\u02e5\u0294\3\2"+
-		"\2\2\u02e5\u0297\3\2\2\2\u02e5\u029a\3\2\2\2\u02e5\u029d\3\2\2\2\u02e5"+
-		"\u02a0\3\2\2\2\u02e5\u02a3\3\2\2\2\u02e5\u02a6\3\2\2\2\u02e5\u02a9\3\2"+
-		"\2\2\u02e5\u02ac\3\2\2\2\u02e5\u02af\3\2\2\2\u02e5\u02b2\3\2\2\2\u02e5"+
-		"\u02b5\3\2\2\2\u02e5\u02b8\3\2\2\2\u02e5\u02bb\3\2\2\2\u02e5\u02be\3\2"+
-		"\2\2\u02e5\u02c1\3\2\2\2\u02e5\u02c4\3\2\2\2\u02e5\u02c7\3\2\2\2\u02e5"+
-		"\u02ca\3\2\2\2\u02e5\u02cd\3\2\2\2\u02e5\u02d0\3\2\2\2\u02e5\u02d3\3\2"+
-		"\2\2\u02e5\u02d6\3\2\2\2\u02e5\u02d9\3\2\2\2\u02e5\u02dc\3\2\2\2\u02e5"+
-		"\u02df\3\2\2\2\u02e5\u02e2\3\2\2\2\u02e6\u009c\3\2\2\2\u02e7\u02e8\7}"+
-		"\2\2\u02e8\u02e9\7}\2\2\u02e9\u02ed\3\2\2\2\u02ea\u02ec\13\2\2\2\u02eb"+
-		"\u02ea\3\2\2\2\u02ec\u02ef\3\2\2\2\u02ed\u02ee\3\2\2\2\u02ed\u02eb\3\2"+
-		"\2\2\u02ee\u02f0\3\2\2\2\u02ef\u02ed\3\2\2\2\u02f0\u02f1\7\177\2\2\u02f1"+
-		"\u02f2\7\177\2\2\u02f2\u009e\3\2\2\2\u02f3\u02f4\7d\2\2\u02f4\u02f5\7"+
-		"{\2\2\u02f5\u02f6\7v\2\2\u02f6\u0319\7g\2\2\u02f7\u02f8\7y\2\2\u02f8\u02f9"+
-		"\7q\2\2\u02f9\u02fa\7t\2\2\u02fa\u0319\7f\2\2\u02fb\u02fc\7f\2\2\u02fc"+
-		"\u02fd\7y\2\2\u02fd\u02fe\7q\2\2\u02fe\u02ff\7t\2\2\u02ff\u0319\7f\2\2"+
-		"\u0300\u0301\7d\2\2\u0301\u0302\7q\2\2\u0302\u0303\7q\2\2\u0303\u0319"+
-		"\7n\2\2\u0304\u0305\7e\2\2\u0305\u0306\7j\2\2\u0306\u0307\7c\2\2\u0307"+
-		"\u0319\7t\2\2\u0308\u0309\7u\2\2\u0309\u030a\7j\2\2\u030a\u030b\7q\2\2"+
-		"\u030b\u030c\7t\2\2\u030c\u0319\7v\2\2\u030d\u030e\7k\2\2\u030e\u030f"+
-		"\7p\2\2\u030f\u0319\7v\2\2\u0310\u0311\7n\2\2\u0311\u0312\7q\2\2\u0312"+
-		"\u0313\7p\2\2\u0313\u0319\7i\2\2\u0314\u0315\7x\2\2\u0315\u0316\7q\2\2"+
-		"\u0316\u0317\7k\2\2\u0317\u0319\7f\2\2\u0318\u02f3\3\2\2\2\u0318\u02f7"+
-		"\3\2\2\2\u0318\u02fb\3\2\2\2\u0318\u0300\3\2\2\2\u0318\u0304\3\2\2\2\u0318"+
-		"\u0308\3\2\2\2\u0318\u030d\3\2\2\2\u0318\u0310\3\2\2\2\u0318\u0314\3\2"+
-		"\2\2\u0319\u00a0\3\2\2\2\u031a\u0320\7$\2\2\u031b\u031c\7^\2\2\u031c\u031f"+
-		"\7$\2\2\u031d\u031f\n\2\2\2\u031e\u031b\3\2\2\2\u031e\u031d\3\2\2\2\u031f"+
-		"\u0322\3\2\2\2\u0320\u031e\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u0323\3\2"+
-		"\2\2\u0322\u0320\3\2\2\2\u0323\u0325\7$\2\2\u0324\u0326\7|\2\2\u0325\u0324"+
-		"\3\2\2\2\u0325\u0326\3\2\2\2\u0326\u00a2\3\2\2\2\u0327\u032b\7)\2\2\u0328"+
-		"\u0329\7^\2\2\u0329\u032c\7)\2\2\u032a\u032c\n\3\2\2\u032b\u0328\3\2\2"+
-		"\2\u032b\u032a\3\2\2\2\u032c\u032d\3\2\2\2\u032d\u032e\7)\2\2\u032e\u00a4"+
-		"\3\2\2\2\u032f\u0330\7v\2\2\u0330\u0331\7t\2\2\u0331\u0332\7w\2\2\u0332"+
-		"\u0339\7g\2\2\u0333\u0334\7h\2\2\u0334\u0335\7c\2\2\u0335\u0336\7n\2\2"+
-		"\u0336\u0337\7u\2\2\u0337\u0339\7g\2\2\u0338\u032f\3\2\2\2\u0338\u0333"+
-		"\3\2\2\2\u0339\u00a6\3\2\2\2\u033a\u033d\5\u00a9U\2\u033b\u033d\5\u00b1"+
-		"Y\2\u033c\u033a\3\2\2\2\u033c\u033b\3\2\2\2\u033d\u00a8\3\2\2\2\u033e"+
-		"\u0342\5\u00abV\2\u033f\u0342\5\u00adW\2\u0340\u0342\5\u00afX\2\u0341"+
-		"\u033e\3\2\2\2\u0341\u033f\3\2\2\2\u0341\u0340\3\2\2\2\u0342\u00aa\3\2"+
-		"\2\2\u0343\u0349\7\'\2\2\u0344\u0345\7\62\2\2\u0345\u0349\7d\2\2\u0346"+
-		"\u0347\7\62\2\2\u0347\u0349\7D\2\2\u0348\u0343\3\2\2\2\u0348\u0344\3\2"+
-		"\2\2\u0348\u0346\3\2\2\2\u0349\u034d\3\2\2\2\u034a\u034c\5\u00b9]\2\u034b"+
-		"\u034a\3\2\2\2\u034c\u034f\3\2\2\2\u034d\u034b\3\2\2\2\u034d\u034e\3\2"+
-		"\2\2\u034e\u0350\3\2\2\2\u034f\u034d\3\2\2\2\u0350\u0352\7\60\2\2\u0351"+
-		"\u0353\5\u00b9]\2\u0352\u0351\3\2\2\2\u0353\u0354\3\2\2\2\u0354\u0352"+
-		"\3\2\2\2\u0354\u0355\3\2\2\2\u0355\u00ac\3\2\2\2\u0356\u0358\5\u00bb^"+
-		"\2\u0357\u0356\3\2\2\2\u0358\u035b\3\2\2\2\u0359\u0357\3\2\2\2\u0359\u035a"+
-		"\3\2\2\2\u035a\u035c\3\2\2\2\u035b\u0359\3\2\2\2\u035c\u035e\7\60\2\2"+
-		"\u035d\u035f\5\u00bb^\2\u035e\u035d\3\2\2\2\u035f\u0360\3\2\2\2\u0360"+
-		"\u035e\3\2\2\2\u0360\u0361\3\2\2\2\u0361\u00ae\3\2\2\2\u0362\u0368\7&"+
-		"\2\2\u0363\u0364\7\62\2\2\u0364\u0368\7z\2\2\u0365\u0366\7\62\2\2\u0366"+
-		"\u0368\7Z\2\2\u0367\u0362\3\2\2\2\u0367\u0363\3\2\2\2\u0367\u0365\3\2"+
-		"\2\2\u0368\u036c\3\2\2\2\u0369\u036b\5\u00bd_\2\u036a\u0369\3\2\2\2\u036b"+
-		"\u036e\3\2\2\2\u036c\u036a\3\2\2\2\u036c\u036d\3\2\2\2\u036d\u036f\3\2"+
-		"\2\2\u036e\u036c\3\2\2\2\u036f\u0371\7\60\2\2\u0370\u0372\5\u00bd_\2\u0371"+
-		"\u0370\3\2\2\2\u0372\u0373\3\2\2\2\u0373\u0371\3\2\2\2\u0373\u0374\3\2"+
-		"\2\2\u0374\u00b0\3\2\2\2\u0375\u0379\5\u00b5[\2\u0376\u0379\5\u00b7\\"+
-		"\2\u0377\u0379\5\u00b3Z\2\u0378\u0375\3\2\2\2\u0378\u0376\3\2\2\2\u0378"+
-		"\u0377\3\2\2\2\u0379\u00b2\3\2\2\2\u037a\u037b\7\62\2\2\u037b\u037d\t"+
-		"\4\2\2\u037c\u037e\5\u00b9]\2\u037d\u037c\3\2\2\2\u037e\u037f\3\2\2\2"+
-		"\u037f\u037d\3\2\2\2\u037f\u0380\3\2\2\2\u0380\u0388\3\2\2\2\u0381\u0383"+
-		"\7\'\2\2\u0382\u0384\5\u00b9]\2\u0383\u0382\3\2\2\2\u0384\u0385\3\2\2"+
-		"\2\u0385\u0383\3\2\2\2\u0385\u0386\3\2\2\2\u0386\u0388\3\2\2\2\u0387\u037a"+
-		"\3\2\2\2\u0387\u0381\3\2\2\2\u0388\u00b4\3\2\2\2\u0389\u038b\5\u00bb^"+
-		"\2\u038a\u0389\3\2\2\2\u038b\u038c\3\2\2\2\u038c\u038a\3\2\2\2\u038c\u038d"+
-		"\3\2\2\2\u038d\u00b6\3\2\2\2\u038e\u0394\7&\2\2\u038f\u0390\7\62\2\2\u0390"+
-		"\u0394\7z\2\2\u0391\u0392\7\62\2\2\u0392\u0394\7Z\2\2\u0393\u038e\3\2"+
-		"\2\2\u0393\u038f\3\2\2\2\u0393\u0391\3\2\2\2\u0394\u0396\3\2\2\2\u0395"+
-		"\u0397\5\u00bd_\2\u0396\u0395\3\2\2\2\u0397\u0398\3\2\2\2\u0398\u0396"+
-		"\3\2\2\2\u0398\u0399\3\2\2\2\u0399\u00b8\3\2\2\2\u039a\u039b\t\5\2\2\u039b"+
-		"\u00ba\3\2\2\2\u039c\u039d\t\6\2\2\u039d\u00bc\3\2\2\2\u039e\u039f\t\7"+
-		"\2\2\u039f\u00be\3\2\2\2\u03a0\u03a4\5\u00c1a\2\u03a1\u03a3\5\u00c3b\2"+
-		"\u03a2\u03a1\3\2\2\2\u03a3\u03a6\3\2\2\2\u03a4\u03a2\3\2\2\2\u03a4\u03a5"+
-		"\3\2\2\2\u03a5\u00c0\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a7\u03a8\t\b\2\2\u03a8"+
-		"\u00c2\3\2\2\2\u03a9\u03aa\t\t\2\2\u03aa\u00c4\3\2\2\2\u03ab\u03af\7#"+
-		"\2\2\u03ac\u03ae\5\u00c3b\2\u03ad\u03ac\3\2\2\2\u03ae\u03b1\3\2\2\2\u03af"+
-		"\u03ad\3\2\2\2\u03af\u03b0\3\2\2\2\u03b0\u03b3\3\2\2\2\u03b1\u03af\3\2"+
-		"\2\2\u03b2\u03b4\t\n\2\2\u03b3\u03b2\3\2\2\2\u03b4\u03b5\3\2\2\2\u03b5"+
-		"\u03b3\3\2\2\2\u03b5\u03b6\3\2\2\2\u03b6\u00c6\3\2\2\2\u03b7\u03b9\t\13"+
-		"\2\2\u03b8\u03b7\3\2\2\2\u03b9\u03ba\3\2\2\2\u03ba\u03b8\3\2\2\2\u03ba"+
-		"\u03bb\3\2\2\2\u03bb\u03bc\3\2\2\2\u03bc\u03bd\bd\2\2\u03bd\u00c8\3\2"+
-		"\2\2\u03be\u03bf\7\61\2\2\u03bf\u03c0\7\61\2\2\u03c0\u03c4\3\2\2\2\u03c1"+
-		"\u03c3\n\f\2\2\u03c2\u03c1\3\2\2\2\u03c3\u03c6\3\2\2\2\u03c4\u03c2\3\2"+
-		"\2\2\u03c4\u03c5\3\2\2\2\u03c5\u03c7\3\2\2\2\u03c6\u03c4\3\2\2\2\u03c7"+
-		"\u03c8\be\3\2\u03c8\u00ca\3\2\2\2\u03c9\u03ca\7\61\2\2\u03ca\u03cb\7,"+
-		"\2\2\u03cb\u03cf\3\2\2\2\u03cc\u03ce\13\2\2\2\u03cd\u03cc\3\2\2\2\u03ce"+
-		"\u03d1\3\2\2\2\u03cf\u03d0\3\2\2\2\u03cf\u03cd\3\2\2\2\u03d0\u03d2\3\2"+
-		"\2\2\u03d1\u03cf\3\2\2\2\u03d2\u03d3\7,\2\2\u03d3\u03d4\7\61\2\2\u03d4"+
-		"\u03d5\3\2\2\2\u03d5\u03d6\bf\3\2\u03d6\u00cc\3\2\2\2\"\2\u02e5\u02ed"+
-		"\u0318\u031e\u0320\u0325\u032b\u0338\u033c\u0341\u0348\u034d\u0354\u0359"+
-		"\u0360\u0367\u036c\u0373\u0378\u037f\u0385\u0387\u038c\u0393\u0398\u03a4"+
-		"\u03af\u03b5\u03ba\u03c4\u03cf\4\2\3\2\2\4\2";
+		"\nY\3Y\3Y\3Y\5Y\u037e\nY\3Z\3Z\3Z\6Z\u0383\nZ\rZ\16Z\u0384\3Z\3Z\6Z\u0389"+
+		"\nZ\rZ\16Z\u038a\5Z\u038d\nZ\3[\6[\u0390\n[\r[\16[\u0391\3\\\3\\\3\\\3"+
+		"\\\3\\\5\\\u0399\n\\\3\\\6\\\u039c\n\\\r\\\16\\\u039d\3]\3]\3^\3^\3_\3"+
+		"_\3`\3`\7`\u03a8\n`\f`\16`\u03ab\13`\3a\3a\3b\3b\3c\3c\7c\u03b3\nc\fc"+
+		"\16c\u03b6\13c\3c\6c\u03b9\nc\rc\16c\u03ba\3d\6d\u03be\nd\rd\16d\u03bf"+
+		"\3d\3d\3e\3e\3e\3e\7e\u03c8\ne\fe\16e\u03cb\13e\3e\3e\3f\3f\3f\3f\7f\u03d3"+
+		"\nf\ff\16f\u03d6\13f\3f\3f\3f\3f\3f\4\u02ed\u03d4\2g\3\3\5\4\7\5\t\6\13"+
+		"\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'"+
+		"\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'"+
+		"M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177"+
+		"A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093"+
+		"K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7"+
+		"U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9\2\u00bb"+
+		"\2\u00bd\2\u00bf^\u00c1\2\u00c3\2\u00c5_\u00c7`\u00c9a\u00cbb\3\2\17\3"+
+		"\2$$\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHc"+
+		"h\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\u044b\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\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2"+
+		"\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k"+
+		"\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\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\u00af"+
+		"\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2"+
+		"\2\2\u00bf\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb"+
+		"\3\2\2\2\3\u00cd\3\2\2\2\5\u00d4\3\2\2\2\7\u00d6\3\2\2\2\t\u00d8\3\2\2"+
+		"\2\13\u00da\3\2\2\2\r\u00dc\3\2\2\2\17\u00de\3\2\2\2\21\u00e0\3\2\2\2"+
+		"\23\u00e2\3\2\2\2\25\u00e8\3\2\2\2\27\u00ef\3\2\2\2\31\u00f5\3\2\2\2\33"+
+		"\u00fe\3\2\2\2\35\u0105\3\2\2\2\37\u010e\3\2\2\2!\u0118\3\2\2\2#\u0120"+
+		"\3\2\2\2%\u0123\3\2\2\2\'\u0128\3\2\2\2)\u012e\3\2\2\2+\u0131\3\2\2\2"+
+		"-\u0135\3\2\2\2/\u013c\3\2\2\2\61\u0142\3\2\2\2\63\u014b\3\2\2\2\65\u014f"+
+		"\3\2\2\2\67\u0151\3\2\2\29\u0154\3\2\2\2;\u015b\3\2\2\2=\u0164\3\2\2\2"+
+		"?\u0166\3\2\2\2A\u0168\3\2\2\2C\u016a\3\2\2\2E\u0171\3\2\2\2G\u0178\3"+
+		"\2\2\2I\u017b\3\2\2\2K\u017e\3\2\2\2M\u0180\3\2\2\2O\u0182\3\2\2\2Q\u0184"+
+		"\3\2\2\2S\u0186\3\2\2\2U\u0188\3\2\2\2W\u018b\3\2\2\2Y\u018e\3\2\2\2["+
+		"\u0190\3\2\2\2]\u0192\3\2\2\2_\u0194\3\2\2\2a\u0196\3\2\2\2c\u0199\3\2"+
+		"\2\2e\u019c\3\2\2\2g\u019f\3\2\2\2i\u01a2\3\2\2\2k\u01a4\3\2\2\2m\u01a6"+
+		"\3\2\2\2o\u01a9\3\2\2\2q\u01ac\3\2\2\2s\u01ae\3\2\2\2u\u01b1\3\2\2\2w"+
+		"\u01b4\3\2\2\2y\u01b7\3\2\2\2{\u01ba\3\2\2\2}\u01bd\3\2\2\2\177\u01c1"+
+		"\3\2\2\2\u0081\u01c5\3\2\2\2\u0083\u01c8\3\2\2\2\u0085\u01cb\3\2\2\2\u0087"+
+		"\u01ce\3\2\2\2\u0089\u01d6\3\2\2\2\u008b\u01df\3\2\2\2\u008d\u01e4\3\2"+
+		"\2\2\u008f\u01ed\3\2\2\2\u0091\u01f3\3\2\2\2\u0093\u01fa\3\2\2\2\u0095"+
+		"\u01fd\3\2\2\2\u0097\u0203\3\2\2\2\u0099\u0205\3\2\2\2\u009b\u02e5\3\2"+
+		"\2\2\u009d\u02e7\3\2\2\2\u009f\u0318\3\2\2\2\u00a1\u031a\3\2\2\2\u00a3"+
+		"\u0327\3\2\2\2\u00a5\u0338\3\2\2\2\u00a7\u033c\3\2\2\2\u00a9\u0341\3\2"+
+		"\2\2\u00ab\u0348\3\2\2\2\u00ad\u0359\3\2\2\2\u00af\u0367\3\2\2\2\u00b1"+
+		"\u0378\3\2\2\2\u00b3\u038c\3\2\2\2\u00b5\u038f\3\2\2\2\u00b7\u0398\3\2"+
+		"\2\2\u00b9\u039f\3\2\2\2\u00bb\u03a1\3\2\2\2\u00bd\u03a3\3\2\2\2\u00bf"+
+		"\u03a5\3\2\2\2\u00c1\u03ac\3\2\2\2\u00c3\u03ae\3\2\2\2\u00c5\u03b0\3\2"+
+		"\2\2\u00c7\u03bd\3\2\2\2\u00c9\u03c3\3\2\2\2\u00cb\u03ce\3\2\2\2\u00cd"+
+		"\u00ce\7k\2\2\u00ce\u00cf\7o\2\2\u00cf\u00d0\7r\2\2\u00d0\u00d1\7q\2\2"+
+		"\u00d1\u00d2\7t\2\2\u00d2\u00d3\7v\2\2\u00d3\4\3\2\2\2\u00d4\u00d5\7="+
+		"\2\2\u00d5\6\3\2\2\2\u00d6\u00d7\7.\2\2\u00d7\b\3\2\2\2\u00d8\u00d9\7"+
+		"?\2\2\u00d9\n\3\2\2\2\u00da\u00db\7*\2\2\u00db\f\3\2\2\2\u00dc\u00dd\7"+
+		"+\2\2\u00dd\16\3\2\2\2\u00de\u00df\7}\2\2\u00df\20\3\2\2\2\u00e0\u00e1"+
+		"\7\177\2\2\u00e1\22\3\2\2\2\u00e2\u00e3\7e\2\2\u00e3\u00e4\7q\2\2\u00e4"+
+		"\u00e5\7p\2\2\u00e5\u00e6\7u\2\2\u00e6\u00e7\7v\2\2\u00e7\24\3\2\2\2\u00e8"+
+		"\u00e9\7g\2\2\u00e9\u00ea\7z\2\2\u00ea\u00eb\7v\2\2\u00eb\u00ec\7g\2\2"+
+		"\u00ec\u00ed\7t\2\2\u00ed\u00ee\7p\2\2\u00ee\26\3\2\2\2\u00ef\u00f0\7"+
+		"c\2\2\u00f0\u00f1\7n\2\2\u00f1\u00f2\7k\2\2\u00f2\u00f3\7i\2\2\u00f3\u00f4"+
+		"\7p\2\2\u00f4\30\3\2\2\2\u00f5\u00f6\7t\2\2\u00f6\u00f7\7g\2\2\u00f7\u00f8"+
+		"\7i\2\2\u00f8\u00f9\7k\2\2\u00f9\u00fa\7u\2\2\u00fa\u00fb\7v\2\2\u00fb"+
+		"\u00fc\7g\2\2\u00fc\u00fd\7t\2\2\u00fd\32\3\2\2\2\u00fe\u00ff\7k\2\2\u00ff"+
+		"\u0100\7p\2\2\u0100\u0101\7n\2\2\u0101\u0102\7k\2\2\u0102\u0103\7p\2\2"+
+		"\u0103\u0104\7g\2\2\u0104\34\3\2\2\2\u0105\u0106\7x\2\2\u0106\u0107\7"+
+		"q\2\2\u0107\u0108\7n\2\2\u0108\u0109\7c\2\2\u0109\u010a\7v\2\2\u010a\u010b"+
+		"\7k\2\2\u010b\u010c\7n\2\2\u010c\u010d\7g\2\2\u010d\36\3\2\2\2\u010e\u010f"+
+		"\7k\2\2\u010f\u0110\7p\2\2\u0110\u0111\7v\2\2\u0111\u0112\7g\2\2\u0112"+
+		"\u0113\7t\2\2\u0113\u0114\7t\2\2\u0114\u0115\7w\2\2\u0115\u0116\7r\2\2"+
+		"\u0116\u0117\7v\2\2\u0117 \3\2\2\2\u0118\u0119\7t\2\2\u0119\u011a\7g\2"+
+		"\2\u011a\u011b\7u\2\2\u011b\u011c\7g\2\2\u011c\u011d\7t\2\2\u011d\u011e"+
+		"\7x\2\2\u011e\u011f\7g\2\2\u011f\"\3\2\2\2\u0120\u0121\7k\2\2\u0121\u0122"+
+		"\7h\2\2\u0122$\3\2\2\2\u0123\u0124\7g\2\2\u0124\u0125\7n\2\2\u0125\u0126"+
+		"\7u\2\2\u0126\u0127\7g\2\2\u0127&\3\2\2\2\u0128\u0129\7y\2\2\u0129\u012a"+
+		"\7j\2\2\u012a\u012b\7k\2\2\u012b\u012c\7n\2\2\u012c\u012d\7g\2\2\u012d"+
+		"(\3\2\2\2\u012e\u012f\7f\2\2\u012f\u0130\7q\2\2\u0130*\3\2\2\2\u0131\u0132"+
+		"\7h\2\2\u0132\u0133\7q\2\2\u0133\u0134\7t\2\2\u0134,\3\2\2\2\u0135\u0136"+
+		"\7t\2\2\u0136\u0137\7g\2\2\u0137\u0138\7v\2\2\u0138\u0139\7w\2\2\u0139"+
+		"\u013a\7t\2\2\u013a\u013b\7p\2\2\u013b.\3\2\2\2\u013c\u013d\7d\2\2\u013d"+
+		"\u013e\7t\2\2\u013e\u013f\7g\2\2\u013f\u0140\7c\2\2\u0140\u0141\7m\2\2"+
+		"\u0141\60\3\2\2\2\u0142\u0143\7e\2\2\u0143\u0144\7q\2\2\u0144\u0145\7"+
+		"p\2\2\u0145\u0146\7v\2\2\u0146\u0147\7k\2\2\u0147\u0148\7p\2\2\u0148\u0149"+
+		"\7w\2\2\u0149\u014a\7g\2\2\u014a\62\3\2\2\2\u014b\u014c\7c\2\2\u014c\u014d"+
+		"\7u\2\2\u014d\u014e\7o\2\2\u014e\64\3\2\2\2\u014f\u0150\7<\2\2\u0150\66"+
+		"\3\2\2\2\u0151\u0152\7\60\2\2\u0152\u0153\7\60\2\2\u01538\3\2\2\2\u0154"+
+		"\u0155\7u\2\2\u0155\u0156\7k\2\2\u0156\u0157\7i\2\2\u0157\u0158\7p\2\2"+
+		"\u0158\u0159\7g\2\2\u0159\u015a\7f\2\2\u015a:\3\2\2\2\u015b\u015c\7w\2"+
+		"\2\u015c\u015d\7p\2\2\u015d\u015e\7u\2\2\u015e\u015f\7k\2\2\u015f\u0160"+
+		"\7i\2\2\u0160\u0161\7p\2\2\u0161\u0162\7g\2\2\u0162\u0163\7f\2\2\u0163"+
+		"<\3\2\2\2\u0164\u0165\7,\2\2\u0165>\3\2\2\2\u0166\u0167\7]\2\2\u0167@"+
+		"\3\2\2\2\u0168\u0169\7_\2\2\u0169B\3\2\2\2\u016a\u016b\7u\2\2\u016b\u016c"+
+		"\7k\2\2\u016c\u016d\7|\2\2\u016d\u016e\7g\2\2\u016e\u016f\7q\2\2\u016f"+
+		"\u0170\7h\2\2\u0170D\3\2\2\2\u0171\u0172\7v\2\2\u0172\u0173\7{\2\2\u0173"+
+		"\u0174\7r\2\2\u0174\u0175\7g\2\2\u0175\u0176\7k\2\2\u0176\u0177\7f\2\2"+
+		"\u0177F\3\2\2\2\u0178\u0179\7/\2\2\u0179\u017a\7/\2\2\u017aH\3\2\2\2\u017b"+
+		"\u017c\7-\2\2\u017c\u017d\7-\2\2\u017dJ\3\2\2\2\u017e\u017f\7-\2\2\u017f"+
+		"L\3\2\2\2\u0180\u0181\7/\2\2\u0181N\3\2\2\2\u0182\u0183\7#\2\2\u0183P"+
+		"\3\2\2\2\u0184\u0185\7(\2\2\u0185R\3\2\2\2\u0186\u0187\7\u0080\2\2\u0187"+
+		"T\3\2\2\2\u0188\u0189\7@\2\2\u0189\u018a\7@\2\2\u018aV\3\2\2\2\u018b\u018c"+
+		"\7>\2\2\u018c\u018d\7>\2\2\u018dX\3\2\2\2\u018e\u018f\7\61\2\2\u018fZ"+
+		"\3\2\2\2\u0190\u0191\7\'\2\2\u0191\\\3\2\2\2\u0192\u0193\7>\2\2\u0193"+
+		"^\3\2\2\2\u0194\u0195\7@\2\2\u0195`\3\2\2\2\u0196\u0197\7?\2\2\u0197\u0198"+
+		"\7?\2\2\u0198b\3\2\2\2\u0199\u019a\7#\2\2\u019a\u019b\7?\2\2\u019bd\3"+
+		"\2\2\2\u019c\u019d\7>\2\2\u019d\u019e\7?\2\2\u019ef\3\2\2\2\u019f\u01a0"+
+		"\7@\2\2\u01a0\u01a1\7?\2\2\u01a1h\3\2\2\2\u01a2\u01a3\7`\2\2\u01a3j\3"+
+		"\2\2\2\u01a4\u01a5\7~\2\2\u01a5l\3\2\2\2\u01a6\u01a7\7(\2\2\u01a7\u01a8"+
+		"\7(\2\2\u01a8n\3\2\2\2\u01a9\u01aa\7~\2\2\u01aa\u01ab\7~\2\2\u01abp\3"+
+		"\2\2\2\u01ac\u01ad\7A\2\2\u01adr\3\2\2\2\u01ae\u01af\7-\2\2\u01af\u01b0"+
+		"\7?\2\2\u01b0t\3\2\2\2\u01b1\u01b2\7/\2\2\u01b2\u01b3\7?\2\2\u01b3v\3"+
+		"\2\2\2\u01b4\u01b5\7,\2\2\u01b5\u01b6\7?\2\2\u01b6x\3\2\2\2\u01b7\u01b8"+
+		"\7\61\2\2\u01b8\u01b9\7?\2\2\u01b9z\3\2\2\2\u01ba\u01bb\7\'\2\2\u01bb"+
+		"\u01bc\7?\2\2\u01bc|\3\2\2\2\u01bd\u01be\7>\2\2\u01be\u01bf\7>\2\2\u01bf"+
+		"\u01c0\7?\2\2\u01c0~\3\2\2\2\u01c1\u01c2\7@\2\2\u01c2\u01c3\7@\2\2\u01c3"+
+		"\u01c4\7?\2\2\u01c4\u0080\3\2\2\2\u01c5\u01c6\7(\2\2\u01c6\u01c7\7?\2"+
+		"\2\u01c7\u0082\3\2\2\2\u01c8\u01c9\7~\2\2\u01c9\u01ca\7?\2\2\u01ca\u0084"+
+		"\3\2\2\2\u01cb\u01cc\7`\2\2\u01cc\u01cd\7?\2\2\u01cd\u0086\3\2\2\2\u01ce"+
+		"\u01cf\7m\2\2\u01cf\u01d0\7k\2\2\u01d0\u01d1\7e\2\2\u01d1\u01d2\7m\2\2"+
+		"\u01d2\u01d3\7c\2\2\u01d3\u01d4\7u\2\2\u01d4\u01d5\7o\2\2\u01d5\u0088"+
+		"\3\2\2\2\u01d6\u01d7\7t\2\2\u01d7\u01d8\7g\2\2\u01d8\u01d9\7u\2\2\u01d9"+
+		"\u01da\7q\2\2\u01da\u01db\7w\2\2\u01db\u01dc\7t\2\2\u01dc\u01dd\7e\2\2"+
+		"\u01dd\u01de\7g\2\2\u01de\u008a\3\2\2\2\u01df\u01e0\7w\2\2\u01e0\u01e1"+
+		"\7u\2\2\u01e1\u01e2\7g\2\2\u01e2\u01e3\7u\2\2\u01e3\u008c\3\2\2\2\u01e4"+
+		"\u01e5\7e\2\2\u01e5\u01e6\7n\2\2\u01e6\u01e7\7q\2\2\u01e7\u01e8\7d\2\2"+
+		"\u01e8\u01e9\7d\2\2\u01e9\u01ea\7g\2\2\u01ea\u01eb\7t\2\2\u01eb\u01ec"+
+		"\7u\2\2\u01ec\u008e\3\2\2\2\u01ed\u01ee\7d\2\2\u01ee\u01ef\7{\2\2\u01ef"+
+		"\u01f0\7v\2\2\u01f0\u01f1\7g\2\2\u01f1\u01f2\7u\2\2\u01f2\u0090\3\2\2"+
+		"\2\u01f3\u01f4\7e\2\2\u01f4\u01f5\7{\2\2\u01f5\u01f6\7e\2\2\u01f6\u01f7"+
+		"\7n\2\2\u01f7\u01f8\7g\2\2\u01f8\u01f9\7u\2\2\u01f9\u0092\3\2\2\2\u01fa"+
+		"\u01fb\7r\2\2\u01fb\u01fc\7e\2\2\u01fc\u0094\3\2\2\2\u01fd\u01fe\7\60"+
+		"\2\2\u01fe\u01ff\7d\2\2\u01ff\u0200\7{\2\2\u0200\u0201\7v\2\2\u0201\u0202"+
+		"\7g\2\2\u0202\u0096\3\2\2\2\u0203\u0204\7%\2\2\u0204\u0098\3\2\2\2\u0205"+
+		"\u0206\7\60\2\2\u0206\u009a\3\2\2\2\u0207\u0208\7d\2\2\u0208\u0209\7t"+
+		"\2\2\u0209\u02e6\7m\2\2\u020a\u020b\7q\2\2\u020b\u020c\7t\2\2\u020c\u02e6"+
+		"\7c\2\2\u020d\u020e\7m\2\2\u020e\u020f\7k\2\2\u020f\u02e6\7n\2\2\u0210"+
+		"\u0211\7u\2\2\u0211\u0212\7n\2\2\u0212\u02e6\7q\2\2\u0213\u0214\7p\2\2"+
+		"\u0214\u0215\7q\2\2\u0215\u02e6\7r\2\2\u0216\u0217\7c\2\2\u0217\u0218"+
+		"\7u\2\2\u0218\u02e6\7n\2\2\u0219\u021a\7r\2\2\u021a\u021b\7j\2\2\u021b"+
+		"\u02e6\7r\2\2\u021c\u021d\7c\2\2\u021d\u021e\7p\2\2\u021e\u02e6\7e\2\2"+
+		"\u021f\u0220\7d\2\2\u0220\u0221\7r\2\2\u0221\u02e6\7n\2\2\u0222\u0223"+
+		"\7e\2\2\u0223\u0224\7n\2\2\u0224\u02e6\7e\2\2\u0225\u0226\7l\2\2\u0226"+
+		"\u0227\7u\2\2\u0227\u02e6\7t\2\2\u0228\u0229\7c\2\2\u0229\u022a\7p\2\2"+
+		"\u022a\u02e6\7f\2\2\u022b\u022c\7t\2\2\u022c\u022d\7n\2\2\u022d\u02e6"+
+		"\7c\2\2\u022e\u022f\7d\2\2\u022f\u0230\7k\2\2\u0230\u02e6\7v\2\2\u0231"+
+		"\u0232\7t\2\2\u0232\u0233\7q\2\2\u0233\u02e6\7n\2\2\u0234\u0235\7r\2\2"+
+		"\u0235\u0236\7n\2\2\u0236\u02e6\7c\2\2\u0237\u0238\7r\2\2\u0238\u0239"+
+		"\7n\2\2\u0239\u02e6\7r\2\2\u023a\u023b\7d\2\2\u023b\u023c\7o\2\2\u023c"+
+		"\u02e6\7k\2\2\u023d\u023e\7u\2\2\u023e\u023f\7g\2\2\u023f\u02e6\7e\2\2"+
+		"\u0240\u0241\7t\2\2\u0241\u0242\7v\2\2\u0242\u02e6\7k\2\2\u0243\u0244"+
+		"\7g\2\2\u0244\u0245\7q\2\2\u0245\u02e6\7t\2\2\u0246\u0247\7u\2\2\u0247"+
+		"\u0248\7t\2\2\u0248\u02e6\7g\2\2\u0249\u024a\7n\2\2\u024a\u024b\7u\2\2"+
+		"\u024b\u02e6\7t\2\2\u024c\u024d\7r\2\2\u024d\u024e\7j\2\2\u024e\u02e6"+
+		"\7c\2\2\u024f\u0250\7c\2\2\u0250\u0251\7n\2\2\u0251\u02e6\7t\2\2\u0252"+
+		"\u0253\7l\2\2\u0253\u0254\7o\2\2\u0254\u02e6\7r\2\2\u0255\u0256\7d\2\2"+
+		"\u0256\u0257\7x\2\2\u0257\u02e6\7e\2\2\u0258\u0259\7e\2\2\u0259\u025a"+
+		"\7n\2\2\u025a\u02e6\7k\2\2\u025b\u025c\7t\2\2\u025c\u025d\7v\2\2\u025d"+
+		"\u02e6\7u\2\2\u025e\u025f\7c\2\2\u025f\u0260\7f\2\2\u0260\u02e6\7e\2\2"+
+		"\u0261\u0262\7t\2\2\u0262\u0263\7t\2\2\u0263\u02e6\7c\2\2\u0264\u0265"+
+		"\7d\2\2\u0265\u0266\7x\2\2\u0266\u02e6\7u\2\2\u0267\u0268\7u\2\2\u0268"+
+		"\u0269\7g\2\2\u0269\u02e6\7k\2\2\u026a\u026b\7u\2\2\u026b\u026c\7c\2\2"+
+		"\u026c\u02e6\7z\2\2\u026d\u026e\7u\2\2\u026e\u026f\7v\2\2\u026f\u02e6"+
+		"\7{\2\2\u0270\u0271\7u\2\2\u0271\u0272\7v\2\2\u0272\u02e6\7c\2\2\u0273"+
+		"\u0274\7u\2\2\u0274\u0275\7v\2\2\u0275\u02e6\7z\2\2\u0276\u0277\7f\2\2"+
+		"\u0277\u0278\7g\2\2\u0278\u02e6\7{\2\2\u0279\u027a\7v\2\2\u027a\u027b"+
+		"\7z\2\2\u027b\u02e6\7c\2\2\u027c\u027d\7z\2\2\u027d\u027e\7c\2\2\u027e"+
+		"\u02e6\7c\2\2\u027f\u0280\7d\2\2\u0280\u0281\7e\2\2\u0281\u02e6\7e\2\2"+
+		"\u0282\u0283\7c\2\2\u0283\u0284\7j\2\2\u0284\u02e6\7z\2\2\u0285\u0286"+
+		"\7v\2\2\u0286\u0287\7{\2\2\u0287\u02e6\7c\2\2\u0288\u0289\7v\2\2\u0289"+
+		"\u028a\7z\2\2\u028a\u02e6\7u\2\2\u028b\u028c\7v\2\2\u028c\u028d\7c\2\2"+
+		"\u028d\u02e6\7u\2\2\u028e\u028f\7u\2\2\u028f\u0290\7j\2\2\u0290\u02e6"+
+		"\7{\2\2\u0291\u0292\7u\2\2\u0292\u0293\7j\2\2\u0293\u02e6\7z\2\2\u0294"+
+		"\u0295\7n\2\2\u0295\u0296\7f\2\2\u0296\u02e6\7{\2\2\u0297\u0298\7n\2\2"+
+		"\u0298\u0299\7f\2\2\u0299\u02e6\7c\2\2\u029a\u029b\7n\2\2\u029b\u029c"+
+		"\7f\2\2\u029c\u02e6\7z\2\2\u029d\u029e\7n\2\2\u029e\u029f\7c\2\2\u029f"+
+		"\u02e6\7z\2\2\u02a0\u02a1\7v\2\2\u02a1\u02a2\7c\2\2\u02a2\u02e6\7{\2\2"+
+		"\u02a3\u02a4\7v\2\2\u02a4\u02a5\7c\2\2\u02a5\u02e6\7z\2\2\u02a6\u02a7"+
+		"\7d\2\2\u02a7\u02a8\7e\2\2\u02a8\u02e6\7u\2\2\u02a9\u02aa\7e\2\2\u02aa"+
+		"\u02ab\7n\2\2\u02ab\u02e6\7x\2\2\u02ac\u02ad\7v\2\2\u02ad\u02ae\7u\2\2"+
+		"\u02ae\u02e6\7z\2\2\u02af\u02b0\7n\2\2\u02b0\u02b1\7c\2\2\u02b1\u02e6"+
+		"\7u\2\2\u02b2\u02b3\7e\2\2\u02b3\u02b4\7r\2\2\u02b4\u02e6\7{\2\2\u02b5"+
+		"\u02b6\7e\2\2\u02b6\u02b7\7o\2\2\u02b7\u02e6\7r\2\2\u02b8\u02b9\7e\2\2"+
+		"\u02b9\u02ba\7r\2\2\u02ba\u02e6\7z\2\2\u02bb\u02bc\7f\2\2\u02bc\u02bd"+
+		"\7e\2\2\u02bd\u02e6\7r\2\2\u02be\u02bf\7f\2\2\u02bf\u02c0\7g\2\2\u02c0"+
+		"\u02e6\7e\2\2\u02c1\u02c2\7k\2\2\u02c2\u02c3\7p\2\2\u02c3\u02e6\7e\2\2"+
+		"\u02c4\u02c5\7c\2\2\u02c5\u02c6\7z\2\2\u02c6\u02e6\7u\2\2\u02c7\u02c8"+
+		"\7d\2\2\u02c8\u02c9\7p\2\2\u02c9\u02e6\7g\2\2\u02ca\u02cb\7e\2\2\u02cb"+
+		"\u02cc\7n\2\2\u02cc\u02e6\7f\2\2\u02cd\u02ce\7u\2\2\u02ce\u02cf\7d\2\2"+
+		"\u02cf\u02e6\7e\2\2\u02d0\u02d1\7k\2\2\u02d1\u02d2\7u\2\2\u02d2\u02e6"+
+		"\7e\2\2\u02d3\u02d4\7k\2\2\u02d4\u02d5\7p\2\2\u02d5\u02e6\7z\2\2\u02d6"+
+		"\u02d7\7d\2\2\u02d7\u02d8\7g\2\2\u02d8\u02e6\7s\2\2\u02d9\u02da\7u\2\2"+
+		"\u02da\u02db\7g\2\2\u02db\u02e6\7f\2\2\u02dc\u02dd\7f\2\2\u02dd\u02de"+
+		"\7g\2\2\u02de\u02e6\7z\2\2\u02df\u02e0\7k\2\2\u02e0\u02e1\7p\2\2\u02e1"+
+		"\u02e6\7{\2\2\u02e2\u02e3\7t\2\2\u02e3\u02e4\7q\2\2\u02e4\u02e6\7t\2\2"+
+		"\u02e5\u0207\3\2\2\2\u02e5\u020a\3\2\2\2\u02e5\u020d\3\2\2\2\u02e5\u0210"+
+		"\3\2\2\2\u02e5\u0213\3\2\2\2\u02e5\u0216\3\2\2\2\u02e5\u0219\3\2\2\2\u02e5"+
+		"\u021c\3\2\2\2\u02e5\u021f\3\2\2\2\u02e5\u0222\3\2\2\2\u02e5\u0225\3\2"+
+		"\2\2\u02e5\u0228\3\2\2\2\u02e5\u022b\3\2\2\2\u02e5\u022e\3\2\2\2\u02e5"+
+		"\u0231\3\2\2\2\u02e5\u0234\3\2\2\2\u02e5\u0237\3\2\2\2\u02e5\u023a\3\2"+
+		"\2\2\u02e5\u023d\3\2\2\2\u02e5\u0240\3\2\2\2\u02e5\u0243\3\2\2\2\u02e5"+
+		"\u0246\3\2\2\2\u02e5\u0249\3\2\2\2\u02e5\u024c\3\2\2\2\u02e5\u024f\3\2"+
+		"\2\2\u02e5\u0252\3\2\2\2\u02e5\u0255\3\2\2\2\u02e5\u0258\3\2\2\2\u02e5"+
+		"\u025b\3\2\2\2\u02e5\u025e\3\2\2\2\u02e5\u0261\3\2\2\2\u02e5\u0264\3\2"+
+		"\2\2\u02e5\u0267\3\2\2\2\u02e5\u026a\3\2\2\2\u02e5\u026d\3\2\2\2\u02e5"+
+		"\u0270\3\2\2\2\u02e5\u0273\3\2\2\2\u02e5\u0276\3\2\2\2\u02e5\u0279\3\2"+
+		"\2\2\u02e5\u027c\3\2\2\2\u02e5\u027f\3\2\2\2\u02e5\u0282\3\2\2\2\u02e5"+
+		"\u0285\3\2\2\2\u02e5\u0288\3\2\2\2\u02e5\u028b\3\2\2\2\u02e5\u028e\3\2"+
+		"\2\2\u02e5\u0291\3\2\2\2\u02e5\u0294\3\2\2\2\u02e5\u0297\3\2\2\2\u02e5"+
+		"\u029a\3\2\2\2\u02e5\u029d\3\2\2\2\u02e5\u02a0\3\2\2\2\u02e5\u02a3\3\2"+
+		"\2\2\u02e5\u02a6\3\2\2\2\u02e5\u02a9\3\2\2\2\u02e5\u02ac\3\2\2\2\u02e5"+
+		"\u02af\3\2\2\2\u02e5\u02b2\3\2\2\2\u02e5\u02b5\3\2\2\2\u02e5\u02b8\3\2"+
+		"\2\2\u02e5\u02bb\3\2\2\2\u02e5\u02be\3\2\2\2\u02e5\u02c1\3\2\2\2\u02e5"+
+		"\u02c4\3\2\2\2\u02e5\u02c7\3\2\2\2\u02e5\u02ca\3\2\2\2\u02e5\u02cd\3\2"+
+		"\2\2\u02e5\u02d0\3\2\2\2\u02e5\u02d3\3\2\2\2\u02e5\u02d6\3\2\2\2\u02e5"+
+		"\u02d9\3\2\2\2\u02e5\u02dc\3\2\2\2\u02e5\u02df\3\2\2\2\u02e5\u02e2\3\2"+
+		"\2\2\u02e6\u009c\3\2\2\2\u02e7\u02e8\7}\2\2\u02e8\u02e9\7}\2\2\u02e9\u02ed"+
+		"\3\2\2\2\u02ea\u02ec\13\2\2\2\u02eb\u02ea\3\2\2\2\u02ec\u02ef\3\2\2\2"+
+		"\u02ed\u02ee\3\2\2\2\u02ed\u02eb\3\2\2\2\u02ee\u02f0\3\2\2\2\u02ef\u02ed"+
+		"\3\2\2\2\u02f0\u02f1\7\177\2\2\u02f1\u02f2\7\177\2\2\u02f2\u009e\3\2\2"+
+		"\2\u02f3\u02f4\7d\2\2\u02f4\u02f5\7{\2\2\u02f5\u02f6\7v\2\2\u02f6\u0319"+
+		"\7g\2\2\u02f7\u02f8\7y\2\2\u02f8\u02f9\7q\2\2\u02f9\u02fa\7t\2\2\u02fa"+
+		"\u0319\7f\2\2\u02fb\u02fc\7f\2\2\u02fc\u02fd\7y\2\2\u02fd\u02fe\7q\2\2"+
+		"\u02fe\u02ff\7t\2\2\u02ff\u0319\7f\2\2\u0300\u0301\7d\2\2\u0301\u0302"+
+		"\7q\2\2\u0302\u0303\7q\2\2\u0303\u0319\7n\2\2\u0304\u0305\7e\2\2\u0305"+
+		"\u0306\7j\2\2\u0306\u0307\7c\2\2\u0307\u0319\7t\2\2\u0308\u0309\7u\2\2"+
+		"\u0309\u030a\7j\2\2\u030a\u030b\7q\2\2\u030b\u030c\7t\2\2\u030c\u0319"+
+		"\7v\2\2\u030d\u030e\7k\2\2\u030e\u030f\7p\2\2\u030f\u0319\7v\2\2\u0310"+
+		"\u0311\7n\2\2\u0311\u0312\7q\2\2\u0312\u0313\7p\2\2\u0313\u0319\7i\2\2"+
+		"\u0314\u0315\7x\2\2\u0315\u0316\7q\2\2\u0316\u0317\7k\2\2\u0317\u0319"+
+		"\7f\2\2\u0318\u02f3\3\2\2\2\u0318\u02f7\3\2\2\2\u0318\u02fb\3\2\2\2\u0318"+
+		"\u0300\3\2\2\2\u0318\u0304\3\2\2\2\u0318\u0308\3\2\2\2\u0318\u030d\3\2"+
+		"\2\2\u0318\u0310\3\2\2\2\u0318\u0314\3\2\2\2\u0319\u00a0\3\2\2\2\u031a"+
+		"\u0320\7$\2\2\u031b\u031c\7^\2\2\u031c\u031f\7$\2\2\u031d\u031f\n\2\2"+
+		"\2\u031e\u031b\3\2\2\2\u031e\u031d\3\2\2\2\u031f\u0322\3\2\2\2\u0320\u031e"+
+		"\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u0323\3\2\2\2\u0322\u0320\3\2\2\2\u0323"+
+		"\u0325\7$\2\2\u0324\u0326\7|\2\2\u0325\u0324\3\2\2\2\u0325\u0326\3\2\2"+
+		"\2\u0326\u00a2\3\2\2\2\u0327\u032b\7)\2\2\u0328\u0329\7^\2\2\u0329\u032c"+
+		"\7)\2\2\u032a\u032c\n\3\2\2\u032b\u0328\3\2\2\2\u032b\u032a\3\2\2\2\u032c"+
+		"\u032d\3\2\2\2\u032d\u032e\7)\2\2\u032e\u00a4\3\2\2\2\u032f\u0330\7v\2"+
+		"\2\u0330\u0331\7t\2\2\u0331\u0332\7w\2\2\u0332\u0339\7g\2\2\u0333\u0334"+
+		"\7h\2\2\u0334\u0335\7c\2\2\u0335\u0336\7n\2\2\u0336\u0337\7u\2\2\u0337"+
+		"\u0339\7g\2\2\u0338\u032f\3\2\2\2\u0338\u0333\3\2\2\2\u0339\u00a6\3\2"+
+		"\2\2\u033a\u033d\5\u00a9U\2\u033b\u033d\5\u00b1Y\2\u033c\u033a\3\2\2\2"+
+		"\u033c\u033b\3\2\2\2\u033d\u00a8\3\2\2\2\u033e\u0342\5\u00abV\2\u033f"+
+		"\u0342\5\u00adW\2\u0340\u0342\5\u00afX\2\u0341\u033e\3\2\2\2\u0341\u033f"+
+		"\3\2\2\2\u0341\u0340\3\2\2\2\u0342\u00aa\3\2\2\2\u0343\u0349\7\'\2\2\u0344"+
+		"\u0345\7\62\2\2\u0345\u0349\7d\2\2\u0346\u0347\7\62\2\2\u0347\u0349\7"+
+		"D\2\2\u0348\u0343\3\2\2\2\u0348\u0344\3\2\2\2\u0348\u0346\3\2\2\2\u0349"+
+		"\u034d\3\2\2\2\u034a\u034c\5\u00b9]\2\u034b\u034a\3\2\2\2\u034c\u034f"+
+		"\3\2\2\2\u034d\u034b\3\2\2\2\u034d\u034e\3\2\2\2\u034e\u0350\3\2\2\2\u034f"+
+		"\u034d\3\2\2\2\u0350\u0352\7\60\2\2\u0351\u0353\5\u00b9]\2\u0352\u0351"+
+		"\3\2\2\2\u0353\u0354\3\2\2\2\u0354\u0352\3\2\2\2\u0354\u0355\3\2\2\2\u0355"+
+		"\u00ac\3\2\2\2\u0356\u0358\5\u00bb^\2\u0357\u0356\3\2\2\2\u0358\u035b"+
+		"\3\2\2\2\u0359\u0357\3\2\2\2\u0359\u035a\3\2\2\2\u035a\u035c\3\2\2\2\u035b"+
+		"\u0359\3\2\2\2\u035c\u035e\7\60\2\2\u035d\u035f\5\u00bb^\2\u035e\u035d"+
+		"\3\2\2\2\u035f\u0360\3\2\2\2\u0360\u035e\3\2\2\2\u0360\u0361\3\2\2\2\u0361"+
+		"\u00ae\3\2\2\2\u0362\u0368\7&\2\2\u0363\u0364\7\62\2\2\u0364\u0368\7z"+
+		"\2\2\u0365\u0366\7\62\2\2\u0366\u0368\7Z\2\2\u0367\u0362\3\2\2\2\u0367"+
+		"\u0363\3\2\2\2\u0367\u0365\3\2\2\2\u0368\u036c\3\2\2\2\u0369\u036b\5\u00bd"+
+		"_\2\u036a\u0369\3\2\2\2\u036b\u036e\3\2\2\2\u036c\u036a\3\2\2\2\u036c"+
+		"\u036d\3\2\2\2\u036d\u036f\3\2\2\2\u036e\u036c\3\2\2\2\u036f\u0371\7\60"+
+		"\2\2\u0370\u0372\5\u00bd_\2\u0371\u0370\3\2\2\2\u0372\u0373\3\2\2\2\u0373"+
+		"\u0371\3\2\2\2\u0373\u0374\3\2\2\2\u0374\u00b0\3\2\2\2\u0375\u0379\5\u00b5"+
+		"[\2\u0376\u0379\5\u00b7\\\2\u0377\u0379\5\u00b3Z\2\u0378\u0375\3\2\2\2"+
+		"\u0378\u0376\3\2\2\2\u0378\u0377\3\2\2\2\u0379\u037d\3\2\2\2\u037a\u037b"+
+		"\t\4\2\2\u037b\u037e\t\5\2\2\u037c\u037e\7n\2\2\u037d\u037a\3\2\2\2\u037d"+
+		"\u037c\3\2\2\2\u037d\u037e\3\2\2\2\u037e\u00b2\3\2\2\2\u037f\u0380\7\62"+
+		"\2\2\u0380\u0382\t\6\2\2\u0381\u0383\5\u00b9]\2\u0382\u0381\3\2\2\2\u0383"+
+		"\u0384\3\2\2\2\u0384\u0382\3\2\2\2\u0384\u0385\3\2\2\2\u0385\u038d\3\2"+
+		"\2\2\u0386\u0388\7\'\2\2\u0387\u0389\5\u00b9]\2\u0388\u0387\3\2\2\2\u0389"+
+		"\u038a\3\2\2\2\u038a\u0388\3\2\2\2\u038a\u038b\3\2\2\2\u038b\u038d\3\2"+
+		"\2\2\u038c\u037f\3\2\2\2\u038c\u0386\3\2\2\2\u038d\u00b4\3\2\2\2\u038e"+
+		"\u0390\5\u00bb^\2\u038f\u038e\3\2\2\2\u0390\u0391\3\2\2\2\u0391\u038f"+
+		"\3\2\2\2\u0391\u0392\3\2\2\2\u0392\u00b6\3\2\2\2\u0393\u0399\7&\2\2\u0394"+
+		"\u0395\7\62\2\2\u0395\u0399\7z\2\2\u0396\u0397\7\62\2\2\u0397\u0399\7"+
+		"Z\2\2\u0398\u0393\3\2\2\2\u0398\u0394\3\2\2\2\u0398\u0396\3\2\2\2\u0399"+
+		"\u039b\3\2\2\2\u039a\u039c\5\u00bd_\2\u039b\u039a\3\2\2\2\u039c\u039d"+
+		"\3\2\2\2\u039d\u039b\3\2\2\2\u039d\u039e\3\2\2\2\u039e\u00b8\3\2\2\2\u039f"+
+		"\u03a0\t\7\2\2\u03a0\u00ba\3\2\2\2\u03a1\u03a2\t\b\2\2\u03a2\u00bc\3\2"+
+		"\2\2\u03a3\u03a4\t\t\2\2\u03a4\u00be\3\2\2\2\u03a5\u03a9\5\u00c1a\2\u03a6"+
+		"\u03a8\5\u00c3b\2\u03a7\u03a6\3\2\2\2\u03a8\u03ab\3\2\2\2\u03a9\u03a7"+
+		"\3\2\2\2\u03a9\u03aa\3\2\2\2\u03aa\u00c0\3\2\2\2\u03ab\u03a9\3\2\2\2\u03ac"+
+		"\u03ad\t\n\2\2\u03ad\u00c2\3\2\2\2\u03ae\u03af\t\13\2\2\u03af\u00c4\3"+
+		"\2\2\2\u03b0\u03b4\7#\2\2\u03b1\u03b3\5\u00c3b\2\u03b2\u03b1\3\2\2\2\u03b3"+
+		"\u03b6\3\2\2\2\u03b4\u03b2\3\2\2\2\u03b4\u03b5\3\2\2\2\u03b5\u03b8\3\2"+
+		"\2\2\u03b6\u03b4\3\2\2\2\u03b7\u03b9\t\f\2\2\u03b8\u03b7\3\2\2\2\u03b9"+
+		"\u03ba\3\2\2\2\u03ba\u03b8\3\2\2\2\u03ba\u03bb\3\2\2\2\u03bb\u00c6\3\2"+
+		"\2\2\u03bc\u03be\t\r\2\2\u03bd\u03bc\3\2\2\2\u03be\u03bf\3\2\2\2\u03bf"+
+		"\u03bd\3\2\2\2\u03bf\u03c0\3\2\2\2\u03c0\u03c1\3\2\2\2\u03c1\u03c2\bd"+
+		"\2\2\u03c2\u00c8\3\2\2\2\u03c3\u03c4\7\61\2\2\u03c4\u03c5\7\61\2\2\u03c5"+
+		"\u03c9\3\2\2\2\u03c6\u03c8\n\16\2\2\u03c7\u03c6\3\2\2\2\u03c8\u03cb\3"+
+		"\2\2\2\u03c9\u03c7\3\2\2\2\u03c9\u03ca\3\2\2\2\u03ca\u03cc\3\2\2\2\u03cb"+
+		"\u03c9\3\2\2\2\u03cc\u03cd\be\3\2\u03cd\u00ca\3\2\2\2\u03ce\u03cf\7\61"+
+		"\2\2\u03cf\u03d0\7,\2\2\u03d0\u03d4\3\2\2\2\u03d1\u03d3\13\2\2\2\u03d2"+
+		"\u03d1\3\2\2\2\u03d3\u03d6\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d4\u03d2\3\2"+
+		"\2\2\u03d5\u03d7\3\2\2\2\u03d6\u03d4\3\2\2\2\u03d7\u03d8\7,\2\2\u03d8"+
+		"\u03d9\7\61\2\2\u03d9\u03da\3\2\2\2\u03da\u03db\bf\3\2\u03db\u00cc\3\2"+
+		"\2\2#\2\u02e5\u02ed\u0318\u031e\u0320\u0325\u032b\u0338\u033c\u0341\u0348"+
+		"\u034d\u0354\u0359\u0360\u0367\u036c\u0373\u0378\u037d\u0384\u038a\u038c"+
+		"\u0391\u0398\u039d\u03a9\u03b4\u03ba\u03bf\u03c9\u03d4\4\2\3\2\2\4\2";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index ed67c18d6..fe61073bd 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,7 +63,7 @@ public class TestPrograms {
       compileAndCompare("typeid-plus-byte-problem", log());
    }
 
-   //@Test
+   @Test
    public void testTypeIdPlusBytes() throws IOException, URISyntaxException {
       compileAndCompare("typeid-plus-bytes");
    }

From eb895fffef967cace46cd921b7d5a92f02ad3236 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 2 May 2019 01:23:49 +0200
Subject: [PATCH 04/93] Added parser for typed integer literal postfix
 (ub/sb/uc/sc/uw/sw/ui/si/us/ss/ud/sd/ul/sl and l)

---
 .../java/dk/camelot64/kickc/NumberParser.java | 73 ++++++++++++-------
 .../kickc/model/values/ConstantInteger.java   |  6 +-
 .../Pass0GenerateStatementSequence.java       |  7 +-
 .../dk/camelot64/kickc/test/TestPrograms.java |  5 ++
 src/test/kc/int-literals.kc                   | 19 +++++
 5 files changed, 78 insertions(+), 32 deletions(-)
 create mode 100644 src/test/kc/int-literals.kc

diff --git a/src/main/java/dk/camelot64/kickc/NumberParser.java b/src/main/java/dk/camelot64/kickc/NumberParser.java
index 5465bad9a..4f222860d 100644
--- a/src/main/java/dk/camelot64/kickc/NumberParser.java
+++ b/src/main/java/dk/camelot64/kickc/NumberParser.java
@@ -1,38 +1,61 @@
 package dk.camelot64.kickc;
 
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+
 /** Parser for converting literal numbers to the corresponding Java Integer/Double */
 public class NumberParser {
 
-   public static Number parseLiteral(String literal) {
-      boolean isInt = !literal.contains(".");
+   public static ConstantInteger parseIntegerLiteral(String literal) {
 
-      if(isInt) {
-         if(literal.startsWith("0x")) {
-            return parseHexInt(literal.substring(2));
-         } else if(literal.startsWith("$")) {
-            return parseHexInt(literal.substring(1));
-         } else if(literal.startsWith("0b")) {
-            return parseBinInt(literal.substring(2));
-         } else if(literal.startsWith("%")) {
-            return parseBinInt(literal.substring(1));
-         } else {
-            return parseDecInt(literal);
-         }
-      } else {
+      boolean isInt = !literal.contains(".");
+      if(!isInt) {
          throw new NumberFormatException("Not Implemented: non-integer parsing. " + literal);
       }
+
+      SymbolType type = null;
+      if(literal.endsWith("ub") || literal.endsWith("uc")) {
+         type = SymbolType.BYTE;
+         literal = literal.substring(0, literal.length()-2);
+      }  else if(literal.endsWith("sb") || literal.endsWith("sc")) {
+         type = SymbolType.SBYTE;
+         literal = literal.substring(0, literal.length()-2);
+      }  else if(literal.endsWith("uw") || literal.endsWith("ui")|| literal.endsWith("us")) {
+         type = SymbolType.WORD;
+         literal = literal.substring(0, literal.length()-2);
+      }  else if(literal.endsWith("sw") || literal.endsWith("si")|| literal.endsWith("ss")) {
+         type = SymbolType.SWORD;
+         literal = literal.substring(0, literal.length()-2);
+      }  else if(literal.endsWith("ud") || literal.endsWith("ul")) {
+         type = SymbolType.DWORD;
+         literal = literal.substring(0, literal.length()-2);
+      }  else if(literal.endsWith("sd") || literal.endsWith("sl")) {
+         type = SymbolType.SDWORD;
+         literal = literal.substring(0, literal.length()-2);
+      }  else if(literal.endsWith("l")) {
+         type = SymbolType.SDWORD;
+         literal = literal.substring(0, literal.length()-1);
+      }
+
+         Long value;
+         if(literal.startsWith("0x")) {
+            value = Long.parseLong(literal.substring(2), 16);
+         } else if(literal.startsWith("$")) {
+            value = Long.parseLong(literal.substring(1), 16);
+         } else if(literal.startsWith("0b")) {
+            value = Long.parseLong(literal.substring(2), 2);
+         } else if(literal.startsWith("%")) {
+            value = Long.parseLong(literal.substring(1), 2);
+         } else {
+            value = Long.parseLong(literal);
+         }
+         return new ConstantInteger(value, type);
+
    }
 
-   private static Long parseHexInt(String literal) {
-      return Long.parseLong(literal, 16);
-   }
-
-   private static Long parseBinInt(String literal) {
-      return Long.parseLong(literal, 2);
-   }
-
-   private static Long parseDecInt(String literal) {
-      return Long.parseLong(literal);
+   public static Number parseLiteral(String literal) {
+      ConstantInteger constantInteger = parseIntegerLiteral(literal);
+      return constantInteger.getValue();
    }
 
 
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
index b0131e99e..c4f8620eb 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
@@ -21,7 +21,11 @@ public class ConstantInteger implements ConstantEnumerable<Long> {
 
    public ConstantInteger(Long number, SymbolType type) {
       this.number = number;
-      this.type = type;
+      if(type!=null) {
+         this.type = type;
+      } else {
+         this.type = SymbolTypeMulti.getMultiType(number);
+      }
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index 6889b48b4..efc72cdbd 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -1298,12 +1298,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
 
    @Override
    public RValue visitExprNumber(KickCParser.ExprNumberContext ctx) {
-      Number number = NumberParser.parseLiteral(ctx.getText());
-      if(number instanceof Long) {
-         return new ConstantInteger((Long) number);
-      } else {
-         return new ConstantDouble((Double) number);
-      }
+      return NumberParser.parseIntegerLiteral(ctx.getText());
    }
 
    @Override
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index fe61073bd..cbc3675db 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,6 +32,11 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testIntegerLiterals() throws IOException, URISyntaxException {
+      compileAndCompare("int-literals");
+   }
+
    @Test
    public void testSimpleLoop() throws IOException, URISyntaxException {
       compileAndCompare("simple-loop");
diff --git a/src/test/kc/int-literals.kc b/src/test/kc/int-literals.kc
new file mode 100644
index 000000000..0a66f2042
--- /dev/null
+++ b/src/test/kc/int-literals.kc
@@ -0,0 +1,19 @@
+// Tests different integer literals
+
+void main() {
+    unsigned byte ub = 12ub;
+    unsigned char uc = 12uc;
+    signed byte sb = 12sb;
+    signed byte sc = 12sc;
+    unsigned word uw = 12uw;
+    unsigned int ui = 12ui;
+    unsigned short us = 12us;
+    signed word sw = 12sw;
+    signed int si = 12si;
+    signed short ss = 12ss;
+    unsigned dword ud = 12ud;
+    unsigned long ul = 12ul;
+    signed dword sd = 12sd;
+    signed long sl = 12sl;
+    long l = 12l;
+}
\ No newline at end of file

From facd8c6c5b611f33cfba2a50864879cdb8c1e089 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Fri, 3 May 2019 08:45:33 +0200
Subject: [PATCH 05/93] Expanded testing of types to include operators

---
 src/test/kc/int-literals.kc | 77 +++++++++++++++++++++++++++++--------
 1 file changed, 61 insertions(+), 16 deletions(-)

diff --git a/src/test/kc/int-literals.kc b/src/test/kc/int-literals.kc
index 0a66f2042..d3fd609c6 100644
--- a/src/test/kc/int-literals.kc
+++ b/src/test/kc/int-literals.kc
@@ -1,19 +1,64 @@
-// Tests different integer literals
+// Tests different integer literal types
+
+const byte RED = 2;
+const byte GREEN = 5;
+
+const byte* SCREEN = $0400;
+const byte* COLS = $d800;
+byte idx = 0;
 
 void main() {
-    unsigned byte ub = 12ub;
-    unsigned char uc = 12uc;
-    signed byte sb = 12sb;
-    signed byte sc = 12sc;
-    unsigned word uw = 12uw;
-    unsigned int ui = 12ui;
-    unsigned short us = 12us;
-    signed word sw = 12sw;
-    signed int si = 12si;
-    signed short ss = 12ss;
-    unsigned dword ud = 12ud;
-    unsigned long ul = 12ul;
-    signed dword sd = 12sd;
-    signed long sl = 12sl;
-    long l = 12l;
+    for(byte* s: SCREEN..SCREEN+999) *s = ' ';
+    idx = 0;
+    testSimpleTypes();
+    idx = 40;
+    testBinaryOperator();
+}
+
+void testSimpleTypes() {
+    // Simple types
+    assertType(typeid(12ub), typeid(byte));
+    assertType(typeid(12uc), typeid(byte));
+    assertType(typeid(12sb), typeid(signed byte));
+    assertType(typeid(12sc), typeid(signed byte));
+    assertType(typeid(12uw), typeid(word));
+    assertType(typeid(12ui), typeid(word));
+    assertType(typeid(12us), typeid(word));
+    assertType(typeid(12sw), typeid(signed word));
+    assertType(typeid(12si), typeid(signed word));
+    assertType(typeid(12ss), typeid(signed word));
+    assertType(typeid(12ud), typeid(dword));
+    assertType(typeid(12ul), typeid(dword));
+    assertType(typeid(12sd), typeid(signed dword));
+    assertType(typeid(12sl), typeid(signed dword));
+    assertType(typeid(12l), typeid(signed dword));
+}
+
+void testBinaryOperator() {
+    // Binary Operations between unsigned byte & other types
+    assertType(typeid(12ub+12ub), typeid(byte));
+    assertType(typeid(12ub+12sb), typeid(byte));
+    assertType(typeid(12ub+12uw), typeid(word));
+    assertType(typeid(12ub+12sw), typeid(signed word));
+    assertType(typeid(12ub+12ud), typeid(dword));
+    assertType(typeid(12ub+12sd), typeid(signed dword));
+    idx++;
+    // Binary Operations between signed byte & other types
+    assertType(typeid(12sb+12ub), typeid(byte));
+    assertType(typeid(12sb+12sb), typeid(signed byte));
+    assertType(typeid(12sb+12uw), typeid(word));
+    assertType(typeid(12sb+12sw), typeid(signed word));
+    assertType(typeid(12sb+12ud), typeid(dword));
+    assertType(typeid(12sb+12sd), typeid(signed dword));
+}
+
+
+
+void assertType(byte t1, byte t2) {
+    if(t1==t2) {
+        COLS[idx] = GREEN;
+    } else {
+        COLS[idx] = RED;
+    }
+    SCREEN[idx++] = t1;
 }
\ No newline at end of file

From 35ec65ce94542548f2e5cfa7e19ec8cc59ffbddd Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 5 May 2019 01:26:40 +0200
Subject: [PATCH 06/93] Implemented much of integer type conversion and the
 number type. Still a lot left to do.

---
 .../java/dk/camelot64/kickc/Compiler.java     |   9 +-
 .../camelot64/kickc/fragment/AsmFormat.java   |  77 +++++----
 .../camelot64/kickc/model/InternalError.java  |  24 +++
 .../model/operators/OperatorBitwiseAnd.java   |  13 +-
 .../model/operators/OperatorBitwiseOr.java    |   9 +-
 .../model/operators/OperatorBitwiseXor.java   |   9 +-
 .../model/operators/OperatorCastByte.java     |   4 +-
 .../model/operators/OperatorCastDWord.java    |   4 +-
 .../model/operators/OperatorCastSByte.java    |   2 +-
 .../model/operators/OperatorCastSDWord.java   |   2 +-
 .../model/operators/OperatorCastSWord.java    |   2 +-
 .../model/operators/OperatorCastWord.java     |   4 +-
 .../kickc/model/operators/OperatorDivide.java |   2 +-
 .../kickc/model/operators/OperatorMinus.java  |   8 +-
 .../kickc/model/operators/OperatorModulo.java |   2 +-
 .../model/operators/OperatorMultiply.java     |   3 +-
 .../kickc/model/operators/OperatorPlus.java   |  21 +--
 .../kickc/model/types/SymbolType.java         |  66 +++++---
 .../model/types/SymbolTypeInference.java      | 152 +-----------------
 .../kickc/model/types/SymbolTypeInteger.java  |  48 +-----
 .../model/types/SymbolTypeIntegerAuto.java    |  42 +++++
 .../model/types/SymbolTypeIntegerFixed.java   |  50 ++++++
 .../kickc/model/types/SymbolTypeMulti.java    |   2 +-
 .../types/SymbolTypeNumberInference.java      | 104 ++++++++++++
 .../kickc/model/values/ConstantInteger.java   |  16 +-
 .../Pass0GenerateStatementSequence.java       |   2 +-
 .../kickc/passes/Pass1AddTypePromotions.java  | 102 ------------
 .../kickc/passes/Pass1Procedures.java         |  43 +++++
 .../kickc/passes/Pass2AssertTypeMatch.java    |   7 +-
 .../passes/Pass2ComparisonOptimization.java   |   6 +-
 .../passes/Pass2ConstantIdentification.java   |  82 +---------
 .../Pass2ConstantRValueConsolidation.java     | 125 ++++++++++++++
 .../passes/Pass2FixInlineConstructors.java    |   6 +-
 .../kickc/passes/Pass2RangeResolving.java     |   8 +-
 .../kickc/passes/PassNAddTypeConversions.java | 134 +++++++++++++++
 ...Inference.java => PassNTypeInference.java} |  15 +-
 .../dk/camelot64/kickc/test/TestPrograms.java |  12 +-
 src/test/kc/int-literals.kc                   |  91 ++++++++---
 src/test/kc/number-type.kc                    |  23 +++
 39 files changed, 793 insertions(+), 538 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/model/InternalError.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerAuto.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
 rename src/main/java/dk/camelot64/kickc/passes/{Pass1TypeInference.java => PassNTypeInference.java} (68%)
 create mode 100644 src/test/kc/number-type.kc

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index cb8d88400..f9a6b1fc6 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -153,7 +153,8 @@ public class Compiler {
       new Pass1GenerateControlFlowGraph(program).execute();
       new Pass1ResolveForwardReferences(program).execute();
       new Pass1UnwindBlockScopes(program).execute();
-      new Pass1TypeInference(program).execute();
+      new Pass1Procedures(program).execute();
+      new PassNTypeInference(program).execute();
       new Pass1TypeIdSimplification(program).execute();
 
       if(getLog().isVerbosePass1CreateSsa()) {
@@ -164,7 +165,7 @@ public class Compiler {
       new Pass1FixLValuesLoHi(program).execute();
       new Pass1AssertNoLValueIntermediate(program).execute();
       new Pass1PointerSizeofFix(program).execute();
-      new Pass1AddTypePromotions(program).execute();
+      new PassNAddTypeConversions(program).execute();
       new Pass1EarlyConstantIdentification(program).execute();
       new PassNStatementIndices(program).step();
       new PassNCallGraphAnalysis(program).step();
@@ -230,6 +231,8 @@ public class Compiler {
 
    private void pass2Optimize() {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
+      optimizations.add(new PassNTypeInference(program));
+      optimizations.add(new PassNAddTypeConversions(program));
       optimizations.add(new Pass2CullEmptyBlocks(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
@@ -240,6 +243,7 @@ public class Compiler {
       optimizations.add(new Pass2IdenticalPhiElimination(program));
       optimizations.add(new Pass2ConditionalJumpSimplification(program));
       optimizations.add(new Pass2ConditionalAndOrRewriting(program));
+      optimizations.add(new Pass2ConstantRValueConsolidation(program));
       optimizations.add(new Pass2ConstantIdentification(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
@@ -294,6 +298,7 @@ public class Compiler {
       constantOptimizations.add(new Pass2ConstantInlining(program));
       constantOptimizations.add(new Pass2ConstantStringConsolidation(program));
       constantOptimizations.add(new Pass2IdenticalPhiElimination(program));
+      constantOptimizations.add(new Pass2ConstantRValueConsolidation(program));
       constantOptimizations.add(new Pass2ConstantIdentification(program));
       constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
       constantOptimizations.add(new Pass2ConstantSimplification(program));
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
index 28f28111f..895e806a8 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
@@ -7,11 +7,11 @@ import dk.camelot64.kickc.model.symbols.ConstantVar;
 import dk.camelot64.kickc.model.symbols.Procedure;
 import dk.camelot64.kickc.model.symbols.Symbol;
 import dk.camelot64.kickc.model.symbols.Variable;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
+import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.*;
 
+import java.util.List;
+
 /** Formatting of numbers, constants, names and more for KickAssembler */
 public class AsmFormat {
 
@@ -61,7 +61,7 @@ public class AsmFormat {
          } else if(symbol instanceof Procedure) {
             return getAsmParamName((Procedure) symbol, codeScope);
          } else {
-            throw new RuntimeException("Unhandled symbol type "+symbol);
+            throw new RuntimeException("Unhandled symbol type " + symbol);
          }
       } else if(value instanceof ConstantCastValue) {
          ConstantCastValue castValue = (ConstantCastValue) value;
@@ -75,6 +75,7 @@ public class AsmFormat {
 
    /**
     * Get ASM for a binary constant expression
+    *
     * @param program The program
     * @param left The left operand of the expression
     * @param operator The binary operator
@@ -85,12 +86,12 @@ public class AsmFormat {
    private static String getAsmConstantBinary(Program program, ConstantValue left, OperatorBinary operator, ConstantValue right, ScopeRef codeScope) {
       if(Operators.MODULO.equals(operator)) {
          // Remainder operator % not supported by KickAss - use modulo function instead
-         return "mod("+
+         return "mod(" +
                getAsmConstant(program, left, operator.getPrecedence(), codeScope) +
                "," +
-               getAsmConstant(program, right, operator.getPrecedence(), codeScope)+
+               getAsmConstant(program, right, operator.getPrecedence(), codeScope) +
                ")";
-      }  else {
+      } else {
          return getAsmConstant(program, left, operator.getPrecedence(), codeScope) +
                operator.getOperator() +
                getAsmConstant(program, right, operator.getPrecedence(), codeScope);
@@ -109,28 +110,49 @@ public class AsmFormat {
    private static String getAsmConstantUnary(Program program, ScopeRef codeScope, Operator operator, ConstantValue operand, int outerPrecedence) {
       if(Operators.CAST_BYTE.equals(operator) || Operators.CAST_SBYTE.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
-         if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
+         if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
             // No cast needed
             return getAsmConstant(program, operand, outerPrecedence, codeScope);
-         } else {
-            return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
          }
-      } else if(operator instanceof OperatorCastPtr || Operators.CAST_WORD.equals(operator) || Operators.CAST_SWORD.equals(operator) ) {
+         if(SymbolType.NUMBER.equals(operandType)) {
+            List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand);
+            if(operandInferedTypes.contains(SymbolType.BYTE) || operandInferedTypes.contains(SymbolType.SBYTE)) {
+               // No cast needed
+               return getAsmConstant(program, operand, outerPrecedence, codeScope);
+            }
+         }
+         // Cast is needed
+         return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
+      } else if(operator instanceof OperatorCastPtr || Operators.CAST_WORD.equals(operator) || Operators.CAST_SWORD.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
-         if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || SymbolType.isByte(operandType) || SymbolType.isSByte(operandType) || operandType instanceof SymbolTypePointer) {
+         if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType) || operandType instanceof SymbolTypePointer) {
             // No cast needed
             return getAsmConstant(program, operand, outerPrecedence, codeScope);
-         } else {
-            return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xffff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
          }
+         if(SymbolType.NUMBER.equals(operandType)) {
+            List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand);
+            if(operandInferedTypes.contains(SymbolType.WORD) || operandInferedTypes.contains(SymbolType.SWORD)) {
+               // No cast needed
+               return getAsmConstant(program, operand, outerPrecedence, codeScope);
+            }
+         }
+         // Cast is needed
+         return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
       } else if(Operators.CAST_DWORD.equals(operator) || Operators.CAST_SDWORD.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
-         if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
+         if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType) || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType) || operandType instanceof SymbolTypePointer) {
             // No cast needed
             return getAsmConstant(program, operand, outerPrecedence, codeScope);
-         } else {
-            return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long)0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
          }
+         if(SymbolType.NUMBER.equals(operandType)) {
+            List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand);
+            if(operandInferedTypes.contains(SymbolType.DWORD) || operandInferedTypes.contains(SymbolType.SDWORD)) {
+               // No cast needed
+               return getAsmConstant(program, operand, outerPrecedence, codeScope);
+            }
+         }
+         // Cast is needed
+         return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
       } else if(Operators.LOWBYTE.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
          if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
@@ -138,9 +160,9 @@ public class AsmFormat {
          } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
             return "<" + getAsmConstant(program, operand, outerPrecedence, codeScope);
          } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
-            return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_AND, new ConstantInteger((long)0xffff)), outerPrecedence, codeScope);
+            return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_AND, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope);
          } else {
-            throw new CompileError("Unhandled type "+operand);
+            throw new CompileError("Unhandled type " + operand);
          }
       } else if(Operators.HIBYTE.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
@@ -149,24 +171,24 @@ public class AsmFormat {
          } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
             return ">" + getAsmConstant(program, operand, outerPrecedence, codeScope);
          } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
-            return getAsmConstant(program, new ConstantBinary(operand, Operators.SHIFT_RIGHT, new ConstantInteger((long)16)), outerPrecedence, codeScope);
+            return getAsmConstant(program, new ConstantBinary(operand, Operators.SHIFT_RIGHT, new ConstantInteger((long) 16)), outerPrecedence, codeScope);
          } else {
-            throw new CompileError("Unhandled type "+operand);
+            throw new CompileError("Unhandled type " + operand);
          }
       } else if(Operators.INCREMENT.equals(operator)) {
-         return getAsmConstant(program, new ConstantBinary(operand, Operators.PLUS, new ConstantInteger((long)1)), outerPrecedence, codeScope);
+         return getAsmConstant(program, new ConstantBinary(operand, Operators.PLUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope);
       } else if(Operators.DECREMENT.equals(operator)) {
-         return getAsmConstant(program, new ConstantBinary(operand, Operators.MINUS, new ConstantInteger((long)1)), outerPrecedence, codeScope);
+         return getAsmConstant(program, new ConstantBinary(operand, Operators.MINUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope);
       } else if(Operators.BOOL_NOT.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
          if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
-            return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xff)), outerPrecedence, codeScope);
+            return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xff)), outerPrecedence, codeScope);
          } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
-            return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xffff)), outerPrecedence, codeScope);
+            return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope);
          } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
-            return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long)0xffffffff)), outerPrecedence, codeScope);
+            return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffffffff)), outerPrecedence, codeScope);
          } else {
-            throw new CompileError("Unhandled type "+operand);
+            throw new CompileError("Unhandled type " + operand);
          }
       } else {
          return operator.getOperator() +
@@ -208,6 +230,7 @@ public class AsmFormat {
 
    /**
     * Get the ASM code for a boolean value
+    *
     * @param bool the boolean vallue
     * @return "0" / "1"
     */
diff --git a/src/main/java/dk/camelot64/kickc/model/InternalError.java b/src/main/java/dk/camelot64/kickc/model/InternalError.java
new file mode 100644
index 000000000..abf3ec469
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/InternalError.java
@@ -0,0 +1,24 @@
+package dk.camelot64.kickc.model;
+
+import dk.camelot64.kickc.model.statements.Statement;
+import dk.camelot64.kickc.model.statements.StatementSource;
+
+/** Signals an internal error in the compiler. Should be reported to the author. */
+public class InternalError extends RuntimeException {
+
+   public InternalError(String message) {
+      super(message);
+   }
+
+   public InternalError(String message, StatementSource source) {
+      super(message+"\n"+source.toString());
+   }
+
+   public InternalError(String message, Statement statement) {
+      this(message, statement.getSource());
+   }
+
+   public InternalError(String message, Throwable cause) {
+      super(message, cause);
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
index af0323d3e..022611a5b 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
@@ -32,16 +32,9 @@ public class OperatorBitwiseAnd extends OperatorBinary {
       if(type2 instanceof SymbolTypePointer) {
          type2 = SymbolType.WORD;
       }
-      // Find smallest bitwise type
-      if(type1 instanceof SymbolTypeInteger && type2 instanceof SymbolTypeInteger) {
-
-         for(SymbolTypeInteger candidate : SymbolType.getIntegerTypes()) {
-            boolean match1 = ((SymbolTypeInteger) type1).getBits() <= candidate.getBits();
-            boolean match2 = ((SymbolTypeInteger) type2).getBits() <= candidate.getBits();
-            if(!candidate.isSigned() && (match1 || match2)) {
-               return candidate;
-            }
-         }
+      // Handle numeric types
+      if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
+         return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
       }
 
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
index 5b7669cf1..cad932fb1 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
@@ -1,10 +1,7 @@
 package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
+import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -32,9 +29,9 @@ public class OperatorBitwiseOr extends OperatorBinary {
       if(type2 instanceof SymbolTypePointer) {
          type2 = SymbolType.WORD;
       }
-      // Handle numeric types through proper promotion
+      // Handle numeric types
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.promotedBitwiseType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
       }
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
index f829640ef..b383ac3f0 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
@@ -1,10 +1,7 @@
 package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
+import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -32,9 +29,9 @@ public class OperatorBitwiseXor extends OperatorBinary {
       if(type2 instanceof SymbolTypePointer) {
          type2 = SymbolType.WORD;
       }
-      // Handle numeric types through proper promotion
+      // Handle numeric types
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.promotedBitwiseType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
       }
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
index de2a37f71..ea24ee803 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
@@ -18,9 +18,9 @@ public class OperatorCastByte extends OperatorUnary {
    @Override
    public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
       if(value instanceof ConstantInteger) {
-         return new ConstantInteger(0xff & ((ConstantInteger) value).getValue());
+         return new ConstantInteger(0xff & ((ConstantInteger) value).getValue(), SymbolType.BYTE);
       } else if(value instanceof ConstantPointer) {
-         return new ConstantInteger(0xff & ((ConstantPointer) value).getLocation());
+         return new ConstantInteger(0xff & ((ConstantPointer) value).getLocation(), SymbolType.BYTE);
       }
       throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
index f27ae69e2..af76dbff4 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
@@ -18,10 +18,10 @@ public class OperatorCastDWord extends OperatorUnary {
    @Override
    public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
       if(value instanceof ConstantInteger) {
-         return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue());
+         return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue(), SymbolType.DWORD);
       }
       if(value instanceof ConstantPointer) {
-         return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation());
+         return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation(), SymbolType.DWORD);
       }
       throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
index 8013ce770..d81cf7414 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
@@ -17,7 +17,7 @@ public class OperatorCastSByte extends OperatorUnary {
    @Override
    public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
       if(value instanceof ConstantInteger) {
-         return new ConstantInteger(0xff & ((ConstantInteger) value).getValue());
+         return new ConstantInteger(0xff & ((ConstantInteger) value).getValue(), SymbolType.SBYTE);
       }
       throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
index 01f5137bf..a07c5cd38 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
@@ -17,7 +17,7 @@ public class OperatorCastSDWord extends OperatorUnary {
    @Override
    public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
       if(value instanceof ConstantInteger) {
-         return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue());
+         return new ConstantInteger(0xffffffffL & ((ConstantInteger) value).getValue(), SymbolType.SDWORD);
       }
       throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
index ca7f35d83..094be277d 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
@@ -17,7 +17,7 @@ public class OperatorCastSWord extends OperatorUnary {
    @Override
    public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
       if(value instanceof ConstantInteger) {
-         return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue());
+         return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue(), SymbolType.SWORD);
       }
       throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
index 6414be198..f84aec9f0 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
@@ -18,10 +18,10 @@ public class OperatorCastWord extends OperatorUnary {
    @Override
    public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
       if(value instanceof ConstantInteger) {
-         return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue());
+         return new ConstantInteger(0xffff & ((ConstantInteger) value).getValue(), SymbolType.WORD);
       }
       if(value instanceof ConstantPointer) {
-         return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation());
+         return new ConstantInteger(0xffff & ((ConstantPointer) value).getLocation(), SymbolType.WORD);
       }
       throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
index 1e1ce9cd6..2a4058f16 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
@@ -38,7 +38,7 @@ public class OperatorDivide extends OperatorBinary {
       }
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
-         return SymbolType.promotedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
+         return SymbolType.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right);
       }
 
       throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
index 3f018c9d5..c06f6b938 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
@@ -1,10 +1,7 @@
 package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
+import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.ConstantChar;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -39,10 +36,9 @@ public class OperatorMinus extends OperatorBinary {
       } else if(type1 instanceof SymbolTypePointer && type2 instanceof SymbolTypePointer) {
          return SymbolType.WORD;
       }
-
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.promotedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
       }
       throw new RuntimeException("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
index c26e36089..2931f6db1 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
@@ -27,7 +27,7 @@ public class OperatorModulo extends OperatorBinary {
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
-         return SymbolType.promotedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
+         return SymbolType.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
       }
       if(left instanceof ConstantPointer && right instanceof ConstantInteger) {
          return ((ConstantInteger) right).getType();
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
index 5da795636..7c3894bb5 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
@@ -3,6 +3,7 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInteger;
+import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
 import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -26,7 +27,7 @@ public class OperatorMultiply extends OperatorBinary {
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
-         return SymbolType.promotedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
+         return SymbolType.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
       }
       throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
index 99556aa2e..f4f6e0ec7 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
@@ -39,31 +39,14 @@ public class OperatorPlus extends OperatorBinary {
    @Override
    public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
       // Handle all non-numeric types
-      if(type1.equals(SymbolType.STRING) && isStringLike(type2)) {
-         return SymbolType.STRING;
-      } else if(isStringLike(type1) && type2.equals(SymbolType.STRING)) {
-         return SymbolType.STRING;
-      } else if(type1 instanceof SymbolTypeArray && type2 instanceof SymbolTypeArray) {
-         SymbolType elemType1 = ((SymbolTypeArray) type1).getElementType();
-         SymbolType elemType2 = ((SymbolTypeArray) type2).getElementType();
-         if(SymbolTypeInference.typeMatch(elemType1, elemType2)) {
-            return new SymbolTypeArray(elemType1);
-         } else if(SymbolTypeInference.typeMatch(elemType2, elemType1)) {
-            return new SymbolTypeArray(elemType2);
-         } else {
-            throw new RuntimeException("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
-         }
-      } else if(SymbolType.isInteger(type1) && type2 instanceof SymbolTypePointer ) {
+      if(SymbolType.isInteger(type1) && type2 instanceof SymbolTypePointer) {
          return new SymbolTypePointer(((SymbolTypePointer) type2).getElementType());
       } else if(type1 instanceof SymbolTypePointer && SymbolType.isInteger(type2)) {
          return new SymbolTypePointer(((SymbolTypePointer) type1).getElementType());
-      } else if(type1 instanceof SymbolTypePointer && type2 instanceof SymbolTypePointer) {
-         throw new NoMatchingType("Two pointers cannot be added.");
       }
-
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.promotedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         return SymbolType.convertedMathType( (SymbolTypeInteger) type1, (SymbolTypeInteger)type2);
       }
 
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
index 9bf23a2f8..c8a043c17 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
@@ -9,17 +9,19 @@ import java.util.Collection;
 public interface SymbolType {
 
    /** Unsigned byte (8 bits)). */
-   SymbolTypeInteger BYTE = new SymbolTypeInteger("byte", 0, 255, false, 8);
+   SymbolTypeIntegerFixed BYTE = new SymbolTypeIntegerFixed("byte", 0, 255, false, 8);
    /** Signed byte (8 bits). */
-   SymbolTypeInteger SBYTE = new SymbolTypeInteger("signed byte", -128, 127, true, 8);
+   SymbolTypeIntegerFixed SBYTE = new SymbolTypeIntegerFixed("signed byte", -128, 127, true, 8);
    /** Unsigned word (2 bytes, 16 bits). */
-   SymbolTypeInteger WORD = new SymbolTypeInteger("word", 0, 65_535, false, 16);
+   SymbolTypeIntegerFixed WORD = new SymbolTypeIntegerFixed("word", 0, 65_535, false, 16);
    /** Signed word (2 bytes, 16 bits). */
-   SymbolTypeInteger SWORD = new SymbolTypeInteger("signed word", -32_768, 32_767, true, 16);
+   SymbolTypeIntegerFixed SWORD = new SymbolTypeIntegerFixed("signed word", -32_768, 32_767, true, 16);
    /** Unsigned double word (4 bytes, 32 bits). */
-   SymbolTypeInteger DWORD = new SymbolTypeInteger("dword", 0, 4_294_967_296L, false, 32);
+   SymbolTypeIntegerFixed DWORD = new SymbolTypeIntegerFixed("dword", 0, 4_294_967_296L, false, 32);
    /** Signed double word (4 bytes, 32 bits). */
-   SymbolTypeInteger SDWORD = new SymbolTypeInteger("signed dword", -2_147_483_648, 2_147_483_647, true, 32);
+   SymbolTypeIntegerFixed SDWORD = new SymbolTypeIntegerFixed("signed dword", -2_147_483_648, 2_147_483_647, true, 32);
+   /** Integer with unknown size. */
+   SymbolTypeIntegerAuto NUMBER = new SymbolTypeIntegerAuto("number");
    /** String value (treated like byte* ). */
    SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99);
    /** Boolean value. */
@@ -204,13 +206,13 @@ public interface SymbolType {
    }
 
    /**
-    * Is the type an integer type or compatible {@link SymbolTypeMulti}
+    * Is the type an integer type (including {@link #NUMBER})
     *
     * @param type The type to examine
     * @return true if the type is integer
     */
    static boolean isInteger(SymbolType type) {
-      return isSDWord(type) || isDWord(type) || isSWord(type) || isWord(type) || isSByte(type) || isByte(type);
+      return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type);
    }
 
    /**
@@ -218,8 +220,8 @@ public interface SymbolType {
     *
     * @return All integeer types
     */
-   static Collection<SymbolTypeInteger> getIntegerTypes() {
-      ArrayList<SymbolTypeInteger> types = new ArrayList<>();
+   static Collection<SymbolTypeIntegerFixed> getIntegerFixedTypes() {
+      ArrayList<SymbolTypeIntegerFixed> types = new ArrayList<>();
       types.add(BYTE);
       types.add(SBYTE);
       types.add(WORD);
@@ -230,21 +232,41 @@ public interface SymbolType {
    }
 
    /**
-    * Find the smallest integer type that contains both sub-types usable for math ( + - * / ).
+    * Find the integer type that results from a binary operator according to C99 6.3.1.8
+    * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70
     *
     * @param type1 Left type in a binary expression
     * @param type2 Right type in a binary expression
-    * @return
+    * @return The type resulting from a binary operator performed on the two parameters
     */
-   static SymbolType promotedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) {
-      for(SymbolTypeInteger candidate : getIntegerTypes()) {
-         boolean match1 = type1.getMinValue() >= candidate.getMinValue() && type1.getMaxValue() <= candidate.getMaxValue();
-         boolean match2 = type2.getMinValue() >= candidate.getMinValue() && type2.getMaxValue() <= candidate.getMaxValue();
-         if(match1 && match2) {
-            return candidate;
-         }
+   static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) {
+      if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) {
+         return NUMBER;
       }
-      throw new NoMatchingType("Cannot promote to a common type for "+type1.toString()+" and "+type2.toString());
+      SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1;
+      SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2;
+      // C99 6.3.1.8 a. If two operands have the same type no conversion is performed
+      if(type1.equals(type2))
+         return type1;
+      // C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword)
+      if(fixed1.isSigned()==fixed2.isSigned())
+         return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2;
+      // C99 6.3.1.8 c. One is signed and one unsigned.
+      // If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword).
+      SymbolTypeIntegerFixed typeS, typeU;
+      if(fixed1.isSigned()) {
+         typeS = fixed1;
+         typeU = fixed2;
+      }  else {
+         typeS = fixed2;
+         typeU = fixed1;
+      }
+      if(typeS.getBits()>typeU.getBits())
+         return typeS;
+      // C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type.
+      // The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value
+      // (sbyte->byte, sbyte->word, sbyte->dword, sword->word, sword->dword, sdword->dword).
+      return typeU;
    }
 
    /**
@@ -254,8 +276,8 @@ public interface SymbolType {
     * @param type2 Right type in a binary expression
     * @return
     */
-   static SymbolType promotedBitwiseType(SymbolTypeInteger type1, SymbolTypeInteger type2) {
-      for(SymbolTypeInteger candidate : getIntegerTypes()) {
+   static SymbolType promotedBitwiseType(SymbolTypeIntegerFixed type1, SymbolTypeIntegerFixed type2) {
+      for(SymbolTypeIntegerFixed candidate : getIntegerFixedTypes()) {
          if(!candidate.isSigned() && type1.getBits()<=candidate.getBits() && type2.getBits()<=candidate.getBits()) {
             return candidate;
          }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index d80e44138..477a34d28 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -1,18 +1,15 @@
 package dk.camelot64.kickc.model.types;
 
 import dk.camelot64.kickc.model.CompileError;
-import dk.camelot64.kickc.model.ConstantNotLiteral;
 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.operators.Operators;
 import dk.camelot64.kickc.model.statements.*;
 import dk.camelot64.kickc.model.symbols.*;
 import dk.camelot64.kickc.model.values.*;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 
@@ -30,23 +27,6 @@ public class SymbolTypeInference {
     * @return The type of the resulting value
     */
    public static SymbolType inferType(ProgramScope programScope, OperatorUnary operator, RValue rValue) {
-      if(Operators.TYPEID.equals(operator)) {
-         return SymbolType.BYTE;
-      } else if(Operators.SIZEOF.equals(operator)) {
-         return SymbolType.BYTE;
-      }
-      if(rValue instanceof ConstantValue) {
-         // Calculate resulting constant literal
-         try {
-            ConstantValue constRValue = (ConstantValue) rValue;
-            ConstantLiteral literalRValue = constRValue.calculateLiteral(programScope);
-            ConstantValue value = operator.calculateLiteral(literalRValue, programScope);
-            return value.getType(programScope);
-         } catch(ConstantNotLiteral e) {
-            // Value literal cannot be calculated
-         }
-      }
-      // Infer value type - and then infer operator result type
       SymbolType valueType = inferType(programScope, rValue);
       return inferType(operator, valueType);
    }
@@ -62,19 +42,7 @@ public class SymbolTypeInference {
       if(operandType instanceof SymbolTypeSimple) {
          return operator.inferType((SymbolTypeSimple) operandType);
       } else {
-         // Infer all resulting types for each sub-type of the multi-type
-         ArrayList<SymbolType> resultTypes = new ArrayList<>();
-         for(SymbolType opType : ((SymbolTypeMulti) operandType).getTypes()) {
-            SymbolType resType = inferType(operator, opType);
-            if(!resultTypes.contains(resType)) {
-               resultTypes.add(resType);
-            }
-         }
-         if(resultTypes.size() == 1) {
-            return resultTypes.get(0);
-         } else {
-            return new SymbolTypeMulti(resultTypes);
-         }
+         throw new RuntimeException("Not implemented!");
       }
    }
 
@@ -88,18 +56,6 @@ public class SymbolTypeInference {
     * @return The type of the resulting value
     */
    public static SymbolType inferType(ProgramScope programScope, RValue left, OperatorBinary operator, RValue right) {
-      if(left instanceof ConstantValue && right instanceof ConstantValue) {
-         // Calculate resulting constant literal
-         try {
-            ConstantValue value = operator.calculateLiteral(
-                  ((ConstantValue) left).calculateLiteral(programScope),
-                  ((ConstantValue) right).calculateLiteral(programScope)
-            );
-            return value.getType(programScope);
-         } catch(ConstantNotLiteral e) {
-            // Value literal cannot be calculated
-         }
-      }
       SymbolType leftType = inferType(programScope, left);
       SymbolType rightType = inferType(programScope, right);
       return inferType(leftType, operator, rightType);
@@ -109,32 +65,7 @@ public class SymbolTypeInference {
       if(left instanceof SymbolTypeSimple && right instanceof SymbolTypeSimple) {
          return operator.inferType((SymbolTypeSimple) left, (SymbolTypeSimple) right);
       } else {
-         // Infer all resulting types for each sub-type of the multi-type
-         if(left instanceof SymbolTypeSimple) {
-            left = new SymbolTypeMulti(Arrays.asList(left));
-         }
-         if(right instanceof SymbolTypeSimple) {
-            right = new SymbolTypeMulti(Arrays.asList(right));
-         }
-         ArrayList<SymbolType> resultTypes = new ArrayList<>();
-         for(SymbolType leftType : ((SymbolTypeMulti) left).getTypes()) {
-            for(SymbolType rightType : ((SymbolTypeMulti) right).getTypes()) {
-               SymbolType resType;
-               try {
-                  resType = inferType(leftType, operator, rightType);
-                  if(!resultTypes.contains(resType)) {
-                     resultTypes.add(resType);
-                  }
-               } catch(NoMatchingType e) {
-                  // Cannot promote to common type - ignore!
-               }
-            }
-         }
-         if(resultTypes.size() == 1) {
-            return resultTypes.get(0);
-         } else {
-            return new SymbolTypeMulti(resultTypes);
-         }
+         throw new RuntimeException("Not implemented!");
       }
    }
 
@@ -209,13 +140,8 @@ public class SymbolTypeInference {
          if(elmType == null) {
             elmType = type;
          } else {
-            // element type already defined - check for a match
-            if(!typeMatch(elmType, type)) {
-               if(typeMatch(type, elmType)) {
-                  elmType = type;
-               } else {
-                  throw new RuntimeException("Array element has type mismatch " + elm.toString() + " not matching type " + elmType.getTypeName());
-               }
+            if(!elmType.equals(type)) {
+               throw new RuntimeException("Array element has type mismatch " + elm.toString() + " not matching type " + elmType.getTypeName());
             }
          }
       }
@@ -256,74 +182,12 @@ public class SymbolTypeInference {
       return rValueType;
    }
 
-   /**
-    * Determine if lValue and rValue types match (the same types, not needing a cast).
-    *
-    * @param lValueType The lValue type
-    * @param rValueType The rvalue type
-    * @return true if the types match
-    */
-   public static boolean typeMatch(SymbolType lValueType, SymbolType rValueType) {
-      if(lValueType.equals(rValueType)) {
-         // Types match directly
-         return true;
-      } else if(rValueType instanceof SymbolTypeMulti) {
-         Collection<SymbolType> rTypes = ((SymbolTypeMulti) rValueType).getTypes();
-         if(lValueType instanceof SymbolTypeMulti) {
-            // Both are inline types - RValue type must be superset of LValue
-            Collection<SymbolType> lTypes = ((SymbolTypeMulti) lValueType).getTypes();
-            return typeContainsMatchAll(lTypes, rTypes);
-         } else {
-            // Types match because the right side matches the left side
-            return typeContainsMatch(lValueType, rTypes);
-         }
-      } else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer) {
-         return typeMatch(
-               ((SymbolTypePointer) lValueType).getElementType(),
-               ((SymbolTypePointer) rValueType).getElementType());
-      } else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType)) {
-         if(SymbolType.isByte(((SymbolTypePointer) lValueType).getElementType())) {
-            return true;
-         }
-      } else if(SymbolType.STRING.equals(lValueType) && rValueType instanceof SymbolTypePointer) {
-         if(SymbolType.isByte(((SymbolTypePointer) rValueType).getElementType())) {
-            return true;
-         }
-      }
-      return false;
-   }
-
-   private static boolean typeContainsMatchAll(Collection<SymbolType> lTypes, Collection<SymbolType> rTypes) {
-      for(SymbolType lType : lTypes) {
-         if(!typeContainsMatch(lType, rTypes)) {
-            return false;
-         }
-      }
-      return true;
-   }
-
-   /**
-    * Determine is a list of potential inferred types contains a match for another type
-    *
-    * @param lValueType The type (rValue) we want to find a match for in the list
-    * @param rTypes The list of inferred potential types
-    * @return true if the list has a match
-    */
-   private static boolean typeContainsMatch(SymbolType lValueType, Collection<SymbolType> rTypes) {
-      for(SymbolType rType : rTypes) {
-         if(typeMatch(lValueType, rType)) {
-            return true;
-         }
-      }
-      return false;
-   }
-
    public static void inferCallLValue(Program program, StatementCall 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())) {
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
             Procedure procedure = programScope.getProcedure(call.getProcedure());
             SymbolType type = procedure.getReturnType();
             setInferedType(program, call, symbol, type);
@@ -336,7 +200,7 @@ public class SymbolTypeInference {
       LValue lValue = call.getlValue();
       if(lValue instanceof VariableRef) {
          Variable symbol = programScope.getVariable((VariableRef) lValue);
-         if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
             SymbolType procedureType = inferType(programScope, call.getProcedure());
             if(procedureType instanceof SymbolTypeProcedure) {
                SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType();
@@ -350,7 +214,7 @@ public class SymbolTypeInference {
       ProgramScope programScope = program.getScope();
 
       Variable symbol = programScope.getVariable(phiVariable.getVariable());
-      if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
+      if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
          SymbolType type = null;
          for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
             RValue rValue = phiRValue.getrValue();
@@ -377,7 +241,7 @@ public class SymbolTypeInference {
       LValue lValue = assignment.getlValue();
       if(lValue instanceof VariableRef) {
          Variable symbol = programScope.getVariable((VariableRef) lValue);
-         if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
             // Unresolved symbol - perform inference
             Operator operator = assignment.getOperator();
             if(assignment.getrValue1() == null && operator == null) {
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java
index 1813650c8..2a4cdfa7f 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java
@@ -1,50 +1,6 @@
 package dk.camelot64.kickc.model.types;
 
-/** Integer symbol types (byte, signed byte, word, ...). */
-public class SymbolTypeInteger implements SymbolTypeSimple {
+/** Integer type marker interface. */
+public interface  SymbolTypeInteger extends SymbolTypeSimple {
 
-   private final String typeName;
-   private final long minValue;
-   private final long maxValue;
-   private final boolean signed;
-   private final int bits;
-
-   SymbolTypeInteger(String typeName, long minValue, long maxValue, boolean signed, int bits) {
-      this.typeName = typeName;
-      this.minValue = minValue;
-      this.maxValue = maxValue;
-      this.signed = signed;
-      this.bits = bits;
-   }
-
-   @Override
-   public String getTypeName() {
-      return typeName;
-   }
-
-   public long getMinValue() {
-      return minValue;
-   }
-
-   public long getMaxValue() {
-      return maxValue;
-   }
-
-   public boolean isSigned() {
-      return signed;
-   }
-
-   public int getBits() {
-      return bits;
-   }
-
-   @Override
-   public int getSizeBytes() {
-      return bits/8;
-   }
-
-   @Override
-   public String toString() {
-      return getTypeName();
-   }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerAuto.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerAuto.java
new file mode 100644
index 000000000..6e643aad8
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerAuto.java
@@ -0,0 +1,42 @@
+package dk.camelot64.kickc.model.types;
+
+import java.util.Objects;
+
+/** Integer type that has not yet been fixed. This is used for constant expressions. The type is fixed when the constant meets a fixed type. */
+public class SymbolTypeIntegerAuto implements SymbolTypeInteger {
+
+   private final String typeName;
+
+   SymbolTypeIntegerAuto(String typeName) {
+      this.typeName = typeName;
+   }
+
+   @Override
+   public String getTypeName() {
+      return typeName;
+   }
+
+   @Override
+   public int getSizeBytes() {
+      return -1;
+   }
+
+   @Override
+   public String toString() {
+      return getTypeName();
+   }
+
+
+   @Override
+   public boolean equals(Object o) {
+      if(this == o) return true;
+      if(o == null || getClass() != o.getClass()) return false;
+      SymbolTypeIntegerAuto that = (SymbolTypeIntegerAuto) o;
+      return Objects.equals(typeName, that.typeName);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hash(typeName);
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java
new file mode 100644
index 000000000..1c6a35cc5
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java
@@ -0,0 +1,50 @@
+package dk.camelot64.kickc.model.types;
+
+/** Integer type with a fixed size (byte, signed byte, word, ...). */
+public class SymbolTypeIntegerFixed implements SymbolTypeInteger {
+
+   private final String typeName;
+   private final long minValue;
+   private final long maxValue;
+   private final boolean signed;
+   private final int bits;
+
+   SymbolTypeIntegerFixed(String typeName, long minValue, long maxValue, boolean signed, int bits) {
+      this.typeName = typeName;
+      this.minValue = minValue;
+      this.maxValue = maxValue;
+      this.signed = signed;
+      this.bits = bits;
+   }
+
+   @Override
+   public String getTypeName() {
+      return typeName;
+   }
+
+   public long getMinValue() {
+      return minValue;
+   }
+
+   public long getMaxValue() {
+      return maxValue;
+   }
+
+   public boolean isSigned() {
+      return signed;
+   }
+
+   public int getBits() {
+      return bits;
+   }
+
+   @Override
+   public int getSizeBytes() {
+      return bits/8;
+   }
+
+   @Override
+   public String toString() {
+      return getTypeName();
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
index 5b1ca45a5..ced732cb9 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
@@ -34,7 +34,7 @@ public class SymbolTypeMulti implements SymbolType {
     */
    public static SymbolType getMultiType(Long number) {
       ArrayList<SymbolType> potentialTypes = new ArrayList<>();
-      for(SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) {
+      for(SymbolTypeIntegerFixed typeInteger : SymbolType.getIntegerFixedTypes()) {
          if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) {
             potentialTypes.add(typeInteger);
          }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
new file mode 100644
index 000000000..7473e4230
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
@@ -0,0 +1,104 @@
+package dk.camelot64.kickc.model.types;
+
+import dk.camelot64.kickc.model.InternalError;
+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.symbols.ProgramScope;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.ConstantLiteral;
+import dk.camelot64.kickc.model.values.ConstantValue;
+import dk.camelot64.kickc.model.values.RValue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Interference of possible types for constant expressions with the {@link SymbolType#NUMBER} type.
+ * This is done by evaluating the constant expression to find the literal value.
+ */
+public class SymbolTypeNumberInference {
+
+   /**
+    * Infer the potential types for an RValue with {@link SymbolType#NUMBER} type
+    *
+    * @return The potential types
+    */
+   public static List<SymbolTypeIntegerFixed> inferTypesRValue(ProgramScope symbols, StatementAssignment assignment) {
+      RValue rValue1 = assignment.getrValue1();
+      RValue rValue2 = assignment.getrValue2();
+      if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof ConstantValue) {
+         return inferTypes(symbols, (ConstantValue) rValue2);
+      } else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary && assignment.getrValue2() instanceof ConstantValue) {
+         return inferTypes(symbols, (OperatorUnary) assignment.getOperator(), (ConstantValue) rValue2);
+      } else if(assignment.getOperator() instanceof OperatorBinary && assignment.getrValue1() instanceof ConstantValue && assignment.getrValue2() instanceof ConstantValue) {
+         return inferTypes(symbols, (ConstantValue) rValue1, (OperatorBinary) assignment.getOperator(), (ConstantValue) rValue2);
+      } else {
+         return new ArrayList<>();
+      }
+   }
+
+   /**
+    * Infer the potential types for a binary operator with {@link SymbolType#NUMBER} type
+    *
+    * @return The potential types
+    */
+   public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantValue leftValue, OperatorBinary operator, ConstantValue rightValue) {
+      if(SymbolType.NUMBER.equals(leftValue.getType(programScope)) && SymbolType.NUMBER.equals(rightValue.getType(programScope))) {
+         // Calculate resulting constant literal
+         ConstantLiteral leftLiteral = leftValue.calculateLiteral(programScope);
+         ConstantLiteral rightLiteral = rightValue.calculateLiteral(programScope);
+         ConstantLiteral constantLiteral = operator.calculateLiteral(leftLiteral, rightLiteral);
+         return inferTypes(programScope, constantLiteral);
+      } else {
+         throw new InternalError("Both operands must be number type.");
+      }
+   }
+
+   /**
+    * Infer the potential types for a unary operator with {@link SymbolType#NUMBER} type
+    *
+    * @return The potential types
+    */
+   public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, OperatorUnary operator, ConstantValue constantValue) {
+      if(SymbolType.NUMBER.equals(constantValue.getType(programScope))) {
+         // Calculate resulting constant literal
+         ConstantLiteral operandLiteral = constantValue.calculateLiteral(programScope);
+         ConstantLiteral constantLiteral = operator.calculateLiteral(operandLiteral, programScope);
+         return inferTypes(programScope, constantLiteral);
+      } else {
+         throw new InternalError("Operand must be number type.");
+      }
+   }
+
+   /**
+    * Infer the potential types for a constant value with {@link SymbolType#NUMBER} type
+    *
+    * @return The potential types
+    */
+   public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantValue constantValue) {
+      // Calculate resulting constant literal
+      ConstantLiteral constantLiteral = constantValue.calculateLiteral(programScope);
+      return inferTypes(programScope, constantLiteral);
+   }
+
+   /**
+    * Infer the potential types for a constant literal with {@link SymbolType#NUMBER} type
+    */
+   public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantLiteral literal) {
+      if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) {
+         ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>();
+         ConstantInteger constantInteger = (ConstantInteger) literal;
+         Long number = constantInteger.getValue();
+         for(SymbolTypeIntegerFixed typeInteger : SymbolType.getIntegerFixedTypes()) {
+            if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) {
+               potentialTypes.add(typeInteger);
+            }
+         }
+         return potentialTypes;
+      } else {
+         throw new InternalError("Literal must number type.");
+      }
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
index c4f8620eb..7eccd45a4 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantInteger.java
@@ -1,30 +1,29 @@
 package dk.camelot64.kickc.model.values;
 
 import dk.camelot64.kickc.fragment.AsmFormat;
-import dk.camelot64.kickc.model.*;
+import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeMulti;
 
 /** Constant integer value */
 public class ConstantInteger implements ConstantEnumerable<Long> {
 
    private Long number;
 
-   /** The type of the number. (Either specific or the multi-type)*/
+   /** The type of the number. (Either fixed size og the "number" type) */
    private SymbolType type;
 
    public ConstantInteger(Long number) {
       this.number = number;
-      this.type = SymbolTypeMulti.getMultiType(number);
+      this.type = SymbolType.NUMBER;
    }
 
    public ConstantInteger(Long number, SymbolType type) {
       this.number = number;
-      if(type!=null) {
+      if(type != null) {
          this.type = type;
       } else {
-         this.type = SymbolTypeMulti.getMultiType(number);
+         this.type = SymbolType.NUMBER;
       }
    }
 
@@ -45,6 +44,10 @@ public class ConstantInteger implements ConstantEnumerable<Long> {
       return type;
    }
 
+   public void setType(SymbolType type) {
+      this.type = type;
+   }
+
    @Override
    public String toString() {
       return toString(null);
@@ -71,4 +74,5 @@ public class ConstantInteger implements ConstantEnumerable<Long> {
    public int hashCode() {
       return number != null ? number.hashCode() : 0;
    }
+
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index efc72cdbd..65afaf38f 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -499,7 +499,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
       if(initializer != null) {
          addInitialAssignment(initializer, lValue, comments);
       } else {
-         if(type instanceof SymbolTypeInteger) {
+         if(type instanceof SymbolTypeIntegerFixed) {
             // Add an zero value initializer
             ConstantInteger zero = new ConstantInteger(0L);
             Statement stmt = new StatementAssignment(lValue.getRef(), zero, new StatementSource(ctx), ensureUnusedComments(comments));
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java
deleted file mode 100644
index afe0863aa..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1AddTypePromotions.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.*;
-import dk.camelot64.kickc.model.operators.Operators;
-import dk.camelot64.kickc.model.statements.StatementSource;
-import dk.camelot64.kickc.model.values.LValue;
-import dk.camelot64.kickc.model.statements.Statement;
-import dk.camelot64.kickc.model.statements.StatementAssignment;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-
-import java.util.List;
-import java.util.ListIterator;
-
-/**
- * Add casts in all assignments where types are not equal, but the rValue type can be promoted to the lValue type.
- */
-public class Pass1AddTypePromotions extends Pass1Base {
-
-   public Pass1AddTypePromotions(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
-         List<Statement> statements = block.getStatements();
-         ListIterator<Statement> stmtIt = statements.listIterator();
-         while(stmtIt.hasNext()) {
-            Statement statement = stmtIt.next();
-            if(statement instanceof StatementAssignment) {
-               getPromotionAssignment((StatementAssignment) statement, stmtIt);
-            }
-            // TODO: Implement promotion for calls
-         }
-      }
-      return false;
-   }
-
-   /**
-    * Examines an assignment to determine if a cast of the rValue is needed (the lvalue type and the rvalue type is not equal)
-    * and possible (the types are promotion compatible).
-    * <p>
-    * If a promotion is needed it is added by adding a new tmp-var with a cast and modifying the statement.
-    *
-    * @param assignment The assignment to examine
-    * @param stmtIt Iterator allowing the method to add a tmp-var-assignment.
-    */
-   private void getPromotionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt) {
-      LValue lValue = assignment.getlValue();
-      SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
-      SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), assignment);
-      if(SymbolTypeInference.typeMatch(lValueType, rValueType)) {
-         return;
-      }
-      // No direct type match - attempt promotion
-      if(canPromote(lValueType, rValueType)) {
-         // Promotion possible - add tmp-var and a cast
-         if(assignment.getOperator() == null) {
-            // No operator - add cast directly!
-            assignment.setOperator(Operators.getCastUnary(lValueType));
-            if(getLog().isVerbosePass1CreateSsa()) {
-               getLog().append("Promoting " + rValueType + " to " + lValueType + " in " + assignment);
-            }
-         } else {
-            throw new RuntimeException("Tmp-var promotions not implemented yet " + assignment);
-         }
-      } else {
-         String msg = "ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). " +
-               "In " + assignment.toString(getProgram(), false);
-         getProgram().getLog().append(msg);
-         throw new CompileError(msg, assignment.getSource());
-      }
-   }
-
-   /**
-    * Determines if it is possible to promote (cast without loss) one type to another
-    *
-    * @param lValueType The type of the lValue
-    * @param rValueType The type of the rValue (that will be cast)
-    * @return True if a cast is possible without any loss
-    */
-   private boolean canPromote(SymbolType lValueType, SymbolType rValueType) {
-      if(lValueType instanceof SymbolTypePointer && SymbolType.isWord(rValueType)) {
-         return true;
-      }
-      if(lValueType.equals(SymbolType.WORD) && SymbolType.isByte(rValueType)) {
-         return true;
-      }
-      if(lValueType.equals(SymbolType.DWORD) && SymbolType.isWord(rValueType)) {
-         return true;
-      }
-      if(lValueType.equals(SymbolType.DWORD) && SymbolType.isByte(rValueType)) {
-         return true;
-      }
-      // No type promotion found
-      return false;
-   }
-
-
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java b/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java
new file mode 100644
index 000000000..8ba6364d2
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass1Procedures.java
@@ -0,0 +1,43 @@
+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.StatementCall;
+import dk.camelot64.kickc.model.symbols.Procedure;
+import dk.camelot64.kickc.model.symbols.Scope;
+
+/**
+ * Updates procedure calls to point to the actual procedure called.
+ */
+public class Pass1Procedures extends Pass2SsaOptimization {
+
+   public Pass1Procedures(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
+         for(Statement statement : block.getStatements()) {
+            if(statement instanceof StatementCall) {
+               StatementCall call = (StatementCall) statement;
+               String procedureName = call.getProcedureName();
+               Scope currentScope = getScope().getScope(block.getScope());
+               Procedure procedure = currentScope.getProcedure(procedureName);
+               if(procedure == null) {
+                  throw new CompileError("Called procedure not found. " + call.toString(getProgram(), false), statement.getSource());
+               }
+               call.setProcedure(procedure.getRef());
+               if(procedure.getParameters().size() != call.getParameters().size()) {
+                  throw new CompileError("Wrong number of parameters in call. Expected " + procedure.getParameters().size() + ". " + statement.toString(), statement.getSource());
+               }
+            }
+
+         }
+      }
+      return false;
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
index ea2611f26..466599cf3 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
@@ -30,7 +30,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion {
                if(conditionalJump.getOperator()==null) {
                   RValue rValue = conditionalJump.getrValue2();
                   SymbolType rValueType = SymbolTypeInference.inferType(getScope(), rValue);
-                  if(!SymbolTypeInference.typeMatch(SymbolType.BOOLEAN, rValueType)) {
+                  if(!SymbolType.BOOLEAN.equals(rValueType)) {
                      getLog().append("ERROR! Type mismatch non-boolean condition from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false));
                      throw new CompileError("ERROR! Type mismatch non-boolean condition from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource());
                   }
@@ -48,10 +48,11 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion {
       LValue lValue = statement.getlValue();
       SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
       SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement);
-      if(SymbolTypeInference.typeMatch(lValueType, rValueType)) {
+      if(lValueType.equals(rValueType)) {
          return;
       }
-      if(SymbolTypeInference.typeMatch(rValueType, lValueType)) {
+      if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
+         // L-value is still a number - constants are probably not done being identified & typed
          return;
       }
       // Types do not match
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ComparisonOptimization.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ComparisonOptimization.java
index 3c9658e9c..0354d3104 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ComparisonOptimization.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ComparisonOptimization.java
@@ -9,7 +9,7 @@ import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementConditionalJump;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
+import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
 import dk.camelot64.kickc.model.values.ConstantBinary;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -48,7 +48,7 @@ public class Pass2ComparisonOptimization extends Pass2SsaOptimization {
                   } catch(ConstantNotLiteral e) {
                      // Ignore
                   }
-                  if(Operators.GT.equals(operator) && valueType instanceof SymbolTypeInteger && constantLiteral instanceof ConstantInteger) {
+                  if(Operators.GT.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
                      // Found > C - rewrite to >= C+1 if possible
                      Long longValue = (Long) constantLiteral.getValue();
                      if(longValue > 0x00L && longValue < 0xffL) {
@@ -58,7 +58,7 @@ public class Pass2ComparisonOptimization extends Pass2SsaOptimization {
                         conditionalJump.setrValue2(new ConstantBinary(constantValue, Operators.PLUS, new ConstantInteger(1L)));
                      }
                   }
-                  if(Operators.LE.equals(operator) && valueType instanceof SymbolTypeInteger && constantLiteral instanceof ConstantInteger) {
+                  if(Operators.LE.equals(operator) && valueType instanceof SymbolTypeIntegerFixed && constantLiteral instanceof ConstantInteger) {
                      // Found <= C - rewrite to < C+1 if possible
                      Long longValue = (Long) constantLiteral.getValue();
                      if(longValue > 0x00L && longValue < 0xffL) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
index f3c968da0..0cde91c25 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
@@ -72,10 +72,8 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
          SymbolType constType = variableType;
 
          if(!valueType.equals(variableType)) {
-            if(SymbolTypeInference.typeMatch(variableType, valueType)) {
+            if(variableType.equals(valueType)) {
                constType = variableType;
-            } else if(SymbolTypeInference.typeMatch(valueType, variableType)) {
-               constType = valueType;
             } else {
                throw new CompileError(
                      "Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) +
@@ -194,86 +192,12 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
             // Volatile variables cannot be constant
             return;
          }
-         ConstantValue constant = getConstantAssignmentValue(assignment, var.getType());
-         if(constant != null) {
-            constants.put(variable, new ConstantVariableValue(variable, constant, assignment));
+         if(assignment.getrValue1()==null && assignment.getOperator()==null && assignment.getrValue2() instanceof ConstantValue) {
+            constants.put(variable, new ConstantVariableValue(variable, (ConstantValue) assignment.getrValue2(), 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.
     *
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
new file mode 100644
index 000000000..a473bd5f8
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
@@ -0,0 +1,125 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.ControlFlowBlock;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.operators.OperatorBinary;
+import dk.camelot64.kickc.model.operators.OperatorUnary;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.statements.Statement;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeArray;
+import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.values.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Compiler Pass consolidating L-values that are constant into a single {@link ConstantValue}
+ */
+public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
+
+   public Pass2ConstantRValueConsolidation(Program program) {
+      super(program);
+   }
+
+   /**
+    * Propagate constants, replacing variables with constants where possible.
+    *
+    * @return true optimization was performed. false if no optimization was possible.
+    */
+   @Override
+   public boolean step() {
+      boolean modified = false;
+      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
+         for(Statement statement : block.getStatements()) {
+            if(statement instanceof StatementAssignment) {
+               StatementAssignment assignment = (StatementAssignment) statement;
+               if(assignment.getrValue1() != null || assignment.getOperator() != null || !(assignment.getrValue2() instanceof ConstantValue)) {
+                  SymbolType lValueType = SymbolTypeInference.inferType(getScope(), assignment.getlValue());
+                  ConstantValue constant = getConstantAssignmentValue(assignment, lValueType);
+                  if(constant != null) {
+                     getLog().append("Constant right-side identified " + assignment.toString(getProgram(), false));
+                     assignment.setrValue2(constant);
+                     assignment.setOperator(null);
+                     assignment.setrValue1(null);
+                     modified = true;
+                  }
+               }
+            }
+         }
+      }
+      return modified;
+   }
+
+   /**
+    * 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 && Pass2ConstantIdentification.getConstant(assignment.getrValue2()) != null) {
+         if(assignment.getOperator() == null) {
+            // Constant assignment
+            return Pass2ConstantIdentification.getConstant(assignment.getrValue2());
+         } else {
+            // Constant unary expression
+            return Pass2ConstantIdentification.createUnary(
+                  (OperatorUnary) assignment.getOperator(),
+                  Pass2ConstantIdentification.getConstant(assignment.getrValue2())
+            );
+         }
+      } else if(Pass2ConstantIdentification.getConstant(assignment.getrValue1()) != null && Pass2ConstantIdentification.getConstant(assignment.getrValue2()) != null) {
+         // Constant binary expression
+         return Pass2ConstantIdentification.createBinary(
+               Pass2ConstantIdentification.getConstant(assignment.getrValue1()),
+               (OperatorBinary) assignment.getOperator(),
+               Pass2ConstantIdentification.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(!listType.equals(elmType)) {
+                        // No overlap between list type and element type
+                        throw new RuntimeException("Array type " + listType + " does not match element type" + elmType + ". Array: " + valueList.toString(getProgram()));
+                     }
+                  }
+                  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;
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
index 1bdd74241..49b6afce4 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
@@ -15,7 +15,7 @@ import dk.camelot64.kickc.model.symbols.VariableIntermediate;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeArray;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
+import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
 import dk.camelot64.kickc.model.values.Value;
 import dk.camelot64.kickc.model.values.ValueList;
 
@@ -68,11 +68,11 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
 
 
    private abstract class InlineConstructor implements ProgramValueHandler {
-      private SymbolTypeInteger constructType;
+      private SymbolTypeIntegerFixed constructType;
       private Operator constructOperator;
       private boolean optimized;
 
-      public InlineConstructor(SymbolTypeInteger constructType, Operator constructOperator) {
+      public InlineConstructor(SymbolTypeIntegerFixed constructType, Operator constructOperator) {
          this.constructType = constructType;
          this.constructOperator = constructOperator;
       }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2RangeResolving.java b/src/main/java/dk/camelot64/kickc/passes/Pass2RangeResolving.java
index b5694442d..5bc71e830 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2RangeResolving.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2RangeResolving.java
@@ -6,7 +6,7 @@ import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
 import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
+import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
 import dk.camelot64.kickc.model.values.*;
 
@@ -51,9 +51,9 @@ public class Pass2RangeResolving extends Pass2SsaOptimization {
 
                if(rangeValue instanceof RangeComparison) {
                   SymbolType type = ((RangeComparison) rangeValue).getType();
-                  SymbolTypeInteger valueType;
-                  if(type instanceof SymbolTypeInteger) {
-                     valueType = (SymbolTypeInteger) type;
+                  SymbolTypeIntegerFixed valueType;
+                  if(type instanceof SymbolTypeIntegerFixed) {
+                     valueType = (SymbolTypeIntegerFixed) type;
                   } else if(type instanceof SymbolTypePointer) {
                      valueType = SymbolType.WORD;
                   } else {
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
new file mode 100644
index 000000000..bf0f55c6f
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
@@ -0,0 +1,134 @@
+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.operators.Operators;
+import dk.camelot64.kickc.model.statements.Statement;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.types.*;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.LValue;
+import dk.camelot64.kickc.model.values.RValue;
+
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * Add casts in all assignments where types are not equal, but the rValue type can be converted to the lValue type.
+ */
+public class PassNAddTypeConversions extends Pass2SsaOptimization {
+
+   public PassNAddTypeConversions(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
+         List<Statement> statements = block.getStatements();
+         ListIterator<Statement> stmtIt = statements.listIterator();
+         while(stmtIt.hasNext()) {
+            Statement statement = stmtIt.next();
+            if(statement instanceof StatementAssignment) {
+               doConversionAssignment((StatementAssignment) statement, stmtIt);
+            }
+            // TODO: Implement conversion for calls
+         }
+      }
+      return false;
+   }
+
+   /**
+    * Examines an assignment to determine if a cast of the rValue is needed (the lvalue type and the rvalue type is not equal)
+    * and possible (the types are conversion compatible).
+    * <p>
+    * If a conversion is needed it is added by adding a new tmp-var with a cast and modifying the statement.
+    *
+    * @param assignment The assignment to examine
+    * @param stmtIt Iterator allowing the method to add a tmp-var-assignment.
+    */
+   private void doConversionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt) {
+      LValue lValue = assignment.getlValue();
+      SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
+      SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), assignment);
+      if(lValueType.equals(rValueType)) {
+         return;
+      }
+      if(SymbolType.NUMBER.equals(rValueType)) {
+         // If the rValue is number type - find the potential types based on the literal value
+         List<SymbolTypeIntegerFixed> potentialTypes = SymbolTypeNumberInference.inferTypesRValue(getScope(), assignment);
+         if(potentialTypes.size()==0) {
+            // number type cannot be calculated currently - save for later
+            return;
+         }
+         for(SymbolTypeIntegerFixed potentialType : potentialTypes) {
+            if(lValueType.equals(potentialType) || canConvert(lValueType, potentialType)) {
+               addConversionCast(assignment, lValueType, rValueType);
+               return;
+            }
+         }
+      } else {
+         // No direct type match - attempt conversion
+         if(canConvert(lValueType, rValueType)) {
+            addConversionCast(assignment, lValueType, rValueType);
+            return;
+         }
+      }
+
+      // Conversion not possible - report a type error!
+      String msg = "ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). " +
+            "In " + assignment.toString(getProgram(), false);
+      getProgram().getLog().append(msg);
+      throw new CompileError(msg, assignment.getSource());
+   }
+
+   /**
+    * Add a conversion cast to the rvalue of an assignment
+    *
+    * @param assignment The assignment to add the cast to
+    * @param lValueType The type of the lValue
+    * @param rValueType The type of the rValue
+    */
+   private void addConversionCast(StatementAssignment assignment, SymbolType lValueType, SymbolType rValueType) {
+      // Promotion possible - add tmp-var and a cast
+      if(assignment.getOperator() == null) {
+         // No operator - add cast directly!
+         RValue rValue = assignment.getrValue2();
+         if((rValue instanceof ConstantInteger) && SymbolType.NUMBER.equals(((ConstantInteger) rValue).getType()) && SymbolType.isInteger(lValueType)) {
+            ((ConstantInteger) rValue).setType(lValueType);
+         } else {
+            assignment.setOperator(Operators.getCastUnary(lValueType));
+         }
+         if(getLog().isVerbosePass1CreateSsa()) {
+            getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment);
+         }
+      } else {
+         throw new RuntimeException("Tmp-var conversion not implemented yet " + assignment);
+      }
+   }
+
+   /**
+    * Determines if it is possible to convert one type to another
+    * as described in C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70
+    *
+    * @param lValueType The type of the lValue
+    * @param rValueType The type of the rValue (that will be cast)
+    * @return True if a cast is possible without any loss
+    */
+   private boolean canConvert(SymbolType lValueType, SymbolType rValueType) {
+      if(lValueType instanceof SymbolTypePointer && SymbolType.isWord(rValueType)) {
+         return true;
+      }
+      if(lValueType instanceof SymbolTypeInteger && rValueType instanceof SymbolTypeInteger) {
+         SymbolType convertedMathType = SymbolType.convertedMathType((SymbolTypeInteger) lValueType, (SymbolTypeInteger) rValueType);
+         if(lValueType.equals(convertedMathType)) {
+            return true;
+         }
+      }
+      // No type promotion found
+      return false;
+   }
+
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
similarity index 68%
rename from src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java
rename to src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
index 0f296642d..d4baa4e7d 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
@@ -12,9 +12,9 @@ import dk.camelot64.kickc.model.types.SymbolTypeInference;
  * Pass through the generated statements inferring types of unresolved variables.
  * Also updates procedure calls to point to the actual procedure called.
  */
-public class Pass1TypeInference extends Pass1Base {
+public class PassNTypeInference extends Pass2SsaOptimization {
 
-   public Pass1TypeInference(Program program) {
+   public PassNTypeInference(Program program) {
       super(program);
    }
 
@@ -38,17 +38,6 @@ public class Pass1TypeInference extends Pass1Base {
                   }
                }
             } else if(statement instanceof StatementCall) {
-               StatementCall call = (StatementCall) statement;
-               String procedureName = call.getProcedureName();
-               Scope currentScope = getScope().getScope(block.getScope());
-               Procedure procedure = currentScope.getProcedure(procedureName);
-               if(procedure == null) {
-                  throw new CompileError("Called procedure not found. " + call.toString(getProgram(), false), statement.getSource());
-               }
-               call.setProcedure(procedure.getRef());
-               if(procedure.getParameters().size() != call.getParameters().size()) {
-                  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);
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index cbc3675db..89f5ff376 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,11 +32,21 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testIntegerLiteralsMin() throws IOException, URISyntaxException {
+      compileAndCompare("int-literals-min");
+   }
+
    @Test
    public void testIntegerLiterals() throws IOException, URISyntaxException {
       compileAndCompare("int-literals");
    }
 
+   @Test
+   public void testNumberType() throws IOException, URISyntaxException {
+      compileAndCompare("number-type", log());
+   }
+
    @Test
    public void testSimpleLoop() throws IOException, URISyntaxException {
       compileAndCompare("simple-loop");
@@ -1636,7 +1646,7 @@ public class TestPrograms {
 
    @Test
    public void testForClassicMin() throws IOException, URISyntaxException {
-      compileAndCompare("forclassicmin");
+      compileAndCompare("forclassicmin", log());
    }
 
    @Test
diff --git a/src/test/kc/int-literals.kc b/src/test/kc/int-literals.kc
index d3fd609c6..5afa560bb 100644
--- a/src/test/kc/int-literals.kc
+++ b/src/test/kc/int-literals.kc
@@ -1,59 +1,106 @@
 // Tests different integer literal types
 
-const byte RED = 2;
-const byte GREEN = 5;
+const byte RED = 2ub;
+const byte GREEN = 5ub;
 
-const byte* SCREEN = $0400;
-const byte* COLS = $d800;
-byte idx = 0;
+const byte* SCREEN = $0400uw;
+const byte* COLS = $d800uw;
+byte idx = 0ub;
 
 void main() {
-    for(byte* s: SCREEN..SCREEN+999) *s = ' ';
-    idx = 0;
+    for(byte* s=SCREEN;s<SCREEN+1000uw;s++) *s = ' ';
     testSimpleTypes();
-    idx = 40;
+    testUnaryOperator();
     testBinaryOperator();
 }
 
 void testSimpleTypes() {
+    idx = 0ub;
     // Simple types
-    assertType(typeid(12ub), typeid(byte));
-    assertType(typeid(12uc), typeid(byte));
+    assertType(typeid(12ub), typeid(unsigned byte));
+    assertType(typeid(12uc), typeid(unsigned byte));
     assertType(typeid(12sb), typeid(signed byte));
     assertType(typeid(12sc), typeid(signed byte));
-    assertType(typeid(12uw), typeid(word));
-    assertType(typeid(12ui), typeid(word));
-    assertType(typeid(12us), typeid(word));
+    assertType(typeid(12uw), typeid(unsigned word));
+    assertType(typeid(12ui), typeid(unsigned word));
+    assertType(typeid(12us), typeid(unsigned word));
     assertType(typeid(12sw), typeid(signed word));
     assertType(typeid(12si), typeid(signed word));
     assertType(typeid(12ss), typeid(signed word));
-    assertType(typeid(12ud), typeid(dword));
-    assertType(typeid(12ul), typeid(dword));
+    assertType(typeid(12ud), typeid(unsigned dword));
+    assertType(typeid(12ul), typeid(unsigned dword));
     assertType(typeid(12sd), typeid(signed dword));
     assertType(typeid(12sl), typeid(signed dword));
     assertType(typeid(12l), typeid(signed dword));
 }
 
+void testUnaryOperator() {
+    idx = 40ub;
+    // Unary Operations
+    assertType(typeid(-12ub), typeid(unsigned byte));
+    assertType(typeid(-12sb), typeid(signed byte));
+    assertType(typeid(-12uw), typeid(unsigned word));
+    assertType(typeid(-12sw), typeid(signed word));
+    assertType(typeid(-12ud), typeid(unsigned dword));
+    assertType(typeid(-12sd), typeid(signed dword));
+}
+
 void testBinaryOperator() {
+    idx = 80ub;
     // Binary Operations between unsigned byte & other types
-    assertType(typeid(12ub+12ub), typeid(byte));
-    assertType(typeid(12ub+12sb), typeid(byte));
-    assertType(typeid(12ub+12uw), typeid(word));
+    assertType(typeid(12ub+12ub), typeid(unsigned byte));
+    assertType(typeid(12ub+12sb), typeid(unsigned byte));
+    assertType(typeid(12ub+12uw), typeid(unsigned word));
     assertType(typeid(12ub+12sw), typeid(signed word));
-    assertType(typeid(12ub+12ud), typeid(dword));
+    assertType(typeid(12ub+12ud), typeid(unsigned dword));
     assertType(typeid(12ub+12sd), typeid(signed dword));
     idx++;
     // Binary Operations between signed byte & other types
-    assertType(typeid(12sb+12ub), typeid(byte));
+    assertType(typeid(12sb+12ub), typeid(unsigned byte));
     assertType(typeid(12sb+12sb), typeid(signed byte));
-    assertType(typeid(12sb+12uw), typeid(word));
+    assertType(typeid(12sb+12uw), typeid(unsigned word));
     assertType(typeid(12sb+12sw), typeid(signed word));
-    assertType(typeid(12sb+12ud), typeid(dword));
+    assertType(typeid(12sb+12ud), typeid(unsigned dword));
     assertType(typeid(12sb+12sd), typeid(signed dword));
+    idx++;
+    // Binary Operations between unsigned word & other types
+    assertType(typeid(12uw+12ub), typeid(unsigned word));
+    assertType(typeid(12uw+12sb), typeid(unsigned word));
+    assertType(typeid(12uw+12uw), typeid(unsigned word));
+    assertType(typeid(12uw+12sw), typeid(unsigned word));
+    assertType(typeid(12uw+12ud), typeid(unsigned dword));
+    assertType(typeid(12uw+12sd), typeid(signed dword));
+    idx = 120ub;
+    // Binary Operations between signed word & other types
+    assertType(typeid(12sw+12ub), typeid(signed word));
+    assertType(typeid(12sw+12sb), typeid(signed word));
+    assertType(typeid(12sw+12uw), typeid(unsigned word));
+    assertType(typeid(12sw+12sw), typeid(signed word));
+    assertType(typeid(12sw+12ud), typeid(unsigned dword));
+    assertType(typeid(12sw+12sd), typeid(signed dword));
+    idx++;
+    // Binary Operations between unsigned dword & other types
+    assertType(typeid(12ud+12ub), typeid(unsigned dword));
+    assertType(typeid(12ud+12sb), typeid(unsigned dword));
+    assertType(typeid(12ud+12uw), typeid(unsigned dword));
+    assertType(typeid(12ud+12sw), typeid(unsigned dword));
+    assertType(typeid(12ud+12ud), typeid(unsigned dword));
+    assertType(typeid(12ud+12sd), typeid(unsigned dword));
+    idx++;
+    // Binary Operations between signed dword & other types
+    assertType(typeid(12sd+12ub), typeid(signed dword));
+    assertType(typeid(12sd+12sb), typeid(signed dword));
+    assertType(typeid(12sd+12uw), typeid(signed dword));
+    assertType(typeid(12sd+12sw), typeid(signed dword));
+    assertType(typeid(12sd+12ud), typeid(unsigned dword));
+    assertType(typeid(12sd+12sd), typeid(signed dword));
 }
 
 
 
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
 void assertType(byte t1, byte t2) {
     if(t1==t2) {
         COLS[idx] = GREEN;
diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc
new file mode 100644
index 000000000..6c333531f
--- /dev/null
+++ b/src/test/kc/number-type.kc
@@ -0,0 +1,23 @@
+// Tests the number type used for constant expressions
+
+const byte* SCREENB = 0x0400;
+
+void main() {
+    // Constant values resolvable to bytes
+    byte idx = 0;
+    SCREENB[idx++] = 12;
+    SCREENB[idx++] = 6+6;
+    SCREENB[idx++] = 18-6;
+    SCREENB[idx++] = 1812-1800;
+    SCREENB[idx++] = 1+2+3+6;
+    SCREENB[idx++] = 2*6;
+    SCREENB[idx++] = 3<<2;
+    SCREENB[idx++] = 24>>1;
+    SCREENB[idx++] = 15&28;
+    SCREENB[idx++] = 4|8;
+    SCREENB[idx++] = 5^9;
+    SCREENB[idx++] = (2+2)*(15/5);
+    SCREENB[idx++] = (byte)(4096+12);
+}
+
+

From d0d5b5715ba2ae62851039da0bf78521edfb680e Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Mon, 6 May 2019 01:08:41 +0200
Subject: [PATCH 07/93] Implemented framework for number type conversion - the
 BinaryExpressionIterator. Added first case (type match) in new
 PassNAddNumberTybeConversions.

---
 .../java/dk/camelot64/kickc/CompileLog.java   |   2 +-
 .../java/dk/camelot64/kickc/Compiler.java     |   5 +-
 .../model/iterator/BinaryExpression.java      | 166 ++++++++++++++++++
 .../iterator/BinaryExpressionHandler.java     |  25 +++
 .../iterator/BinaryExpressionIterator.java    |  63 +++++++
 .../model/operators/OperatorAssignment.java   |  27 +++
 .../kickc/model/operators/Operators.java      |   1 +
 .../kickc/model/types/SymbolType.java         |   2 +-
 .../model/types/SymbolTypeInference.java      |   2 +
 .../kickc/model/values/AssignmentRValue.java  |  28 +++
 .../passes/Pass1TypeIdSimplification.java     |  24 ++-
 .../kickc/passes/Pass3AssertNoNumbers.java    |  63 +++++++
 .../kickc/passes/Pass3AssertNoTypeId.java     |  34 ++++
 .../kickc/passes/Pass3AssertRValues.java      |   6 +-
 .../passes/PassNAddNumberTypeConversions.java |  59 +++++++
 .../kickc/passes/PassNAddTypeConversions.java |  27 ++-
 .../dk/camelot64/kickc/test/TestPrograms.java |  23 ++-
 src/test/kc/int-conversion.kc                 |  90 ++++++++++
 src/test/kc/int-literals.kc                   |  66 -------
 src/test/kc/number-conversion.kc              |  83 +++++++++
 src/test/kc/number-type.kc                    |  53 ++++--
 21 files changed, 738 insertions(+), 111 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoNumbers.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoTypeId.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
 create mode 100644 src/test/kc/int-conversion.kc
 create mode 100644 src/test/kc/number-conversion.kc

diff --git a/src/main/java/dk/camelot64/kickc/CompileLog.java b/src/main/java/dk/camelot64/kickc/CompileLog.java
index 2b82efc32..545d45140 100644
--- a/src/main/java/dk/camelot64/kickc/CompileLog.java
+++ b/src/main/java/dk/camelot64/kickc/CompileLog.java
@@ -192,7 +192,7 @@ public class CompileLog {
       return verboseSSAOptimize;
    }
 
-   public CompileLog setVerboseSSAOptimize() {
+   public CompileLog verboseSSAOptimize() {
       setVerboseSSAOptimize(true);
       return this;
    }
diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index f9a6b1fc6..bf72c2051 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -233,6 +233,7 @@ public class Compiler {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
       optimizations.add(new PassNTypeInference(program));
       optimizations.add(new PassNAddTypeConversions(program));
+      optimizations.add(new PassNAddNumberTypeConversions(program));
       optimizations.add(new Pass2CullEmptyBlocks(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
@@ -247,7 +248,7 @@ public class Compiler {
       optimizations.add(new Pass2ConstantIdentification(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
-      optimizations.add(new Pass2ConstantAdditionElimination(program));
+      //optimizations.add(new Pass2ConstantAdditionElimination(program));
       optimizations.add(new Pass2ConstantIfs(program));
       optimizations.add(new Pass2ConstantStringConsolidation(program));
       optimizations.add(new Pass2FixInlineConstructors(program));
@@ -356,7 +357,9 @@ public class Compiler {
    }
 
    private void pass3Analysis() {
+      new Pass3AssertNoTypeId(program).check();
       new Pass3AssertRValues(program).check();
+      new Pass3AssertNoNumbers(program).check();
       new Pass3AssertConstants(program).check();
       new Pass3AssertArrayLengths(program).check();
       new Pass3AssertNoMulDivMod(program).check();
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java
new file mode 100644
index 000000000..d0993af17
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java
@@ -0,0 +1,166 @@
+package dk.camelot64.kickc.model.iterator;
+
+import dk.camelot64.kickc.model.operators.OperatorBinary;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.statements.StatementConditionalJump;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.values.*;
+
+/**
+ * A binary expression in the program being iterated by {@link BinaryExpressionIterator}
+ */
+public interface BinaryExpression {
+
+   /**
+    * Get the left operand
+    *
+    * @return The left operand
+    */
+   RValue getLeft();
+
+   /**
+    * Get the binary operator
+    *
+    * @return the operator
+    */
+   OperatorBinary getOperator();
+
+   /**
+    * Get the right operand
+    *
+    * @return The right operand
+    */
+   RValue getRight();
+
+   /**
+    * Adds a cast to the right operand
+    * @param toType The toType to cast to
+    */
+   void addRightCast(SymbolType toType);
+
+   /** Binary expression assignment rvalue. */
+   class BinaryExpressionAssignmentRValue implements BinaryExpression {
+      private final StatementAssignment assignment;
+
+      BinaryExpressionAssignmentRValue(StatementAssignment assignment) {
+         this.assignment = assignment;
+      }
+
+      @Override
+      public RValue getLeft() {
+         return assignment.getrValue1();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return (OperatorBinary) assignment.getOperator();
+      }
+
+      @Override
+      public RValue getRight() {
+         return assignment.getrValue2();
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType) {
+         if(assignment.getrValue2() instanceof ConstantValue) {
+            assignment.setrValue2(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2()));
+         } else {
+            throw new InternalError("Not implemented!");
+         }
+      }
+   }
+
+   /** Binary expression - assignment lvalue and the "total" rvalue. */
+   class BinaryExpressionAssignmentLValue implements BinaryExpression {
+      private final StatementAssignment assignment;
+
+      BinaryExpressionAssignmentLValue(StatementAssignment assignment) {
+         this.assignment = assignment;
+      }
+
+      @Override
+      public RValue getLeft() {
+         return assignment.getlValue();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return Operators.ASSIGNMENT;
+      }
+
+      @Override
+      public RValue getRight() {
+         return new AssignmentRValue(assignment);
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType) {
+         throw new InternalError("Not implemented!");
+      }
+
+
+   }
+
+
+   /** Binary expression conditional jump. */
+   class BinaryExpressionConditionalJump implements BinaryExpression {
+      private final StatementConditionalJump conditionalJump;
+
+      BinaryExpressionConditionalJump(StatementConditionalJump assignment) {
+         this.conditionalJump = assignment;
+      }
+
+      @Override
+      public RValue getLeft() {
+         return conditionalJump.getrValue1();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return (OperatorBinary) conditionalJump.getOperator();
+      }
+
+      @Override
+      public RValue getRight() {
+         return conditionalJump.getrValue2();
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType) {
+         throw new InternalError("Not implemented!");
+      }
+
+
+   }
+
+   /** Binary expression as part of a constant expression. */
+   class BinaryExpressionConstant implements BinaryExpression {
+      private ConstantBinary constantBinary;
+
+      BinaryExpressionConstant(ConstantBinary constantBinary) {
+         this.constantBinary = constantBinary;
+      }
+
+      @Override
+      public RValue getLeft() {
+         return constantBinary.getLeft();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return constantBinary.getOperator();
+      }
+
+      @Override
+      public RValue getRight() {
+         return constantBinary.getRight();
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType) {
+         constantBinary.setRight(new ConstantCastValue(toType, constantBinary.getRight()));
+      }
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java
new file mode 100644
index 000000000..f5b10f5e0
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java
@@ -0,0 +1,25 @@
+package dk.camelot64.kickc.model.iterator;
+
+import dk.camelot64.kickc.model.ControlFlowBlock;
+import dk.camelot64.kickc.model.statements.Statement;
+
+import java.util.ListIterator;
+
+/** A handler that performs some action for binary expressions in the program.
+ *  A {@link BinaryExpressionIterator} can be used to iterate all binary expressions in a part of the program.
+ *  The Handler then receives all binary expressions one at a time. The Handler has the option of modifying the binary expression. After the handler is executed all sub-values are recursed.
+ *  The execute() method furthermore receives some extra parameters with information about the context of the passed value.
+ */
+public interface BinaryExpressionHandler {
+
+   /**
+    * Handle a single binary expression
+    *
+    * @param binaryExpression The binary expression
+    * @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling
+    * @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
+    * @param currentBlock The current block that the value is a part of
+    */
+   void execute(BinaryExpression binaryExpression, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java
new file mode 100644
index 000000000..05c761267
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java
@@ -0,0 +1,63 @@
+package dk.camelot64.kickc.model.iterator;
+
+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.StatementConditionalJump;
+import dk.camelot64.kickc.model.values.ConstantBinary;
+
+import java.util.ListIterator;
+
+/**
+ * Capable of iterating the different structures of a Program (graph, block, statement, symboltable, symbol).
+ * Creates appropriate BinaryExpressions and passes them to a BinaryExpressionHandler.
+ * Iteration might be guided (eg. filtering some types of the structure to iterate at call-time)
+ */
+public class BinaryExpressionIterator {
+
+   /**
+    * Execute a handler on all values in the entire program (both in the control flow graph and the symbol table.)
+    *
+    * @param program The program
+    * @param handler The handler to execute
+    */
+   public static void execute(Program program, BinaryExpressionHandler handler) {
+      // Iterate all symbols
+      ProgramValueIterator.execute(program.getScope(), (programValue, currentStmt, stmtIt, currentBlock) -> {
+         if(programValue.get() instanceof ConstantBinary) {
+            ConstantBinary constantBinary = (ConstantBinary) programValue.get();
+            handler.execute( new BinaryExpression.BinaryExpressionConstant(constantBinary), null, null, null);
+         }
+      });
+
+      // Iterate all blocks/statements
+      for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
+         ListIterator<Statement> stmtIt = block.getStatements().listIterator();
+         while(stmtIt.hasNext()) {
+            Statement stmt = stmtIt.next();
+            if(stmt instanceof StatementAssignment) {
+               StatementAssignment assignment = (StatementAssignment) stmt;
+               if(assignment.getrValue1() != null && assignment.getOperator()!=null &&assignment.getrValue2() != null) {
+                  handler.execute( new BinaryExpression.BinaryExpressionAssignmentRValue(assignment), stmt, stmtIt, block);
+               }
+               handler.execute( new BinaryExpression.BinaryExpressionAssignmentLValue(assignment), stmt, stmtIt, block);
+            } else if(stmt instanceof StatementConditionalJump) {
+               StatementConditionalJump condJump = (StatementConditionalJump) stmt;
+               if(condJump.getrValue1()!=null && condJump.getOperator()!=null && condJump.getrValue2()!=null) {
+                  handler.execute( new BinaryExpression.BinaryExpressionConditionalJump(condJump), stmt, stmtIt, block);
+               }
+            }
+            // Iterate all statement values
+            ProgramValueIterator.execute(stmt, (programValue, currentStmt, stmtIt1, currentBlock) -> {
+               if(programValue.get() instanceof ConstantBinary) {
+                  ConstantBinary constantBinary = (ConstantBinary) programValue.get();
+                  handler.execute( new BinaryExpression.BinaryExpressionConstant(constantBinary), stmt, stmtIt, block);
+               }
+            }, stmtIt, block);
+         }
+      }
+
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java
new file mode 100644
index 000000000..b42c177eb
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java
@@ -0,0 +1,27 @@
+package dk.camelot64.kickc.model.operators;
+
+import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeSimple;
+import dk.camelot64.kickc.model.values.ConstantBool;
+import dk.camelot64.kickc.model.values.ConstantLiteral;
+
+/** Binary assignment operator ( x = y ) */
+public class OperatorAssignment extends OperatorBinary {
+
+   public OperatorAssignment(int precedence) {
+      super("=", "_assign_", precedence);
+   }
+
+   @Override
+   public ConstantLiteral calculateLiteral(ConstantLiteral left, ConstantLiteral right) {
+      throw new CompileError("Calculation not implemented " + left + " " + getOperator() + " " + right);
+   }
+
+   @Override
+   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+      return left;
+   }
+
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
index b9470a3c8..d50decce2 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
@@ -48,6 +48,7 @@ public class Operators {
    public static final OperatorBinary BOOL_OR = new OperatorBitwiseOr(11);
    public static final OperatorBinary LOGIC_AND = new OperatorLogicAnd(12);
    public static final OperatorBinary LOGIC_OR = new OperatorLogicOr(13);
+   public static final OperatorBinary ASSIGNMENT = new OperatorAssignment(14);
 
    public static Operator getBinary(String op) {
       switch(op) {
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
index c8a043c17..685017e26 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
@@ -20,7 +20,7 @@ public interface SymbolType {
    SymbolTypeIntegerFixed DWORD = new SymbolTypeIntegerFixed("dword", 0, 4_294_967_296L, false, 32);
    /** Signed double word (4 bytes, 32 bits). */
    SymbolTypeIntegerFixed SDWORD = new SymbolTypeIntegerFixed("signed dword", -2_147_483_648, 2_147_483_647, true, 32);
-   /** Integer with unknown size. */
+   /** Integer with unknown size (used for constant expressions). */
    SymbolTypeIntegerAuto NUMBER = new SymbolTypeIntegerAuto("number");
    /** String value (treated like byte* ). */
    SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99);
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index 477a34d28..31bf4b7a9 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -126,6 +126,8 @@ public class SymbolTypeInference {
       } else if(rValue instanceof ProcedureRef) {
          Procedure procedure = symbols.getProcedure((ProcedureRef) rValue);
          return procedure.getType();
+      }  else if(rValue instanceof AssignmentRValue) {
+         return inferTypeRValue(symbols, ((AssignmentRValue) rValue).getAssignment());
       }
       if(type == null) {
          throw new RuntimeException("Cannot infer type for " + rValue.toString());
diff --git a/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java b/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java
new file mode 100644
index 000000000..6222c6fd2
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java
@@ -0,0 +1,28 @@
+package dk.camelot64.kickc.model.values;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+
+/** The "total" RValue of an assigment. */
+public class AssignmentRValue implements RValue {
+
+   private StatementAssignment assignment;
+
+   public AssignmentRValue(StatementAssignment assignment) {
+      this.assignment = assignment;
+   }
+
+   public StatementAssignment getAssignment() {
+      return assignment;
+   }
+
+   @Override
+   public String toString(Program program) {
+      return
+            (assignment.getrValue1() == null ? "" : assignment.getrValue1().toString(program) + " ") +
+                  (assignment.getOperator() == null ? "" : assignment.getOperator() + " ") +
+                  assignment.getrValue2().toString(program)
+            ;
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java
index 736cb21ca..a1ffcf01a 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java
@@ -1,6 +1,7 @@
 package dk.camelot64.kickc.passes;
 
 import dk.camelot64.kickc.model.ControlFlowBlock;
+import dk.camelot64.kickc.model.InternalError;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.operators.OperatorTypeId;
 import dk.camelot64.kickc.model.operators.Operators;
@@ -8,9 +9,15 @@ import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
+import dk.camelot64.kickc.model.types.SymbolTypeNumberInference;
+import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantRef;
+import dk.camelot64.kickc.model.values.ConstantValue;
 import dk.camelot64.kickc.model.values.RValue;
 
+import java.util.List;
+
 /**
  * Converts typeid() operators to constants
  */
@@ -30,11 +37,18 @@ public class Pass1TypeIdSimplification extends Pass1Base {
                if(Operators.TYPEID.equals(assignment.getOperator())) {
                   RValue rValue = assignment.getrValue2();
                   SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue);
-                  getLog().append("Resolving typeid() " + assignment.toString(getProgram(), false));
-                  ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getScope(), symbolType);
-                  assignment.setrValue2(typeIDConstantVar);
-                  assignment.setOperator(null);
-                  modified = true;
+                  if(SymbolType.NUMBER.equals(symbolType)) {
+                     if(rValue instanceof ConstantValue) {
+                        List<SymbolTypeIntegerFixed> fixedTypes = SymbolTypeNumberInference.inferTypes(getScope(), (ConstantLiteral) rValue);
+                        throw new InternalError("TODO: Implement typeof(const)!");
+                     }
+                  } else {
+                     getLog().append("Resolving typeid() " + assignment.toString(getProgram(), false));
+                     ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getScope(), symbolType);
+                     assignment.setrValue2(typeIDConstantVar);
+                     assignment.setOperator(null);
+                     modified = true;
+                  }
                }
             }
          }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoNumbers.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoNumbers.java
new file mode 100644
index 000000000..2a92f6d79
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoNumbers.java
@@ -0,0 +1,63 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.ControlFlowBlock;
+import dk.camelot64.kickc.model.InternalError;
+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.StatementConditionalJump;
+import dk.camelot64.kickc.model.statements.StatementPhiBlock;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.values.RValue;
+
+/**
+ * Assert that all values with type number have been resolved to fixed size in pass 2.
+ */
+public class Pass3AssertNoNumbers extends Pass2SsaAssertion {
+
+   public Pass3AssertNoNumbers(Program program) {
+      super(program);
+   }
+
+   @Override
+   public void check() throws AssertionFailed {
+      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
+         for(Statement statement : block.getStatements()) {
+            if(statement instanceof StatementAssignment) {
+               checkValue(((StatementAssignment) statement).getlValue(), statement);
+               checkValue(((StatementAssignment) statement).getrValue1(), statement);
+               checkValue(((StatementAssignment) statement).getrValue2(), statement);
+            } else if(statement instanceof StatementPhiBlock) {
+               for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
+                  for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) {
+                     checkValue(value.getrValue(), statement);
+                  }
+               }
+            } else if(statement instanceof StatementConditionalJump) {
+               checkValue(((StatementConditionalJump) statement).getrValue1(), statement);
+               checkValue(((StatementConditionalJump) statement).getrValue2(), statement);
+            }
+         }
+      }
+   }
+
+   /**
+    * Check a value to ensure it is does not have the {@link SymbolType#NUMBER}.
+    *
+    * @param rValue The value to check
+    * @param statement The statement containing the value
+    */
+   public void checkValue(RValue rValue, Statement statement) {
+      if(rValue == null) return;
+      SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue);
+      if(SymbolType.NUMBER.equals(symbolType)) {
+         throw new InternalError(
+               "Error! Number integer type not resolved to fixed size integer type " +
+                     "\n value: " + rValue.toString(getProgram()) +
+                     "\n statement: " + statement.toString(getProgram(), false)
+               , statement.getSource()
+         );
+      }
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoTypeId.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoTypeId.java
new file mode 100644
index 000000000..fa8c01773
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoTypeId.java
@@ -0,0 +1,34 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.InternalError;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.values.ConstantUnary;
+import dk.camelot64.kickc.model.values.Value;
+
+/**
+ * Assert that no typeid() expressions exist in the code anymore (they must have been resolved to constants in phase 1-2)
+ */
+public class Pass3AssertNoTypeId extends Pass2SsaAssertion {
+
+   public Pass3AssertNoTypeId(Program program) {
+      super(program);
+   }
+
+   @Override
+   public void check() throws AssertionFailed {
+      ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
+         Value value = programValue.get();
+         if(value instanceof ConstantUnary) {
+            if(Operators.TYPEID.equals(((ConstantUnary) value).getOperator())) {
+               throw new InternalError(
+                     "Error! Typeid() not resolved during compile. " +
+                           "\n statement: " + currentStmt.toString(getProgram(), false)
+                     , currentStmt.getSource()
+               );
+            }
+         }
+      });
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertRValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertRValues.java
index 70a4e99f8..b0b9cdf05 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertRValues.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertRValues.java
@@ -1,6 +1,6 @@
 package dk.camelot64.kickc.passes;
 
-import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.InternalError;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
 import dk.camelot64.kickc.model.values.RangeValue;
@@ -24,7 +24,7 @@ public class Pass3AssertRValues extends Pass2SsaAssertion {
       ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
          Value value = programValue.get();
          if(value instanceof ValueList) {
-            throw new CompileError(
+            throw new InternalError(
                   "Error! Value list not resolved to word constructor or array initializer" +
                         "\n value list: " + value.toString(getProgram()) +
                         "\n statement: " + currentStmt.toString(getProgram(), false)
@@ -32,7 +32,7 @@ public class Pass3AssertRValues extends Pass2SsaAssertion {
             );
          }
          if(value instanceof RangeValue) {
-            throw new CompileError(
+            throw new InternalError(
                   "Error! Ranged for() not resolved to constants" +
                         "\n Range: " + value.toString(getProgram()) +
                         "\n statement: " + currentStmt.toString(getProgram(), false)
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
new file mode 100644
index 000000000..f1bed6038
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -0,0 +1,59 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.InternalError;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.BinaryExpressionIterator;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
+import dk.camelot64.kickc.model.values.*;
+
+/**
+ * Add casts to {@link SymbolType#NUMBER} expressions that meet a typed value in a binary expression (including assignment)
+ */
+public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
+
+   public PassNAddNumberTypeConversions(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      BinaryExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
+         RValue left = binaryExpression.getLeft();
+         RValue right = binaryExpression.getRight();
+
+         SymbolType leftType = SymbolTypeInference.inferType(getScope(), left);
+         SymbolType rightType = SymbolTypeInference.inferType(getScope(), right);
+         if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) {
+            SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType;
+            // Attempt to find number conversion!
+            if(right instanceof ConstantValue) {
+               ConstantLiteral constantLiteral = ((ConstantValue) right).calculateLiteral(getProgram().getScope());
+               if(constantLiteral instanceof ConstantInteger) {
+                  ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
+                  if(SymbolType.NUMBER.equals(constantInteger.getType())) {
+                     Long value = constantInteger.getValue();
+                     if(leftIntType.getMinValue()<=value && leftIntType.getMaxValue()>=value) {
+                        // The value matches the left type!
+                        getLog().append("Adding number conversion cast ("+leftIntType+") "+binaryExpression.getRight().toString()+" in "+currentStmt.toString(getProgram(), false));
+                        binaryExpression.addRightCast(leftIntType);
+                     }  else {
+                        throw new InternalError("TODO: Implement number conversion for non-equal types "+right.toString(), currentStmt);
+                     }
+                  } else {
+                     throw new InternalError("Non-number constant has type number "+right.toString(), currentStmt);
+                  }
+               }
+            }  else {
+               // Postpone til later!
+               // Maybe handle AssignmentRValue separately!
+               getLog().append("Postponed number conversion " + right.toString());
+            }
+         }
+      });
+      return false;
+   }
+
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
index bf0f55c6f..562d251f0 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
@@ -1,15 +1,19 @@
 package dk.camelot64.kickc.passes;
 
+import dk.camelot64.kickc.model.Comment;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.ControlFlowBlock;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.symbols.Scope;
+import dk.camelot64.kickc.model.symbols.VariableIntermediate;
 import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.LValue;
 import dk.camelot64.kickc.model.values.RValue;
+import dk.camelot64.kickc.model.values.ScopeRef;
 
 import java.util.List;
 import java.util.ListIterator;
@@ -31,7 +35,7 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization {
          while(stmtIt.hasNext()) {
             Statement statement = stmtIt.next();
             if(statement instanceof StatementAssignment) {
-               doConversionAssignment((StatementAssignment) statement, stmtIt);
+               doConversionAssignment((StatementAssignment) statement, stmtIt, block);
             }
             // TODO: Implement conversion for calls
          }
@@ -48,7 +52,7 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization {
     * @param assignment The assignment to examine
     * @param stmtIt Iterator allowing the method to add a tmp-var-assignment.
     */
-   private void doConversionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt) {
+   private void doConversionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock block) {
       LValue lValue = assignment.getlValue();
       SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
       SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), assignment);
@@ -64,14 +68,14 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization {
          }
          for(SymbolTypeIntegerFixed potentialType : potentialTypes) {
             if(lValueType.equals(potentialType) || canConvert(lValueType, potentialType)) {
-               addConversionCast(assignment, lValueType, rValueType);
+               addConversionCast(assignment, stmtIt, block, lValueType, rValueType);
                return;
             }
          }
       } else {
          // No direct type match - attempt conversion
          if(canConvert(lValueType, rValueType)) {
-            addConversionCast(assignment, lValueType, rValueType);
+            addConversionCast(assignment, stmtIt, block, lValueType, rValueType);
             return;
          }
       }
@@ -90,7 +94,7 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization {
     * @param lValueType The type of the lValue
     * @param rValueType The type of the rValue
     */
-   private void addConversionCast(StatementAssignment assignment, SymbolType lValueType, SymbolType rValueType) {
+   private void addConversionCast(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, SymbolType lValueType, SymbolType rValueType) {
       // Promotion possible - add tmp-var and a cast
       if(assignment.getOperator() == null) {
          // No operator - add cast directly!
@@ -100,11 +104,16 @@ public class PassNAddTypeConversions extends Pass2SsaOptimization {
          } else {
             assignment.setOperator(Operators.getCastUnary(lValueType));
          }
-         if(getLog().isVerbosePass1CreateSsa()) {
-            getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment);
-         }
+         getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment);
       } else {
-         throw new RuntimeException("Tmp-var conversion not implemented yet " + assignment);
+         ScopeRef currentScope = currentBlock.getScope();
+         Scope blockScope = getScope().getScope(currentScope);
+         VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
+         tmpVar.setType(rValueType);
+         StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(lValueType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
+         getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment + " adding "+tmpVar);
+         assignment.setlValue(tmpVar.getRef());
+         stmtIt.add(newAssignment);
       }
    }
 
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 89f5ff376..95b07f371 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -33,8 +33,18 @@ public class TestPrograms {
    }
 
    @Test
-   public void testIntegerLiteralsMin() throws IOException, URISyntaxException {
-      compileAndCompare("int-literals-min");
+   public void testNumberConversion() throws IOException, URISyntaxException {
+      compileAndCompare("number-conversion", log());
+   }
+
+   @Test
+   public void testNumberType() throws IOException, URISyntaxException {
+      compileAndCompare("number-type");
+   }
+
+   @Test
+   public void testIntegerConversion() throws IOException, URISyntaxException {
+      compileAndCompare("int-conversion");
    }
 
    @Test
@@ -42,11 +52,6 @@ public class TestPrograms {
       compileAndCompare("int-literals");
    }
 
-   @Test
-   public void testNumberType() throws IOException, URISyntaxException {
-      compileAndCompare("number-type", log());
-   }
-
    @Test
    public void testSimpleLoop() throws IOException, URISyntaxException {
       compileAndCompare("simple-loop");
@@ -59,7 +64,7 @@ public class TestPrograms {
 
    @Test
    public void testPaulNelsenSandboxTernaryError() throws IOException, URISyntaxException {
-      compileAndCompare("sandbox-ternary-error", log().verboseParse().verboseCreateSsa().setVerboseSSAOptimize().verboseStatementSequence());
+      compileAndCompare("sandbox-ternary-error");
    }
 
    @Test
@@ -75,7 +80,7 @@ public class TestPrograms {
 
    @Test
    public void testTypeIdPlusByteProblem() throws IOException, URISyntaxException {
-      compileAndCompare("typeid-plus-byte-problem", log());
+      compileAndCompare("typeid-plus-byte-problem");
    }
 
    @Test
diff --git a/src/test/kc/int-conversion.kc b/src/test/kc/int-conversion.kc
new file mode 100644
index 000000000..2617ce6af
--- /dev/null
+++ b/src/test/kc/int-conversion.kc
@@ -0,0 +1,90 @@
+// Tests different integer literal types
+
+const byte RED = 2ub;
+const byte GREEN = 5ub;
+
+const byte* SCREEN = $0400uw;
+const byte* COLS = $d800uw;
+byte idx = 0ub;
+
+void main() {
+    for(byte* s=SCREEN;s<SCREEN+1000uw;s++) *s = ' ';
+    testUnaryOperator();
+    testBinaryOperator();
+}
+
+void testUnaryOperator() {
+    idx = 00ub;
+    // Unary Operations
+    assertType(typeid(-12ub), typeid(unsigned byte));
+    assertType(typeid(-12sb), typeid(signed byte));
+    assertType(typeid(-12uw), typeid(unsigned word));
+    assertType(typeid(-12sw), typeid(signed word));
+    assertType(typeid(-12ud), typeid(unsigned dword));
+    assertType(typeid(-12sd), typeid(signed dword));
+}
+
+void testBinaryOperator() {
+    idx = 40ub;
+    // Binary Operations between unsigned byte & other types
+    assertType(typeid(12ub+12ub), typeid(unsigned byte));
+    assertType(typeid(12ub+12sb), typeid(unsigned byte));
+    assertType(typeid(12ub+12uw), typeid(unsigned word));
+    assertType(typeid(12ub+12sw), typeid(signed word));
+    assertType(typeid(12ub+12ud), typeid(unsigned dword));
+    assertType(typeid(12ub+12sd), typeid(signed dword));
+    idx++;
+    // Binary Operations between signed byte & other types
+    assertType(typeid(12sb+12ub), typeid(unsigned byte));
+    assertType(typeid(12sb+12sb), typeid(signed byte));
+    assertType(typeid(12sb+12uw), typeid(unsigned word));
+    assertType(typeid(12sb+12sw), typeid(signed word));
+    assertType(typeid(12sb+12ud), typeid(unsigned dword));
+    assertType(typeid(12sb+12sd), typeid(signed dword));
+    idx++;
+    // Binary Operations between unsigned word & other types
+    assertType(typeid(12uw+12ub), typeid(unsigned word));
+    assertType(typeid(12uw+12sb), typeid(unsigned word));
+    assertType(typeid(12uw+12uw), typeid(unsigned word));
+    assertType(typeid(12uw+12sw), typeid(unsigned word));
+    assertType(typeid(12uw+12ud), typeid(unsigned dword));
+    assertType(typeid(12uw+12sd), typeid(signed dword));
+    idx = 80ub;
+    // Binary Operations between signed word & other types
+    assertType(typeid(12sw+12ub), typeid(signed word));
+    assertType(typeid(12sw+12sb), typeid(signed word));
+    assertType(typeid(12sw+12uw), typeid(unsigned word));
+    assertType(typeid(12sw+12sw), typeid(signed word));
+    assertType(typeid(12sw+12ud), typeid(unsigned dword));
+    assertType(typeid(12sw+12sd), typeid(signed dword));
+    idx++;
+    // Binary Operations between unsigned dword & other types
+    assertType(typeid(12ud+12ub), typeid(unsigned dword));
+    assertType(typeid(12ud+12sb), typeid(unsigned dword));
+    assertType(typeid(12ud+12uw), typeid(unsigned dword));
+    assertType(typeid(12ud+12sw), typeid(unsigned dword));
+    assertType(typeid(12ud+12ud), typeid(unsigned dword));
+    assertType(typeid(12ud+12sd), typeid(unsigned dword));
+    idx++;
+    // Binary Operations between signed dword & other types
+    assertType(typeid(12sd+12ub), typeid(signed dword));
+    assertType(typeid(12sd+12sb), typeid(signed dword));
+    assertType(typeid(12sd+12uw), typeid(signed dword));
+    assertType(typeid(12sd+12sw), typeid(signed dword));
+    assertType(typeid(12sd+12ud), typeid(unsigned dword));
+    assertType(typeid(12sd+12sd), typeid(signed dword));
+}
+
+
+
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+void assertType(byte t1, byte t2) {
+    if(t1==t2) {
+        COLS[idx] = GREEN;
+    } else {
+        COLS[idx] = RED;
+    }
+    SCREEN[idx++] = t1;
+}
\ No newline at end of file
diff --git a/src/test/kc/int-literals.kc b/src/test/kc/int-literals.kc
index 5afa560bb..6c478a300 100644
--- a/src/test/kc/int-literals.kc
+++ b/src/test/kc/int-literals.kc
@@ -10,8 +10,6 @@ byte idx = 0ub;
 void main() {
     for(byte* s=SCREEN;s<SCREEN+1000uw;s++) *s = ' ';
     testSimpleTypes();
-    testUnaryOperator();
-    testBinaryOperator();
 }
 
 void testSimpleTypes() {
@@ -34,70 +32,6 @@ void testSimpleTypes() {
     assertType(typeid(12l), typeid(signed dword));
 }
 
-void testUnaryOperator() {
-    idx = 40ub;
-    // Unary Operations
-    assertType(typeid(-12ub), typeid(unsigned byte));
-    assertType(typeid(-12sb), typeid(signed byte));
-    assertType(typeid(-12uw), typeid(unsigned word));
-    assertType(typeid(-12sw), typeid(signed word));
-    assertType(typeid(-12ud), typeid(unsigned dword));
-    assertType(typeid(-12sd), typeid(signed dword));
-}
-
-void testBinaryOperator() {
-    idx = 80ub;
-    // Binary Operations between unsigned byte & other types
-    assertType(typeid(12ub+12ub), typeid(unsigned byte));
-    assertType(typeid(12ub+12sb), typeid(unsigned byte));
-    assertType(typeid(12ub+12uw), typeid(unsigned word));
-    assertType(typeid(12ub+12sw), typeid(signed word));
-    assertType(typeid(12ub+12ud), typeid(unsigned dword));
-    assertType(typeid(12ub+12sd), typeid(signed dword));
-    idx++;
-    // Binary Operations between signed byte & other types
-    assertType(typeid(12sb+12ub), typeid(unsigned byte));
-    assertType(typeid(12sb+12sb), typeid(signed byte));
-    assertType(typeid(12sb+12uw), typeid(unsigned word));
-    assertType(typeid(12sb+12sw), typeid(signed word));
-    assertType(typeid(12sb+12ud), typeid(unsigned dword));
-    assertType(typeid(12sb+12sd), typeid(signed dword));
-    idx++;
-    // Binary Operations between unsigned word & other types
-    assertType(typeid(12uw+12ub), typeid(unsigned word));
-    assertType(typeid(12uw+12sb), typeid(unsigned word));
-    assertType(typeid(12uw+12uw), typeid(unsigned word));
-    assertType(typeid(12uw+12sw), typeid(unsigned word));
-    assertType(typeid(12uw+12ud), typeid(unsigned dword));
-    assertType(typeid(12uw+12sd), typeid(signed dword));
-    idx = 120ub;
-    // Binary Operations between signed word & other types
-    assertType(typeid(12sw+12ub), typeid(signed word));
-    assertType(typeid(12sw+12sb), typeid(signed word));
-    assertType(typeid(12sw+12uw), typeid(unsigned word));
-    assertType(typeid(12sw+12sw), typeid(signed word));
-    assertType(typeid(12sw+12ud), typeid(unsigned dword));
-    assertType(typeid(12sw+12sd), typeid(signed dword));
-    idx++;
-    // Binary Operations between unsigned dword & other types
-    assertType(typeid(12ud+12ub), typeid(unsigned dword));
-    assertType(typeid(12ud+12sb), typeid(unsigned dword));
-    assertType(typeid(12ud+12uw), typeid(unsigned dword));
-    assertType(typeid(12ud+12sw), typeid(unsigned dword));
-    assertType(typeid(12ud+12ud), typeid(unsigned dword));
-    assertType(typeid(12ud+12sd), typeid(unsigned dword));
-    idx++;
-    // Binary Operations between signed dword & other types
-    assertType(typeid(12sd+12ub), typeid(signed dword));
-    assertType(typeid(12sd+12sb), typeid(signed dword));
-    assertType(typeid(12sd+12uw), typeid(signed dword));
-    assertType(typeid(12sd+12sw), typeid(signed dword));
-    assertType(typeid(12sd+12ud), typeid(unsigned dword));
-    assertType(typeid(12sd+12sd), typeid(signed dword));
-}
-
-
-
 // Check that the two passed type IDs are equal.
 // Shows a letter symbolizing t1
 // If they are equal the letter is green - if not it is red.
diff --git a/src/test/kc/number-conversion.kc b/src/test/kc/number-conversion.kc
new file mode 100644
index 000000000..6d7a7b833
--- /dev/null
+++ b/src/test/kc/number-conversion.kc
@@ -0,0 +1,83 @@
+// Tests conversion of numbers to correct int types
+// See https://gitlab.com/camelot/kickc/issues/181
+
+void main() {
+
+    // Signed type and number
+    // a) If one operand is a signed type and the other a number.
+    //    The number becomes the smallest signed type that can hold its value (if one exists).
+    //    The two operands are then converted normally (using 2a or 2b).
+    idx = 0ub;
+    assertType(typeid(12sb+12), typeid(signed byte));
+    assertType(typeid(12sb+130), typeid(signed word));
+    assertType(typeid(12sb+32000), typeid(signed dword));
+    assertType(typeid(12sw+12), typeid(signed word));
+    assertType(typeid(12sw+130), typeid(signed word));
+    assertType(typeid(12sw+100000), typeid(signed dword));
+    assertType(typeid(12sd+12), typeid(signed dword));
+    assertType(typeid(12sd+130), typeid(signed dword));
+    assertType(typeid(12sd+100000), typeid(signed dword));
+    // Test number larger than largest signed type
+    assertType(typeid(12sb+3000000000), typeid(unsigned dword));
+
+    // Unsigned type and positive number
+    // b) If one operand is an unsigned type and the other a positive number.
+    //    The number is converted to the smallest unsigned type that can hold the value.
+    //    The two operands are then converted normally (using 2a or 2b).
+    idx = 40ub;
+    assertType(typeid(12ub+12), typeid(unsigned byte));
+    assertType(typeid(12ub+250), typeid(unsigned byte));
+    assertType(typeid(12ub+300), typeid(unsigned word));
+    assertType(typeid(12ub+65534), typeid(unsigned word));
+    assertType(typeid(12ub+66000), typeid(unsigned dword));
+    assertType(typeid(12uw+12), typeid(unsigned word));
+    assertType(typeid(12uw+130), typeid(unsigned word));
+    assertType(typeid(12uw+66000), typeid(unsigned dword));
+    assertType(typeid(12ud+12), typeid(unsigned dword));
+    assertType(typeid(12ud+130), typeid(unsigned dword));
+    assertType(typeid(12ud+66000), typeid(unsigned dword));
+    assertType(typeid(12sb+3000000000), typeid(unsigned dword));
+
+    // Unsigned type and negative number
+    // If one operand is an unsigned type and the other a negative number.
+    // The number is first converted to the smallest signed type that can hold its value (if one exits).
+    // If the signed type is smaller than the unsigned type it is converted up to the size of the unsigned type.
+    // The signed type is finally converted to unsigned.
+    // The two unsigned operands are then finally converted to the size of the largest type (using 2b).
+    idx = 80ub;
+    assertType(typeid(12ub+-12), typeid(unsigned byte));
+    assertType(typeid(12ub+-120), typeid(unsigned byte));
+    assertType(typeid(12ub+-250), typeid(unsigned word));
+    assertType(typeid(12ub+-32000), typeid(unsigned dword));
+    assertType(typeid(12ub+-66000), typeid(unsigned dword));
+    assertType(typeid(12uw+-12), typeid(unsigned word));
+    assertType(typeid(12uw+-130), typeid(unsigned word));
+    assertType(typeid(12uw+-32000), typeid(unsigned dword));
+    assertType(typeid(12ud+-12), typeid(unsigned dword));
+    assertType(typeid(12ud+-130), typeid(unsigned dword));
+    assertType(typeid(12ud+-66000), typeid(unsigned dword));
+    assertType(typeid(12sb+-3000000000), typeid(unsigned dword));
+
+}
+
+
+
+
+const byte RED = 2ub;
+const byte GREEN = 5ub;
+
+const byte* SCREEN = $0400uw;
+const byte* COLS = $d800uw;
+byte idx = 0ub;
+
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+void assertType(byte t1, byte t2) {
+    if(t1==t2) {
+        COLS[idx] = GREEN;
+    } else {
+        COLS[idx] = RED;
+    }
+    SCREEN[idx++] = t1;
+}
\ No newline at end of file
diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc
index 6c333531f..74f270661 100644
--- a/src/test/kc/number-type.kc
+++ b/src/test/kc/number-type.kc
@@ -1,23 +1,44 @@
 // Tests the number type used for constant expressions
 
-const byte* SCREENB = 0x0400;
 
 void main() {
-    // Constant values resolvable to bytes
-    byte idx = 0;
-    SCREENB[idx++] = 12;
-    SCREENB[idx++] = 6+6;
-    SCREENB[idx++] = 18-6;
-    SCREENB[idx++] = 1812-1800;
-    SCREENB[idx++] = 1+2+3+6;
-    SCREENB[idx++] = 2*6;
-    SCREENB[idx++] = 3<<2;
-    SCREENB[idx++] = 24>>1;
-    SCREENB[idx++] = 15&28;
-    SCREENB[idx++] = 4|8;
-    SCREENB[idx++] = 5^9;
-    SCREENB[idx++] = (2+2)*(15/5);
-    SCREENB[idx++] = (byte)(4096+12);
+    testBytes();
+    testSBytes();
 }
 
+void testBytes() {
+    // Constant values resolvable to bytes
+    const byte* SCREEN = 0x0400;
+    byte idx = 0;
+    SCREEN[idx++] = 12;
+    SCREEN[idx++] = 6+6;
+    SCREEN[idx++] = 18-6;
+    SCREEN[idx++] = 1812-1800;
+    SCREEN[idx++] = 1+2+3+6;
+    SCREEN[idx++] = 2*6;
+    SCREEN[idx++] = 3<<2;
+    SCREEN[idx++] = 24>>1;
+    SCREEN[idx++] = 15&28;
+    SCREEN[idx++] = 4|8;
+    SCREEN[idx++] = 5^9;
+    SCREEN[idx++] = (2+2)*(15/5);
+    SCREEN[idx++] = (byte)(4096+12);
+}
 
+void testSBytes() {
+    // Constant values resolvable to signed bytes
+    const signed byte* SCREEN = 0x0428;
+    byte idx = 0;
+    SCREEN[idx++] = -12;
+    SCREEN[idx++] = -6-6;
+    SCREEN[idx++] = -18+6;
+    SCREEN[idx++] = -1812+1800;
+    SCREEN[idx++] = -1-2-3-6;
+    SCREEN[idx++] = -2*6;
+    SCREEN[idx++] = -3<<2;
+    SCREEN[idx++] = -24>>1;
+    SCREEN[idx++] = -4&-9;
+    SCREEN[idx++] = -0x10|-0xfc;
+    SCREEN[idx++] = (-2-2)*(15/5);
+    SCREEN[idx++] = (signed byte)(4096-12);
+}

From 49ae6a0e66317e017644b26b4ca3d62a007b0c3c Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Mon, 6 May 2019 08:06:18 +0200
Subject: [PATCH 08/93] Working on number conversion... not compiling atm.

---
 .../passes/PassNAddNumberTypeConversions.java | 108 +++++++++++++-----
 1 file changed, 80 insertions(+), 28 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
index f1bed6038..b12ad19ca 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -1,12 +1,16 @@
 package dk.camelot64.kickc.passes;
 
+import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.InternalError;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.iterator.BinaryExpressionIterator;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
 import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
-import dk.camelot64.kickc.model.values.*;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.ConstantLiteral;
+import dk.camelot64.kickc.model.values.ConstantValue;
+import dk.camelot64.kickc.model.values.RValue;
 
 /**
  * Add casts to {@link SymbolType#NUMBER} expressions that meet a typed value in a binary expression (including assignment)
@@ -22,38 +26,86 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
       BinaryExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
          RValue left = binaryExpression.getLeft();
          RValue right = binaryExpression.getRight();
+         SymbolType conversionType = getNumberConversionType(left, right);
+         if(conversionType != null) {
+            // Convert both left and right to the found type
+
+            getLog().append("Adding number conversion cast (" + fixedType+ ") " + binaryExpression.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
+
 
-         SymbolType leftType = SymbolTypeInference.inferType(getScope(), left);
-         SymbolType rightType = SymbolTypeInference.inferType(getScope(), right);
-         if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) {
-            SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType;
-            // Attempt to find number conversion!
-            if(right instanceof ConstantValue) {
-               ConstantLiteral constantLiteral = ((ConstantValue) right).calculateLiteral(getProgram().getScope());
-               if(constantLiteral instanceof ConstantInteger) {
-                  ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
-                  if(SymbolType.NUMBER.equals(constantInteger.getType())) {
-                     Long value = constantInteger.getValue();
-                     if(leftIntType.getMinValue()<=value && leftIntType.getMaxValue()>=value) {
-                        // The value matches the left type!
-                        getLog().append("Adding number conversion cast ("+leftIntType+") "+binaryExpression.getRight().toString()+" in "+currentStmt.toString(getProgram(), false));
-                        binaryExpression.addRightCast(leftIntType);
-                     }  else {
-                        throw new InternalError("TODO: Implement number conversion for non-equal types "+right.toString(), currentStmt);
-                     }
-                  } else {
-                     throw new InternalError("Non-number constant has type number "+right.toString(), currentStmt);
-                  }
-               }
-            }  else {
-               // Postpone til later!
-               // Maybe handle AssignmentRValue separately!
-               getLog().append("Postponed number conversion " + right.toString());
-            }
          }
+
       });
       return false;
    }
 
+   private SymbolType getNumberConversionType(RValue left, RValue right) {
+
+      SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
+      SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
+
+      if(SymbolType.NUMBER.equals(leftType) || SymbolType.NUMBER.equals(rightType)) {
+         // A special type number is assigned to integer constants without a postfix literal.
+         // Numbers are flexible and will take a type based on their actual value when they meet a typed number in a calculation.
+         // Number types are only usable at compile time.
+
+         if(leftType.equals(rightType)) {
+            // a) If the two operands are numbers the result is a number
+            return null;
+         }
+
+         RValue numberVal;
+         SymbolTypeIntegerFixed fixedType;
+         if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) {
+            // Left is the number
+            numberVal = left;
+            fixedType = (SymbolTypeIntegerFixed) rightType;
+         } else if(SymbolType.NUMBER.equals(rightType) && SymbolType.isInteger(leftType)) {
+            // Right is the number
+            numberVal = right;
+            fixedType = (SymbolTypeIntegerFixed) leftType;
+         } else {
+            // Non-integer number binary
+            throw new CompileError("Error! Incompatible operands "+left.toString()+" and "+right.toString());
+         }
+
+         if(numberVal instanceof ConstantValue) {
+            ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(getProgram().getScope());
+            if(constantLiteral instanceof ConstantInteger) {
+               ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
+               if(SymbolType.NUMBER.equals(constantInteger.getType())) {
+                  Long value = constantInteger.getValue();
+                  if(fixedType.getMinValue() <= value && fixedType.getMaxValue() >= value) {
+                     // The value matches the left type!
+                     binaryExpression.addRightCast(leftIntType);
+                  } else {
+                     throw new InternalError("TODO: Implement number conversion for non-equal types " + right.toString(), currentStmt);
+                  }
+               } else {
+                  throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
+               }
+            }
+         } else {
+            // Postpone til later!
+            // Maybe handle AssignmentRValue separately!
+            getLog().append("Postponed number conversion " + right.toString());
+         }
+
+
+
+
+      }
+
+      // No number conversion
+      return null;
+
+      if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) {
+         SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType;
+         // Attempt to find number conversion!
+      }
+
+      return null;
+   }
+
 
 }

From 7e174898b85a700603f06ec28196360d2175fd3f Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 7 May 2019 00:59:54 +0200
Subject: [PATCH 09/93] Number conversion working. Added program expression
 iterator.

---
 .../java/dk/camelot64/kickc/Compiler.java     |   11 +-
 .../model/iterator/BinaryExpression.java      |  166 -
 .../model/iterator/ProgramExpression.java     |   28 +
 .../iterator/ProgramExpressionBinary.java     |  262 ++
 ...ler.java => ProgramExpressionHandler.java} |   15 +-
 ...or.java => ProgramExpressionIterator.java} |   28 +-
 .../iterator/ProgramExpressionUnary.java      |   84 +
 .../kickc/model/iterator/ProgramValue.java    |  989 ++--
 .../model/iterator/ProgramValueIterator.java  |   50 +-
 .../model/operators/OperatorBitwiseAnd.java   |    7 +-
 .../model/operators/OperatorBitwiseOr.java    |    2 +-
 .../model/operators/OperatorBitwiseXor.java   |    2 +-
 .../kickc/model/operators/OperatorCast.java   |   18 +
 .../model/operators/OperatorCastBool.java     |    4 +-
 .../model/operators/OperatorCastByte.java     |    4 +-
 .../model/operators/OperatorCastDWord.java    |    4 +-
 .../model/operators/OperatorCastPtr.java      |    4 +-
 .../model/operators/OperatorCastSByte.java    |    4 +-
 .../model/operators/OperatorCastSDWord.java   |    4 +-
 .../model/operators/OperatorCastSWord.java    |    4 +-
 .../model/operators/OperatorCastWord.java     |    4 +-
 .../kickc/model/operators/OperatorDivide.java |    2 +-
 .../kickc/model/operators/OperatorMinus.java  |    2 +-
 .../kickc/model/operators/OperatorModulo.java |    2 +-
 .../model/operators/OperatorMultiply.java     |    7 +-
 .../kickc/model/operators/OperatorPlus.java   |    2 +-
 .../kickc/model/operators/Operators.java      |    1 +
 .../kickc/model/types/SymbolType.java         |   79 +-
 .../model/types/SymbolTypeConversion.java     |  134 +
 .../model/types/SymbolTypeIntegerFixed.java   |   55 +
 .../kickc/model/types/SymbolTypeMulti.java    |   16 -
 .../types/SymbolTypeNumberInference.java      |    4 +-
 .../kickc/model/values/AssignmentRValue.java  |    2 +-
 ...ss1GenerateSingleStaticAssignmentForm.java |    2 +-
 .../Pass2ConstantCastSimplification.java      |   43 +
 .../passes/PassNAddNumberTypeConversions.java |  108 +-
 .../kickc/passes/PassNAddTypeConversions.java |  143 -
 .../passes/PassNAddTypeConversionsNew.java    |   55 +
 ...on.java => PassNTypeIdSimplification.java} |   46 +-
 .../dk/camelot64/kickc/test/TestPrograms.java |    4 +-
 src/test/kc/number-conversion.kc              |   17 +-
 src/test/ref/int-conversion.asm               |  242 +
 src/test/ref/int-conversion.cfg               |  222 +
 src/test/ref/int-conversion.log               | 4159 +++++++++++++++++
 src/test/ref/int-conversion.sym               |   90 +
 src/test/ref/int-literals.asm                 |  122 +
 src/test/ref/int-literals.cfg                 |  107 +
 src/test/ref/int-literals.log                 | 1947 ++++++++
 src/test/ref/int-literals.sym                 |   55 +
 src/test/ref/number-conversion.asm            |  180 +
 src/test/ref/number-conversion.cfg            |  171 +
 src/test/ref/number-conversion.log            | 3609 ++++++++++++++
 src/test/ref/number-conversion.sym            |   67 +
 src/test/ref/number-type.asm                  |   69 +
 src/test/ref/number-type.cfg                  |   55 +
 src/test/ref/number-type.log                  | 1204 +++++
 src/test/ref/number-type.sym                  |   17 +
 57 files changed, 13641 insertions(+), 1093 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpression.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
 rename src/main/java/dk/camelot64/kickc/model/iterator/{BinaryExpressionHandler.java => ProgramExpressionHandler.java} (51%)
 rename src/main/java/dk/camelot64/kickc/model/iterator/{BinaryExpressionIterator.java => ProgramExpressionIterator.java} (56%)
 create mode 100644 src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/operators/OperatorCast.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
 rename src/main/java/dk/camelot64/kickc/passes/{Pass1TypeIdSimplification.java => PassNTypeIdSimplification.java} (52%)
 create mode 100644 src/test/ref/int-conversion.asm
 create mode 100644 src/test/ref/int-conversion.cfg
 create mode 100644 src/test/ref/int-conversion.log
 create mode 100644 src/test/ref/int-conversion.sym
 create mode 100644 src/test/ref/int-literals.asm
 create mode 100644 src/test/ref/int-literals.cfg
 create mode 100644 src/test/ref/int-literals.log
 create mode 100644 src/test/ref/int-literals.sym
 create mode 100644 src/test/ref/number-conversion.asm
 create mode 100644 src/test/ref/number-conversion.cfg
 create mode 100644 src/test/ref/number-conversion.log
 create mode 100644 src/test/ref/number-conversion.sym
 create mode 100644 src/test/ref/number-type.asm
 create mode 100644 src/test/ref/number-type.cfg
 create mode 100644 src/test/ref/number-type.log
 create mode 100644 src/test/ref/number-type.sym

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index bf72c2051..74445a9ff 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -155,7 +155,7 @@ public class Compiler {
       new Pass1UnwindBlockScopes(program).execute();
       new Pass1Procedures(program).execute();
       new PassNTypeInference(program).execute();
-      new Pass1TypeIdSimplification(program).execute();
+      new PassNTypeIdSimplification(program).execute();
 
       if(getLog().isVerbosePass1CreateSsa()) {
          getLog().append("SYMBOLS");
@@ -165,7 +165,7 @@ public class Compiler {
       new Pass1FixLValuesLoHi(program).execute();
       new Pass1AssertNoLValueIntermediate(program).execute();
       new Pass1PointerSizeofFix(program).execute();
-      new PassNAddTypeConversions(program).execute();
+      new PassNAddTypeConversionsNew(program).execute();
       new Pass1EarlyConstantIdentification(program).execute();
       new PassNStatementIndices(program).step();
       new PassNCallGraphAnalysis(program).step();
@@ -231,9 +231,10 @@ public class Compiler {
 
    private void pass2Optimize() {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
-      optimizations.add(new PassNTypeInference(program));
-      optimizations.add(new PassNAddTypeConversions(program));
+      optimizations.add(new PassNAddTypeConversionsNew(program));
       optimizations.add(new PassNAddNumberTypeConversions(program));
+      optimizations.add(new PassNTypeInference(program));
+      optimizations.add(new PassNTypeIdSimplification(program));
       optimizations.add(new Pass2CullEmptyBlocks(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
@@ -264,6 +265,7 @@ public class Compiler {
       optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new Pass2InlineDerefIdx(program));
       optimizations.add(new Pass2DeInlineWordDerefIdx(program));
+      optimizations.add(new Pass2ConstantCastSimplification(program));
       pass2Execute(optimizations);
    }
 
@@ -303,6 +305,7 @@ public class Compiler {
       constantOptimizations.add(new Pass2ConstantIdentification(program));
       constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
       constantOptimizations.add(new Pass2ConstantSimplification(program));
+      constantOptimizations.add(new Pass2ConstantCastSimplification(program));
       constantOptimizations.add(new Pass2ConstantIfs(program));
       pass2Execute(constantOptimizations);
 
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java b/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java
deleted file mode 100644
index d0993af17..000000000
--- a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpression.java
+++ /dev/null
@@ -1,166 +0,0 @@
-package dk.camelot64.kickc.model.iterator;
-
-import dk.camelot64.kickc.model.operators.OperatorBinary;
-import dk.camelot64.kickc.model.operators.Operators;
-import dk.camelot64.kickc.model.statements.StatementAssignment;
-import dk.camelot64.kickc.model.statements.StatementConditionalJump;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.values.*;
-
-/**
- * A binary expression in the program being iterated by {@link BinaryExpressionIterator}
- */
-public interface BinaryExpression {
-
-   /**
-    * Get the left operand
-    *
-    * @return The left operand
-    */
-   RValue getLeft();
-
-   /**
-    * Get the binary operator
-    *
-    * @return the operator
-    */
-   OperatorBinary getOperator();
-
-   /**
-    * Get the right operand
-    *
-    * @return The right operand
-    */
-   RValue getRight();
-
-   /**
-    * Adds a cast to the right operand
-    * @param toType The toType to cast to
-    */
-   void addRightCast(SymbolType toType);
-
-   /** Binary expression assignment rvalue. */
-   class BinaryExpressionAssignmentRValue implements BinaryExpression {
-      private final StatementAssignment assignment;
-
-      BinaryExpressionAssignmentRValue(StatementAssignment assignment) {
-         this.assignment = assignment;
-      }
-
-      @Override
-      public RValue getLeft() {
-         return assignment.getrValue1();
-      }
-
-      @Override
-      public OperatorBinary getOperator() {
-         return (OperatorBinary) assignment.getOperator();
-      }
-
-      @Override
-      public RValue getRight() {
-         return assignment.getrValue2();
-      }
-
-      @Override
-      public void addRightCast(SymbolType toType) {
-         if(assignment.getrValue2() instanceof ConstantValue) {
-            assignment.setrValue2(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2()));
-         } else {
-            throw new InternalError("Not implemented!");
-         }
-      }
-   }
-
-   /** Binary expression - assignment lvalue and the "total" rvalue. */
-   class BinaryExpressionAssignmentLValue implements BinaryExpression {
-      private final StatementAssignment assignment;
-
-      BinaryExpressionAssignmentLValue(StatementAssignment assignment) {
-         this.assignment = assignment;
-      }
-
-      @Override
-      public RValue getLeft() {
-         return assignment.getlValue();
-      }
-
-      @Override
-      public OperatorBinary getOperator() {
-         return Operators.ASSIGNMENT;
-      }
-
-      @Override
-      public RValue getRight() {
-         return new AssignmentRValue(assignment);
-      }
-
-      @Override
-      public void addRightCast(SymbolType toType) {
-         throw new InternalError("Not implemented!");
-      }
-
-
-   }
-
-
-   /** Binary expression conditional jump. */
-   class BinaryExpressionConditionalJump implements BinaryExpression {
-      private final StatementConditionalJump conditionalJump;
-
-      BinaryExpressionConditionalJump(StatementConditionalJump assignment) {
-         this.conditionalJump = assignment;
-      }
-
-      @Override
-      public RValue getLeft() {
-         return conditionalJump.getrValue1();
-      }
-
-      @Override
-      public OperatorBinary getOperator() {
-         return (OperatorBinary) conditionalJump.getOperator();
-      }
-
-      @Override
-      public RValue getRight() {
-         return conditionalJump.getrValue2();
-      }
-
-      @Override
-      public void addRightCast(SymbolType toType) {
-         throw new InternalError("Not implemented!");
-      }
-
-
-   }
-
-   /** Binary expression as part of a constant expression. */
-   class BinaryExpressionConstant implements BinaryExpression {
-      private ConstantBinary constantBinary;
-
-      BinaryExpressionConstant(ConstantBinary constantBinary) {
-         this.constantBinary = constantBinary;
-      }
-
-      @Override
-      public RValue getLeft() {
-         return constantBinary.getLeft();
-      }
-
-      @Override
-      public OperatorBinary getOperator() {
-         return constantBinary.getOperator();
-      }
-
-      @Override
-      public RValue getRight() {
-         return constantBinary.getRight();
-      }
-
-      @Override
-      public void addRightCast(SymbolType toType) {
-         constantBinary.setRight(new ConstantCastValue(toType, constantBinary.getRight()));
-      }
-   }
-}
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpression.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpression.java
new file mode 100644
index 000000000..68658fc11
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpression.java
@@ -0,0 +1,28 @@
+package dk.camelot64.kickc.model.iterator;
+
+import dk.camelot64.kickc.model.operators.Operator;
+import dk.camelot64.kickc.model.values.ConstantRef;
+import dk.camelot64.kickc.model.values.RValue;
+import dk.camelot64.kickc.model.values.Value;
+
+/** A unary or binary operator expression.
+ * Iterable using {@link ProgramExpressionIterator}.
+ * */
+public interface ProgramExpression {
+
+   /**
+    * Get the operator
+    *
+    * @return the operator
+    */
+   Operator getOperator();
+
+   /**
+    * Replace the unary/binary expression with a new value.
+    *
+    * Throws an exception if replacement is not possible
+    *
+    * @param value The new value.
+    */
+   void set(Value value);
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
new file mode 100644
index 000000000..655ca17e4
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
@@ -0,0 +1,262 @@
+package dk.camelot64.kickc.model.iterator;
+
+import dk.camelot64.kickc.model.Comment;
+import dk.camelot64.kickc.model.InternalError;
+import dk.camelot64.kickc.model.operators.OperatorBinary;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.statements.Statement;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.statements.StatementConditionalJump;
+import dk.camelot64.kickc.model.symbols.ProgramScope;
+import dk.camelot64.kickc.model.symbols.Scope;
+import dk.camelot64.kickc.model.symbols.VariableIntermediate;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.values.*;
+
+import java.util.ListIterator;
+
+/**
+ * A binary expression in the program being iterated by {@link ProgramExpressionIterator}
+ */
+public interface ProgramExpressionBinary extends ProgramExpression {
+
+   /**
+    * Get the left operand
+    *
+    * @return The left operand
+    */
+   RValue getLeft();
+
+   /**
+    * Get the binary operator
+    *
+    * @return the operator
+    */
+   OperatorBinary getOperator();
+
+   /**
+    * Get the right operand
+    *
+    * @return The right operand
+    */
+   RValue getRight();
+
+   /**
+    * Adds a cast to the left operand
+    * @param toType The toType to cast to
+    */
+   void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols);
+
+   /**
+    * Adds a cast to the right operand
+    * @param toType The toType to cast to
+    */
+   void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols);
+
+
+   /** Binary expression assignment rvalue. */
+   class ProgramExpressionBinaryAssignmentRValue implements ProgramExpressionBinary {
+
+      private final StatementAssignment assignment;
+
+      ProgramExpressionBinaryAssignmentRValue(StatementAssignment assignment) {
+         this.assignment = assignment;
+      }
+
+      @Override
+      public RValue getLeft() {
+         return assignment.getrValue1();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return (OperatorBinary) assignment.getOperator();
+      }
+
+      @Override
+      public RValue getRight() {
+         return assignment.getrValue2();
+      }
+
+      @Override
+      public void set(Value value) {
+         assignment.setrValue2((RValue) value);
+         assignment.setOperator(null);
+         assignment.setrValue1(null);
+      }
+
+      @Override
+      public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         if(assignment.getrValue1() instanceof ConstantValue) {
+            assignment.setrValue1(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue1()));
+         } else {
+            Scope blockScope = symbols.getScope(currentScope);
+            VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
+            tmpVar.setType(toType);
+            StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS);
+            assignment.setrValue1(tmpVar.getRef());
+            stmtIt.add(newAssignment);
+         }
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         if(assignment.getrValue2() instanceof ConstantValue) {
+            assignment.setrValue2(new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2()));
+         } else {
+            Scope blockScope = symbols.getScope(currentScope);
+            VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
+            tmpVar.setType(toType);
+            StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS);
+            assignment.setrValue2(tmpVar.getRef());
+            stmtIt.add(newAssignment);
+         }
+      }
+   }
+
+   /** Binary expression - assignment lvalue and the "total" rvalue. */
+   class ProgramExpressionBinaryAssignmentLValue implements ProgramExpressionBinary {
+      private final StatementAssignment assignment;
+
+      ProgramExpressionBinaryAssignmentLValue(StatementAssignment assignment) {
+         this.assignment = assignment;
+      }
+
+      @Override
+      public RValue getLeft() {
+         return assignment.getlValue();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return Operators.ASSIGNMENT;
+      }
+
+      @Override
+      public RValue getRight() {
+         if(assignment.getrValue1()==null && assignment.getOperator()==null) {
+            return assignment.getrValue2();
+         } else {
+            return new AssignmentRValue(assignment);
+         }
+      }
+
+      @Override
+      public void set(Value value) {
+         throw new InternalError("Updating an entire assignment is not allowed!");
+      }
+
+      @Override
+      public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         Scope blockScope = symbols.getScope(currentScope);
+         VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
+         SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
+         tmpVar.setType(rightType);
+         StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
+         assignment.setlValue(tmpVar.getRef());
+         stmtIt.add(newAssignment);
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         if(assignment.getrValue1()==null && assignment.getOperator()==null) {
+            //if(assignment.getrValue2() instanceof ConstantInteger) {
+            //   ((ConstantInteger) assignment.getrValue2()).setType(toType);
+            //}  else {
+               assignment.setOperator(Operators.getCastUnary(toType));
+            //}
+         }  else {
+            throw new InternalError("Not implemented!");
+         }
+      }
+
+   }
+
+   /** Binary expression conditional jump. */
+   class ProgramExpressionBinaryConditionalJump implements ProgramExpressionBinary {
+      private final StatementConditionalJump conditionalJump;
+
+      ProgramExpressionBinaryConditionalJump(StatementConditionalJump assignment) {
+         this.conditionalJump = assignment;
+      }
+
+      @Override
+      public RValue getLeft() {
+         return conditionalJump.getrValue1();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return (OperatorBinary) conditionalJump.getOperator();
+      }
+
+      @Override
+      public RValue getRight() {
+         return conditionalJump.getrValue2();
+      }
+
+      @Override
+      public void set(Value value) {
+         conditionalJump.setrValue2((RValue) value);
+         conditionalJump.setOperator(null);
+         conditionalJump.setrValue1(null);
+      }
+
+      @Override
+      public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         throw new InternalError("Not implemented!");
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         throw new InternalError("Not implemented!");
+      }
+
+
+   }
+
+   /** Binary expression as part of a constant expression. */
+   class ProgramExpressionBinaryConstant implements ProgramExpressionBinary {
+      /** A program value containing a {@link ConstantBinary}. */
+      private ProgramValue programValue;
+
+      public ProgramExpressionBinaryConstant(ProgramValue programValue) {
+         this.programValue = programValue;
+      }
+
+      public ConstantBinary getConstantBinary() {
+         return (ConstantBinary)programValue.get();
+      }
+
+      @Override
+      public RValue getLeft() {
+         return getConstantBinary().getLeft();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return getConstantBinary().getOperator();
+      }
+
+      @Override
+      public RValue getRight() {
+         return getConstantBinary().getRight();
+      }
+
+      @Override
+      public void set(Value value) {
+         programValue.set(value);
+      }
+
+      @Override
+      public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         getConstantBinary().setLeft(new ConstantCastValue(toType, getConstantBinary().getLeft()));
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         getConstantBinary().setRight(new ConstantCastValue(toType, getConstantBinary().getRight()));
+      }
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionHandler.java
similarity index 51%
rename from src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java
rename to src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionHandler.java
index f5b10f5e0..077eb7cdd 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionHandler.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionHandler.java
@@ -5,21 +5,22 @@ import dk.camelot64.kickc.model.statements.Statement;
 
 import java.util.ListIterator;
 
-/** A handler that performs some action for binary expressions in the program.
- *  A {@link BinaryExpressionIterator} can be used to iterate all binary expressions in a part of the program.
- *  The Handler then receives all binary expressions one at a time. The Handler has the option of modifying the binary expression. After the handler is executed all sub-values are recursed.
+/** A handler that performs some action for unary/binary expressions in the program.
+ *  A {@link ProgramExpressionIterator} can be used to iterate all unary/binary expressions in a part of the program.
+ *  The Handler then receives all unary/binary expressions one at a time.
+ *  The Handler has the option of modifying the expression. After the handler is executed all sub-values are recursed.
  *  The execute() method furthermore receives some extra parameters with information about the context of the passed value.
  */
-public interface BinaryExpressionHandler {
+public interface ProgramExpressionHandler {
 
    /**
-    * Handle a single binary expression
+    * Handle a single expression
     *
-    * @param binaryExpression The binary expression
+    * @param programExpression The expression
     * @param currentStmt The statement iterator - just past the current statement that the value is a part of. Current statment can be retrieved by calling
     * @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
     * @param currentBlock The current block that the value is a part of
     */
-   void execute(BinaryExpression binaryExpression, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
+   void execute(ProgramExpression programExpression, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
similarity index 56%
rename from src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java
rename to src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
index 05c761267..a8ae53aca 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/BinaryExpressionIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
@@ -6,15 +6,16 @@ import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementConditionalJump;
 import dk.camelot64.kickc.model.values.ConstantBinary;
+import dk.camelot64.kickc.model.values.ConstantUnary;
 
 import java.util.ListIterator;
 
 /**
  * Capable of iterating the different structures of a Program (graph, block, statement, symboltable, symbol).
- * Creates appropriate BinaryExpressions and passes them to a BinaryExpressionHandler.
+ * Creates appropriate BinaryExpressions and passes them to a ProgramExpressionHandler.
  * Iteration might be guided (eg. filtering some types of the structure to iterate at call-time)
  */
-public class BinaryExpressionIterator {
+public class ProgramExpressionIterator {
 
    /**
     * Execute a handler on all values in the entire program (both in the control flow graph and the symbol table.)
@@ -22,12 +23,11 @@ public class BinaryExpressionIterator {
     * @param program The program
     * @param handler The handler to execute
     */
-   public static void execute(Program program, BinaryExpressionHandler handler) {
+   public static void execute(Program program, ProgramExpressionHandler handler) {
       // Iterate all symbols
       ProgramValueIterator.execute(program.getScope(), (programValue, currentStmt, stmtIt, currentBlock) -> {
          if(programValue.get() instanceof ConstantBinary) {
-            ConstantBinary constantBinary = (ConstantBinary) programValue.get();
-            handler.execute( new BinaryExpression.BinaryExpressionConstant(constantBinary), null, null, null);
+            handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), null, null, null);
          }
       });
 
@@ -38,22 +38,26 @@ public class BinaryExpressionIterator {
             Statement stmt = stmtIt.next();
             if(stmt instanceof StatementAssignment) {
                StatementAssignment assignment = (StatementAssignment) stmt;
-               if(assignment.getrValue1() != null && assignment.getOperator()!=null &&assignment.getrValue2() != null) {
-                  handler.execute( new BinaryExpression.BinaryExpressionAssignmentRValue(assignment), stmt, stmtIt, block);
+               if(assignment.getrValue1() != null && assignment.getOperator() != null && assignment.getrValue2() != null) {
+                  handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryAssignmentRValue(assignment), stmt, stmtIt, block);
+               } else if(assignment.getrValue1() == null && assignment.getOperator() != null && assignment.getrValue2() != null) {
+                  handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryAssignmentRValue(assignment), stmt, stmtIt, block);
                }
-               handler.execute( new BinaryExpression.BinaryExpressionAssignmentLValue(assignment), stmt, stmtIt, block);
+               handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue(assignment), stmt, stmtIt, block);
             } else if(stmt instanceof StatementConditionalJump) {
                StatementConditionalJump condJump = (StatementConditionalJump) stmt;
-               if(condJump.getrValue1()!=null && condJump.getOperator()!=null && condJump.getrValue2()!=null) {
-                  handler.execute( new BinaryExpression.BinaryExpressionConditionalJump(condJump), stmt, stmtIt, block);
+               if(condJump.getrValue1() != null && condJump.getOperator() != null && condJump.getrValue2() != null) {
+                  handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConditionalJump(condJump), stmt, stmtIt, block);
                }
             }
             // Iterate all statement values
             ProgramValueIterator.execute(stmt, (programValue, currentStmt, stmtIt1, currentBlock) -> {
                if(programValue.get() instanceof ConstantBinary) {
-                  ConstantBinary constantBinary = (ConstantBinary) programValue.get();
-                  handler.execute( new BinaryExpression.BinaryExpressionConstant(constantBinary), stmt, stmtIt, block);
+                  handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), stmt, stmtIt, block);
+               } else if(programValue.get() instanceof ConstantUnary) {
+                  handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), stmt, stmtIt, block);
                }
+
             }, stmtIt, block);
          }
       }
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
new file mode 100644
index 000000000..a2795032d
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
@@ -0,0 +1,84 @@
+package dk.camelot64.kickc.model.iterator;
+
+import dk.camelot64.kickc.model.operators.OperatorUnary;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.values.ConstantUnary;
+import dk.camelot64.kickc.model.values.RValue;
+import dk.camelot64.kickc.model.values.Value;
+
+/**
+ * A binary expression in the program being iterated by {@link ProgramExpressionIterator}
+ */
+public interface ProgramExpressionUnary extends ProgramExpression {
+
+   /**
+    * Get the unary operator
+    *
+    * @return the operator
+    */
+   OperatorUnary getOperator();
+
+   /**
+    * Get the right operand
+    *
+    * @return The right operand
+    */
+   RValue getOperand();
+
+   /** Unary expression assignment rvalue. */
+   class ProgramExpressionUnaryAssignmentRValue implements ProgramExpressionUnary {
+      private final StatementAssignment assignment;
+
+      ProgramExpressionUnaryAssignmentRValue(StatementAssignment assignment) {
+         this.assignment = assignment;
+      }
+
+      @Override
+      public OperatorUnary getOperator() {
+         return (OperatorUnary) assignment.getOperator();
+      }
+
+      @Override
+      public RValue getOperand() {
+         return assignment.getrValue2();
+      }
+
+      @Override
+      public void set(Value value) {
+         assignment.setrValue2((RValue) value);
+         assignment.setOperator(null);
+      }
+   }
+
+   /** Unary expression as part of a constant expression. */
+   class ProgramExpressionUnaryConstant implements ProgramExpressionUnary {
+      
+      /** A ProgramValue containing a {@link ConstantUnary}. */
+      private ProgramValue programValue;
+
+      ProgramExpressionUnaryConstant(ProgramValue programValue) {
+         this.programValue = programValue;
+      }
+
+      public ConstantUnary getConstantUnary() {
+         return (ConstantUnary) programValue.get();
+      }
+
+      @Override
+      public OperatorUnary getOperator() {
+         return (getConstantUnary()).getOperator();
+      }
+
+      @Override
+      public RValue getOperand() {
+         return getConstantUnary().getOperand();
+      }
+
+      @Override
+      public void set(Value value) {
+         programValue.set(value);
+      }
+
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
index 9f34e3c20..551863bf9 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
@@ -7,489 +7,23 @@ import dk.camelot64.kickc.model.types.SymbolTypeArray;
 import dk.camelot64.kickc.model.values.*;
 
 /**
- * An RValue in the program being iterated by {@link ProgramValueIterator}.
+ * Any Value in the program being iterated by {@link ProgramValueIterator}.
  *
- * The RValue can be inspected using get() and replaced inside the model using set(val).
+ * The Value can be inspected using get() and replaced inside the model using set(val).
  *
- * The context of the RValue can be determined from the sub-class containing it plus the parameters to the ProgramValueHandler.
+ * The context of the Value can be determined from the sub-class containing it plus the parameters to the ProgramValueHandler.
  *
  */
-public abstract class ProgramValue {
+public interface ProgramValue {
 
-   public abstract Value get();
+   Value get();
 
-   public abstract void set(Value value);
+   void set(Value value);
 
-   public static class ConstantVariableValue extends ProgramValue {
-      private final ConstantVar constantVar;
-
-      ConstantVariableValue(ConstantVar constantVar) {
-         this.constantVar = constantVar;
-      }
-
-      @Override
-      public Value get() {
-         return constantVar.getValue();
-      }
-
-      @Override
-      public void set(Value val) {
-         constantVar.setValue((ConstantValue) val);
-      }
-
-   }
-
-   /** Size inside a fixed size array. */
-   public static class TypeArraySize extends ProgramValue {
-      private final SymbolTypeArray array;
-
-      TypeArraySize(SymbolTypeArray array) {
-         this.array = array;
-      }
-
-      @Override
-      public Value get() {
-         return array.getSize();
-      }
-
-      @Override
-      public void set(Value val) {
-         array.setSize((RValue) val);
-      }
-
-   }
-
-   /** Value inside a array filled expression. */
-   public static class ArrayFilledSize extends ProgramValue {
-      private final ArrayFilled array;
-
-      ArrayFilledSize(ArrayFilled array) {
-         this.array = array;
-      }
-
-      @Override
-      public Value get() {
-         return array.getSize();
-      }
-
-      @Override
-      public void set(Value val) {
-         array.setSize((RValue) val);
-      }
-
-   }
-
-   /** Value inside an intermediate LValue. */
-   public static class LValueIntermediateVariable  extends ProgramValue {
-      private final LvalueIntermediate intermediate;
-
-      LValueIntermediateVariable(LvalueIntermediate intermediate) {
-         this.intermediate = intermediate;
-      }
-
-      @Override
-      public Value get() {
-         return intermediate.getVariable();
-      }
-
-      @Override
-      public void set(Value val) {
-         intermediate.setVariable((VariableRef) val);
-      }
-
-   }
-
-   /** Value inside a constant array filled expression. */
-   public static class ConstantArrayFilledSize extends ProgramValue {
-      private final ConstantArrayFilled array;
-
-      ConstantArrayFilledSize(ConstantArrayFilled array) {
-         this.array = array;
-      }
-
-      @Override
-      public Value get() {
-         return array.getSize();
-      }
-
-      @Override
-      public void set(Value val) {
-         array.setSize((ConstantValue) val);
-      }
-
-   }
-
-   /** Value inside a constant unary expression. */
-   public static class ConstantUnaryValue extends ProgramValue {
-      private final ConstantUnary unary;
-
-      ConstantUnaryValue(ConstantUnary unary) {
-         this.unary = unary;
-      }
-
-      @Override
-      public Value get() {
-         return unary.getOperand();
-      }
-
-      @Override
-      public void set(Value val) {
-         unary.setOperand((ConstantValue) val);
-      }
-
-   }
-
-   /** Left value inside a constant binary expression. */
-   public static class ConstantBinaryLeft extends ProgramValue {
-      private final ConstantBinary binary;
-
-      ConstantBinaryLeft(ConstantBinary binary) {
-         this.binary = binary;
-      }
-
-      @Override
-      public Value get() {
-         return binary.getLeft();
-      }
-
-      @Override
-      public void set(Value val) {
-         binary.setLeft((ConstantValue) val);
-      }
-
-   }
-
-   /** Right value inside a constant binary expression. */
-   public static class ConstantBinaryRight extends ProgramValue {
-      private final ConstantBinary binary;
-
-      ConstantBinaryRight(ConstantBinary range) {
-         this.binary = range;
-      }
-
-      @Override
-      public Value get() {
-         return binary.getRight();
-      }
-
-      @Override
-      public void set(Value val) {
-         binary.setRight((ConstantValue) val);
-      }
-
-   }
-
-   /**
-    * First value inside a ranged comparison value.
-    */
-   public static class RangeFirst extends ProgramValue {
-      private final RangeValue range;
-
-      RangeFirst(RangeValue range) {
-         this.range = range;
-      }
-
-      @Override
-      public Value get() {
-         return range.getRangeFirst();
-      }
-
-      @Override
-      public void set(Value val) {
-         range.setRangeFirst((RValue) val);
-      }
-
-   }
-
-   /**
-    * Last value inside inside a ranged comparison value.
-    */
-   public static class RangeLast extends ProgramValue {
-      private final RangeValue range;
-
-      RangeLast(RangeValue range) {
-         this.range = range;
-      }
-
-      @Override
-      public Value get() {
-         return range.getRangeLast();
-      }
-
-      @Override
-      public void set(Value val) {
-         range.setRangeLast((RValue) val);
-      }
-
-   }
-
-   /** A variable/constant referenced inside inline ASM. */
-   public static class AsmReferenced extends ProgramValue {
-      private StatementAsm statementAsm;
-      private String label;
-
-      public AsmReferenced(StatementAsm statementAsm, String label) {
-         this.statementAsm = statementAsm;
-         this.label = label;
-      }
-
-      @Override
-      public Value get() {
-         return statementAsm.getReferenced().get(label);
-      }
-
-      @Override
-      public void set(Value value) {
-         statementAsm.getReferenced().put(label, (SymbolVariableRef) value);
-      }
-   }
-
-   /** Location inside inline kickasm code. */
-   public static class KickAsmLocation extends ProgramValue {
-
-      private StatementKickAsm statementKickAsm;
-
-      KickAsmLocation(StatementKickAsm statementKickAsm) {
-         super();
-         this.statementKickAsm = statementKickAsm;
-      }
-
-      @Override
-      public Value get() {
-         return statementKickAsm.getLocation();
-      }
-
-      @Override
-      public void set(Value value) {
-         statementKickAsm.setLocation((RValue) value);
-      }
-
-   }
-
-   /** Bytes inside inline kickasm code. */
-   public static class KickAsmBytes extends ProgramValue {
-
-      private StatementKickAsm statementKickAsm;
-
-      KickAsmBytes(StatementKickAsm statementKickAsm) {
-         super();
-         this.statementKickAsm = statementKickAsm;
-      }
-
-      @Override
-      public Value get() {
-         return statementKickAsm.getBytes();
-      }
-
-      @Override
-      public void set(Value value) {
-         statementKickAsm.setBytes((RValue) value);
-      }
-
-   }
-
-   /** Cycles inside inline kickasm code. */
-   public static class KickAsmCycles extends ProgramValue {
-
-      private StatementKickAsm statementKickAsm;
-
-      KickAsmCycles(StatementKickAsm statementKickAsm) {
-         super();
-         this.statementKickAsm = statementKickAsm;
-      }
-
-      @Override
-      public Value get() {
-         return statementKickAsm.getCycles();
-      }
-
-      @Override
-      public void set(Value value) {
-         statementKickAsm.setCycles((RValue) value);
-      }
-
-   }
-
-   /**
-    * LValue as part of an assignment statement (or a call).
-    */
-   public static class LValue extends ProgramValue {
-      private final StatementLValue statement;
-
-      public LValue(StatementLValue statement) {
-         this.statement = statement;
-      }
-
-      @Override
-      public Value get() {
-         return statement.getlValue();
-      }
-
-      @Override
-      public void set(Value value) {
-         statement.setlValue((dk.camelot64.kickc.model.values.LValue) value);
-      }
-
-   }
-
-   /**
-    * Pointer inside a pointer dererence value.
-    */
-   public static class Pointer extends ProgramValue {
-      private final PointerDereference pointer;
-
-      Pointer(PointerDereference pointer) {
-         this.pointer = pointer;
-      }
-
-      @Override
-      public Value get() {
-         return pointer.getPointer();
-      }
-
-      @Override
-      public void set(Value val) {
-         pointer.setPointer((RValue) val);
-      }
-
-   }
-
-   /**
-    * Value inside a noop cast.
-    */
-   public static class CastValue extends ProgramValue {
-      private final dk.camelot64.kickc.model.values.CastValue castValue;
-
-
-      public CastValue(dk.camelot64.kickc.model.values.CastValue castValue) {
-         this.castValue = castValue;
-      }
-
-      @Override
-      public Value get() {
-         return castValue.getValue();
-      }
-
-      @Override
-      public void set(Value val) {
-         castValue.setValue((RValue) val);
-      }
-
-   }
-
-   /**
-    * Value inside a constant noop cast.
-    */
-   public static class ConstantCastValue extends ProgramValue {
-      private final dk.camelot64.kickc.model.values.ConstantCastValue castValue;
-
-
-      ConstantCastValue(dk.camelot64.kickc.model.values.ConstantCastValue castValue) {
-         this.castValue = castValue;
-      }
-
-      @Override
-      public Value get() {
-         return castValue.getValue();
-      }
-
-      @Override
-      public void set(Value val) {
-         castValue.setValue((ConstantValue) val);
-      }
-
-   }
-
-   /**
-    * Pointer inside a variable pointer.
-    */
-   public static class ConstantSymbolPointerTo extends ProgramValue {
-      private final ConstantSymbolPointer varPointer;
-
-
-      ConstantSymbolPointerTo(ConstantSymbolPointer varPointer) {
-         this.varPointer = varPointer;
-      }
-
-      @Override
-      public Value get() {
-         return (RValue) varPointer.getToSymbol();
-      }
-
-      @Override
-      public void set(Value val) {
-         varPointer.setToSymbol((VariableRef) val);
-      }
-
-   }
-
-   public static class ConstantArrayElement extends ProgramValue {
-      private final ConstantArrayList arrayList;
-      private final int idx;
-
-      ConstantArrayElement(ConstantArrayList arrayList, int idx) {
-         this.arrayList = arrayList;
-         this.idx = idx;
-      }
-
-      @Override
-      public Value get() {
-         return arrayList.getElements().get(idx);
-      }
-
-      @Override
-      public void set(Value value) {
-         arrayList.getElements().set(idx, (ConstantValue) value);
-      }
-   }
-
-   public static class ListElement extends ProgramValue {
-      private ValueList list;
-      private int idx;
-
-      ListElement(ValueList list, int idx) {
-         this.list = list;
-         this.idx = idx;
-      }
-
-      @Override
-      public Value get() {
-         return list.getList().get(idx);
-      }
-
-      @Override
-      public void set(Value value) {
-         list.getList().set(idx, (RValue) value);
-      }
-
-   }
-
-   /**
-    * Pointer index inside a indexed pointer dererence value.
-    */
-   public static class PointerIndex extends ProgramValue {
-      private final PointerDereferenceIndexed pointer;
-
-      PointerIndex(PointerDereferenceIndexed pointer) {
-         this.pointer = pointer;
-      }
-
-      @Override
-      public Value get() {
-         return pointer.getIndex();
-      }
-
-      @Override
-      public void set(Value val) {
-         pointer.setIndex((RValue) val);
-      }
-
-   }
-
-   public static class RValue1 extends ProgramValue {
+   class RValue1 implements ProgramValue {
       private final StatementAssignment statement;
 
-      public RValue1(StatementAssignment statement) {
+      RValue1(StatementAssignment statement) {
          this.statement = statement;
       }
 
@@ -504,10 +38,10 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class RValue2 extends ProgramValue {
+   class RValue2 implements ProgramValue {
       private final StatementAssignment statement;
 
-      public RValue2(StatementAssignment statement) {
+      RValue2(StatementAssignment statement) {
          this.statement = statement;
       }
 
@@ -522,7 +56,7 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class CallParameter extends ProgramValue {
+   class CallParameter implements ProgramValue {
       private final StatementCall call;
       private final int i;
 
@@ -542,7 +76,7 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class CallPointerProcedure extends ProgramValue {
+   class CallPointerProcedure implements ProgramValue {
       private final StatementCallPointer call;
 
       CallPointerProcedure(StatementCallPointer call) {
@@ -560,7 +94,7 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class CallPointerParameter extends ProgramValue {
+   class CallPointerParameter implements ProgramValue {
       private final StatementCallPointer call;
       private final int i;
 
@@ -580,10 +114,10 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class CondRValue1 extends ProgramValue {
+   class CondRValue1 implements ProgramValue {
       private final StatementConditionalJump statement;
 
-      public CondRValue1(StatementConditionalJump statement) {
+      CondRValue1(StatementConditionalJump statement) {
          this.statement = statement;
       }
 
@@ -598,10 +132,10 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class CondRValue2 extends ProgramValue {
+   class CondRValue2 implements ProgramValue {
       private final StatementConditionalJump statement;
 
-      public CondRValue2(StatementConditionalJump statement) {
+      CondRValue2(StatementConditionalJump statement) {
          this.statement = statement;
       }
 
@@ -616,10 +150,10 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class CondLabel extends ProgramValue {
+   class CondLabel implements ProgramValue {
       private final StatementConditionalJump statement;
 
-      public CondLabel(StatementConditionalJump statement) {
+      CondLabel(StatementConditionalJump statement) {
          this.statement = statement;
       }
 
@@ -634,7 +168,7 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class Return extends ProgramValue {
+   class Return implements ProgramValue {
       private final StatementReturn statement;
 
       public Return(StatementReturn statement) {
@@ -652,7 +186,7 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class PhiValue extends ProgramValue {
+   class PhiValue implements ProgramValue {
       private final StatementPhiBlock.PhiVariable phiVariable;
       private final int i;
 
@@ -672,7 +206,7 @@ public abstract class ProgramValue {
       }
    }
 
-   public static class PhiValuePredecessor extends ProgramValue {
+   class PhiValuePredecessor implements ProgramValue {
       private final StatementPhiBlock.PhiVariable phiVariable;
       private final int i;
 
@@ -695,7 +229,7 @@ public abstract class ProgramValue {
    /**
     * LValue as part of an assignment statement (or a call).
     */
-   public static class PhiVariable extends ProgramValue {
+   class PhiVariable implements ProgramValue {
       private final StatementPhiBlock.PhiVariable phiVariable;
 
       public PhiVariable(StatementPhiBlock.PhiVariable phiVariable) {
@@ -715,7 +249,7 @@ public abstract class ProgramValue {
    }
 
    /** A generic Value. */
-   public static class GenericValue extends ProgramValue {
+   class GenericValue implements ProgramValue {
       private RValue rValue;
 
       public GenericValue(RValue rValue) {
@@ -734,11 +268,11 @@ public abstract class ProgramValue {
    }
 
    /** A variable used by inline kickasm. */
-   public static class KickAsmUses extends ProgramValue {
+   class KickAsmUses implements ProgramValue {
       private StatementKickAsm statementKickAsm;
       private int idx;
 
-      public KickAsmUses(StatementKickAsm statementKickAsm, int idx) {
+      KickAsmUses(StatementKickAsm statementKickAsm, int idx) {
          this.statementKickAsm = statementKickAsm;
          this.idx = idx;
       }
@@ -756,7 +290,7 @@ public abstract class ProgramValue {
 
    }
 
-   public static class BlockLabel extends ProgramValue {
+   class BlockLabel implements ProgramValue {
 
       private final ControlFlowBlock block;
 
@@ -776,7 +310,7 @@ public abstract class ProgramValue {
 
    }
 
-   public static class BlockDefaultSuccessor extends ProgramValue {
+   class BlockDefaultSuccessor implements ProgramValue {
 
       private final ControlFlowBlock block;
 
@@ -796,7 +330,7 @@ public abstract class ProgramValue {
 
    }
 
-   public static class BlockConditionalSuccessor extends ProgramValue {
+   class BlockConditionalSuccessor implements ProgramValue {
 
       private final ControlFlowBlock block;
 
@@ -816,7 +350,7 @@ public abstract class ProgramValue {
 
    }
 
-   public static class BlockCallSuccessor extends ProgramValue {
+   class BlockCallSuccessor implements ProgramValue {
 
       private final ControlFlowBlock block;
 
@@ -836,4 +370,467 @@ public abstract class ProgramValue {
 
    }
 
+   /** Value inside a array filled expression. */
+   class ProgramValueArrayFilledSize implements ProgramValue {
+      private final ArrayFilled array;
+
+      ProgramValueArrayFilledSize(ArrayFilled array) {
+         this.array = array;
+      }
+
+      @Override
+      public Value get() {
+         return array.getSize();
+      }
+
+      @Override
+      public void set(Value val) {
+         array.setSize((RValue) val);
+      }
+
+   }
+
+   /** A variable/constant referenced inside inline ASM. */
+   class ProgramValueAsmReferenced implements ProgramValue {
+      private StatementAsm statementAsm;
+      private String label;
+
+      ProgramValueAsmReferenced(StatementAsm statementAsm, String label) {
+         this.statementAsm = statementAsm;
+         this.label = label;
+      }
+
+      @Override
+      public Value get() {
+         return statementAsm.getReferenced().get(label);
+      }
+
+      @Override
+      public void set(Value value) {
+         statementAsm.getReferenced().put(label, (SymbolVariableRef) value);
+      }
+   }
+
+   /**
+    * Value inside a noop cast.
+    */
+   class ProgramValueCastValue implements ProgramValue {
+      private final CastValue castValue;
+
+
+      public ProgramValueCastValue(CastValue castValue) {
+         this.castValue = castValue;
+      }
+
+      @Override
+      public Value get() {
+         return castValue.getValue();
+      }
+
+      @Override
+      public void set(Value val) {
+         castValue.setValue((RValue) val);
+      }
+
+   }
+
+   class ProgramValueConstantArrayElement implements ProgramValue {
+      private final ConstantArrayList arrayList;
+      private final int idx;
+
+      ProgramValueConstantArrayElement(ConstantArrayList arrayList, int idx) {
+         this.arrayList = arrayList;
+         this.idx = idx;
+      }
+
+      @Override
+      public Value get() {
+         return arrayList.getElements().get(idx);
+      }
+
+      @Override
+      public void set(Value value) {
+         arrayList.getElements().set(idx, (ConstantValue) value);
+      }
+   }
+
+   /** Value inside a constant array filled expression. */
+   class ProgramValueConstantArrayFilledSize implements ProgramValue {
+      private final ConstantArrayFilled array;
+
+      ProgramValueConstantArrayFilledSize(ConstantArrayFilled array) {
+         this.array = array;
+      }
+
+      @Override
+      public Value get() {
+         return array.getSize();
+      }
+
+      @Override
+      public void set(Value val) {
+         array.setSize((ConstantValue) val);
+      }
+
+   }
+
+   /** Left value inside a constant binary expression. */
+   class ProgramValueConstantBinaryLeft implements ProgramValue {
+      private final ConstantBinary binary;
+
+      ProgramValueConstantBinaryLeft(ConstantBinary binary) {
+         this.binary = binary;
+      }
+
+      @Override
+      public Value get() {
+         return binary.getLeft();
+      }
+
+      @Override
+      public void set(Value val) {
+         binary.setLeft((ConstantValue) val);
+      }
+
+   }
+
+   /** Right value inside a constant binary expression. */
+   class ProgramValueConstantBinaryRight implements ProgramValue {
+      private final ConstantBinary binary;
+
+      ProgramValueConstantBinaryRight(ConstantBinary range) {
+         this.binary = range;
+      }
+
+      @Override
+      public Value get() {
+         return binary.getRight();
+      }
+
+      @Override
+      public void set(Value val) {
+         binary.setRight((ConstantValue) val);
+      }
+
+   }
+
+   /**
+    * Value inside a constant noop cast.
+    */
+   class ProgramValueConstantCastValue implements ProgramValue {
+      private final ConstantCastValue castValue;
+
+
+      ProgramValueConstantCastValue(ConstantCastValue castValue) {
+         this.castValue = castValue;
+      }
+
+      @Override
+      public Value get() {
+         return castValue.getValue();
+      }
+
+      @Override
+      public void set(Value val) {
+         castValue.setValue((ConstantValue) val);
+      }
+
+   }
+
+   /**
+    * Pointer inside a variable pointer.
+    */
+   class ProgramValueConstantSymbolPointerTo implements ProgramValue {
+      private final ConstantSymbolPointer varPointer;
+
+
+      ProgramValueConstantSymbolPointerTo(ConstantSymbolPointer varPointer) {
+         this.varPointer = varPointer;
+      }
+
+      @Override
+      public Value get() {
+         return varPointer.getToSymbol();
+      }
+
+      @Override
+      public void set(Value val) {
+         varPointer.setToSymbol((VariableRef) val);
+      }
+
+   }
+
+   /** Value inside a constant unary expression. */
+   class ProgramValueConstantUnaryValue implements ProgramValue {
+      private final ConstantUnary unary;
+
+      ProgramValueConstantUnaryValue(ConstantUnary unary) {
+         this.unary = unary;
+      }
+
+      @Override
+      public Value get() {
+         return unary.getOperand();
+      }
+
+      @Override
+      public void set(Value val) {
+         unary.setOperand((ConstantValue) val);
+      }
+
+   }
+
+   class ProgramValueConstantVar implements ProgramValue {
+      private final ConstantVar constantVar;
+
+      ProgramValueConstantVar(ConstantVar constantVar) {
+         this.constantVar = constantVar;
+      }
+
+      @Override
+      public Value get() {
+         return constantVar.getValue();
+      }
+
+      @Override
+      public void set(Value val) {
+         constantVar.setValue((ConstantValue) val);
+      }
+
+   }
+
+   /** Bytes inside inline kickasm code. */
+   class ProgramValueKickAsmBytes implements ProgramValue {
+
+      private StatementKickAsm statementKickAsm;
+
+      ProgramValueKickAsmBytes(StatementKickAsm statementKickAsm) {
+         this.statementKickAsm = statementKickAsm;
+      }
+
+      @Override
+      public Value get() {
+         return statementKickAsm.getBytes();
+      }
+
+      @Override
+      public void set(Value value) {
+         statementKickAsm.setBytes((RValue) value);
+      }
+
+   }
+
+   /** Cycles inside inline kickasm code. */
+   class ProgramValueKickAsmCycles implements ProgramValue {
+
+      private StatementKickAsm statementKickAsm;
+
+      ProgramValueKickAsmCycles(StatementKickAsm statementKickAsm) {
+         this.statementKickAsm = statementKickAsm;
+      }
+
+      @Override
+      public Value get() {
+         return statementKickAsm.getCycles();
+      }
+
+      @Override
+      public void set(Value value) {
+         statementKickAsm.setCycles((RValue) value);
+      }
+
+   }
+
+   /** Location inside inline kickasm code. */
+   class ProgramValueKickAsmLocation implements ProgramValue {
+
+      private StatementKickAsm statementKickAsm;
+
+      ProgramValueKickAsmLocation(StatementKickAsm statementKickAsm) {
+         super();
+         this.statementKickAsm = statementKickAsm;
+      }
+
+      @Override
+      public Value get() {
+         return statementKickAsm.getLocation();
+      }
+
+      @Override
+      public void set(Value value) {
+         statementKickAsm.setLocation((RValue) value);
+      }
+
+   }
+
+   class ProgramValueListElement implements ProgramValue {
+      private ValueList list;
+      private int idx;
+
+      ProgramValueListElement(ValueList list, int idx) {
+         this.list = list;
+         this.idx = idx;
+      }
+
+      @Override
+      public Value get() {
+         return list.getList().get(idx);
+      }
+
+      @Override
+      public void set(Value value) {
+         list.getList().set(idx, (RValue) value);
+      }
+
+   }
+
+   /**
+    * LValue as part of an assignment statement (or a call).
+    */
+   class ProgramValueLValue implements ProgramValue {
+      private final StatementLValue statement;
+
+      public ProgramValueLValue(StatementLValue statement) {
+         this.statement = statement;
+      }
+
+      @Override
+      public Value get() {
+         return statement.getlValue();
+      }
+
+      @Override
+      public void set(Value value) {
+         statement.setlValue((LValue) value);
+      }
+
+   }
+
+   /** Value inside an intermediate LValue. */
+   class ProgramValueLValueIntermediateVariable implements ProgramValue {
+      private final LvalueIntermediate intermediate;
+
+      ProgramValueLValueIntermediateVariable(LvalueIntermediate intermediate) {
+         this.intermediate = intermediate;
+      }
+
+      @Override
+      public Value get() {
+         return intermediate.getVariable();
+      }
+
+      @Override
+      public void set(Value val) {
+         intermediate.setVariable((VariableRef) val);
+      }
+
+   }
+
+   /**
+    * Pointer inside a pointer dererence value.
+    */
+   class ProgramValuePointer implements ProgramValue {
+      private final PointerDereference pointer;
+
+      ProgramValuePointer(PointerDereference pointer) {
+         this.pointer = pointer;
+      }
+
+      @Override
+      public Value get() {
+         return pointer.getPointer();
+      }
+
+      @Override
+      public void set(Value val) {
+         pointer.setPointer((RValue) val);
+      }
+
+   }
+
+   /**
+    * Pointer index inside a indexed pointer dererence value.
+    */
+   class ProgramValuePointerIndex implements ProgramValue {
+      private final PointerDereferenceIndexed pointer;
+
+      ProgramValuePointerIndex(PointerDereferenceIndexed pointer) {
+         this.pointer = pointer;
+      }
+
+      @Override
+      public Value get() {
+         return pointer.getIndex();
+      }
+
+      @Override
+      public void set(Value val) {
+         pointer.setIndex((RValue) val);
+      }
+
+   }
+
+   /**
+    * First value inside a ranged comparison value.
+    */
+   class ProgramValueRangeFirst implements ProgramValue {
+      private final RangeValue range;
+
+      ProgramValueRangeFirst(RangeValue range) {
+         this.range = range;
+      }
+
+      @Override
+      public Value get() {
+         return range.getRangeFirst();
+      }
+
+      @Override
+      public void set(Value val) {
+         range.setRangeFirst((RValue) val);
+      }
+
+   }
+
+   /**
+    * Last value inside inside a ranged comparison value.
+    */
+   class ProgramValueRangeLast implements ProgramValue {
+      private final RangeValue range;
+
+      ProgramValueRangeLast(RangeValue range) {
+         this.range = range;
+      }
+
+      @Override
+      public Value get() {
+         return range.getRangeLast();
+      }
+
+      @Override
+      public void set(Value val) {
+         range.setRangeLast((RValue) val);
+      }
+
+   }
+
+   /** Size inside a fixed size array. */
+   class ProgramValueTypeArraySize implements ProgramValue {
+      private final SymbolTypeArray array;
+
+      ProgramValueTypeArraySize(SymbolTypeArray array) {
+         this.array = array;
+      }
+
+      @Override
+      public Value get() {
+         return array.getSize();
+      }
+
+      @Override
+      public void set(Value val) {
+         array.setSize((RValue) val);
+      }
+
+   }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java
index 7ca0243de..6fe274204 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java
@@ -50,10 +50,10 @@ public class ProgramValueIterator {
     */
    public static void execute(SymbolVariable symbolVariable, ProgramValueHandler programValueHandler) {
       if(symbolVariable.getType() instanceof SymbolTypeArray) {
-         execute(new ProgramValue.TypeArraySize((SymbolTypeArray) symbolVariable.getType()), programValueHandler, null, null, null);
+         execute(new ProgramValue.ProgramValueTypeArraySize((SymbolTypeArray) symbolVariable.getType()), programValueHandler, null, null, null);
       }
       if(symbolVariable instanceof ConstantVar) {
-         execute(new ProgramValue.ConstantVariableValue((ConstantVar) symbolVariable), programValueHandler, null, null, null);
+         execute(new ProgramValue.ProgramValueConstantVar((ConstantVar) symbolVariable), programValueHandler, null, null, null);
       }
    }
 
@@ -98,7 +98,7 @@ public class ProgramValueIterator {
          // The sequence RValue1, RValue2, LValue is important - as it is essential for {@link dk.camelot64.kickc.passes.Pass1GenerateSingleStaticAssignmentForm} to create the correct SSA
          execute(new ProgramValue.RValue1((StatementAssignment) statement), handler, statement, statementsIt, block);
          execute(new ProgramValue.RValue2((StatementAssignment) statement), handler, statement, statementsIt, block);
-         execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
+         execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block);
       } else if(statement instanceof StatementCall) {
          StatementCall call = (StatementCall) statement;
          if(call.getParameters() != null) {
@@ -107,7 +107,7 @@ public class ProgramValueIterator {
                execute(new ProgramValue.CallParameter(call, i), handler, statement, statementsIt, block);
             }
          }
-         execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
+         execute(new ProgramValue.ProgramValueLValue((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);
@@ -117,7 +117,7 @@ public class ProgramValueIterator {
                execute(new ProgramValue.CallPointerParameter(call, i), handler, statement, statementsIt, block);
             }
          }
-         execute(new ProgramValue.LValue((StatementLValue) statement), handler, statement, statementsIt, block);
+         execute(new ProgramValue.ProgramValueLValue((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);
@@ -137,15 +137,15 @@ public class ProgramValueIterator {
          StatementKickAsm statementKickAsm = (StatementKickAsm) statement;
          RValue location = statementKickAsm.getLocation();
          if(location!=null) {
-            execute(new ProgramValue.KickAsmLocation(statementKickAsm), handler, statement, statementsIt, block);
+            execute(new ProgramValue.ProgramValueKickAsmLocation(statementKickAsm), handler, statement, statementsIt, block);
          }
          RValue bytes = statementKickAsm.getLocation();
          if(bytes!=null) {
-            execute(new ProgramValue.KickAsmBytes(statementKickAsm), handler, statement, statementsIt, block);
+            execute(new ProgramValue.ProgramValueKickAsmBytes(statementKickAsm), handler, statement, statementsIt, block);
          }
          RValue cycles = statementKickAsm.getLocation();
          if(cycles!=null) {
-            execute(new ProgramValue.KickAsmCycles(statementKickAsm), handler, statement, statementsIt, block);
+            execute(new ProgramValue.ProgramValueKickAsmCycles(statementKickAsm), handler, statement, statementsIt, block);
          }
          List<SymbolVariableRef> uses = statementKickAsm.getUses();
          for(int i = 0; i < uses.size(); i++) {
@@ -155,7 +155,7 @@ public class ProgramValueIterator {
          StatementAsm statementAsm = (StatementAsm) statement;
          Map<String, SymbolVariableRef> referenced = statementAsm.getReferenced();
          for(String label : referenced.keySet()) {
-            execute(new ProgramValue.AsmReferenced(statementAsm, label), handler, statement, statementsIt, block);
+            execute(new ProgramValue.ProgramValueAsmReferenced(statementAsm, label), handler, statement, statementsIt, block);
          }
       }
    }
@@ -182,42 +182,42 @@ public class ProgramValueIterator {
    private static Collection<ProgramValue> getSubValues(Value value) {
       ArrayList<ProgramValue> subValues = new ArrayList<>();
       if(value instanceof PointerDereferenceIndexed) {
-         subValues.add(new ProgramValue.Pointer((PointerDereference) value));
-         subValues.add(new ProgramValue.PointerIndex((PointerDereferenceIndexed) value));
+         subValues.add(new ProgramValue.ProgramValuePointer((PointerDereference) value));
+         subValues.add(new ProgramValue.ProgramValuePointerIndex((PointerDereferenceIndexed) value));
       } else if(value instanceof PointerDereferenceSimple) {
-         subValues.add(new ProgramValue.Pointer((PointerDereference) value));
+         subValues.add(new ProgramValue.ProgramValuePointer((PointerDereference) value));
       } else if(value instanceof ValueList) {
          ValueList valueList = (ValueList) value;
          int size = valueList.getList().size();
          for(int i = 0; i < size; i++) {
-            subValues.add(new ProgramValue.ListElement(valueList, i));
+            subValues.add(new ProgramValue.ProgramValueListElement(valueList, i));
          }
       } else if(value instanceof ConstantArrayList) {
          ConstantArrayList constantArrayList = (ConstantArrayList) value;
          int size = constantArrayList.getElements().size();
          for(int i = 0; i < size; i++) {
-            subValues.add(new ProgramValue.ConstantArrayElement(constantArrayList, i));
+            subValues.add(new ProgramValue.ProgramValueConstantArrayElement(constantArrayList, i));
          }
       } else if(value instanceof CastValue) {
-         subValues.add(new ProgramValue.CastValue((CastValue) value));
+         subValues.add(new ProgramValue.ProgramValueCastValue((CastValue) value));
       } else if(value instanceof ConstantCastValue) {
-         subValues.add(new ProgramValue.ConstantCastValue((ConstantCastValue) value));
+         subValues.add(new ProgramValue.ProgramValueConstantCastValue((ConstantCastValue) value));
       } else if(value instanceof ConstantSymbolPointer) {
-         subValues.add(new ProgramValue.ConstantSymbolPointerTo((ConstantSymbolPointer) value));
+         subValues.add(new ProgramValue.ProgramValueConstantSymbolPointerTo((ConstantSymbolPointer) value));
       } else if(value instanceof RangeValue) {
-         subValues.add(new ProgramValue.RangeFirst((RangeValue) value));
-         subValues.add(new ProgramValue.RangeLast((RangeValue) value));
+         subValues.add(new ProgramValue.ProgramValueRangeFirst((RangeValue) value));
+         subValues.add(new ProgramValue.ProgramValueRangeLast((RangeValue) value));
       } else if(value instanceof ConstantBinary) {
-         subValues.add(new ProgramValue.ConstantBinaryLeft((ConstantBinary) value));
-         subValues.add(new ProgramValue.ConstantBinaryRight((ConstantBinary) value));
+         subValues.add(new ProgramValue.ProgramValueConstantBinaryLeft((ConstantBinary) value));
+         subValues.add(new ProgramValue.ProgramValueConstantBinaryRight((ConstantBinary) value));
       } else if(value instanceof ConstantUnary) {
-         subValues.add(new ProgramValue.ConstantUnaryValue((ConstantUnary) value));
+         subValues.add(new ProgramValue.ProgramValueConstantUnaryValue((ConstantUnary) value));
       } else if(value instanceof ArrayFilled) {
-         subValues.add(new ProgramValue.ArrayFilledSize((ArrayFilled) value));
+         subValues.add(new ProgramValue.ProgramValueArrayFilledSize((ArrayFilled) value));
       } else if(value instanceof ConstantArrayFilled) {
-         subValues.add(new ProgramValue.ConstantArrayFilledSize((ConstantArrayFilled) value));
+         subValues.add(new ProgramValue.ProgramValueConstantArrayFilledSize((ConstantArrayFilled) value));
       } else if(value instanceof LvalueIntermediate) {
-         subValues.add(new ProgramValue.LValueIntermediateVariable((LvalueIntermediate) value));
+         subValues.add(new ProgramValue.ProgramValueLValueIntermediateVariable((LvalueIntermediate) value));
       } else if(value == null ||
             value instanceof VariableRef ||
             value instanceof ProcedureRef ||
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
index 022611a5b..e7906ff6f 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
@@ -1,10 +1,7 @@
 package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
+import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -34,7 +31,7 @@ public class OperatorBitwiseAnd extends OperatorBinary {
       }
       // Handle numeric types
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
       }
 
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
index cad932fb1..3e6a46208 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
@@ -31,7 +31,7 @@ public class OperatorBitwiseOr extends OperatorBinary {
       }
       // Handle numeric types
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
       }
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
index b383ac3f0..2d614f2ab 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
@@ -31,7 +31,7 @@ public class OperatorBitwiseXor extends OperatorBinary {
       }
       // Handle numeric types
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
       }
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCast.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCast.java
new file mode 100644
index 000000000..8783a1e60
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCast.java
@@ -0,0 +1,18 @@
+package dk.camelot64.kickc.model.operators;
+
+import dk.camelot64.kickc.model.types.SymbolType;
+
+/** Abstract cast operator. */
+public abstract class OperatorCast extends OperatorUnary {
+
+   private SymbolType toType;
+
+   public OperatorCast(String operator, String asmOperator, int precedence, SymbolType toType) {
+      super(operator, asmOperator, precedence);
+      this.toType = toType;
+   }
+
+   public SymbolType getToType() {
+      return toType;
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java
index cb1c8a00e..24b02a921 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java
@@ -9,10 +9,10 @@ import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
 
 /** Unary Cast to boolean operator ( (boolean) x ) */
-public class OperatorCastBool extends OperatorUnary {
+public class OperatorCastBool extends OperatorCast  {
 
    public OperatorCastBool(int precedence) {
-      super("((bool))", "_bool_", precedence);
+      super("((bool))", "_bool_", precedence, SymbolType.BOOLEAN);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
index ea24ee803..b00ba311a 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
@@ -9,10 +9,10 @@ import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
 
 /** Unary Cast to byte operator ( (byte) x ) */
-public class OperatorCastByte extends OperatorUnary {
+public class OperatorCastByte extends OperatorCast {
 
    public OperatorCastByte(int precedence) {
-      super("((byte))", "_byte_", precedence);
+      super("((byte))", "_byte_", precedence, SymbolType.BYTE);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
index af76dbff4..111b94b7a 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
@@ -9,10 +9,10 @@ import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
 
 /** Unary Cast to double word operator ( (dword) x ) */
-public class OperatorCastDWord extends OperatorUnary {
+public class OperatorCastDWord extends OperatorCast {
 
    public OperatorCastDWord(int precedence) {
-      super("((dword))", "_dword_", precedence);
+      super("((dword))", "_dword_", precedence, SymbolType.DWORD);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java
index 33215cfdb..142ecc533 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java
@@ -10,12 +10,12 @@ import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
 
 /** Unary Cast to a pointer ( type* ) */
-public class OperatorCastPtr extends OperatorUnary {
+public class OperatorCastPtr extends OperatorCast {
 
    private final SymbolType elementType;
 
    public OperatorCastPtr(int precedence, SymbolType elementType) {
-      super("((" + elementType.toString() + "*))", "_ptr_", precedence);
+      super("((" + elementType.toString() + "*))", "_ptr_", precedence, new SymbolTypePointer(elementType));
       this.elementType = elementType;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
index d81cf7414..9487eae97 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
@@ -8,10 +8,10 @@ import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Unary Cast to signed byte operator ( (signed byte) x ) */
-public class OperatorCastSByte extends OperatorUnary {
+public class OperatorCastSByte extends OperatorCast {
 
    public OperatorCastSByte(int precedence) {
-      super("((signed byte))", "_sbyte_", precedence);
+      super("((signed byte))", "_sbyte_", precedence, SymbolType.SBYTE);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
index a07c5cd38..6ec765ca7 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
@@ -8,10 +8,10 @@ import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Unary Cast to signed double word operator ( (signed dword) x ) */
-public class OperatorCastSDWord extends OperatorUnary {
+public class OperatorCastSDWord extends OperatorCast {
 
    public OperatorCastSDWord(int precedence) {
-      super("((signed dword))", "_sdword_", precedence);
+      super("((signed dword))", "_sdword_", precedence, SymbolType.SDWORD);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
index 094be277d..b8a618979 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
@@ -8,10 +8,10 @@ import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Unary Cast to signed word operator ( (signed word) x ) */
-public class OperatorCastSWord extends OperatorUnary {
+public class OperatorCastSWord extends OperatorCast {
 
    public OperatorCastSWord(int precedence) {
-      super("((signed word))", "_sword_", precedence);
+      super("((signed word))", "_sword_", precedence, SymbolType.SWORD);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
index f84aec9f0..0b1097086 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
@@ -9,10 +9,10 @@ import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
 
 /** Unary Cast to word operator ( (word) x ) */
-public class OperatorCastWord extends OperatorUnary {
+public class OperatorCastWord extends OperatorCast {
 
    public OperatorCastWord(int precedence) {
-      super("((word))", "_word_", precedence);
+      super("((word))", "_word_", precedence, SymbolType.WORD);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
index 2a4058f16..3ce383230 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
@@ -38,7 +38,7 @@ public class OperatorDivide extends OperatorBinary {
       }
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
-         return SymbolType.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right);
+         return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right);
       }
 
       throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
index c06f6b938..ce472ffd7 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
@@ -38,7 +38,7 @@ public class OperatorMinus extends OperatorBinary {
       }
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
       }
       throw new RuntimeException("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
index 2931f6db1..4fc0a3388 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
@@ -27,7 +27,7 @@ public class OperatorModulo extends OperatorBinary {
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
-         return SymbolType.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
+         return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
       }
       if(left instanceof ConstantPointer && right instanceof ConstantInteger) {
          return ((ConstantInteger) right).getType();
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
index 7c3894bb5..76bb36ec6 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
@@ -1,10 +1,7 @@
 package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
-import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
+import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -27,7 +24,7 @@ public class OperatorMultiply extends OperatorBinary {
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
-         return SymbolType.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
+         return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
       }
       throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
index f4f6e0ec7..00844a779 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
@@ -46,7 +46,7 @@ public class OperatorPlus extends OperatorBinary {
       }
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolType.convertedMathType( (SymbolTypeInteger) type1, (SymbolTypeInteger)type2);
+         return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) type1, (SymbolTypeInteger)type2);
       }
 
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
index d50decce2..173ab0e8c 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
@@ -159,4 +159,5 @@ public class Operators {
       }
    }
 
+
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
index 685017e26..2d6c20a6b 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
@@ -1,10 +1,5 @@
 package dk.camelot64.kickc.model.types;
 
-import dk.camelot64.kickc.model.CompileError;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
 /** Symbol Types */
 public interface SymbolType {
 
@@ -91,6 +86,8 @@ public interface SymbolType {
             return BOOLEAN;
          case "void":
             return VOID;
+         case "number":
+            return NUMBER;
       }
       return null;
    }
@@ -105,7 +102,7 @@ public interface SymbolType {
 
    /**
     * Get the size of the type (in bytes).
-    * @return The size
+    * @return The size. -1 if the type is compile-time only.
     */
    int getSizeBytes();
 
@@ -215,74 +212,4 @@ public interface SymbolType {
       return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type);
    }
 
-   /**
-    * Get all integer types.
-    *
-    * @return All integeer types
-    */
-   static Collection<SymbolTypeIntegerFixed> getIntegerFixedTypes() {
-      ArrayList<SymbolTypeIntegerFixed> types = new ArrayList<>();
-      types.add(BYTE);
-      types.add(SBYTE);
-      types.add(WORD);
-      types.add(SWORD);
-      types.add(DWORD);
-      types.add(SDWORD);
-      return types;
-   }
-
-   /**
-    * Find the integer type that results from a binary operator according to C99 6.3.1.8
-    * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70
-    *
-    * @param type1 Left type in a binary expression
-    * @param type2 Right type in a binary expression
-    * @return The type resulting from a binary operator performed on the two parameters
-    */
-   static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) {
-      if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) {
-         return NUMBER;
-      }
-      SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1;
-      SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2;
-      // C99 6.3.1.8 a. If two operands have the same type no conversion is performed
-      if(type1.equals(type2))
-         return type1;
-      // C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword)
-      if(fixed1.isSigned()==fixed2.isSigned())
-         return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2;
-      // C99 6.3.1.8 c. One is signed and one unsigned.
-      // If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword).
-      SymbolTypeIntegerFixed typeS, typeU;
-      if(fixed1.isSigned()) {
-         typeS = fixed1;
-         typeU = fixed2;
-      }  else {
-         typeS = fixed2;
-         typeU = fixed1;
-      }
-      if(typeS.getBits()>typeU.getBits())
-         return typeS;
-      // C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type.
-      // The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value
-      // (sbyte->byte, sbyte->word, sbyte->dword, sword->word, sword->dword, sdword->dword).
-      return typeU;
-   }
-
-   /**
-    * Find the unsigned integer type that contains both sub-types usable for binary operations ( & | ^ ).
-    *
-    * @param type1 Left type in a binary expression
-    * @param type2 Right type in a binary expression
-    * @return
-    */
-   static SymbolType promotedBitwiseType(SymbolTypeIntegerFixed type1, SymbolTypeIntegerFixed type2) {
-      for(SymbolTypeIntegerFixed candidate : getIntegerFixedTypes()) {
-         if(!candidate.isSigned() && type1.getBits()<=candidate.getBits() && type2.getBits()<=candidate.getBits()) {
-            return candidate;
-         }
-      }
-      throw new CompileError("Cannot promote to a common type for "+type1.toString()+" and "+type2.toString());
-   }
-
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
new file mode 100644
index 000000000..7b93fa1de
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -0,0 +1,134 @@
+package dk.camelot64.kickc.model.types;
+
+import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.InternalError;
+import dk.camelot64.kickc.model.statements.Statement;
+import dk.camelot64.kickc.model.symbols.ProgramScope;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.ConstantLiteral;
+import dk.camelot64.kickc.model.values.ConstantValue;
+import dk.camelot64.kickc.model.values.RValue;
+
+/**
+ * Rules for converting integer types.
+ *
+ * Integer conversion implements C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70
+ *
+ * The special number type is converted as described here https://gitlab.com/camelot/kickc/issues/181
+ * 
+ */
+public class SymbolTypeConversion {
+
+   /**
+    * Find the integer type that results from a binary operator according to C99 6.3.1.8
+    * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70
+    *
+    * @param type1 Left type in a binary expression
+    * @param type2 Right type in a binary expression
+    * @return The type resulting from a binary operator performed on the two parameters
+    */
+   public static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) {
+      if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) {
+         return SymbolType.NUMBER;
+      }
+      SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1;
+      SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2;
+      // C99 6.3.1.8 a. If two operands have the same type no conversion is performed
+      if(type1.equals(type2))
+         return type1;
+      // C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword)
+      if(fixed1.isSigned()==fixed2.isSigned())
+         return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2;
+      // C99 6.3.1.8 c. One is signed and one unsigned.
+      // If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword).
+      SymbolTypeIntegerFixed typeS, typeU;
+      if(fixed1.isSigned()) {
+         typeS = fixed1;
+         typeU = fixed2;
+      }  else {
+         typeS = fixed2;
+         typeU = fixed1;
+      }
+      if(typeS.getBits()>typeU.getBits())
+         return typeS;
+      // C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type.
+      // The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value
+      // (sbyte->byte, sbyte->word, sbyte->dword, sword->word, sword->dword, sdword->dword).
+      return typeU;
+   }
+
+   /**
+    * Find the integer type that results from a binary operator according to the special number type conversion https://gitlab.com/camelot/kickc/issues/181
+    * @param left The left value
+    * @param right The right value
+    * @param symbols The program scope symbols (used for looking up symbols and constants)
+    * @param currentStmt The current statement (used only for exception context)
+    * @return a non-null fixed integer type if a number type conversion is relevant.
+    */
+   public static SymbolType convertedNumberType(RValue left, RValue right, ProgramScope symbols, Statement currentStmt) {
+
+      SymbolType leftType = SymbolTypeInference.inferType(symbols, left);
+      SymbolType rightType = SymbolTypeInference.inferType(symbols, right);
+
+      if(SymbolType.NUMBER.equals(leftType) || SymbolType.NUMBER.equals(rightType)) {
+         // A special type number is assigned to integer constants without a postfix literal.
+         // Numbers are flexible and will take a type based on their actual value when they meet a typed number in a calculation.
+         // Number types are only usable at compile time.
+
+         if(leftType.equals(rightType)) {
+            // a) If the two operands are numbers the result is a number
+            return null;
+         }
+
+         RValue numberVal;
+         SymbolTypeIntegerFixed fixedType;
+         if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) {
+            // Left is the number type - right is the fixed type
+            numberVal = left;
+            fixedType = (SymbolTypeIntegerFixed) rightType;
+         } else if(SymbolType.NUMBER.equals(rightType) && SymbolType.isInteger(leftType)) {
+            // Right is the number type - left is the fixed type
+            numberVal = right;
+            fixedType = (SymbolTypeIntegerFixed) leftType;
+         } else {
+            // Binary operator combining number and non-integer
+            throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt);
+         }
+
+         if(numberVal instanceof ConstantValue) {
+            ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols);
+            if(constantLiteral instanceof ConstantInteger) {
+               ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
+               if(SymbolType.NUMBER.equals(constantInteger.getType())) {
+                  Long value = constantInteger.getValue();
+                  if(fixedType.isSigned()) {
+                     // b) If one operand is a signed type and the other a number they are both converted to the smallest signed type that can hold the values.
+                     SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value);
+                     if(smallestSignedType == null) {
+                        throw new CompileError("Number constant has value that cannot be represented by a signed type " + value, currentStmt);
+                     }
+                     return smallestSignedType.getBits() > fixedType.getBits() ? smallestSignedType : fixedType;
+                  } else {
+                     // c) If one operand is an unsigned type and the other a number they are both converted to the smallest unsigned type that can hold the values.
+                     //    If the number value is negative it is converted to unsigned using two's complement.
+                     SymbolTypeIntegerFixed smallestUnsignedType;
+                     if(value < 0) {
+                        smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value);
+                     } else {
+                        smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
+                     }
+                     return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType;
+                  }
+               } else {
+                  throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
+               }
+            }
+         } else {
+            // Postpone til later!
+            return null;
+         }
+      }
+      // No number conversion
+      return null;
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java
index 1c6a35cc5..42f4a2659 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeIntegerFixed.java
@@ -1,5 +1,8 @@
 package dk.camelot64.kickc.model.types;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 /** Integer type with a fixed size (byte, signed byte, word, ...). */
 public class SymbolTypeIntegerFixed implements SymbolTypeInteger {
 
@@ -17,6 +20,58 @@ public class SymbolTypeIntegerFixed implements SymbolTypeInteger {
       this.bits = bits;
    }
 
+   /**
+    * Get all fixed size integer types.
+    *
+    * @return All fixed size integer types
+    */
+   public static Collection<SymbolTypeIntegerFixed> getIntegerFixedTypes() {
+      ArrayList<SymbolTypeIntegerFixed> types = new ArrayList<>();
+      types.add(BYTE);
+      types.add(SBYTE);
+      types.add(WORD);
+      types.add(SWORD);
+      types.add(DWORD);
+      types.add(SDWORD);
+      return types;
+   }
+   /**
+    * Find the smallest signed type that can hold the passed value
+    * @param value The value
+    * @return The smallest signed type that can hold the value
+    */
+   public static SymbolTypeIntegerFixed getSmallestSigned(Long value) {
+      for(SymbolTypeIntegerFixed fixedType : getIntegerFixedTypes()) {
+         if(fixedType.isSigned() && fixedType.contains(value))
+            return fixedType;
+      }
+      return null;
+   }
+
+   /**
+    * Find the smallest unsigned type that can hold the passed value
+    * @param value The value
+    * @return The smallest unsigned type that can hold the value
+    */
+   public static SymbolTypeIntegerFixed getSmallestUnsigned(Long value) {
+      for(SymbolTypeIntegerFixed fixedType : getIntegerFixedTypes()) {
+         if(!fixedType.isSigned() && fixedType.contains(value))
+            return fixedType;
+      }
+      return null;
+   }
+
+
+   /**
+    * Determines if a value can be represented by the type without loss of information
+    *
+    * @param value The value to examine
+    * @return true if the type contains the value
+    */
+   public boolean contains(Long number) {
+      return number >= getMinValue() && number <= getMaxValue();
+   }
+
    @Override
    public String getTypeName() {
       return typeName;
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
index ced732cb9..f3438573e 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
@@ -26,22 +26,6 @@ public class SymbolTypeMulti implements SymbolType {
       return types;
    }
 
-
-   /**
-    * Get the multi-type that can contain the passed number.
-    * @param number The number
-    * @return The multi-type
-    */
-   public static SymbolType getMultiType(Long number) {
-      ArrayList<SymbolType> potentialTypes = new ArrayList<>();
-      for(SymbolTypeIntegerFixed typeInteger : SymbolType.getIntegerFixedTypes()) {
-         if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) {
-            potentialTypes.add(typeInteger);
-         }
-      }
-      return new SymbolTypeMulti(potentialTypes);
-   }
-
    @Override
    public int getSizeBytes() {
       // Find the minimal sizeof - and return that
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
index 7473e4230..4967f0bfa 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
@@ -90,8 +90,8 @@ public class SymbolTypeNumberInference {
          ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>();
          ConstantInteger constantInteger = (ConstantInteger) literal;
          Long number = constantInteger.getValue();
-         for(SymbolTypeIntegerFixed typeInteger : SymbolType.getIntegerFixedTypes()) {
-            if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) {
+         for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) {
+            if(typeInteger.contains(number)) {
                potentialTypes.add(typeInteger);
             }
          }
diff --git a/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java b/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java
index 6222c6fd2..36cb5d6ea 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/AssignmentRValue.java
@@ -3,7 +3,7 @@ package dk.camelot64.kickc.model.values;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 
-/** The "total" RValue of an assigment. */
+/** The "total" RValue of an assignment. */
 public class AssignmentRValue implements RValue {
 
    private StatementAssignment assignment;
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java
index db834cb48..b1f4777da 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java
@@ -96,7 +96,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
                programValue.set(version.getRef());
             }
             // Update map of versions encountered in the block
-            if(currentStmt instanceof StatementAssignment && programValue instanceof ProgramValue.LValue) {
+            if(currentStmt instanceof StatementAssignment && programValue instanceof ProgramValue.ProgramValueLValue) {
                StatementAssignment assignment = (StatementAssignment) currentStmt;
                LValue lValue = assignment.getlValue();
                if(lValue instanceof VariableRef) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
new file mode 100644
index 000000000..a40c02fd0
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
@@ -0,0 +1,43 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpression;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
+import dk.camelot64.kickc.model.operators.OperatorCast;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.ConstantValue;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/** Simplifies casts of (number) constants to a type. */
+public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
+
+   public Pass2ConstantCastSimplification(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean optimized = new AtomicBoolean(false);
+      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(programExpression.getOperator() instanceof OperatorCast) {
+            OperatorCast operatorCast = (OperatorCast) programExpression.getOperator();
+            ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression;
+            if(unary.getOperand() instanceof ConstantInteger) {
+               ConstantInteger constantInteger = (ConstantInteger) unary.getOperand();
+               if(constantInteger.getType().equals(SymbolType.NUMBER)) {
+                  SymbolType castType = operatorCast.getToType();
+                  ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
+                  programExpression.set(newConstInt);
+                  getLog().append("Simplifying constant integer cast "+newConstInt);
+               }
+            }
+         }
+      });
+      return optimized.get();
+   }
+
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
index b12ad19ca..39d15dc0c 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -1,15 +1,11 @@
 package dk.camelot64.kickc.passes;
 
-import dk.camelot64.kickc.model.CompileError;
-import dk.camelot64.kickc.model.InternalError;
 import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.iterator.BinaryExpressionIterator;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
-import dk.camelot64.kickc.model.values.ConstantInteger;
-import dk.camelot64.kickc.model.values.ConstantLiteral;
-import dk.camelot64.kickc.model.values.ConstantValue;
 import dk.camelot64.kickc.model.values.RValue;
 
 /**
@@ -23,89 +19,29 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
 
    @Override
    public boolean step() {
-      BinaryExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
-         RValue left = binaryExpression.getLeft();
-         RValue right = binaryExpression.getRight();
-         SymbolType conversionType = getNumberConversionType(left, right);
-         if(conversionType != null) {
-            // Convert both left and right to the found type
-
-            getLog().append("Adding number conversion cast (" + fixedType+ ") " + binaryExpression.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
-
-
+      ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(binaryExpression instanceof ProgramExpressionBinary) {
+            ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression;
+            RValue left = binary.getLeft();
+            RValue right = binary.getRight();
+            SymbolType conversionType = SymbolTypeConversion.convertedNumberType(left, right, getScope(), currentStmt);
+            if(conversionType != null) {
+               // Convert both left and right to the found type
+               SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
+               if(!leftType.equals(conversionType)) {
+                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
+                  binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
+               }
+               SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
+               if(!rightType.equals(conversionType)) {
+                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
+                  binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
+               }
+            }
          }
-
       });
       return false;
    }
 
-   private SymbolType getNumberConversionType(RValue left, RValue right) {
-
-      SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
-      SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
-
-      if(SymbolType.NUMBER.equals(leftType) || SymbolType.NUMBER.equals(rightType)) {
-         // A special type number is assigned to integer constants without a postfix literal.
-         // Numbers are flexible and will take a type based on their actual value when they meet a typed number in a calculation.
-         // Number types are only usable at compile time.
-
-         if(leftType.equals(rightType)) {
-            // a) If the two operands are numbers the result is a number
-            return null;
-         }
-
-         RValue numberVal;
-         SymbolTypeIntegerFixed fixedType;
-         if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) {
-            // Left is the number
-            numberVal = left;
-            fixedType = (SymbolTypeIntegerFixed) rightType;
-         } else if(SymbolType.NUMBER.equals(rightType) && SymbolType.isInteger(leftType)) {
-            // Right is the number
-            numberVal = right;
-            fixedType = (SymbolTypeIntegerFixed) leftType;
-         } else {
-            // Non-integer number binary
-            throw new CompileError("Error! Incompatible operands "+left.toString()+" and "+right.toString());
-         }
-
-         if(numberVal instanceof ConstantValue) {
-            ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(getProgram().getScope());
-            if(constantLiteral instanceof ConstantInteger) {
-               ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
-               if(SymbolType.NUMBER.equals(constantInteger.getType())) {
-                  Long value = constantInteger.getValue();
-                  if(fixedType.getMinValue() <= value && fixedType.getMaxValue() >= value) {
-                     // The value matches the left type!
-                     binaryExpression.addRightCast(leftIntType);
-                  } else {
-                     throw new InternalError("TODO: Implement number conversion for non-equal types " + right.toString(), currentStmt);
-                  }
-               } else {
-                  throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
-               }
-            }
-         } else {
-            // Postpone til later!
-            // Maybe handle AssignmentRValue separately!
-            getLog().append("Postponed number conversion " + right.toString());
-         }
-
-
-
-
-      }
-
-      // No number conversion
-      return null;
-
-      if(SymbolType.isInteger(leftType) && !SymbolType.NUMBER.equals(leftType) && SymbolType.NUMBER.equals(rightType)) {
-         SymbolTypeIntegerFixed leftIntType = (SymbolTypeIntegerFixed) leftType;
-         // Attempt to find number conversion!
-      }
-
-      return null;
-   }
-
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
deleted file mode 100644
index 562d251f0..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversions.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.Comment;
-import dk.camelot64.kickc.model.CompileError;
-import dk.camelot64.kickc.model.ControlFlowBlock;
-import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.operators.Operators;
-import dk.camelot64.kickc.model.statements.Statement;
-import dk.camelot64.kickc.model.statements.StatementAssignment;
-import dk.camelot64.kickc.model.symbols.Scope;
-import dk.camelot64.kickc.model.symbols.VariableIntermediate;
-import dk.camelot64.kickc.model.types.*;
-import dk.camelot64.kickc.model.values.ConstantInteger;
-import dk.camelot64.kickc.model.values.LValue;
-import dk.camelot64.kickc.model.values.RValue;
-import dk.camelot64.kickc.model.values.ScopeRef;
-
-import java.util.List;
-import java.util.ListIterator;
-
-/**
- * Add casts in all assignments where types are not equal, but the rValue type can be converted to the lValue type.
- */
-public class PassNAddTypeConversions extends Pass2SsaOptimization {
-
-   public PassNAddTypeConversions(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
-         List<Statement> statements = block.getStatements();
-         ListIterator<Statement> stmtIt = statements.listIterator();
-         while(stmtIt.hasNext()) {
-            Statement statement = stmtIt.next();
-            if(statement instanceof StatementAssignment) {
-               doConversionAssignment((StatementAssignment) statement, stmtIt, block);
-            }
-            // TODO: Implement conversion for calls
-         }
-      }
-      return false;
-   }
-
-   /**
-    * Examines an assignment to determine if a cast of the rValue is needed (the lvalue type and the rvalue type is not equal)
-    * and possible (the types are conversion compatible).
-    * <p>
-    * If a conversion is needed it is added by adding a new tmp-var with a cast and modifying the statement.
-    *
-    * @param assignment The assignment to examine
-    * @param stmtIt Iterator allowing the method to add a tmp-var-assignment.
-    */
-   private void doConversionAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock block) {
-      LValue lValue = assignment.getlValue();
-      SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
-      SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), assignment);
-      if(lValueType.equals(rValueType)) {
-         return;
-      }
-      if(SymbolType.NUMBER.equals(rValueType)) {
-         // If the rValue is number type - find the potential types based on the literal value
-         List<SymbolTypeIntegerFixed> potentialTypes = SymbolTypeNumberInference.inferTypesRValue(getScope(), assignment);
-         if(potentialTypes.size()==0) {
-            // number type cannot be calculated currently - save for later
-            return;
-         }
-         for(SymbolTypeIntegerFixed potentialType : potentialTypes) {
-            if(lValueType.equals(potentialType) || canConvert(lValueType, potentialType)) {
-               addConversionCast(assignment, stmtIt, block, lValueType, rValueType);
-               return;
-            }
-         }
-      } else {
-         // No direct type match - attempt conversion
-         if(canConvert(lValueType, rValueType)) {
-            addConversionCast(assignment, stmtIt, block, lValueType, rValueType);
-            return;
-         }
-      }
-
-      // Conversion not possible - report a type error!
-      String msg = "ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). " +
-            "In " + assignment.toString(getProgram(), false);
-      getProgram().getLog().append(msg);
-      throw new CompileError(msg, assignment.getSource());
-   }
-
-   /**
-    * Add a conversion cast to the rvalue of an assignment
-    *
-    * @param assignment The assignment to add the cast to
-    * @param lValueType The type of the lValue
-    * @param rValueType The type of the rValue
-    */
-   private void addConversionCast(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, SymbolType lValueType, SymbolType rValueType) {
-      // Promotion possible - add tmp-var and a cast
-      if(assignment.getOperator() == null) {
-         // No operator - add cast directly!
-         RValue rValue = assignment.getrValue2();
-         if((rValue instanceof ConstantInteger) && SymbolType.NUMBER.equals(((ConstantInteger) rValue).getType()) && SymbolType.isInteger(lValueType)) {
-            ((ConstantInteger) rValue).setType(lValueType);
-         } else {
-            assignment.setOperator(Operators.getCastUnary(lValueType));
-         }
-         getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment);
-      } else {
-         ScopeRef currentScope = currentBlock.getScope();
-         Scope blockScope = getScope().getScope(currentScope);
-         VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
-         tmpVar.setType(rValueType);
-         StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(lValueType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
-         getLog().append("Converting " + rValueType + " to " + lValueType + " in " + assignment + " adding "+tmpVar);
-         assignment.setlValue(tmpVar.getRef());
-         stmtIt.add(newAssignment);
-      }
-   }
-
-   /**
-    * Determines if it is possible to convert one type to another
-    * as described in C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70
-    *
-    * @param lValueType The type of the lValue
-    * @param rValueType The type of the rValue (that will be cast)
-    * @return True if a cast is possible without any loss
-    */
-   private boolean canConvert(SymbolType lValueType, SymbolType rValueType) {
-      if(lValueType instanceof SymbolTypePointer && SymbolType.isWord(rValueType)) {
-         return true;
-      }
-      if(lValueType instanceof SymbolTypeInteger && rValueType instanceof SymbolTypeInteger) {
-         SymbolType convertedMathType = SymbolType.convertedMathType((SymbolTypeInteger) lValueType, (SymbolTypeInteger) rValueType);
-         if(lValueType.equals(convertedMathType)) {
-            return true;
-         }
-      }
-      // No type promotion found
-      return false;
-   }
-
-
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
new file mode 100644
index 000000000..fd47ffd3c
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
@@ -0,0 +1,55 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.types.*;
+import dk.camelot64.kickc.model.values.RValue;
+
+/**
+ * Add casts in binary expressions where left/right types are not equal according to the C99 type conversion rules
+ * 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70.
+ */
+public class PassNAddTypeConversionsNew extends Pass2SsaOptimization {
+
+   public PassNAddTypeConversionsNew(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(programExpression instanceof ProgramExpressionBinary) {
+            ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression;
+            RValue left = binary.getLeft();
+            RValue right = binary.getRight();
+            SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
+            SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
+
+            // Special handling of assigning a pointer from an unsigned word
+            if((programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) && (leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) {
+               getLog().append("Adding pointer type conversion cast (" + leftType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
+               binary.addLeftCast(leftType, stmtIt, currentBlock.getScope(), getScope());
+            }
+
+            if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) {
+               SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
+               if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) {
+                  // Convert both left and right to the found type
+                  if(!leftType.equals(conversionType)) {
+                     getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
+                     binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
+                  }
+                  if(!rightType.equals(conversionType)) {
+                     getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
+                     binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
+                  }
+               }
+            }
+         }
+      });
+      return false;
+   }
+
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
similarity index 52%
rename from src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java
rename to src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
index a1ffcf01a..43d47670d 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1TypeIdSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
@@ -1,50 +1,63 @@
 package dk.camelot64.kickc.passes;
 
-import dk.camelot64.kickc.model.ControlFlowBlock;
-import dk.camelot64.kickc.model.InternalError;
 import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
 import dk.camelot64.kickc.model.operators.OperatorTypeId;
 import dk.camelot64.kickc.model.operators.Operators;
-import dk.camelot64.kickc.model.statements.Statement;
-import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
-import dk.camelot64.kickc.model.types.SymbolTypeNumberInference;
-import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantRef;
-import dk.camelot64.kickc.model.values.ConstantValue;
 import dk.camelot64.kickc.model.values.RValue;
 
-import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Converts typeid() operators to constants
  */
-public class Pass1TypeIdSimplification extends Pass1Base {
+public class PassNTypeIdSimplification extends Pass2SsaOptimization {
 
-   public Pass1TypeIdSimplification(Program program) {
+   public PassNTypeIdSimplification(Program program) {
       super(program);
    }
 
    @Override
    public boolean step() {
-      boolean modified = false;
+      AtomicBoolean modified = new AtomicBoolean(false);
+      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(programExpression instanceof ProgramExpressionUnary) {
+            ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression;
+            if(Operators.TYPEID.equals(unary.getOperator())) {
+               RValue rValue = unary.getOperand();
+               SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue);
+               if(symbolType.equals(SymbolType.VAR) || symbolType.equals(SymbolType.NUMBER)) {
+
+               }  else {
+                  getLog().append("Resolving typeid() " + currentStmt.toString(getProgram(), false));
+                  ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getScope(), symbolType);
+                  unary.set(typeIDConstantVar);
+                  modified.set(true);
+               }
+            }
+         }
+      });
+
+      /*
       for(ControlFlowBlock block : getGraph().getAllBlocks()) {
          for(Statement statement : block.getStatements()) {
             if(statement instanceof StatementAssignment) {
                StatementAssignment assignment = (StatementAssignment) statement;
                if(Operators.TYPEID.equals(assignment.getOperator())) {
                   RValue rValue = assignment.getrValue2();
-                  SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue);
+                  SymbolType symbolType = SymbolTypeInference.inferType(getSymbols(), rValue);
                   if(SymbolType.NUMBER.equals(symbolType)) {
                      if(rValue instanceof ConstantValue) {
-                        List<SymbolTypeIntegerFixed> fixedTypes = SymbolTypeNumberInference.inferTypes(getScope(), (ConstantLiteral) rValue);
+                        List<SymbolTypeIntegerFixed> fixedTypes = SymbolTypeNumberInference.inferTypes(getSymbols(), (ConstantLiteral) rValue);
                         throw new InternalError("TODO: Implement typeof(const)!");
                      }
                   } else {
                      getLog().append("Resolving typeid() " + assignment.toString(getProgram(), false));
-                     ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getScope(), symbolType);
+                     ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getSymbols(), symbolType);
                      assignment.setrValue2(typeIDConstantVar);
                      assignment.setOperator(null);
                      modified = true;
@@ -53,6 +66,7 @@ public class Pass1TypeIdSimplification extends Pass1Base {
             }
          }
       }
-      return modified;
+      */
+      return modified.get();
    }
 }
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 95b07f371..b77d09e82 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -34,12 +34,12 @@ public class TestPrograms {
 
    @Test
    public void testNumberConversion() throws IOException, URISyntaxException {
-      compileAndCompare("number-conversion", log());
+      compileAndCompare("number-conversion");
    }
 
    @Test
    public void testNumberType() throws IOException, URISyntaxException {
-      compileAndCompare("number-type");
+      compileAndCompare("number-type", log());
    }
 
    @Test
diff --git a/src/test/kc/number-conversion.kc b/src/test/kc/number-conversion.kc
index 6d7a7b833..67ee702f6 100644
--- a/src/test/kc/number-conversion.kc
+++ b/src/test/kc/number-conversion.kc
@@ -10,15 +10,13 @@ void main() {
     idx = 0ub;
     assertType(typeid(12sb+12), typeid(signed byte));
     assertType(typeid(12sb+130), typeid(signed word));
-    assertType(typeid(12sb+32000), typeid(signed dword));
+    assertType(typeid(12sb+33000), typeid(signed dword));
     assertType(typeid(12sw+12), typeid(signed word));
     assertType(typeid(12sw+130), typeid(signed word));
     assertType(typeid(12sw+100000), typeid(signed dword));
     assertType(typeid(12sd+12), typeid(signed dword));
     assertType(typeid(12sd+130), typeid(signed dword));
     assertType(typeid(12sd+100000), typeid(signed dword));
-    // Test number larger than largest signed type
-    assertType(typeid(12sb+3000000000), typeid(unsigned dword));
 
     // Unsigned type and positive number
     // b) If one operand is an unsigned type and the other a positive number.
@@ -36,7 +34,7 @@ void main() {
     assertType(typeid(12ud+12), typeid(unsigned dword));
     assertType(typeid(12ud+130), typeid(unsigned dword));
     assertType(typeid(12ud+66000), typeid(unsigned dword));
-    assertType(typeid(12sb+3000000000), typeid(unsigned dword));
+    assertType(typeid(12ub+3000000000), typeid(unsigned dword));
 
     // Unsigned type and negative number
     // If one operand is an unsigned type and the other a negative number.
@@ -47,16 +45,19 @@ void main() {
     idx = 80ub;
     assertType(typeid(12ub+-12), typeid(unsigned byte));
     assertType(typeid(12ub+-120), typeid(unsigned byte));
-    assertType(typeid(12ub+-250), typeid(unsigned word));
-    assertType(typeid(12ub+-32000), typeid(unsigned dword));
+    assertType(typeid(12ub+-250), typeid(unsigned byte));
+    assertType(typeid(12ub+-260), typeid(unsigned word));
+    assertType(typeid(12ub+-65000), typeid(unsigned word));
     assertType(typeid(12ub+-66000), typeid(unsigned dword));
     assertType(typeid(12uw+-12), typeid(unsigned word));
     assertType(typeid(12uw+-130), typeid(unsigned word));
-    assertType(typeid(12uw+-32000), typeid(unsigned dword));
+    assertType(typeid(12uw+-65000), typeid(unsigned word));
+    assertType(typeid(12uw+-66000), typeid(unsigned dword));
     assertType(typeid(12ud+-12), typeid(unsigned dword));
     assertType(typeid(12ud+-130), typeid(unsigned dword));
     assertType(typeid(12ud+-66000), typeid(unsigned dword));
-    assertType(typeid(12sb+-3000000000), typeid(unsigned dword));
+    assertType(typeid(12sb+-2100000000), typeid(unsigned dword));
+
 
 }
 
diff --git a/src/test/ref/int-conversion.asm b/src/test/ref/int-conversion.asm
new file mode 100644
index 000000000..9ad08351c
--- /dev/null
+++ b/src/test/ref/int-conversion.asm
@@ -0,0 +1,242 @@
+// Tests different integer literal types
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .const TYPEID_BYTE = 1
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_WORD = 3
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_DWORD = 5
+  .const TYPEID_SIGNED_DWORD = 6
+  .const RED = 2
+  .const GREEN = 5
+  .label SCREEN = $400
+  .label COLS = $d800
+main: {
+    .label s = 2
+    lda #<SCREEN
+    sta s
+    lda #>SCREEN
+    sta s+1
+  b1:
+    lda #' '
+    ldy #0
+    sta (s),y
+    inc s
+    bne !+
+    inc s+1
+  !:
+    lda s+1
+    cmp #>SCREEN+$3e8
+    bcc b1
+    bne !+
+    lda s
+    cmp #<SCREEN+$3e8
+    bcc b1
+  !:
+    jsr testUnaryOperator
+    jsr testBinaryOperator
+    rts
+}
+testBinaryOperator: {
+    ldx #$28
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    inx
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    inx
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    ldx #$50
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    inx
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    inx
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    rts
+}
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(4) t2)
+assertType: {
+    .label t2 = 4
+    tya
+    cmp t2
+    beq b1
+    lda #RED
+    sta COLS,x
+  b2:
+    tya
+    sta SCREEN,x
+    inx
+    rts
+  b1:
+    lda #GREEN
+    sta COLS,x
+    jmp b2
+}
+testUnaryOperator: {
+    ldx #0
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    rts
+}
diff --git a/src/test/ref/int-conversion.cfg b/src/test/ref/int-conversion.cfg
new file mode 100644
index 000000000..a3454c904
--- /dev/null
+++ b/src/test/ref/int-conversion.cfg
@@ -0,0 +1,222 @@
+@begin: scope:[]  from
+  [0] phi()
+  to:@1
+@1: scope:[]  from @begin
+  [1] phi()
+  [2] call main 
+  to:@end
+@end: scope:[]  from @1
+  [3] phi()
+main: scope:[main]  from @1
+  [4] phi()
+  to:main::@1
+main::@1: scope:[main]  from main main::@1
+  [5] (byte*) main::s#2 ← phi( main/(const byte*) SCREEN#0 main::@1/(byte*) main::s#1 )
+  [6] *((byte*) main::s#2) ← (byte) ' '
+  [7] (byte*) main::s#1 ← ++ (byte*) main::s#2
+  [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  [9] phi()
+  [10] call testUnaryOperator 
+  to:main::@3
+main::@3: scope:[main]  from main::@2
+  [11] phi()
+  [12] call testBinaryOperator 
+  to:main::@return
+main::@return: scope:[main]  from main::@3
+  [13] return 
+  to:@return
+testBinaryOperator: scope:[testBinaryOperator]  from main::@3
+  [14] phi()
+  [15] call assertType 
+  to:testBinaryOperator::@1
+testBinaryOperator::@1: scope:[testBinaryOperator]  from testBinaryOperator
+  [16] phi()
+  [17] call assertType 
+  to:testBinaryOperator::@2
+testBinaryOperator::@2: scope:[testBinaryOperator]  from testBinaryOperator::@1
+  [18] phi()
+  [19] call assertType 
+  to:testBinaryOperator::@3
+testBinaryOperator::@3: scope:[testBinaryOperator]  from testBinaryOperator::@2
+  [20] phi()
+  [21] call assertType 
+  to:testBinaryOperator::@4
+testBinaryOperator::@4: scope:[testBinaryOperator]  from testBinaryOperator::@3
+  [22] phi()
+  [23] call assertType 
+  to:testBinaryOperator::@5
+testBinaryOperator::@5: scope:[testBinaryOperator]  from testBinaryOperator::@4
+  [24] phi()
+  [25] call assertType 
+  to:testBinaryOperator::@6
+testBinaryOperator::@6: scope:[testBinaryOperator]  from testBinaryOperator::@5
+  [26] (byte) idx#19 ← ++ (byte) idx#108
+  [27] call assertType 
+  to:testBinaryOperator::@7
+testBinaryOperator::@7: scope:[testBinaryOperator]  from testBinaryOperator::@6
+  [28] phi()
+  [29] call assertType 
+  to:testBinaryOperator::@8
+testBinaryOperator::@8: scope:[testBinaryOperator]  from testBinaryOperator::@7
+  [30] phi()
+  [31] call assertType 
+  to:testBinaryOperator::@9
+testBinaryOperator::@9: scope:[testBinaryOperator]  from testBinaryOperator::@8
+  [32] phi()
+  [33] call assertType 
+  to:testBinaryOperator::@10
+testBinaryOperator::@10: scope:[testBinaryOperator]  from testBinaryOperator::@9
+  [34] phi()
+  [35] call assertType 
+  to:testBinaryOperator::@11
+testBinaryOperator::@11: scope:[testBinaryOperator]  from testBinaryOperator::@10
+  [36] phi()
+  [37] call assertType 
+  to:testBinaryOperator::@12
+testBinaryOperator::@12: scope:[testBinaryOperator]  from testBinaryOperator::@11
+  [38] (byte) idx#26 ← ++ (byte) idx#108
+  [39] call assertType 
+  to:testBinaryOperator::@13
+testBinaryOperator::@13: scope:[testBinaryOperator]  from testBinaryOperator::@12
+  [40] phi()
+  [41] call assertType 
+  to:testBinaryOperator::@14
+testBinaryOperator::@14: scope:[testBinaryOperator]  from testBinaryOperator::@13
+  [42] phi()
+  [43] call assertType 
+  to:testBinaryOperator::@15
+testBinaryOperator::@15: scope:[testBinaryOperator]  from testBinaryOperator::@14
+  [44] phi()
+  [45] call assertType 
+  to:testBinaryOperator::@16
+testBinaryOperator::@16: scope:[testBinaryOperator]  from testBinaryOperator::@15
+  [46] phi()
+  [47] call assertType 
+  to:testBinaryOperator::@17
+testBinaryOperator::@17: scope:[testBinaryOperator]  from testBinaryOperator::@16
+  [48] phi()
+  [49] call assertType 
+  to:testBinaryOperator::@18
+testBinaryOperator::@18: scope:[testBinaryOperator]  from testBinaryOperator::@17
+  [50] phi()
+  [51] call assertType 
+  to:testBinaryOperator::@19
+testBinaryOperator::@19: scope:[testBinaryOperator]  from testBinaryOperator::@18
+  [52] phi()
+  [53] call assertType 
+  to:testBinaryOperator::@20
+testBinaryOperator::@20: scope:[testBinaryOperator]  from testBinaryOperator::@19
+  [54] phi()
+  [55] call assertType 
+  to:testBinaryOperator::@21
+testBinaryOperator::@21: scope:[testBinaryOperator]  from testBinaryOperator::@20
+  [56] phi()
+  [57] call assertType 
+  to:testBinaryOperator::@22
+testBinaryOperator::@22: scope:[testBinaryOperator]  from testBinaryOperator::@21
+  [58] phi()
+  [59] call assertType 
+  to:testBinaryOperator::@23
+testBinaryOperator::@23: scope:[testBinaryOperator]  from testBinaryOperator::@22
+  [60] phi()
+  [61] call assertType 
+  to:testBinaryOperator::@24
+testBinaryOperator::@24: scope:[testBinaryOperator]  from testBinaryOperator::@23
+  [62] (byte) idx#40 ← ++ (byte) idx#108
+  [63] call assertType 
+  to:testBinaryOperator::@25
+testBinaryOperator::@25: scope:[testBinaryOperator]  from testBinaryOperator::@24
+  [64] phi()
+  [65] call assertType 
+  to:testBinaryOperator::@26
+testBinaryOperator::@26: scope:[testBinaryOperator]  from testBinaryOperator::@25
+  [66] phi()
+  [67] call assertType 
+  to:testBinaryOperator::@27
+testBinaryOperator::@27: scope:[testBinaryOperator]  from testBinaryOperator::@26
+  [68] phi()
+  [69] call assertType 
+  to:testBinaryOperator::@28
+testBinaryOperator::@28: scope:[testBinaryOperator]  from testBinaryOperator::@27
+  [70] phi()
+  [71] call assertType 
+  to:testBinaryOperator::@29
+testBinaryOperator::@29: scope:[testBinaryOperator]  from testBinaryOperator::@28
+  [72] phi()
+  [73] call assertType 
+  to:testBinaryOperator::@30
+testBinaryOperator::@30: scope:[testBinaryOperator]  from testBinaryOperator::@29
+  [74] (byte) idx#47 ← ++ (byte) idx#108
+  [75] call assertType 
+  to:testBinaryOperator::@31
+testBinaryOperator::@31: scope:[testBinaryOperator]  from testBinaryOperator::@30
+  [76] phi()
+  [77] call assertType 
+  to:testBinaryOperator::@32
+testBinaryOperator::@32: scope:[testBinaryOperator]  from testBinaryOperator::@31
+  [78] phi()
+  [79] call assertType 
+  to:testBinaryOperator::@33
+testBinaryOperator::@33: scope:[testBinaryOperator]  from testBinaryOperator::@32
+  [80] phi()
+  [81] call assertType 
+  to:testBinaryOperator::@34
+testBinaryOperator::@34: scope:[testBinaryOperator]  from testBinaryOperator::@33
+  [82] phi()
+  [83] call assertType 
+  to:testBinaryOperator::@35
+testBinaryOperator::@35: scope:[testBinaryOperator]  from testBinaryOperator::@34
+  [84] phi()
+  [85] call assertType 
+  to:testBinaryOperator::@return
+testBinaryOperator::@return: scope:[testBinaryOperator]  from testBinaryOperator::@35
+  [86] return 
+  to:@return
+assertType: scope:[assertType]  from testBinaryOperator testBinaryOperator::@1 testBinaryOperator::@10 testBinaryOperator::@11 testBinaryOperator::@12 testBinaryOperator::@13 testBinaryOperator::@14 testBinaryOperator::@15 testBinaryOperator::@16 testBinaryOperator::@17 testBinaryOperator::@18 testBinaryOperator::@19 testBinaryOperator::@2 testBinaryOperator::@20 testBinaryOperator::@21 testBinaryOperator::@22 testBinaryOperator::@23 testBinaryOperator::@24 testBinaryOperator::@25 testBinaryOperator::@26 testBinaryOperator::@27 testBinaryOperator::@28 testBinaryOperator::@29 testBinaryOperator::@3 testBinaryOperator::@30 testBinaryOperator::@31 testBinaryOperator::@32 testBinaryOperator::@33 testBinaryOperator::@34 testBinaryOperator::@35 testBinaryOperator::@4 testBinaryOperator::@5 testBinaryOperator::@6 testBinaryOperator::@7 testBinaryOperator::@8 testBinaryOperator::@9 testUnaryOperator testUnaryOperator::@1 testUnaryOperator::@2 testUnaryOperator::@3 testUnaryOperator::@4 testUnaryOperator::@5
+  [87] (byte) idx#105 ← phi( testBinaryOperator/(byte) $28 testBinaryOperator::@1/(byte) idx#108 testBinaryOperator::@10/(byte) idx#108 testBinaryOperator::@11/(byte) idx#108 testBinaryOperator::@12/(byte) idx#26 testBinaryOperator::@13/(byte) idx#108 testBinaryOperator::@14/(byte) idx#108 testBinaryOperator::@15/(byte) idx#108 testBinaryOperator::@16/(byte) idx#108 testBinaryOperator::@17/(byte) idx#108 testBinaryOperator::@18/(byte) $50 testBinaryOperator::@19/(byte) idx#108 testBinaryOperator::@2/(byte) idx#108 testBinaryOperator::@20/(byte) idx#108 testBinaryOperator::@21/(byte) idx#108 testBinaryOperator::@22/(byte) idx#108 testBinaryOperator::@23/(byte) idx#108 testBinaryOperator::@24/(byte) idx#40 testBinaryOperator::@25/(byte) idx#108 testBinaryOperator::@26/(byte) idx#108 testBinaryOperator::@27/(byte) idx#108 testBinaryOperator::@28/(byte) idx#108 testBinaryOperator::@29/(byte) idx#108 testBinaryOperator::@3/(byte) idx#108 testBinaryOperator::@30/(byte) idx#47 testBinaryOperator::@31/(byte) idx#108 testBinaryOperator::@32/(byte) idx#108 testBinaryOperator::@33/(byte) idx#108 testBinaryOperator::@34/(byte) idx#108 testBinaryOperator::@35/(byte) idx#108 testBinaryOperator::@4/(byte) idx#108 testBinaryOperator::@5/(byte) idx#108 testBinaryOperator::@6/(byte) idx#19 testBinaryOperator::@7/(byte) idx#108 testBinaryOperator::@8/(byte) idx#108 testBinaryOperator::@9/(byte) idx#108 testUnaryOperator/(byte) 0 testUnaryOperator::@1/(byte) idx#108 testUnaryOperator::@2/(byte) idx#108 testUnaryOperator::@3/(byte) idx#108 testUnaryOperator::@4/(byte) idx#108 testUnaryOperator::@5/(byte) idx#108 )
+  [87] (byte) assertType::t2#42 ← phi( testBinaryOperator/(const byte) TYPEID_BYTE testBinaryOperator::@1/(const byte) TYPEID_BYTE testBinaryOperator::@10/(const byte) TYPEID_DWORD testBinaryOperator::@11/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@12/(const byte) TYPEID_WORD testBinaryOperator::@13/(const byte) TYPEID_WORD testBinaryOperator::@14/(const byte) TYPEID_WORD testBinaryOperator::@15/(const byte) TYPEID_WORD testBinaryOperator::@16/(const byte) TYPEID_DWORD testBinaryOperator::@17/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@18/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@19/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@2/(const byte) TYPEID_WORD testBinaryOperator::@20/(const byte) TYPEID_WORD testBinaryOperator::@21/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@22/(const byte) TYPEID_DWORD testBinaryOperator::@23/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@24/(const byte) TYPEID_DWORD testBinaryOperator::@25/(const byte) TYPEID_DWORD testBinaryOperator::@26/(const byte) TYPEID_DWORD testBinaryOperator::@27/(const byte) TYPEID_DWORD testBinaryOperator::@28/(const byte) TYPEID_DWORD testBinaryOperator::@29/(const byte) TYPEID_DWORD testBinaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@30/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@31/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@32/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@33/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@34/(const byte) TYPEID_DWORD testBinaryOperator::@35/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@4/(const byte) TYPEID_DWORD testBinaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@6/(const byte) TYPEID_BYTE testBinaryOperator::@7/(const byte) TYPEID_SIGNED_BYTE testBinaryOperator::@8/(const byte) TYPEID_WORD testBinaryOperator::@9/(const byte) TYPEID_SIGNED_WORD testUnaryOperator/(const byte) TYPEID_BYTE testUnaryOperator::@1/(const byte) TYPEID_SIGNED_BYTE testUnaryOperator::@2/(const byte) TYPEID_WORD testUnaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testUnaryOperator::@4/(const byte) TYPEID_DWORD testUnaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD )
+  [87] (byte) assertType::t1#42 ← phi( testBinaryOperator/(const byte) TYPEID_BYTE testBinaryOperator::@1/(const byte) TYPEID_BYTE testBinaryOperator::@10/(const byte) TYPEID_DWORD testBinaryOperator::@11/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@12/(const byte) TYPEID_WORD testBinaryOperator::@13/(const byte) TYPEID_WORD testBinaryOperator::@14/(const byte) TYPEID_WORD testBinaryOperator::@15/(const byte) TYPEID_WORD testBinaryOperator::@16/(const byte) TYPEID_DWORD testBinaryOperator::@17/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@18/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@19/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@2/(const byte) TYPEID_WORD testBinaryOperator::@20/(const byte) TYPEID_WORD testBinaryOperator::@21/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@22/(const byte) TYPEID_DWORD testBinaryOperator::@23/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@24/(const byte) TYPEID_DWORD testBinaryOperator::@25/(const byte) TYPEID_DWORD testBinaryOperator::@26/(const byte) TYPEID_DWORD testBinaryOperator::@27/(const byte) TYPEID_DWORD testBinaryOperator::@28/(const byte) TYPEID_DWORD testBinaryOperator::@29/(const byte) TYPEID_DWORD testBinaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@30/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@31/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@32/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@33/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@34/(const byte) TYPEID_DWORD testBinaryOperator::@35/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@4/(const byte) TYPEID_DWORD testBinaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@6/(const byte) TYPEID_BYTE testBinaryOperator::@7/(const byte) TYPEID_SIGNED_BYTE testBinaryOperator::@8/(const byte) TYPEID_WORD testBinaryOperator::@9/(const byte) TYPEID_SIGNED_WORD testUnaryOperator/(const byte) TYPEID_BYTE testUnaryOperator::@1/(const byte) TYPEID_SIGNED_BYTE testUnaryOperator::@2/(const byte) TYPEID_WORD testUnaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testUnaryOperator::@4/(const byte) TYPEID_DWORD testUnaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD )
+  [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1
+  to:assertType::@3
+assertType::@3: scope:[assertType]  from assertType
+  [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42
+  [91] (byte) idx#108 ← ++ (byte) idx#105
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  [92] return 
+  to:@return
+assertType::@1: scope:[assertType]  from assertType
+  [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0
+  to:assertType::@2
+testUnaryOperator: scope:[testUnaryOperator]  from main::@2
+  [94] phi()
+  [95] call assertType 
+  to:testUnaryOperator::@1
+testUnaryOperator::@1: scope:[testUnaryOperator]  from testUnaryOperator
+  [96] phi()
+  [97] call assertType 
+  to:testUnaryOperator::@2
+testUnaryOperator::@2: scope:[testUnaryOperator]  from testUnaryOperator::@1
+  [98] phi()
+  [99] call assertType 
+  to:testUnaryOperator::@3
+testUnaryOperator::@3: scope:[testUnaryOperator]  from testUnaryOperator::@2
+  [100] phi()
+  [101] call assertType 
+  to:testUnaryOperator::@4
+testUnaryOperator::@4: scope:[testUnaryOperator]  from testUnaryOperator::@3
+  [102] phi()
+  [103] call assertType 
+  to:testUnaryOperator::@5
+testUnaryOperator::@5: scope:[testUnaryOperator]  from testUnaryOperator::@4
+  [104] phi()
+  [105] call assertType 
+  to:testUnaryOperator::@return
+testUnaryOperator::@return: scope:[testUnaryOperator]  from testUnaryOperator::@5
+  [106] return 
+  to:@return
diff --git a/src/test/ref/int-conversion.log b/src/test/ref/int-conversion.log
new file mode 100644
index 000000000..df50fcd7f
--- /dev/null
+++ b/src/test/ref/int-conversion.log
@@ -0,0 +1,4159 @@
+Resolving typeid() (byte~) testUnaryOperator::$1 ← typeid  (byte~) testUnaryOperator::$0
+Resolving typeid() (byte~) testUnaryOperator::$4 ← typeid  (signed byte~) testUnaryOperator::$3
+Resolving typeid() (byte~) testUnaryOperator::$7 ← typeid  (word~) testUnaryOperator::$6
+Resolving typeid() (byte~) testUnaryOperator::$10 ← typeid  (signed word~) testUnaryOperator::$9
+Resolving typeid() (byte~) testUnaryOperator::$13 ← typeid  (dword~) testUnaryOperator::$12
+Resolving typeid() (byte~) testUnaryOperator::$16 ← typeid  (signed dword~) testUnaryOperator::$15
+Resolving typeid() (byte~) testBinaryOperator::$1 ← typeid  (byte~) testBinaryOperator::$0
+Resolving typeid() (byte~) testBinaryOperator::$4 ← typeid  (byte~) testBinaryOperator::$3
+Resolving typeid() (byte~) testBinaryOperator::$7 ← typeid  (word~) testBinaryOperator::$6
+Resolving typeid() (byte~) testBinaryOperator::$10 ← typeid  (signed word~) testBinaryOperator::$9
+Resolving typeid() (byte~) testBinaryOperator::$13 ← typeid  (dword~) testBinaryOperator::$12
+Resolving typeid() (byte~) testBinaryOperator::$16 ← typeid  (signed dword~) testBinaryOperator::$15
+Resolving typeid() (byte~) testBinaryOperator::$19 ← typeid  (byte~) testBinaryOperator::$18
+Resolving typeid() (byte~) testBinaryOperator::$22 ← typeid  (signed byte~) testBinaryOperator::$21
+Resolving typeid() (byte~) testBinaryOperator::$25 ← typeid  (word~) testBinaryOperator::$24
+Resolving typeid() (byte~) testBinaryOperator::$28 ← typeid  (signed word~) testBinaryOperator::$27
+Resolving typeid() (byte~) testBinaryOperator::$31 ← typeid  (dword~) testBinaryOperator::$30
+Resolving typeid() (byte~) testBinaryOperator::$34 ← typeid  (signed dword~) testBinaryOperator::$33
+Resolving typeid() (byte~) testBinaryOperator::$37 ← typeid  (word~) testBinaryOperator::$36
+Resolving typeid() (byte~) testBinaryOperator::$40 ← typeid  (word~) testBinaryOperator::$39
+Resolving typeid() (byte~) testBinaryOperator::$43 ← typeid  (word~) testBinaryOperator::$42
+Resolving typeid() (byte~) testBinaryOperator::$46 ← typeid  (word~) testBinaryOperator::$45
+Resolving typeid() (byte~) testBinaryOperator::$49 ← typeid  (dword~) testBinaryOperator::$48
+Resolving typeid() (byte~) testBinaryOperator::$52 ← typeid  (signed dword~) testBinaryOperator::$51
+Resolving typeid() (byte~) testBinaryOperator::$55 ← typeid  (signed word~) testBinaryOperator::$54
+Resolving typeid() (byte~) testBinaryOperator::$58 ← typeid  (signed word~) testBinaryOperator::$57
+Resolving typeid() (byte~) testBinaryOperator::$61 ← typeid  (word~) testBinaryOperator::$60
+Resolving typeid() (byte~) testBinaryOperator::$64 ← typeid  (signed word~) testBinaryOperator::$63
+Resolving typeid() (byte~) testBinaryOperator::$67 ← typeid  (dword~) testBinaryOperator::$66
+Resolving typeid() (byte~) testBinaryOperator::$70 ← typeid  (signed dword~) testBinaryOperator::$69
+Resolving typeid() (byte~) testBinaryOperator::$73 ← typeid  (dword~) testBinaryOperator::$72
+Resolving typeid() (byte~) testBinaryOperator::$76 ← typeid  (dword~) testBinaryOperator::$75
+Resolving typeid() (byte~) testBinaryOperator::$79 ← typeid  (dword~) testBinaryOperator::$78
+Resolving typeid() (byte~) testBinaryOperator::$82 ← typeid  (dword~) testBinaryOperator::$81
+Resolving typeid() (byte~) testBinaryOperator::$85 ← typeid  (dword~) testBinaryOperator::$84
+Resolving typeid() (byte~) testBinaryOperator::$88 ← typeid  (dword~) testBinaryOperator::$87
+Resolving typeid() (byte~) testBinaryOperator::$91 ← typeid  (signed dword~) testBinaryOperator::$90
+Resolving typeid() (byte~) testBinaryOperator::$94 ← typeid  (signed dword~) testBinaryOperator::$93
+Resolving typeid() (byte~) testBinaryOperator::$97 ← typeid  (signed dword~) testBinaryOperator::$96
+Resolving typeid() (byte~) testBinaryOperator::$100 ← typeid  (signed dword~) testBinaryOperator::$99
+Resolving typeid() (byte~) testBinaryOperator::$103 ← typeid  (dword~) testBinaryOperator::$102
+Resolving typeid() (byte~) testBinaryOperator::$106 ← typeid  (signed dword~) testBinaryOperator::$105
+Converting word to byte* in SCREEN ← ((byte*)) $400
+Converting word to byte* in COLS ← ((byte*)) $d800
+
+CONTROL FLOW GRAPH SSA
+@begin: scope:[]  from
+  (byte) RED#0 ← (byte) 2
+  (byte) GREEN#0 ← (byte) 5
+  (byte*) SCREEN#0 ← ((byte*)) (word) $400
+  (byte*) COLS#0 ← ((byte*)) (word) $d800
+  (byte) idx#0 ← (byte) 0
+  to:@4
+main: scope:[main]  from @4
+  (byte) idx#114 ← phi( @4/(byte) idx#112 )
+  (byte*) main::s#0 ← (byte*) SCREEN#0
+  to:main::@1
+main::@1: scope:[main]  from main main::@1
+  (byte) idx#113 ← phi( main/(byte) idx#114 main::@1/(byte) idx#113 )
+  (byte*) main::s#2 ← phi( main/(byte*) main::s#0 main::@1/(byte*) main::s#1 )
+  *((byte*) main::s#2) ← (byte) ' '
+  (byte*) main::s#1 ← ++ (byte*) main::s#2
+  (byte*~) main::$2 ← (byte*) SCREEN#0 + (word) $3e8
+  (bool~) main::$3 ← (byte*) main::s#1 < (byte*~) main::$2
+  if((bool~) main::$3) goto main::@1
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  (byte) idx#110 ← phi( main::@1/(byte) idx#113 )
+  call testUnaryOperator 
+  to:main::@3
+main::@3: scope:[main]  from main::@2
+  (byte) idx#58 ← phi( main::@2/(byte) idx#11 )
+  (byte) idx#1 ← (byte) idx#58
+  call testBinaryOperator 
+  to:main::@4
+main::@4: scope:[main]  from main::@3
+  (byte) idx#59 ← phi( main::@3/(byte) idx#54 )
+  (byte) idx#2 ← (byte) idx#59
+  to:main::@return
+main::@return: scope:[main]  from main::@4
+  (byte) idx#60 ← phi( main::@4/(byte) idx#2 )
+  (byte) idx#3 ← (byte) idx#60
+  return 
+  to:@return
+testUnaryOperator: scope:[testUnaryOperator]  from main::@2
+  (byte) idx#4 ← (byte) 0
+  (byte~) testUnaryOperator::$1 ← (const byte) TYPEID_BYTE
+  (byte) assertType::t1#0 ← (byte~) testUnaryOperator::$1
+  (byte) assertType::t2#0 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:testUnaryOperator::@1
+testUnaryOperator::@1: scope:[testUnaryOperator]  from testUnaryOperator
+  (byte) idx#61 ← phi( testUnaryOperator/(byte) idx#56 )
+  (byte) idx#5 ← (byte) idx#61
+  (byte~) testUnaryOperator::$4 ← (const byte) TYPEID_SIGNED_BYTE
+  (byte) assertType::t1#1 ← (byte~) testUnaryOperator::$4
+  (byte) assertType::t2#1 ← (const byte) TYPEID_SIGNED_BYTE
+  call assertType 
+  to:testUnaryOperator::@2
+testUnaryOperator::@2: scope:[testUnaryOperator]  from testUnaryOperator::@1
+  (byte) idx#62 ← phi( testUnaryOperator::@1/(byte) idx#56 )
+  (byte) idx#6 ← (byte) idx#62
+  (byte~) testUnaryOperator::$7 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#2 ← (byte~) testUnaryOperator::$7
+  (byte) assertType::t2#2 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testUnaryOperator::@3
+testUnaryOperator::@3: scope:[testUnaryOperator]  from testUnaryOperator::@2
+  (byte) idx#63 ← phi( testUnaryOperator::@2/(byte) idx#56 )
+  (byte) idx#7 ← (byte) idx#63
+  (byte~) testUnaryOperator::$10 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#3 ← (byte~) testUnaryOperator::$10
+  (byte) assertType::t2#3 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testUnaryOperator::@4
+testUnaryOperator::@4: scope:[testUnaryOperator]  from testUnaryOperator::@3
+  (byte) idx#64 ← phi( testUnaryOperator::@3/(byte) idx#56 )
+  (byte) idx#8 ← (byte) idx#64
+  (byte~) testUnaryOperator::$13 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#4 ← (byte~) testUnaryOperator::$13
+  (byte) assertType::t2#4 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testUnaryOperator::@5
+testUnaryOperator::@5: scope:[testUnaryOperator]  from testUnaryOperator::@4
+  (byte) idx#65 ← phi( testUnaryOperator::@4/(byte) idx#56 )
+  (byte) idx#9 ← (byte) idx#65
+  (byte~) testUnaryOperator::$16 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#5 ← (byte~) testUnaryOperator::$16
+  (byte) assertType::t2#5 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testUnaryOperator::@6
+testUnaryOperator::@6: scope:[testUnaryOperator]  from testUnaryOperator::@5
+  (byte) idx#66 ← phi( testUnaryOperator::@5/(byte) idx#56 )
+  (byte) idx#10 ← (byte) idx#66
+  to:testUnaryOperator::@return
+testUnaryOperator::@return: scope:[testUnaryOperator]  from testUnaryOperator::@6
+  (byte) idx#67 ← phi( testUnaryOperator::@6/(byte) idx#10 )
+  (byte) idx#11 ← (byte) idx#67
+  return 
+  to:@return
+testBinaryOperator: scope:[testBinaryOperator]  from main::@3
+  (byte) idx#12 ← (byte) $28
+  (byte~) testBinaryOperator::$1 ← (const byte) TYPEID_BYTE
+  (byte) assertType::t1#6 ← (byte~) testBinaryOperator::$1
+  (byte) assertType::t2#6 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:testBinaryOperator::@1
+testBinaryOperator::@1: scope:[testBinaryOperator]  from testBinaryOperator
+  (byte) idx#68 ← phi( testBinaryOperator/(byte) idx#56 )
+  (byte) idx#13 ← (byte) idx#68
+  (byte~) testBinaryOperator::$4 ← (const byte) TYPEID_BYTE
+  (byte) assertType::t1#7 ← (byte~) testBinaryOperator::$4
+  (byte) assertType::t2#7 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:testBinaryOperator::@2
+testBinaryOperator::@2: scope:[testBinaryOperator]  from testBinaryOperator::@1
+  (byte) idx#69 ← phi( testBinaryOperator::@1/(byte) idx#56 )
+  (byte) idx#14 ← (byte) idx#69
+  (byte~) testBinaryOperator::$7 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#8 ← (byte~) testBinaryOperator::$7
+  (byte) assertType::t2#8 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testBinaryOperator::@3
+testBinaryOperator::@3: scope:[testBinaryOperator]  from testBinaryOperator::@2
+  (byte) idx#70 ← phi( testBinaryOperator::@2/(byte) idx#56 )
+  (byte) idx#15 ← (byte) idx#70
+  (byte~) testBinaryOperator::$10 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#9 ← (byte~) testBinaryOperator::$10
+  (byte) assertType::t2#9 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testBinaryOperator::@4
+testBinaryOperator::@4: scope:[testBinaryOperator]  from testBinaryOperator::@3
+  (byte) idx#71 ← phi( testBinaryOperator::@3/(byte) idx#56 )
+  (byte) idx#16 ← (byte) idx#71
+  (byte~) testBinaryOperator::$13 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#10 ← (byte~) testBinaryOperator::$13
+  (byte) assertType::t2#10 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@5
+testBinaryOperator::@5: scope:[testBinaryOperator]  from testBinaryOperator::@4
+  (byte) idx#72 ← phi( testBinaryOperator::@4/(byte) idx#56 )
+  (byte) idx#17 ← (byte) idx#72
+  (byte~) testBinaryOperator::$16 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#11 ← (byte~) testBinaryOperator::$16
+  (byte) assertType::t2#11 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@6
+testBinaryOperator::@6: scope:[testBinaryOperator]  from testBinaryOperator::@5
+  (byte) idx#73 ← phi( testBinaryOperator::@5/(byte) idx#56 )
+  (byte) idx#18 ← (byte) idx#73
+  (byte) idx#19 ← ++ (byte) idx#18
+  (byte~) testBinaryOperator::$19 ← (const byte) TYPEID_BYTE
+  (byte) assertType::t1#12 ← (byte~) testBinaryOperator::$19
+  (byte) assertType::t2#12 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:testBinaryOperator::@7
+testBinaryOperator::@7: scope:[testBinaryOperator]  from testBinaryOperator::@6
+  (byte) idx#74 ← phi( testBinaryOperator::@6/(byte) idx#56 )
+  (byte) idx#20 ← (byte) idx#74
+  (byte~) testBinaryOperator::$22 ← (const byte) TYPEID_SIGNED_BYTE
+  (byte) assertType::t1#13 ← (byte~) testBinaryOperator::$22
+  (byte) assertType::t2#13 ← (const byte) TYPEID_SIGNED_BYTE
+  call assertType 
+  to:testBinaryOperator::@8
+testBinaryOperator::@8: scope:[testBinaryOperator]  from testBinaryOperator::@7
+  (byte) idx#75 ← phi( testBinaryOperator::@7/(byte) idx#56 )
+  (byte) idx#21 ← (byte) idx#75
+  (byte~) testBinaryOperator::$25 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#14 ← (byte~) testBinaryOperator::$25
+  (byte) assertType::t2#14 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testBinaryOperator::@9
+testBinaryOperator::@9: scope:[testBinaryOperator]  from testBinaryOperator::@8
+  (byte) idx#76 ← phi( testBinaryOperator::@8/(byte) idx#56 )
+  (byte) idx#22 ← (byte) idx#76
+  (byte~) testBinaryOperator::$28 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#15 ← (byte~) testBinaryOperator::$28
+  (byte) assertType::t2#15 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testBinaryOperator::@10
+testBinaryOperator::@10: scope:[testBinaryOperator]  from testBinaryOperator::@9
+  (byte) idx#77 ← phi( testBinaryOperator::@9/(byte) idx#56 )
+  (byte) idx#23 ← (byte) idx#77
+  (byte~) testBinaryOperator::$31 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#16 ← (byte~) testBinaryOperator::$31
+  (byte) assertType::t2#16 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@11
+testBinaryOperator::@11: scope:[testBinaryOperator]  from testBinaryOperator::@10
+  (byte) idx#78 ← phi( testBinaryOperator::@10/(byte) idx#56 )
+  (byte) idx#24 ← (byte) idx#78
+  (byte~) testBinaryOperator::$34 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#17 ← (byte~) testBinaryOperator::$34
+  (byte) assertType::t2#17 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@12
+testBinaryOperator::@12: scope:[testBinaryOperator]  from testBinaryOperator::@11
+  (byte) idx#79 ← phi( testBinaryOperator::@11/(byte) idx#56 )
+  (byte) idx#25 ← (byte) idx#79
+  (byte) idx#26 ← ++ (byte) idx#25
+  (byte~) testBinaryOperator::$37 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#18 ← (byte~) testBinaryOperator::$37
+  (byte) assertType::t2#18 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testBinaryOperator::@13
+testBinaryOperator::@13: scope:[testBinaryOperator]  from testBinaryOperator::@12
+  (byte) idx#80 ← phi( testBinaryOperator::@12/(byte) idx#56 )
+  (byte) idx#27 ← (byte) idx#80
+  (byte~) testBinaryOperator::$40 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#19 ← (byte~) testBinaryOperator::$40
+  (byte) assertType::t2#19 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testBinaryOperator::@14
+testBinaryOperator::@14: scope:[testBinaryOperator]  from testBinaryOperator::@13
+  (byte) idx#81 ← phi( testBinaryOperator::@13/(byte) idx#56 )
+  (byte) idx#28 ← (byte) idx#81
+  (byte~) testBinaryOperator::$43 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#20 ← (byte~) testBinaryOperator::$43
+  (byte) assertType::t2#20 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testBinaryOperator::@15
+testBinaryOperator::@15: scope:[testBinaryOperator]  from testBinaryOperator::@14
+  (byte) idx#82 ← phi( testBinaryOperator::@14/(byte) idx#56 )
+  (byte) idx#29 ← (byte) idx#82
+  (byte~) testBinaryOperator::$46 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#21 ← (byte~) testBinaryOperator::$46
+  (byte) assertType::t2#21 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testBinaryOperator::@16
+testBinaryOperator::@16: scope:[testBinaryOperator]  from testBinaryOperator::@15
+  (byte) idx#83 ← phi( testBinaryOperator::@15/(byte) idx#56 )
+  (byte) idx#30 ← (byte) idx#83
+  (byte~) testBinaryOperator::$49 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#22 ← (byte~) testBinaryOperator::$49
+  (byte) assertType::t2#22 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@17
+testBinaryOperator::@17: scope:[testBinaryOperator]  from testBinaryOperator::@16
+  (byte) idx#84 ← phi( testBinaryOperator::@16/(byte) idx#56 )
+  (byte) idx#31 ← (byte) idx#84
+  (byte~) testBinaryOperator::$52 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#23 ← (byte~) testBinaryOperator::$52
+  (byte) assertType::t2#23 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@18
+testBinaryOperator::@18: scope:[testBinaryOperator]  from testBinaryOperator::@17
+  (byte) idx#85 ← phi( testBinaryOperator::@17/(byte) idx#56 )
+  (byte) idx#32 ← (byte) idx#85
+  (byte) idx#33 ← (byte) $50
+  (byte~) testBinaryOperator::$55 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#24 ← (byte~) testBinaryOperator::$55
+  (byte) assertType::t2#24 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testBinaryOperator::@19
+testBinaryOperator::@19: scope:[testBinaryOperator]  from testBinaryOperator::@18
+  (byte) idx#86 ← phi( testBinaryOperator::@18/(byte) idx#56 )
+  (byte) idx#34 ← (byte) idx#86
+  (byte~) testBinaryOperator::$58 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#25 ← (byte~) testBinaryOperator::$58
+  (byte) assertType::t2#25 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testBinaryOperator::@20
+testBinaryOperator::@20: scope:[testBinaryOperator]  from testBinaryOperator::@19
+  (byte) idx#87 ← phi( testBinaryOperator::@19/(byte) idx#56 )
+  (byte) idx#35 ← (byte) idx#87
+  (byte~) testBinaryOperator::$61 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#26 ← (byte~) testBinaryOperator::$61
+  (byte) assertType::t2#26 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testBinaryOperator::@21
+testBinaryOperator::@21: scope:[testBinaryOperator]  from testBinaryOperator::@20
+  (byte) idx#88 ← phi( testBinaryOperator::@20/(byte) idx#56 )
+  (byte) idx#36 ← (byte) idx#88
+  (byte~) testBinaryOperator::$64 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#27 ← (byte~) testBinaryOperator::$64
+  (byte) assertType::t2#27 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testBinaryOperator::@22
+testBinaryOperator::@22: scope:[testBinaryOperator]  from testBinaryOperator::@21
+  (byte) idx#89 ← phi( testBinaryOperator::@21/(byte) idx#56 )
+  (byte) idx#37 ← (byte) idx#89
+  (byte~) testBinaryOperator::$67 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#28 ← (byte~) testBinaryOperator::$67
+  (byte) assertType::t2#28 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@23
+testBinaryOperator::@23: scope:[testBinaryOperator]  from testBinaryOperator::@22
+  (byte) idx#90 ← phi( testBinaryOperator::@22/(byte) idx#56 )
+  (byte) idx#38 ← (byte) idx#90
+  (byte~) testBinaryOperator::$70 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#29 ← (byte~) testBinaryOperator::$70
+  (byte) assertType::t2#29 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@24
+testBinaryOperator::@24: scope:[testBinaryOperator]  from testBinaryOperator::@23
+  (byte) idx#91 ← phi( testBinaryOperator::@23/(byte) idx#56 )
+  (byte) idx#39 ← (byte) idx#91
+  (byte) idx#40 ← ++ (byte) idx#39
+  (byte~) testBinaryOperator::$73 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#30 ← (byte~) testBinaryOperator::$73
+  (byte) assertType::t2#30 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@25
+testBinaryOperator::@25: scope:[testBinaryOperator]  from testBinaryOperator::@24
+  (byte) idx#92 ← phi( testBinaryOperator::@24/(byte) idx#56 )
+  (byte) idx#41 ← (byte) idx#92
+  (byte~) testBinaryOperator::$76 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#31 ← (byte~) testBinaryOperator::$76
+  (byte) assertType::t2#31 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@26
+testBinaryOperator::@26: scope:[testBinaryOperator]  from testBinaryOperator::@25
+  (byte) idx#93 ← phi( testBinaryOperator::@25/(byte) idx#56 )
+  (byte) idx#42 ← (byte) idx#93
+  (byte~) testBinaryOperator::$79 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#32 ← (byte~) testBinaryOperator::$79
+  (byte) assertType::t2#32 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@27
+testBinaryOperator::@27: scope:[testBinaryOperator]  from testBinaryOperator::@26
+  (byte) idx#94 ← phi( testBinaryOperator::@26/(byte) idx#56 )
+  (byte) idx#43 ← (byte) idx#94
+  (byte~) testBinaryOperator::$82 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#33 ← (byte~) testBinaryOperator::$82
+  (byte) assertType::t2#33 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@28
+testBinaryOperator::@28: scope:[testBinaryOperator]  from testBinaryOperator::@27
+  (byte) idx#95 ← phi( testBinaryOperator::@27/(byte) idx#56 )
+  (byte) idx#44 ← (byte) idx#95
+  (byte~) testBinaryOperator::$85 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#34 ← (byte~) testBinaryOperator::$85
+  (byte) assertType::t2#34 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@29
+testBinaryOperator::@29: scope:[testBinaryOperator]  from testBinaryOperator::@28
+  (byte) idx#96 ← phi( testBinaryOperator::@28/(byte) idx#56 )
+  (byte) idx#45 ← (byte) idx#96
+  (byte~) testBinaryOperator::$88 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#35 ← (byte~) testBinaryOperator::$88
+  (byte) assertType::t2#35 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@30
+testBinaryOperator::@30: scope:[testBinaryOperator]  from testBinaryOperator::@29
+  (byte) idx#97 ← phi( testBinaryOperator::@29/(byte) idx#56 )
+  (byte) idx#46 ← (byte) idx#97
+  (byte) idx#47 ← ++ (byte) idx#46
+  (byte~) testBinaryOperator::$91 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#36 ← (byte~) testBinaryOperator::$91
+  (byte) assertType::t2#36 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@31
+testBinaryOperator::@31: scope:[testBinaryOperator]  from testBinaryOperator::@30
+  (byte) idx#98 ← phi( testBinaryOperator::@30/(byte) idx#56 )
+  (byte) idx#48 ← (byte) idx#98
+  (byte~) testBinaryOperator::$94 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#37 ← (byte~) testBinaryOperator::$94
+  (byte) assertType::t2#37 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@32
+testBinaryOperator::@32: scope:[testBinaryOperator]  from testBinaryOperator::@31
+  (byte) idx#99 ← phi( testBinaryOperator::@31/(byte) idx#56 )
+  (byte) idx#49 ← (byte) idx#99
+  (byte~) testBinaryOperator::$97 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#38 ← (byte~) testBinaryOperator::$97
+  (byte) assertType::t2#38 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@33
+testBinaryOperator::@33: scope:[testBinaryOperator]  from testBinaryOperator::@32
+  (byte) idx#100 ← phi( testBinaryOperator::@32/(byte) idx#56 )
+  (byte) idx#50 ← (byte) idx#100
+  (byte~) testBinaryOperator::$100 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#39 ← (byte~) testBinaryOperator::$100
+  (byte) assertType::t2#39 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@34
+testBinaryOperator::@34: scope:[testBinaryOperator]  from testBinaryOperator::@33
+  (byte) idx#101 ← phi( testBinaryOperator::@33/(byte) idx#56 )
+  (byte) idx#51 ← (byte) idx#101
+  (byte~) testBinaryOperator::$103 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#40 ← (byte~) testBinaryOperator::$103
+  (byte) assertType::t2#40 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testBinaryOperator::@35
+testBinaryOperator::@35: scope:[testBinaryOperator]  from testBinaryOperator::@34
+  (byte) idx#102 ← phi( testBinaryOperator::@34/(byte) idx#56 )
+  (byte) idx#52 ← (byte) idx#102
+  (byte~) testBinaryOperator::$106 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#41 ← (byte~) testBinaryOperator::$106
+  (byte) assertType::t2#41 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testBinaryOperator::@36
+testBinaryOperator::@36: scope:[testBinaryOperator]  from testBinaryOperator::@35
+  (byte) idx#103 ← phi( testBinaryOperator::@35/(byte) idx#56 )
+  (byte) idx#53 ← (byte) idx#103
+  to:testBinaryOperator::@return
+testBinaryOperator::@return: scope:[testBinaryOperator]  from testBinaryOperator::@36
+  (byte) idx#104 ← phi( testBinaryOperator::@36/(byte) idx#53 )
+  (byte) idx#54 ← (byte) idx#104
+  return 
+  to:@return
+assertType: scope:[assertType]  from testBinaryOperator testBinaryOperator::@1 testBinaryOperator::@10 testBinaryOperator::@11 testBinaryOperator::@12 testBinaryOperator::@13 testBinaryOperator::@14 testBinaryOperator::@15 testBinaryOperator::@16 testBinaryOperator::@17 testBinaryOperator::@18 testBinaryOperator::@19 testBinaryOperator::@2 testBinaryOperator::@20 testBinaryOperator::@21 testBinaryOperator::@22 testBinaryOperator::@23 testBinaryOperator::@24 testBinaryOperator::@25 testBinaryOperator::@26 testBinaryOperator::@27 testBinaryOperator::@28 testBinaryOperator::@29 testBinaryOperator::@3 testBinaryOperator::@30 testBinaryOperator::@31 testBinaryOperator::@32 testBinaryOperator::@33 testBinaryOperator::@34 testBinaryOperator::@35 testBinaryOperator::@4 testBinaryOperator::@5 testBinaryOperator::@6 testBinaryOperator::@7 testBinaryOperator::@8 testBinaryOperator::@9 testUnaryOperator testUnaryOperator::@1 testUnaryOperator::@2 testUnaryOperator::@3 testUnaryOperator::@4 testUnaryOperator::@5
+  (byte) idx#111 ← phi( testBinaryOperator/(byte) idx#12 testBinaryOperator::@1/(byte) idx#13 testBinaryOperator::@10/(byte) idx#23 testBinaryOperator::@11/(byte) idx#24 testBinaryOperator::@12/(byte) idx#26 testBinaryOperator::@13/(byte) idx#27 testBinaryOperator::@14/(byte) idx#28 testBinaryOperator::@15/(byte) idx#29 testBinaryOperator::@16/(byte) idx#30 testBinaryOperator::@17/(byte) idx#31 testBinaryOperator::@18/(byte) idx#33 testBinaryOperator::@19/(byte) idx#34 testBinaryOperator::@2/(byte) idx#14 testBinaryOperator::@20/(byte) idx#35 testBinaryOperator::@21/(byte) idx#36 testBinaryOperator::@22/(byte) idx#37 testBinaryOperator::@23/(byte) idx#38 testBinaryOperator::@24/(byte) idx#40 testBinaryOperator::@25/(byte) idx#41 testBinaryOperator::@26/(byte) idx#42 testBinaryOperator::@27/(byte) idx#43 testBinaryOperator::@28/(byte) idx#44 testBinaryOperator::@29/(byte) idx#45 testBinaryOperator::@3/(byte) idx#15 testBinaryOperator::@30/(byte) idx#47 testBinaryOperator::@31/(byte) idx#48 testBinaryOperator::@32/(byte) idx#49 testBinaryOperator::@33/(byte) idx#50 testBinaryOperator::@34/(byte) idx#51 testBinaryOperator::@35/(byte) idx#52 testBinaryOperator::@4/(byte) idx#16 testBinaryOperator::@5/(byte) idx#17 testBinaryOperator::@6/(byte) idx#19 testBinaryOperator::@7/(byte) idx#20 testBinaryOperator::@8/(byte) idx#21 testBinaryOperator::@9/(byte) idx#22 testUnaryOperator/(byte) idx#4 testUnaryOperator::@1/(byte) idx#5 testUnaryOperator::@2/(byte) idx#6 testUnaryOperator::@3/(byte) idx#7 testUnaryOperator::@4/(byte) idx#8 testUnaryOperator::@5/(byte) idx#9 )
+  (byte) assertType::t2#42 ← phi( testBinaryOperator/(byte) assertType::t2#6 testBinaryOperator::@1/(byte) assertType::t2#7 testBinaryOperator::@10/(byte) assertType::t2#16 testBinaryOperator::@11/(byte) assertType::t2#17 testBinaryOperator::@12/(byte) assertType::t2#18 testBinaryOperator::@13/(byte) assertType::t2#19 testBinaryOperator::@14/(byte) assertType::t2#20 testBinaryOperator::@15/(byte) assertType::t2#21 testBinaryOperator::@16/(byte) assertType::t2#22 testBinaryOperator::@17/(byte) assertType::t2#23 testBinaryOperator::@18/(byte) assertType::t2#24 testBinaryOperator::@19/(byte) assertType::t2#25 testBinaryOperator::@2/(byte) assertType::t2#8 testBinaryOperator::@20/(byte) assertType::t2#26 testBinaryOperator::@21/(byte) assertType::t2#27 testBinaryOperator::@22/(byte) assertType::t2#28 testBinaryOperator::@23/(byte) assertType::t2#29 testBinaryOperator::@24/(byte) assertType::t2#30 testBinaryOperator::@25/(byte) assertType::t2#31 testBinaryOperator::@26/(byte) assertType::t2#32 testBinaryOperator::@27/(byte) assertType::t2#33 testBinaryOperator::@28/(byte) assertType::t2#34 testBinaryOperator::@29/(byte) assertType::t2#35 testBinaryOperator::@3/(byte) assertType::t2#9 testBinaryOperator::@30/(byte) assertType::t2#36 testBinaryOperator::@31/(byte) assertType::t2#37 testBinaryOperator::@32/(byte) assertType::t2#38 testBinaryOperator::@33/(byte) assertType::t2#39 testBinaryOperator::@34/(byte) assertType::t2#40 testBinaryOperator::@35/(byte) assertType::t2#41 testBinaryOperator::@4/(byte) assertType::t2#10 testBinaryOperator::@5/(byte) assertType::t2#11 testBinaryOperator::@6/(byte) assertType::t2#12 testBinaryOperator::@7/(byte) assertType::t2#13 testBinaryOperator::@8/(byte) assertType::t2#14 testBinaryOperator::@9/(byte) assertType::t2#15 testUnaryOperator/(byte) assertType::t2#0 testUnaryOperator::@1/(byte) assertType::t2#1 testUnaryOperator::@2/(byte) assertType::t2#2 testUnaryOperator::@3/(byte) assertType::t2#3 testUnaryOperator::@4/(byte) assertType::t2#4 testUnaryOperator::@5/(byte) assertType::t2#5 )
+  (byte) assertType::t1#42 ← phi( testBinaryOperator/(byte) assertType::t1#6 testBinaryOperator::@1/(byte) assertType::t1#7 testBinaryOperator::@10/(byte) assertType::t1#16 testBinaryOperator::@11/(byte) assertType::t1#17 testBinaryOperator::@12/(byte) assertType::t1#18 testBinaryOperator::@13/(byte) assertType::t1#19 testBinaryOperator::@14/(byte) assertType::t1#20 testBinaryOperator::@15/(byte) assertType::t1#21 testBinaryOperator::@16/(byte) assertType::t1#22 testBinaryOperator::@17/(byte) assertType::t1#23 testBinaryOperator::@18/(byte) assertType::t1#24 testBinaryOperator::@19/(byte) assertType::t1#25 testBinaryOperator::@2/(byte) assertType::t1#8 testBinaryOperator::@20/(byte) assertType::t1#26 testBinaryOperator::@21/(byte) assertType::t1#27 testBinaryOperator::@22/(byte) assertType::t1#28 testBinaryOperator::@23/(byte) assertType::t1#29 testBinaryOperator::@24/(byte) assertType::t1#30 testBinaryOperator::@25/(byte) assertType::t1#31 testBinaryOperator::@26/(byte) assertType::t1#32 testBinaryOperator::@27/(byte) assertType::t1#33 testBinaryOperator::@28/(byte) assertType::t1#34 testBinaryOperator::@29/(byte) assertType::t1#35 testBinaryOperator::@3/(byte) assertType::t1#9 testBinaryOperator::@30/(byte) assertType::t1#36 testBinaryOperator::@31/(byte) assertType::t1#37 testBinaryOperator::@32/(byte) assertType::t1#38 testBinaryOperator::@33/(byte) assertType::t1#39 testBinaryOperator::@34/(byte) assertType::t1#40 testBinaryOperator::@35/(byte) assertType::t1#41 testBinaryOperator::@4/(byte) assertType::t1#10 testBinaryOperator::@5/(byte) assertType::t1#11 testBinaryOperator::@6/(byte) assertType::t1#12 testBinaryOperator::@7/(byte) assertType::t1#13 testBinaryOperator::@8/(byte) assertType::t1#14 testBinaryOperator::@9/(byte) assertType::t1#15 testUnaryOperator/(byte) assertType::t1#0 testUnaryOperator::@1/(byte) assertType::t1#1 testUnaryOperator::@2/(byte) assertType::t1#2 testUnaryOperator::@3/(byte) assertType::t1#3 testUnaryOperator::@4/(byte) assertType::t1#4 testUnaryOperator::@5/(byte) assertType::t1#5 )
+  (bool~) assertType::$0 ← (byte) assertType::t1#42 == (byte) assertType::t2#42
+  if((bool~) assertType::$0) goto assertType::@1
+  to:assertType::@3
+assertType::@1: scope:[assertType]  from assertType
+  (byte) assertType::t1#44 ← phi( assertType/(byte) assertType::t1#42 )
+  (byte) idx#105 ← phi( assertType/(byte) idx#111 )
+  *((byte*) COLS#0 + (byte) idx#105) ← (byte) GREEN#0
+  to:assertType::@2
+assertType::@3: scope:[assertType]  from assertType
+  (byte) assertType::t1#45 ← phi( assertType/(byte) assertType::t1#42 )
+  (byte) idx#106 ← phi( assertType/(byte) idx#111 )
+  *((byte*) COLS#0 + (byte) idx#106) ← (byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  (byte) idx#107 ← phi( assertType::@1/(byte) idx#105 assertType::@3/(byte) idx#106 )
+  (byte) assertType::t1#43 ← phi( assertType::@1/(byte) assertType::t1#44 assertType::@3/(byte) assertType::t1#45 )
+  *((byte*) SCREEN#0 + (byte) idx#107) ← (byte) assertType::t1#43
+  (byte) idx#55 ← ++ (byte) idx#107
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  (byte) idx#108 ← phi( assertType::@2/(byte) idx#55 )
+  (byte) idx#56 ← (byte) idx#108
+  return 
+  to:@return
+@4: scope:[]  from @begin
+  (byte) idx#112 ← phi( @begin/(byte) idx#0 )
+  call main 
+  to:@5
+@5: scope:[]  from @4
+  (byte) idx#109 ← phi( @4/(byte) idx#3 )
+  (byte) idx#57 ← (byte) idx#109
+  to:@end
+@end: scope:[]  from @5
+
+SYMBOL TABLE SSA
+(label) @4
+(label) @5
+(label) @begin
+(label) @end
+(byte*) COLS
+(byte*) COLS#0
+(byte) GREEN
+(byte) GREEN#0
+(byte) RED
+(byte) RED#0
+(byte*) SCREEN
+(byte*) SCREEN#0
+(const byte) TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(bool~) assertType::$0
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#0
+(byte) assertType::t1#1
+(byte) assertType::t1#10
+(byte) assertType::t1#11
+(byte) assertType::t1#12
+(byte) assertType::t1#13
+(byte) assertType::t1#14
+(byte) assertType::t1#15
+(byte) assertType::t1#16
+(byte) assertType::t1#17
+(byte) assertType::t1#18
+(byte) assertType::t1#19
+(byte) assertType::t1#2
+(byte) assertType::t1#20
+(byte) assertType::t1#21
+(byte) assertType::t1#22
+(byte) assertType::t1#23
+(byte) assertType::t1#24
+(byte) assertType::t1#25
+(byte) assertType::t1#26
+(byte) assertType::t1#27
+(byte) assertType::t1#28
+(byte) assertType::t1#29
+(byte) assertType::t1#3
+(byte) assertType::t1#30
+(byte) assertType::t1#31
+(byte) assertType::t1#32
+(byte) assertType::t1#33
+(byte) assertType::t1#34
+(byte) assertType::t1#35
+(byte) assertType::t1#36
+(byte) assertType::t1#37
+(byte) assertType::t1#38
+(byte) assertType::t1#39
+(byte) assertType::t1#4
+(byte) assertType::t1#40
+(byte) assertType::t1#41
+(byte) assertType::t1#42
+(byte) assertType::t1#43
+(byte) assertType::t1#44
+(byte) assertType::t1#45
+(byte) assertType::t1#5
+(byte) assertType::t1#6
+(byte) assertType::t1#7
+(byte) assertType::t1#8
+(byte) assertType::t1#9
+(byte) assertType::t2
+(byte) assertType::t2#0
+(byte) assertType::t2#1
+(byte) assertType::t2#10
+(byte) assertType::t2#11
+(byte) assertType::t2#12
+(byte) assertType::t2#13
+(byte) assertType::t2#14
+(byte) assertType::t2#15
+(byte) assertType::t2#16
+(byte) assertType::t2#17
+(byte) assertType::t2#18
+(byte) assertType::t2#19
+(byte) assertType::t2#2
+(byte) assertType::t2#20
+(byte) assertType::t2#21
+(byte) assertType::t2#22
+(byte) assertType::t2#23
+(byte) assertType::t2#24
+(byte) assertType::t2#25
+(byte) assertType::t2#26
+(byte) assertType::t2#27
+(byte) assertType::t2#28
+(byte) assertType::t2#29
+(byte) assertType::t2#3
+(byte) assertType::t2#30
+(byte) assertType::t2#31
+(byte) assertType::t2#32
+(byte) assertType::t2#33
+(byte) assertType::t2#34
+(byte) assertType::t2#35
+(byte) assertType::t2#36
+(byte) assertType::t2#37
+(byte) assertType::t2#38
+(byte) assertType::t2#39
+(byte) assertType::t2#4
+(byte) assertType::t2#40
+(byte) assertType::t2#41
+(byte) assertType::t2#42
+(byte) assertType::t2#5
+(byte) assertType::t2#6
+(byte) assertType::t2#7
+(byte) assertType::t2#8
+(byte) assertType::t2#9
+(byte) idx
+(byte) idx#0
+(byte) idx#1
+(byte) idx#10
+(byte) idx#100
+(byte) idx#101
+(byte) idx#102
+(byte) idx#103
+(byte) idx#104
+(byte) idx#105
+(byte) idx#106
+(byte) idx#107
+(byte) idx#108
+(byte) idx#109
+(byte) idx#11
+(byte) idx#110
+(byte) idx#111
+(byte) idx#112
+(byte) idx#113
+(byte) idx#114
+(byte) idx#12
+(byte) idx#13
+(byte) idx#14
+(byte) idx#15
+(byte) idx#16
+(byte) idx#17
+(byte) idx#18
+(byte) idx#19
+(byte) idx#2
+(byte) idx#20
+(byte) idx#21
+(byte) idx#22
+(byte) idx#23
+(byte) idx#24
+(byte) idx#25
+(byte) idx#26
+(byte) idx#27
+(byte) idx#28
+(byte) idx#29
+(byte) idx#3
+(byte) idx#30
+(byte) idx#31
+(byte) idx#32
+(byte) idx#33
+(byte) idx#34
+(byte) idx#35
+(byte) idx#36
+(byte) idx#37
+(byte) idx#38
+(byte) idx#39
+(byte) idx#4
+(byte) idx#40
+(byte) idx#41
+(byte) idx#42
+(byte) idx#43
+(byte) idx#44
+(byte) idx#45
+(byte) idx#46
+(byte) idx#47
+(byte) idx#48
+(byte) idx#49
+(byte) idx#5
+(byte) idx#50
+(byte) idx#51
+(byte) idx#52
+(byte) idx#53
+(byte) idx#54
+(byte) idx#55
+(byte) idx#56
+(byte) idx#57
+(byte) idx#58
+(byte) idx#59
+(byte) idx#6
+(byte) idx#60
+(byte) idx#61
+(byte) idx#62
+(byte) idx#63
+(byte) idx#64
+(byte) idx#65
+(byte) idx#66
+(byte) idx#67
+(byte) idx#68
+(byte) idx#69
+(byte) idx#7
+(byte) idx#70
+(byte) idx#71
+(byte) idx#72
+(byte) idx#73
+(byte) idx#74
+(byte) idx#75
+(byte) idx#76
+(byte) idx#77
+(byte) idx#78
+(byte) idx#79
+(byte) idx#8
+(byte) idx#80
+(byte) idx#81
+(byte) idx#82
+(byte) idx#83
+(byte) idx#84
+(byte) idx#85
+(byte) idx#86
+(byte) idx#87
+(byte) idx#88
+(byte) idx#89
+(byte) idx#9
+(byte) idx#90
+(byte) idx#91
+(byte) idx#92
+(byte) idx#93
+(byte) idx#94
+(byte) idx#95
+(byte) idx#96
+(byte) idx#97
+(byte) idx#98
+(byte) idx#99
+(void()) main()
+(byte*~) main::$2
+(bool~) main::$3
+(label) main::@1
+(label) main::@2
+(label) main::@3
+(label) main::@4
+(label) main::@return
+(byte*) main::s
+(byte*) main::s#0
+(byte*) main::s#1
+(byte*) main::s#2
+(void()) testBinaryOperator()
+(byte~) testBinaryOperator::$1
+(byte~) testBinaryOperator::$10
+(byte~) testBinaryOperator::$100
+(byte~) testBinaryOperator::$103
+(byte~) testBinaryOperator::$106
+(byte~) testBinaryOperator::$13
+(byte~) testBinaryOperator::$16
+(byte~) testBinaryOperator::$19
+(byte~) testBinaryOperator::$22
+(byte~) testBinaryOperator::$25
+(byte~) testBinaryOperator::$28
+(byte~) testBinaryOperator::$31
+(byte~) testBinaryOperator::$34
+(byte~) testBinaryOperator::$37
+(byte~) testBinaryOperator::$4
+(byte~) testBinaryOperator::$40
+(byte~) testBinaryOperator::$43
+(byte~) testBinaryOperator::$46
+(byte~) testBinaryOperator::$49
+(byte~) testBinaryOperator::$52
+(byte~) testBinaryOperator::$55
+(byte~) testBinaryOperator::$58
+(byte~) testBinaryOperator::$61
+(byte~) testBinaryOperator::$64
+(byte~) testBinaryOperator::$67
+(byte~) testBinaryOperator::$7
+(byte~) testBinaryOperator::$70
+(byte~) testBinaryOperator::$73
+(byte~) testBinaryOperator::$76
+(byte~) testBinaryOperator::$79
+(byte~) testBinaryOperator::$82
+(byte~) testBinaryOperator::$85
+(byte~) testBinaryOperator::$88
+(byte~) testBinaryOperator::$91
+(byte~) testBinaryOperator::$94
+(byte~) testBinaryOperator::$97
+(label) testBinaryOperator::@1
+(label) testBinaryOperator::@10
+(label) testBinaryOperator::@11
+(label) testBinaryOperator::@12
+(label) testBinaryOperator::@13
+(label) testBinaryOperator::@14
+(label) testBinaryOperator::@15
+(label) testBinaryOperator::@16
+(label) testBinaryOperator::@17
+(label) testBinaryOperator::@18
+(label) testBinaryOperator::@19
+(label) testBinaryOperator::@2
+(label) testBinaryOperator::@20
+(label) testBinaryOperator::@21
+(label) testBinaryOperator::@22
+(label) testBinaryOperator::@23
+(label) testBinaryOperator::@24
+(label) testBinaryOperator::@25
+(label) testBinaryOperator::@26
+(label) testBinaryOperator::@27
+(label) testBinaryOperator::@28
+(label) testBinaryOperator::@29
+(label) testBinaryOperator::@3
+(label) testBinaryOperator::@30
+(label) testBinaryOperator::@31
+(label) testBinaryOperator::@32
+(label) testBinaryOperator::@33
+(label) testBinaryOperator::@34
+(label) testBinaryOperator::@35
+(label) testBinaryOperator::@36
+(label) testBinaryOperator::@4
+(label) testBinaryOperator::@5
+(label) testBinaryOperator::@6
+(label) testBinaryOperator::@7
+(label) testBinaryOperator::@8
+(label) testBinaryOperator::@9
+(label) testBinaryOperator::@return
+(void()) testUnaryOperator()
+(byte~) testUnaryOperator::$1
+(byte~) testUnaryOperator::$10
+(byte~) testUnaryOperator::$13
+(byte~) testUnaryOperator::$16
+(byte~) testUnaryOperator::$4
+(byte~) testUnaryOperator::$7
+(label) testUnaryOperator::@1
+(label) testUnaryOperator::@2
+(label) testUnaryOperator::@3
+(label) testUnaryOperator::@4
+(label) testUnaryOperator::@5
+(label) testUnaryOperator::@6
+(label) testUnaryOperator::@return
+
+Alias (byte) idx#110 = (byte) idx#113 
+Alias (byte) idx#1 = (byte) idx#58 
+Alias (byte) idx#2 = (byte) idx#59 (byte) idx#60 (byte) idx#3 
+Alias (byte) assertType::t1#0 = (byte~) testUnaryOperator::$1 
+Alias (byte) idx#5 = (byte) idx#61 
+Alias (byte) assertType::t1#1 = (byte~) testUnaryOperator::$4 
+Alias (byte) idx#6 = (byte) idx#62 
+Alias (byte) assertType::t1#2 = (byte~) testUnaryOperator::$7 
+Alias (byte) idx#63 = (byte) idx#7 
+Alias (byte) assertType::t1#3 = (byte~) testUnaryOperator::$10 
+Alias (byte) idx#64 = (byte) idx#8 
+Alias (byte) assertType::t1#4 = (byte~) testUnaryOperator::$13 
+Alias (byte) idx#65 = (byte) idx#9 
+Alias (byte) assertType::t1#5 = (byte~) testUnaryOperator::$16 
+Alias (byte) idx#10 = (byte) idx#66 (byte) idx#67 (byte) idx#11 
+Alias (byte) assertType::t1#6 = (byte~) testBinaryOperator::$1 
+Alias (byte) idx#13 = (byte) idx#68 
+Alias (byte) assertType::t1#7 = (byte~) testBinaryOperator::$4 
+Alias (byte) idx#14 = (byte) idx#69 
+Alias (byte) assertType::t1#8 = (byte~) testBinaryOperator::$7 
+Alias (byte) idx#15 = (byte) idx#70 
+Alias (byte) assertType::t1#9 = (byte~) testBinaryOperator::$10 
+Alias (byte) idx#16 = (byte) idx#71 
+Alias (byte) assertType::t1#10 = (byte~) testBinaryOperator::$13 
+Alias (byte) idx#17 = (byte) idx#72 
+Alias (byte) assertType::t1#11 = (byte~) testBinaryOperator::$16 
+Alias (byte) idx#18 = (byte) idx#73 
+Alias (byte) assertType::t1#12 = (byte~) testBinaryOperator::$19 
+Alias (byte) idx#20 = (byte) idx#74 
+Alias (byte) assertType::t1#13 = (byte~) testBinaryOperator::$22 
+Alias (byte) idx#21 = (byte) idx#75 
+Alias (byte) assertType::t1#14 = (byte~) testBinaryOperator::$25 
+Alias (byte) idx#22 = (byte) idx#76 
+Alias (byte) assertType::t1#15 = (byte~) testBinaryOperator::$28 
+Alias (byte) idx#23 = (byte) idx#77 
+Alias (byte) assertType::t1#16 = (byte~) testBinaryOperator::$31 
+Alias (byte) idx#24 = (byte) idx#78 
+Alias (byte) assertType::t1#17 = (byte~) testBinaryOperator::$34 
+Alias (byte) idx#25 = (byte) idx#79 
+Alias (byte) assertType::t1#18 = (byte~) testBinaryOperator::$37 
+Alias (byte) idx#27 = (byte) idx#80 
+Alias (byte) assertType::t1#19 = (byte~) testBinaryOperator::$40 
+Alias (byte) idx#28 = (byte) idx#81 
+Alias (byte) assertType::t1#20 = (byte~) testBinaryOperator::$43 
+Alias (byte) idx#29 = (byte) idx#82 
+Alias (byte) assertType::t1#21 = (byte~) testBinaryOperator::$46 
+Alias (byte) idx#30 = (byte) idx#83 
+Alias (byte) assertType::t1#22 = (byte~) testBinaryOperator::$49 
+Alias (byte) idx#31 = (byte) idx#84 
+Alias (byte) assertType::t1#23 = (byte~) testBinaryOperator::$52 
+Alias (byte) idx#32 = (byte) idx#85 
+Alias (byte) assertType::t1#24 = (byte~) testBinaryOperator::$55 
+Alias (byte) idx#34 = (byte) idx#86 
+Alias (byte) assertType::t1#25 = (byte~) testBinaryOperator::$58 
+Alias (byte) idx#35 = (byte) idx#87 
+Alias (byte) assertType::t1#26 = (byte~) testBinaryOperator::$61 
+Alias (byte) idx#36 = (byte) idx#88 
+Alias (byte) assertType::t1#27 = (byte~) testBinaryOperator::$64 
+Alias (byte) idx#37 = (byte) idx#89 
+Alias (byte) assertType::t1#28 = (byte~) testBinaryOperator::$67 
+Alias (byte) idx#38 = (byte) idx#90 
+Alias (byte) assertType::t1#29 = (byte~) testBinaryOperator::$70 
+Alias (byte) idx#39 = (byte) idx#91 
+Alias (byte) assertType::t1#30 = (byte~) testBinaryOperator::$73 
+Alias (byte) idx#41 = (byte) idx#92 
+Alias (byte) assertType::t1#31 = (byte~) testBinaryOperator::$76 
+Alias (byte) idx#42 = (byte) idx#93 
+Alias (byte) assertType::t1#32 = (byte~) testBinaryOperator::$79 
+Alias (byte) idx#43 = (byte) idx#94 
+Alias (byte) assertType::t1#33 = (byte~) testBinaryOperator::$82 
+Alias (byte) idx#44 = (byte) idx#95 
+Alias (byte) assertType::t1#34 = (byte~) testBinaryOperator::$85 
+Alias (byte) idx#45 = (byte) idx#96 
+Alias (byte) assertType::t1#35 = (byte~) testBinaryOperator::$88 
+Alias (byte) idx#46 = (byte) idx#97 
+Alias (byte) assertType::t1#36 = (byte~) testBinaryOperator::$91 
+Alias (byte) idx#48 = (byte) idx#98 
+Alias (byte) assertType::t1#37 = (byte~) testBinaryOperator::$94 
+Alias (byte) idx#49 = (byte) idx#99 
+Alias (byte) assertType::t1#38 = (byte~) testBinaryOperator::$97 
+Alias (byte) idx#100 = (byte) idx#50 
+Alias (byte) assertType::t1#39 = (byte~) testBinaryOperator::$100 
+Alias (byte) idx#101 = (byte) idx#51 
+Alias (byte) assertType::t1#40 = (byte~) testBinaryOperator::$103 
+Alias (byte) idx#102 = (byte) idx#52 
+Alias (byte) assertType::t1#41 = (byte~) testBinaryOperator::$106 
+Alias (byte) idx#103 = (byte) idx#53 (byte) idx#104 (byte) idx#54 
+Alias (byte) idx#105 = (byte) idx#111 (byte) idx#106 
+Alias (byte) assertType::t1#42 = (byte) assertType::t1#44 (byte) assertType::t1#45 
+Alias (byte) idx#108 = (byte) idx#55 (byte) idx#56 
+Alias (byte) idx#0 = (byte) idx#112 
+Alias (byte) idx#109 = (byte) idx#57 
+Successful SSA optimization Pass2AliasElimination
+Alias (byte) assertType::t1#42 = (byte) assertType::t1#43 
+Alias (byte) idx#105 = (byte) idx#107 
+Successful SSA optimization Pass2AliasElimination
+Self Phi Eliminated (byte) idx#110
+Successful SSA optimization Pass2SelfPhiElimination
+Redundant Phi (byte) idx#114 (byte) idx#0
+Redundant Phi (byte) idx#110 (byte) idx#114
+Redundant Phi (byte) idx#1 (byte) idx#10
+Redundant Phi (byte) idx#2 (byte) idx#103
+Redundant Phi (byte) idx#5 (byte) idx#108
+Redundant Phi (byte) idx#6 (byte) idx#108
+Redundant Phi (byte) idx#63 (byte) idx#108
+Redundant Phi (byte) idx#64 (byte) idx#108
+Redundant Phi (byte) idx#65 (byte) idx#108
+Redundant Phi (byte) idx#10 (byte) idx#108
+Redundant Phi (byte) idx#13 (byte) idx#108
+Redundant Phi (byte) idx#14 (byte) idx#108
+Redundant Phi (byte) idx#15 (byte) idx#108
+Redundant Phi (byte) idx#16 (byte) idx#108
+Redundant Phi (byte) idx#17 (byte) idx#108
+Redundant Phi (byte) idx#18 (byte) idx#108
+Redundant Phi (byte) idx#20 (byte) idx#108
+Redundant Phi (byte) idx#21 (byte) idx#108
+Redundant Phi (byte) idx#22 (byte) idx#108
+Redundant Phi (byte) idx#23 (byte) idx#108
+Redundant Phi (byte) idx#24 (byte) idx#108
+Redundant Phi (byte) idx#25 (byte) idx#108
+Redundant Phi (byte) idx#27 (byte) idx#108
+Redundant Phi (byte) idx#28 (byte) idx#108
+Redundant Phi (byte) idx#29 (byte) idx#108
+Redundant Phi (byte) idx#30 (byte) idx#108
+Redundant Phi (byte) idx#31 (byte) idx#108
+Redundant Phi (byte) idx#32 (byte) idx#108
+Redundant Phi (byte) idx#34 (byte) idx#108
+Redundant Phi (byte) idx#35 (byte) idx#108
+Redundant Phi (byte) idx#36 (byte) idx#108
+Redundant Phi (byte) idx#37 (byte) idx#108
+Redundant Phi (byte) idx#38 (byte) idx#108
+Redundant Phi (byte) idx#39 (byte) idx#108
+Redundant Phi (byte) idx#41 (byte) idx#108
+Redundant Phi (byte) idx#42 (byte) idx#108
+Redundant Phi (byte) idx#43 (byte) idx#108
+Redundant Phi (byte) idx#44 (byte) idx#108
+Redundant Phi (byte) idx#45 (byte) idx#108
+Redundant Phi (byte) idx#46 (byte) idx#108
+Redundant Phi (byte) idx#48 (byte) idx#108
+Redundant Phi (byte) idx#49 (byte) idx#108
+Redundant Phi (byte) idx#100 (byte) idx#108
+Redundant Phi (byte) idx#101 (byte) idx#108
+Redundant Phi (byte) idx#102 (byte) idx#108
+Redundant Phi (byte) idx#103 (byte) idx#108
+Redundant Phi (byte) idx#109 (byte) idx#2
+Successful SSA optimization Pass2RedundantPhiElimination
+Simple Condition (bool~) main::$3 [12] if((byte*) main::s#1<(byte*~) main::$2) goto main::@1
+Simple Condition (bool~) assertType::$0 [290] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1
+Successful SSA optimization Pass2ConditionalJumpSimplification
+Constant right-side identified [2] (byte*) SCREEN#0 ← ((byte*)) (word) $400
+Constant right-side identified [3] (byte*) COLS#0 ← ((byte*)) (word) $d800
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) RED#0 = 2
+Constant (const byte) GREEN#0 = 5
+Constant (const byte*) SCREEN#0 = ((byte*))$400
+Constant (const byte*) COLS#0 = ((byte*))$d800
+Constant (const byte) idx#0 = 0
+Constant (const byte) idx#4 = 0
+Constant (const byte) assertType::t1#0 = TYPEID_BYTE
+Constant (const byte) assertType::t2#0 = TYPEID_BYTE
+Constant (const byte) assertType::t1#1 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t2#1 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t1#2 = TYPEID_WORD
+Constant (const byte) assertType::t2#2 = TYPEID_WORD
+Constant (const byte) assertType::t1#3 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#3 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#4 = TYPEID_DWORD
+Constant (const byte) assertType::t2#4 = TYPEID_DWORD
+Constant (const byte) assertType::t1#5 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#5 = TYPEID_SIGNED_DWORD
+Constant (const byte) idx#12 = $28
+Constant (const byte) assertType::t1#6 = TYPEID_BYTE
+Constant (const byte) assertType::t2#6 = TYPEID_BYTE
+Constant (const byte) assertType::t1#7 = TYPEID_BYTE
+Constant (const byte) assertType::t2#7 = TYPEID_BYTE
+Constant (const byte) assertType::t1#8 = TYPEID_WORD
+Constant (const byte) assertType::t2#8 = TYPEID_WORD
+Constant (const byte) assertType::t1#9 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#9 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#10 = TYPEID_DWORD
+Constant (const byte) assertType::t2#10 = TYPEID_DWORD
+Constant (const byte) assertType::t1#11 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#11 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#12 = TYPEID_BYTE
+Constant (const byte) assertType::t2#12 = TYPEID_BYTE
+Constant (const byte) assertType::t1#13 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t2#13 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t1#14 = TYPEID_WORD
+Constant (const byte) assertType::t2#14 = TYPEID_WORD
+Constant (const byte) assertType::t1#15 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#15 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#16 = TYPEID_DWORD
+Constant (const byte) assertType::t2#16 = TYPEID_DWORD
+Constant (const byte) assertType::t1#17 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#17 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#18 = TYPEID_WORD
+Constant (const byte) assertType::t2#18 = TYPEID_WORD
+Constant (const byte) assertType::t1#19 = TYPEID_WORD
+Constant (const byte) assertType::t2#19 = TYPEID_WORD
+Constant (const byte) assertType::t1#20 = TYPEID_WORD
+Constant (const byte) assertType::t2#20 = TYPEID_WORD
+Constant (const byte) assertType::t1#21 = TYPEID_WORD
+Constant (const byte) assertType::t2#21 = TYPEID_WORD
+Constant (const byte) assertType::t1#22 = TYPEID_DWORD
+Constant (const byte) assertType::t2#22 = TYPEID_DWORD
+Constant (const byte) assertType::t1#23 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#23 = TYPEID_SIGNED_DWORD
+Constant (const byte) idx#33 = $50
+Constant (const byte) assertType::t1#24 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#24 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#25 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#25 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#26 = TYPEID_WORD
+Constant (const byte) assertType::t2#26 = TYPEID_WORD
+Constant (const byte) assertType::t1#27 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#27 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#28 = TYPEID_DWORD
+Constant (const byte) assertType::t2#28 = TYPEID_DWORD
+Constant (const byte) assertType::t1#29 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#29 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#30 = TYPEID_DWORD
+Constant (const byte) assertType::t2#30 = TYPEID_DWORD
+Constant (const byte) assertType::t1#31 = TYPEID_DWORD
+Constant (const byte) assertType::t2#31 = TYPEID_DWORD
+Constant (const byte) assertType::t1#32 = TYPEID_DWORD
+Constant (const byte) assertType::t2#32 = TYPEID_DWORD
+Constant (const byte) assertType::t1#33 = TYPEID_DWORD
+Constant (const byte) assertType::t2#33 = TYPEID_DWORD
+Constant (const byte) assertType::t1#34 = TYPEID_DWORD
+Constant (const byte) assertType::t2#34 = TYPEID_DWORD
+Constant (const byte) assertType::t1#35 = TYPEID_DWORD
+Constant (const byte) assertType::t2#35 = TYPEID_DWORD
+Constant (const byte) assertType::t1#36 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#36 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#37 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#37 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#38 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#38 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#39 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#39 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#40 = TYPEID_DWORD
+Constant (const byte) assertType::t2#40 = TYPEID_DWORD
+Constant (const byte) assertType::t1#41 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#41 = TYPEID_SIGNED_DWORD
+Successful SSA optimization Pass2ConstantIdentification
+Constant (const byte*) main::s#0 = SCREEN#0
+Successful SSA optimization Pass2ConstantIdentification
+Eliminating unused constant (const byte) idx#0
+Successful SSA optimization PassNEliminateUnusedVars
+Culled Empty Block (label) main::@4
+Culled Empty Block (label) testUnaryOperator::@6
+Culled Empty Block (label) testBinaryOperator::@36
+Culled Empty Block (label) @5
+Successful SSA optimization Pass2CullEmptyBlocks
+Constant right-side identified [3] (byte*~) main::$2 ← (const byte*) SCREEN#0 + (word) $3e8
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte*) main::$2 = SCREEN#0+$3e8
+Successful SSA optimization Pass2ConstantIdentification
+Inlining constant with var siblings (const byte*) main::s#0
+Inlining constant with var siblings (const byte) assertType::t1#0
+Inlining constant with var siblings (const byte) assertType::t2#0
+Inlining constant with var siblings (const byte) assertType::t1#1
+Inlining constant with var siblings (const byte) assertType::t2#1
+Inlining constant with var siblings (const byte) assertType::t1#2
+Inlining constant with var siblings (const byte) assertType::t2#2
+Inlining constant with var siblings (const byte) assertType::t1#3
+Inlining constant with var siblings (const byte) assertType::t2#3
+Inlining constant with var siblings (const byte) assertType::t1#4
+Inlining constant with var siblings (const byte) assertType::t2#4
+Inlining constant with var siblings (const byte) assertType::t1#5
+Inlining constant with var siblings (const byte) assertType::t2#5
+Inlining constant with var siblings (const byte) assertType::t1#6
+Inlining constant with var siblings (const byte) assertType::t2#6
+Inlining constant with var siblings (const byte) assertType::t1#7
+Inlining constant with var siblings (const byte) assertType::t2#7
+Inlining constant with var siblings (const byte) assertType::t1#8
+Inlining constant with var siblings (const byte) assertType::t2#8
+Inlining constant with var siblings (const byte) assertType::t1#9
+Inlining constant with var siblings (const byte) assertType::t2#9
+Inlining constant with var siblings (const byte) assertType::t1#10
+Inlining constant with var siblings (const byte) assertType::t2#10
+Inlining constant with var siblings (const byte) assertType::t1#11
+Inlining constant with var siblings (const byte) assertType::t2#11
+Inlining constant with var siblings (const byte) assertType::t1#12
+Inlining constant with var siblings (const byte) assertType::t2#12
+Inlining constant with var siblings (const byte) assertType::t1#13
+Inlining constant with var siblings (const byte) assertType::t2#13
+Inlining constant with var siblings (const byte) assertType::t1#14
+Inlining constant with var siblings (const byte) assertType::t2#14
+Inlining constant with var siblings (const byte) assertType::t1#15
+Inlining constant with var siblings (const byte) assertType::t2#15
+Inlining constant with var siblings (const byte) assertType::t1#16
+Inlining constant with var siblings (const byte) assertType::t2#16
+Inlining constant with var siblings (const byte) assertType::t1#17
+Inlining constant with var siblings (const byte) assertType::t2#17
+Inlining constant with var siblings (const byte) assertType::t1#18
+Inlining constant with var siblings (const byte) assertType::t2#18
+Inlining constant with var siblings (const byte) assertType::t1#19
+Inlining constant with var siblings (const byte) assertType::t2#19
+Inlining constant with var siblings (const byte) assertType::t1#20
+Inlining constant with var siblings (const byte) assertType::t2#20
+Inlining constant with var siblings (const byte) assertType::t1#21
+Inlining constant with var siblings (const byte) assertType::t2#21
+Inlining constant with var siblings (const byte) assertType::t1#22
+Inlining constant with var siblings (const byte) assertType::t2#22
+Inlining constant with var siblings (const byte) assertType::t1#23
+Inlining constant with var siblings (const byte) assertType::t2#23
+Inlining constant with var siblings (const byte) assertType::t1#24
+Inlining constant with var siblings (const byte) assertType::t2#24
+Inlining constant with var siblings (const byte) assertType::t1#25
+Inlining constant with var siblings (const byte) assertType::t2#25
+Inlining constant with var siblings (const byte) assertType::t1#26
+Inlining constant with var siblings (const byte) assertType::t2#26
+Inlining constant with var siblings (const byte) assertType::t1#27
+Inlining constant with var siblings (const byte) assertType::t2#27
+Inlining constant with var siblings (const byte) assertType::t1#28
+Inlining constant with var siblings (const byte) assertType::t2#28
+Inlining constant with var siblings (const byte) assertType::t1#29
+Inlining constant with var siblings (const byte) assertType::t2#29
+Inlining constant with var siblings (const byte) assertType::t1#30
+Inlining constant with var siblings (const byte) assertType::t2#30
+Inlining constant with var siblings (const byte) assertType::t1#31
+Inlining constant with var siblings (const byte) assertType::t2#31
+Inlining constant with var siblings (const byte) assertType::t1#32
+Inlining constant with var siblings (const byte) assertType::t2#32
+Inlining constant with var siblings (const byte) assertType::t1#33
+Inlining constant with var siblings (const byte) assertType::t2#33
+Inlining constant with var siblings (const byte) assertType::t1#34
+Inlining constant with var siblings (const byte) assertType::t2#34
+Inlining constant with var siblings (const byte) assertType::t1#35
+Inlining constant with var siblings (const byte) assertType::t2#35
+Inlining constant with var siblings (const byte) assertType::t1#36
+Inlining constant with var siblings (const byte) assertType::t2#36
+Inlining constant with var siblings (const byte) assertType::t1#37
+Inlining constant with var siblings (const byte) assertType::t2#37
+Inlining constant with var siblings (const byte) assertType::t1#38
+Inlining constant with var siblings (const byte) assertType::t2#38
+Inlining constant with var siblings (const byte) assertType::t1#39
+Inlining constant with var siblings (const byte) assertType::t2#39
+Inlining constant with var siblings (const byte) assertType::t1#40
+Inlining constant with var siblings (const byte) assertType::t2#40
+Inlining constant with var siblings (const byte) assertType::t1#41
+Inlining constant with var siblings (const byte) assertType::t2#41
+Inlining constant with var siblings (const byte) idx#4
+Inlining constant with var siblings (const byte) idx#12
+Inlining constant with var siblings (const byte) idx#33
+Constant inlined assertType::t2#5 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#6 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#7 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#8 = (const byte) TYPEID_WORD
+Constant inlined idx#33 = (byte) $50
+Constant inlined assertType::t2#9 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#31 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#30 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#21 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#33 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#20 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#32 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#23 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#35 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#22 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#34 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#25 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#37 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined idx#4 = (byte) 0
+Constant inlined assertType::t1#24 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#36 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#27 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#39 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#0 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#26 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#38 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#1 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t1#29 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#2 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#28 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#3 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#4 = (const byte) TYPEID_DWORD
+Constant inlined main::s#0 = (const byte*) SCREEN#0
+Constant inlined assertType::t2#20 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#10 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#22 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#21 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#12 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#24 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t1#11 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#23 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#14 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#26 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#13 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t2#25 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t1#16 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#28 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#27 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t1#18 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#17 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#29 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#19 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#6 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#7 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#8 = (const byte) TYPEID_WORD
+Constant inlined idx#12 = (byte) $28
+Constant inlined assertType::t1#9 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t1#41 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#40 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#11 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#10 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#13 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t2#12 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#14 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#0 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#17 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#1 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t2#16 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#2 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#19 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#3 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#18 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#4 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#5 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#40 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#30 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#41 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#32 = (const byte) TYPEID_DWORD
+Constant inlined main::$2 = (const byte*) SCREEN#0+(word) $3e8
+Constant inlined assertType::t1#31 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#34 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#33 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#36 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#35 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#38 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#37 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#39 = (const byte) TYPEID_SIGNED_DWORD
+Successful SSA optimization Pass2ConstantInlining
+Added new block during phi lifting main::@5(between main::@1 and main::@1)
+Adding NOP phi() at start of @begin
+Adding NOP phi() at start of @4
+Adding NOP phi() at start of @end
+Adding NOP phi() at start of main
+Adding NOP phi() at start of main::@2
+Adding NOP phi() at start of main::@3
+Adding NOP phi() at start of testBinaryOperator
+Adding NOP phi() at start of testBinaryOperator::@18
+Adding NOP phi() at start of testUnaryOperator
+CALL GRAPH
+Calls in [] to main:2 
+Calls in [main] to testUnaryOperator:10 testBinaryOperator:12 
+Calls in [testBinaryOperator] to assertType:16 assertType:18 assertType:20 assertType:22 assertType:24 assertType:26 assertType:29 assertType:31 assertType:33 assertType:35 assertType:37 assertType:39 assertType:42 assertType:44 assertType:46 assertType:48 assertType:50 assertType:52 assertType:54 assertType:56 assertType:58 assertType:60 assertType:62 assertType:64 assertType:67 assertType:69 assertType:71 assertType:73 assertType:75 assertType:77 assertType:80 assertType:82 assertType:84 assertType:86 assertType:88 assertType:90 
+Calls in [testUnaryOperator] to assertType:100 assertType:102 assertType:104 assertType:106 assertType:108 assertType:110 
+
+Created 4 initial phi equivalence classes
+Coalesced [14] main::s#3 ← main::s#1
+Coalesced [17] idx#115 ← idx#108
+Coalesced (already) [19] idx#125 ← idx#108
+Coalesced (already) [21] idx#136 ← idx#108
+Coalesced (already) [23] idx#143 ← idx#108
+Coalesced (already) [25] idx#144 ← idx#108
+Coalesced [28] idx#145 ← idx#19
+Coalesced (already) [30] idx#146 ← idx#108
+Coalesced (already) [32] idx#147 ← idx#108
+Coalesced (already) [34] idx#148 ← idx#108
+Coalesced (already) [36] idx#116 ← idx#108
+Coalesced (already) [38] idx#117 ← idx#108
+Coalesced [41] idx#118 ← idx#26
+Coalesced (already) [43] idx#119 ← idx#108
+Coalesced (already) [45] idx#120 ← idx#108
+Coalesced (already) [47] idx#121 ← idx#108
+Coalesced (already) [49] idx#122 ← idx#108
+Coalesced (already) [51] idx#123 ← idx#108
+Coalesced (already) [55] idx#124 ← idx#108
+Coalesced (already) [57] idx#126 ← idx#108
+Coalesced (already) [59] idx#127 ← idx#108
+Coalesced (already) [61] idx#128 ← idx#108
+Coalesced (already) [63] idx#129 ← idx#108
+Coalesced [66] idx#130 ← idx#40
+Coalesced (already) [68] idx#131 ← idx#108
+Coalesced (already) [70] idx#132 ← idx#108
+Coalesced (already) [72] idx#133 ← idx#108
+Coalesced (already) [74] idx#134 ← idx#108
+Coalesced (already) [76] idx#135 ← idx#108
+Coalesced [79] idx#137 ← idx#47
+Coalesced (already) [81] idx#138 ← idx#108
+Coalesced (already) [83] idx#139 ← idx#108
+Coalesced (already) [85] idx#140 ← idx#108
+Coalesced (already) [87] idx#141 ← idx#108
+Coalesced (already) [89] idx#142 ← idx#108
+Coalesced (already) [101] idx#149 ← idx#108
+Coalesced (already) [103] idx#150 ← idx#108
+Coalesced (already) [105] idx#151 ← idx#108
+Coalesced (already) [107] idx#152 ← idx#108
+Coalesced (already) [109] idx#153 ← idx#108
+Coalesced down to 4 phi equivalence classes
+Culled Empty Block (label) main::@5
+Renumbering block @4 to @1
+Adding NOP phi() at start of @begin
+Adding NOP phi() at start of @1
+Adding NOP phi() at start of @end
+Adding NOP phi() at start of main
+Adding NOP phi() at start of main::@2
+Adding NOP phi() at start of main::@3
+Adding NOP phi() at start of testBinaryOperator
+Adding NOP phi() at start of testBinaryOperator::@1
+Adding NOP phi() at start of testBinaryOperator::@2
+Adding NOP phi() at start of testBinaryOperator::@3
+Adding NOP phi() at start of testBinaryOperator::@4
+Adding NOP phi() at start of testBinaryOperator::@5
+Adding NOP phi() at start of testBinaryOperator::@7
+Adding NOP phi() at start of testBinaryOperator::@8
+Adding NOP phi() at start of testBinaryOperator::@9
+Adding NOP phi() at start of testBinaryOperator::@10
+Adding NOP phi() at start of testBinaryOperator::@11
+Adding NOP phi() at start of testBinaryOperator::@13
+Adding NOP phi() at start of testBinaryOperator::@14
+Adding NOP phi() at start of testBinaryOperator::@15
+Adding NOP phi() at start of testBinaryOperator::@16
+Adding NOP phi() at start of testBinaryOperator::@17
+Adding NOP phi() at start of testBinaryOperator::@18
+Adding NOP phi() at start of testBinaryOperator::@19
+Adding NOP phi() at start of testBinaryOperator::@20
+Adding NOP phi() at start of testBinaryOperator::@21
+Adding NOP phi() at start of testBinaryOperator::@22
+Adding NOP phi() at start of testBinaryOperator::@23
+Adding NOP phi() at start of testBinaryOperator::@25
+Adding NOP phi() at start of testBinaryOperator::@26
+Adding NOP phi() at start of testBinaryOperator::@27
+Adding NOP phi() at start of testBinaryOperator::@28
+Adding NOP phi() at start of testBinaryOperator::@29
+Adding NOP phi() at start of testBinaryOperator::@31
+Adding NOP phi() at start of testBinaryOperator::@32
+Adding NOP phi() at start of testBinaryOperator::@33
+Adding NOP phi() at start of testBinaryOperator::@34
+Adding NOP phi() at start of testBinaryOperator::@35
+Adding NOP phi() at start of testUnaryOperator
+Adding NOP phi() at start of testUnaryOperator::@1
+Adding NOP phi() at start of testUnaryOperator::@2
+Adding NOP phi() at start of testUnaryOperator::@3
+Adding NOP phi() at start of testUnaryOperator::@4
+Adding NOP phi() at start of testUnaryOperator::@5
+
+FINAL CONTROL FLOW GRAPH
+@begin: scope:[]  from
+  [0] phi()
+  to:@1
+@1: scope:[]  from @begin
+  [1] phi()
+  [2] call main 
+  to:@end
+@end: scope:[]  from @1
+  [3] phi()
+main: scope:[main]  from @1
+  [4] phi()
+  to:main::@1
+main::@1: scope:[main]  from main main::@1
+  [5] (byte*) main::s#2 ← phi( main/(const byte*) SCREEN#0 main::@1/(byte*) main::s#1 )
+  [6] *((byte*) main::s#2) ← (byte) ' '
+  [7] (byte*) main::s#1 ← ++ (byte*) main::s#2
+  [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  [9] phi()
+  [10] call testUnaryOperator 
+  to:main::@3
+main::@3: scope:[main]  from main::@2
+  [11] phi()
+  [12] call testBinaryOperator 
+  to:main::@return
+main::@return: scope:[main]  from main::@3
+  [13] return 
+  to:@return
+testBinaryOperator: scope:[testBinaryOperator]  from main::@3
+  [14] phi()
+  [15] call assertType 
+  to:testBinaryOperator::@1
+testBinaryOperator::@1: scope:[testBinaryOperator]  from testBinaryOperator
+  [16] phi()
+  [17] call assertType 
+  to:testBinaryOperator::@2
+testBinaryOperator::@2: scope:[testBinaryOperator]  from testBinaryOperator::@1
+  [18] phi()
+  [19] call assertType 
+  to:testBinaryOperator::@3
+testBinaryOperator::@3: scope:[testBinaryOperator]  from testBinaryOperator::@2
+  [20] phi()
+  [21] call assertType 
+  to:testBinaryOperator::@4
+testBinaryOperator::@4: scope:[testBinaryOperator]  from testBinaryOperator::@3
+  [22] phi()
+  [23] call assertType 
+  to:testBinaryOperator::@5
+testBinaryOperator::@5: scope:[testBinaryOperator]  from testBinaryOperator::@4
+  [24] phi()
+  [25] call assertType 
+  to:testBinaryOperator::@6
+testBinaryOperator::@6: scope:[testBinaryOperator]  from testBinaryOperator::@5
+  [26] (byte) idx#19 ← ++ (byte) idx#108
+  [27] call assertType 
+  to:testBinaryOperator::@7
+testBinaryOperator::@7: scope:[testBinaryOperator]  from testBinaryOperator::@6
+  [28] phi()
+  [29] call assertType 
+  to:testBinaryOperator::@8
+testBinaryOperator::@8: scope:[testBinaryOperator]  from testBinaryOperator::@7
+  [30] phi()
+  [31] call assertType 
+  to:testBinaryOperator::@9
+testBinaryOperator::@9: scope:[testBinaryOperator]  from testBinaryOperator::@8
+  [32] phi()
+  [33] call assertType 
+  to:testBinaryOperator::@10
+testBinaryOperator::@10: scope:[testBinaryOperator]  from testBinaryOperator::@9
+  [34] phi()
+  [35] call assertType 
+  to:testBinaryOperator::@11
+testBinaryOperator::@11: scope:[testBinaryOperator]  from testBinaryOperator::@10
+  [36] phi()
+  [37] call assertType 
+  to:testBinaryOperator::@12
+testBinaryOperator::@12: scope:[testBinaryOperator]  from testBinaryOperator::@11
+  [38] (byte) idx#26 ← ++ (byte) idx#108
+  [39] call assertType 
+  to:testBinaryOperator::@13
+testBinaryOperator::@13: scope:[testBinaryOperator]  from testBinaryOperator::@12
+  [40] phi()
+  [41] call assertType 
+  to:testBinaryOperator::@14
+testBinaryOperator::@14: scope:[testBinaryOperator]  from testBinaryOperator::@13
+  [42] phi()
+  [43] call assertType 
+  to:testBinaryOperator::@15
+testBinaryOperator::@15: scope:[testBinaryOperator]  from testBinaryOperator::@14
+  [44] phi()
+  [45] call assertType 
+  to:testBinaryOperator::@16
+testBinaryOperator::@16: scope:[testBinaryOperator]  from testBinaryOperator::@15
+  [46] phi()
+  [47] call assertType 
+  to:testBinaryOperator::@17
+testBinaryOperator::@17: scope:[testBinaryOperator]  from testBinaryOperator::@16
+  [48] phi()
+  [49] call assertType 
+  to:testBinaryOperator::@18
+testBinaryOperator::@18: scope:[testBinaryOperator]  from testBinaryOperator::@17
+  [50] phi()
+  [51] call assertType 
+  to:testBinaryOperator::@19
+testBinaryOperator::@19: scope:[testBinaryOperator]  from testBinaryOperator::@18
+  [52] phi()
+  [53] call assertType 
+  to:testBinaryOperator::@20
+testBinaryOperator::@20: scope:[testBinaryOperator]  from testBinaryOperator::@19
+  [54] phi()
+  [55] call assertType 
+  to:testBinaryOperator::@21
+testBinaryOperator::@21: scope:[testBinaryOperator]  from testBinaryOperator::@20
+  [56] phi()
+  [57] call assertType 
+  to:testBinaryOperator::@22
+testBinaryOperator::@22: scope:[testBinaryOperator]  from testBinaryOperator::@21
+  [58] phi()
+  [59] call assertType 
+  to:testBinaryOperator::@23
+testBinaryOperator::@23: scope:[testBinaryOperator]  from testBinaryOperator::@22
+  [60] phi()
+  [61] call assertType 
+  to:testBinaryOperator::@24
+testBinaryOperator::@24: scope:[testBinaryOperator]  from testBinaryOperator::@23
+  [62] (byte) idx#40 ← ++ (byte) idx#108
+  [63] call assertType 
+  to:testBinaryOperator::@25
+testBinaryOperator::@25: scope:[testBinaryOperator]  from testBinaryOperator::@24
+  [64] phi()
+  [65] call assertType 
+  to:testBinaryOperator::@26
+testBinaryOperator::@26: scope:[testBinaryOperator]  from testBinaryOperator::@25
+  [66] phi()
+  [67] call assertType 
+  to:testBinaryOperator::@27
+testBinaryOperator::@27: scope:[testBinaryOperator]  from testBinaryOperator::@26
+  [68] phi()
+  [69] call assertType 
+  to:testBinaryOperator::@28
+testBinaryOperator::@28: scope:[testBinaryOperator]  from testBinaryOperator::@27
+  [70] phi()
+  [71] call assertType 
+  to:testBinaryOperator::@29
+testBinaryOperator::@29: scope:[testBinaryOperator]  from testBinaryOperator::@28
+  [72] phi()
+  [73] call assertType 
+  to:testBinaryOperator::@30
+testBinaryOperator::@30: scope:[testBinaryOperator]  from testBinaryOperator::@29
+  [74] (byte) idx#47 ← ++ (byte) idx#108
+  [75] call assertType 
+  to:testBinaryOperator::@31
+testBinaryOperator::@31: scope:[testBinaryOperator]  from testBinaryOperator::@30
+  [76] phi()
+  [77] call assertType 
+  to:testBinaryOperator::@32
+testBinaryOperator::@32: scope:[testBinaryOperator]  from testBinaryOperator::@31
+  [78] phi()
+  [79] call assertType 
+  to:testBinaryOperator::@33
+testBinaryOperator::@33: scope:[testBinaryOperator]  from testBinaryOperator::@32
+  [80] phi()
+  [81] call assertType 
+  to:testBinaryOperator::@34
+testBinaryOperator::@34: scope:[testBinaryOperator]  from testBinaryOperator::@33
+  [82] phi()
+  [83] call assertType 
+  to:testBinaryOperator::@35
+testBinaryOperator::@35: scope:[testBinaryOperator]  from testBinaryOperator::@34
+  [84] phi()
+  [85] call assertType 
+  to:testBinaryOperator::@return
+testBinaryOperator::@return: scope:[testBinaryOperator]  from testBinaryOperator::@35
+  [86] return 
+  to:@return
+assertType: scope:[assertType]  from testBinaryOperator testBinaryOperator::@1 testBinaryOperator::@10 testBinaryOperator::@11 testBinaryOperator::@12 testBinaryOperator::@13 testBinaryOperator::@14 testBinaryOperator::@15 testBinaryOperator::@16 testBinaryOperator::@17 testBinaryOperator::@18 testBinaryOperator::@19 testBinaryOperator::@2 testBinaryOperator::@20 testBinaryOperator::@21 testBinaryOperator::@22 testBinaryOperator::@23 testBinaryOperator::@24 testBinaryOperator::@25 testBinaryOperator::@26 testBinaryOperator::@27 testBinaryOperator::@28 testBinaryOperator::@29 testBinaryOperator::@3 testBinaryOperator::@30 testBinaryOperator::@31 testBinaryOperator::@32 testBinaryOperator::@33 testBinaryOperator::@34 testBinaryOperator::@35 testBinaryOperator::@4 testBinaryOperator::@5 testBinaryOperator::@6 testBinaryOperator::@7 testBinaryOperator::@8 testBinaryOperator::@9 testUnaryOperator testUnaryOperator::@1 testUnaryOperator::@2 testUnaryOperator::@3 testUnaryOperator::@4 testUnaryOperator::@5
+  [87] (byte) idx#105 ← phi( testBinaryOperator/(byte) $28 testBinaryOperator::@1/(byte) idx#108 testBinaryOperator::@10/(byte) idx#108 testBinaryOperator::@11/(byte) idx#108 testBinaryOperator::@12/(byte) idx#26 testBinaryOperator::@13/(byte) idx#108 testBinaryOperator::@14/(byte) idx#108 testBinaryOperator::@15/(byte) idx#108 testBinaryOperator::@16/(byte) idx#108 testBinaryOperator::@17/(byte) idx#108 testBinaryOperator::@18/(byte) $50 testBinaryOperator::@19/(byte) idx#108 testBinaryOperator::@2/(byte) idx#108 testBinaryOperator::@20/(byte) idx#108 testBinaryOperator::@21/(byte) idx#108 testBinaryOperator::@22/(byte) idx#108 testBinaryOperator::@23/(byte) idx#108 testBinaryOperator::@24/(byte) idx#40 testBinaryOperator::@25/(byte) idx#108 testBinaryOperator::@26/(byte) idx#108 testBinaryOperator::@27/(byte) idx#108 testBinaryOperator::@28/(byte) idx#108 testBinaryOperator::@29/(byte) idx#108 testBinaryOperator::@3/(byte) idx#108 testBinaryOperator::@30/(byte) idx#47 testBinaryOperator::@31/(byte) idx#108 testBinaryOperator::@32/(byte) idx#108 testBinaryOperator::@33/(byte) idx#108 testBinaryOperator::@34/(byte) idx#108 testBinaryOperator::@35/(byte) idx#108 testBinaryOperator::@4/(byte) idx#108 testBinaryOperator::@5/(byte) idx#108 testBinaryOperator::@6/(byte) idx#19 testBinaryOperator::@7/(byte) idx#108 testBinaryOperator::@8/(byte) idx#108 testBinaryOperator::@9/(byte) idx#108 testUnaryOperator/(byte) 0 testUnaryOperator::@1/(byte) idx#108 testUnaryOperator::@2/(byte) idx#108 testUnaryOperator::@3/(byte) idx#108 testUnaryOperator::@4/(byte) idx#108 testUnaryOperator::@5/(byte) idx#108 )
+  [87] (byte) assertType::t2#42 ← phi( testBinaryOperator/(const byte) TYPEID_BYTE testBinaryOperator::@1/(const byte) TYPEID_BYTE testBinaryOperator::@10/(const byte) TYPEID_DWORD testBinaryOperator::@11/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@12/(const byte) TYPEID_WORD testBinaryOperator::@13/(const byte) TYPEID_WORD testBinaryOperator::@14/(const byte) TYPEID_WORD testBinaryOperator::@15/(const byte) TYPEID_WORD testBinaryOperator::@16/(const byte) TYPEID_DWORD testBinaryOperator::@17/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@18/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@19/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@2/(const byte) TYPEID_WORD testBinaryOperator::@20/(const byte) TYPEID_WORD testBinaryOperator::@21/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@22/(const byte) TYPEID_DWORD testBinaryOperator::@23/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@24/(const byte) TYPEID_DWORD testBinaryOperator::@25/(const byte) TYPEID_DWORD testBinaryOperator::@26/(const byte) TYPEID_DWORD testBinaryOperator::@27/(const byte) TYPEID_DWORD testBinaryOperator::@28/(const byte) TYPEID_DWORD testBinaryOperator::@29/(const byte) TYPEID_DWORD testBinaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@30/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@31/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@32/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@33/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@34/(const byte) TYPEID_DWORD testBinaryOperator::@35/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@4/(const byte) TYPEID_DWORD testBinaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@6/(const byte) TYPEID_BYTE testBinaryOperator::@7/(const byte) TYPEID_SIGNED_BYTE testBinaryOperator::@8/(const byte) TYPEID_WORD testBinaryOperator::@9/(const byte) TYPEID_SIGNED_WORD testUnaryOperator/(const byte) TYPEID_BYTE testUnaryOperator::@1/(const byte) TYPEID_SIGNED_BYTE testUnaryOperator::@2/(const byte) TYPEID_WORD testUnaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testUnaryOperator::@4/(const byte) TYPEID_DWORD testUnaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD )
+  [87] (byte) assertType::t1#42 ← phi( testBinaryOperator/(const byte) TYPEID_BYTE testBinaryOperator::@1/(const byte) TYPEID_BYTE testBinaryOperator::@10/(const byte) TYPEID_DWORD testBinaryOperator::@11/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@12/(const byte) TYPEID_WORD testBinaryOperator::@13/(const byte) TYPEID_WORD testBinaryOperator::@14/(const byte) TYPEID_WORD testBinaryOperator::@15/(const byte) TYPEID_WORD testBinaryOperator::@16/(const byte) TYPEID_DWORD testBinaryOperator::@17/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@18/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@19/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@2/(const byte) TYPEID_WORD testBinaryOperator::@20/(const byte) TYPEID_WORD testBinaryOperator::@21/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@22/(const byte) TYPEID_DWORD testBinaryOperator::@23/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@24/(const byte) TYPEID_DWORD testBinaryOperator::@25/(const byte) TYPEID_DWORD testBinaryOperator::@26/(const byte) TYPEID_DWORD testBinaryOperator::@27/(const byte) TYPEID_DWORD testBinaryOperator::@28/(const byte) TYPEID_DWORD testBinaryOperator::@29/(const byte) TYPEID_DWORD testBinaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testBinaryOperator::@30/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@31/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@32/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@33/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@34/(const byte) TYPEID_DWORD testBinaryOperator::@35/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@4/(const byte) TYPEID_DWORD testBinaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD testBinaryOperator::@6/(const byte) TYPEID_BYTE testBinaryOperator::@7/(const byte) TYPEID_SIGNED_BYTE testBinaryOperator::@8/(const byte) TYPEID_WORD testBinaryOperator::@9/(const byte) TYPEID_SIGNED_WORD testUnaryOperator/(const byte) TYPEID_BYTE testUnaryOperator::@1/(const byte) TYPEID_SIGNED_BYTE testUnaryOperator::@2/(const byte) TYPEID_WORD testUnaryOperator::@3/(const byte) TYPEID_SIGNED_WORD testUnaryOperator::@4/(const byte) TYPEID_DWORD testUnaryOperator::@5/(const byte) TYPEID_SIGNED_DWORD )
+  [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1
+  to:assertType::@3
+assertType::@3: scope:[assertType]  from assertType
+  [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42
+  [91] (byte) idx#108 ← ++ (byte) idx#105
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  [92] return 
+  to:@return
+assertType::@1: scope:[assertType]  from assertType
+  [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0
+  to:assertType::@2
+testUnaryOperator: scope:[testUnaryOperator]  from main::@2
+  [94] phi()
+  [95] call assertType 
+  to:testUnaryOperator::@1
+testUnaryOperator::@1: scope:[testUnaryOperator]  from testUnaryOperator
+  [96] phi()
+  [97] call assertType 
+  to:testUnaryOperator::@2
+testUnaryOperator::@2: scope:[testUnaryOperator]  from testUnaryOperator::@1
+  [98] phi()
+  [99] call assertType 
+  to:testUnaryOperator::@3
+testUnaryOperator::@3: scope:[testUnaryOperator]  from testUnaryOperator::@2
+  [100] phi()
+  [101] call assertType 
+  to:testUnaryOperator::@4
+testUnaryOperator::@4: scope:[testUnaryOperator]  from testUnaryOperator::@3
+  [102] phi()
+  [103] call assertType 
+  to:testUnaryOperator::@5
+testUnaryOperator::@5: scope:[testUnaryOperator]  from testUnaryOperator::@4
+  [104] phi()
+  [105] call assertType 
+  to:testUnaryOperator::@return
+testUnaryOperator::@return: scope:[testUnaryOperator]  from testUnaryOperator::@5
+  [106] return 
+  to:@return
+
+
+VARIABLE REGISTER WEIGHTS
+(byte*) COLS
+(byte) GREEN
+(byte) RED
+(byte*) SCREEN
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(byte) assertType::t1
+(byte) assertType::t1#42 1.0
+(byte) assertType::t2
+(byte) assertType::t2#42 2.0
+(byte) idx
+(byte) idx#105 17.200000000000003
+(byte) idx#108 1.0526315789473677
+(byte) idx#19 4.0
+(byte) idx#26 4.0
+(byte) idx#40 4.0
+(byte) idx#47 4.0
+(void()) main()
+(byte*) main::s
+(byte*) main::s#1 16.5
+(byte*) main::s#2 16.5
+(void()) testBinaryOperator()
+(void()) testUnaryOperator()
+
+Initial phi equivalence classes
+[ main::s#2 main::s#1 ]
+[ assertType::t1#42 ]
+[ assertType::t2#42 ]
+[ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ]
+Complete equivalence classes
+[ main::s#2 main::s#1 ]
+[ assertType::t1#42 ]
+[ assertType::t2#42 ]
+[ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ]
+Allocated zp ZP_WORD:2 [ main::s#2 main::s#1 ]
+Allocated zp ZP_BYTE:4 [ assertType::t1#42 ]
+Allocated zp ZP_BYTE:5 [ assertType::t2#42 ]
+Allocated zp ZP_BYTE:6 [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ]
+
+INITIAL ASM
+//SEG0 File Comments
+// Tests different integer literal types
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_BYTE = 1
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_WORD = 3
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_DWORD = 5
+  .const TYPEID_SIGNED_DWORD = 6
+  .const RED = 2
+  .const GREEN = 5
+  .label SCREEN = $400
+  .label COLS = $d800
+  .label idx = 6
+//SEG3 @begin
+bbegin:
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+b1_from_bbegin:
+  jmp b1
+//SEG5 @1
+b1:
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+main_from_b1:
+  jsr main
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+bend_from_b1:
+  jmp bend
+//SEG9 @end
+bend:
+//SEG10 main
+main: {
+    .label s = 2
+  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
+  b1_from_main:
+  //SEG12 [5] phi (byte*) main::s#2 = (const byte*) SCREEN#0 [phi:main->main::@1#0] -- pbuz1=pbuc1 
+    lda #<SCREEN
+    sta s
+    lda #>SCREEN
+    sta s+1
+    jmp b1
+  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
+  b1_from_b1:
+  //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy 
+    jmp b1
+  //SEG15 main::@1
+  b1:
+  //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 
+    lda #' '
+    ldy #0
+    sta (s),y
+  //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 
+    inc s
+    bne !+
+    inc s+1
+  !:
+  //SEG18 [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 
+    lda s+1
+    cmp #>SCREEN+$3e8
+    bcc b1_from_b1
+    bne !+
+    lda s
+    cmp #<SCREEN+$3e8
+    bcc b1_from_b1
+  !:
+  //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG20 main::@2
+  b2:
+  //SEG21 [10] call testUnaryOperator 
+  //SEG22 [94] phi from main::@2 to testUnaryOperator [phi:main::@2->testUnaryOperator]
+  testUnaryOperator_from_b2:
+    jsr testUnaryOperator
+  //SEG23 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG24 main::@3
+  b3:
+  //SEG25 [12] call testBinaryOperator 
+  //SEG26 [14] phi from main::@3 to testBinaryOperator [phi:main::@3->testBinaryOperator]
+  testBinaryOperator_from_b3:
+    jsr testBinaryOperator
+    jmp breturn
+  //SEG27 main::@return
+  breturn:
+  //SEG28 [13] return 
+    rts
+}
+//SEG29 testBinaryOperator
+testBinaryOperator: {
+  //SEG30 [15] call assertType 
+  //SEG31 [87] phi from testBinaryOperator to assertType [phi:testBinaryOperator->assertType]
+  assertType_from_testBinaryOperator:
+  //SEG32 [87] phi (byte) idx#105 = (byte) $28 [phi:testBinaryOperator->assertType#0] -- vbuz1=vbuc1 
+    lda #$28
+    sta idx
+  //SEG33 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG34 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG35 [16] phi from testBinaryOperator to testBinaryOperator::@1 [phi:testBinaryOperator->testBinaryOperator::@1]
+  b1_from_testBinaryOperator:
+    jmp b1
+  //SEG36 testBinaryOperator::@1
+  b1:
+  //SEG37 [17] call assertType 
+  //SEG38 [87] phi from testBinaryOperator::@1 to assertType [phi:testBinaryOperator::@1->assertType]
+  assertType_from_b1:
+  //SEG39 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@1->assertType#0] -- register_copy 
+  //SEG40 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG41 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG42 [18] phi from testBinaryOperator::@1 to testBinaryOperator::@2 [phi:testBinaryOperator::@1->testBinaryOperator::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG43 testBinaryOperator::@2
+  b2:
+  //SEG44 [19] call assertType 
+  //SEG45 [87] phi from testBinaryOperator::@2 to assertType [phi:testBinaryOperator::@2->assertType]
+  assertType_from_b2:
+  //SEG46 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@2->assertType#0] -- register_copy 
+  //SEG47 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG48 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG49 [20] phi from testBinaryOperator::@2 to testBinaryOperator::@3 [phi:testBinaryOperator::@2->testBinaryOperator::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG50 testBinaryOperator::@3
+  b3:
+  //SEG51 [21] call assertType 
+  //SEG52 [87] phi from testBinaryOperator::@3 to assertType [phi:testBinaryOperator::@3->assertType]
+  assertType_from_b3:
+  //SEG53 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@3->assertType#0] -- register_copy 
+  //SEG54 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG55 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG56 [22] phi from testBinaryOperator::@3 to testBinaryOperator::@4 [phi:testBinaryOperator::@3->testBinaryOperator::@4]
+  b4_from_b3:
+    jmp b4
+  //SEG57 testBinaryOperator::@4
+  b4:
+  //SEG58 [23] call assertType 
+  //SEG59 [87] phi from testBinaryOperator::@4 to assertType [phi:testBinaryOperator::@4->assertType]
+  assertType_from_b4:
+  //SEG60 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@4->assertType#0] -- register_copy 
+  //SEG61 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG62 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG63 [24] phi from testBinaryOperator::@4 to testBinaryOperator::@5 [phi:testBinaryOperator::@4->testBinaryOperator::@5]
+  b5_from_b4:
+    jmp b5
+  //SEG64 testBinaryOperator::@5
+  b5:
+  //SEG65 [25] call assertType 
+  //SEG66 [87] phi from testBinaryOperator::@5 to assertType [phi:testBinaryOperator::@5->assertType]
+  assertType_from_b5:
+  //SEG67 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@5->assertType#0] -- register_copy 
+  //SEG68 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG69 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+    jmp b6
+  //SEG70 testBinaryOperator::@6
+  b6:
+  //SEG71 [26] (byte) idx#19 ← ++ (byte) idx#108 -- vbuz1=_inc_vbuz1 
+    inc idx
+  //SEG72 [27] call assertType 
+  //SEG73 [87] phi from testBinaryOperator::@6 to assertType [phi:testBinaryOperator::@6->assertType]
+  assertType_from_b6:
+  //SEG74 [87] phi (byte) idx#105 = (byte) idx#19 [phi:testBinaryOperator::@6->assertType#0] -- register_copy 
+  //SEG75 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG76 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG77 [28] phi from testBinaryOperator::@6 to testBinaryOperator::@7 [phi:testBinaryOperator::@6->testBinaryOperator::@7]
+  b7_from_b6:
+    jmp b7
+  //SEG78 testBinaryOperator::@7
+  b7:
+  //SEG79 [29] call assertType 
+  //SEG80 [87] phi from testBinaryOperator::@7 to assertType [phi:testBinaryOperator::@7->assertType]
+  assertType_from_b7:
+  //SEG81 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@7->assertType#0] -- register_copy 
+  //SEG82 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG83 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG84 [30] phi from testBinaryOperator::@7 to testBinaryOperator::@8 [phi:testBinaryOperator::@7->testBinaryOperator::@8]
+  b8_from_b7:
+    jmp b8
+  //SEG85 testBinaryOperator::@8
+  b8:
+  //SEG86 [31] call assertType 
+  //SEG87 [87] phi from testBinaryOperator::@8 to assertType [phi:testBinaryOperator::@8->assertType]
+  assertType_from_b8:
+  //SEG88 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@8->assertType#0] -- register_copy 
+  //SEG89 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG90 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG91 [32] phi from testBinaryOperator::@8 to testBinaryOperator::@9 [phi:testBinaryOperator::@8->testBinaryOperator::@9]
+  b9_from_b8:
+    jmp b9
+  //SEG92 testBinaryOperator::@9
+  b9:
+  //SEG93 [33] call assertType 
+  //SEG94 [87] phi from testBinaryOperator::@9 to assertType [phi:testBinaryOperator::@9->assertType]
+  assertType_from_b9:
+  //SEG95 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@9->assertType#0] -- register_copy 
+  //SEG96 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG97 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG98 [34] phi from testBinaryOperator::@9 to testBinaryOperator::@10 [phi:testBinaryOperator::@9->testBinaryOperator::@10]
+  b10_from_b9:
+    jmp b10
+  //SEG99 testBinaryOperator::@10
+  b10:
+  //SEG100 [35] call assertType 
+  //SEG101 [87] phi from testBinaryOperator::@10 to assertType [phi:testBinaryOperator::@10->assertType]
+  assertType_from_b10:
+  //SEG102 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@10->assertType#0] -- register_copy 
+  //SEG103 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG104 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG105 [36] phi from testBinaryOperator::@10 to testBinaryOperator::@11 [phi:testBinaryOperator::@10->testBinaryOperator::@11]
+  b11_from_b10:
+    jmp b11
+  //SEG106 testBinaryOperator::@11
+  b11:
+  //SEG107 [37] call assertType 
+  //SEG108 [87] phi from testBinaryOperator::@11 to assertType [phi:testBinaryOperator::@11->assertType]
+  assertType_from_b11:
+  //SEG109 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@11->assertType#0] -- register_copy 
+  //SEG110 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG111 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+    jmp b12
+  //SEG112 testBinaryOperator::@12
+  b12:
+  //SEG113 [38] (byte) idx#26 ← ++ (byte) idx#108 -- vbuz1=_inc_vbuz1 
+    inc idx
+  //SEG114 [39] call assertType 
+  //SEG115 [87] phi from testBinaryOperator::@12 to assertType [phi:testBinaryOperator::@12->assertType]
+  assertType_from_b12:
+  //SEG116 [87] phi (byte) idx#105 = (byte) idx#26 [phi:testBinaryOperator::@12->assertType#0] -- register_copy 
+  //SEG117 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG118 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG119 [40] phi from testBinaryOperator::@12 to testBinaryOperator::@13 [phi:testBinaryOperator::@12->testBinaryOperator::@13]
+  b13_from_b12:
+    jmp b13
+  //SEG120 testBinaryOperator::@13
+  b13:
+  //SEG121 [41] call assertType 
+  //SEG122 [87] phi from testBinaryOperator::@13 to assertType [phi:testBinaryOperator::@13->assertType]
+  assertType_from_b13:
+  //SEG123 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@13->assertType#0] -- register_copy 
+  //SEG124 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG125 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG126 [42] phi from testBinaryOperator::@13 to testBinaryOperator::@14 [phi:testBinaryOperator::@13->testBinaryOperator::@14]
+  b14_from_b13:
+    jmp b14
+  //SEG127 testBinaryOperator::@14
+  b14:
+  //SEG128 [43] call assertType 
+  //SEG129 [87] phi from testBinaryOperator::@14 to assertType [phi:testBinaryOperator::@14->assertType]
+  assertType_from_b14:
+  //SEG130 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@14->assertType#0] -- register_copy 
+  //SEG131 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG132 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG133 [44] phi from testBinaryOperator::@14 to testBinaryOperator::@15 [phi:testBinaryOperator::@14->testBinaryOperator::@15]
+  b15_from_b14:
+    jmp b15
+  //SEG134 testBinaryOperator::@15
+  b15:
+  //SEG135 [45] call assertType 
+  //SEG136 [87] phi from testBinaryOperator::@15 to assertType [phi:testBinaryOperator::@15->assertType]
+  assertType_from_b15:
+  //SEG137 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@15->assertType#0] -- register_copy 
+  //SEG138 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG139 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG140 [46] phi from testBinaryOperator::@15 to testBinaryOperator::@16 [phi:testBinaryOperator::@15->testBinaryOperator::@16]
+  b16_from_b15:
+    jmp b16
+  //SEG141 testBinaryOperator::@16
+  b16:
+  //SEG142 [47] call assertType 
+  //SEG143 [87] phi from testBinaryOperator::@16 to assertType [phi:testBinaryOperator::@16->assertType]
+  assertType_from_b16:
+  //SEG144 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@16->assertType#0] -- register_copy 
+  //SEG145 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG146 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG147 [48] phi from testBinaryOperator::@16 to testBinaryOperator::@17 [phi:testBinaryOperator::@16->testBinaryOperator::@17]
+  b17_from_b16:
+    jmp b17
+  //SEG148 testBinaryOperator::@17
+  b17:
+  //SEG149 [49] call assertType 
+  //SEG150 [87] phi from testBinaryOperator::@17 to assertType [phi:testBinaryOperator::@17->assertType]
+  assertType_from_b17:
+  //SEG151 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@17->assertType#0] -- register_copy 
+  //SEG152 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG153 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG154 [50] phi from testBinaryOperator::@17 to testBinaryOperator::@18 [phi:testBinaryOperator::@17->testBinaryOperator::@18]
+  b18_from_b17:
+    jmp b18
+  //SEG155 testBinaryOperator::@18
+  b18:
+  //SEG156 [51] call assertType 
+  //SEG157 [87] phi from testBinaryOperator::@18 to assertType [phi:testBinaryOperator::@18->assertType]
+  assertType_from_b18:
+  //SEG158 [87] phi (byte) idx#105 = (byte) $50 [phi:testBinaryOperator::@18->assertType#0] -- vbuz1=vbuc1 
+    lda #$50
+    sta idx
+  //SEG159 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG160 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG161 [52] phi from testBinaryOperator::@18 to testBinaryOperator::@19 [phi:testBinaryOperator::@18->testBinaryOperator::@19]
+  b19_from_b18:
+    jmp b19
+  //SEG162 testBinaryOperator::@19
+  b19:
+  //SEG163 [53] call assertType 
+  //SEG164 [87] phi from testBinaryOperator::@19 to assertType [phi:testBinaryOperator::@19->assertType]
+  assertType_from_b19:
+  //SEG165 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@19->assertType#0] -- register_copy 
+  //SEG166 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG167 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG168 [54] phi from testBinaryOperator::@19 to testBinaryOperator::@20 [phi:testBinaryOperator::@19->testBinaryOperator::@20]
+  b20_from_b19:
+    jmp b20
+  //SEG169 testBinaryOperator::@20
+  b20:
+  //SEG170 [55] call assertType 
+  //SEG171 [87] phi from testBinaryOperator::@20 to assertType [phi:testBinaryOperator::@20->assertType]
+  assertType_from_b20:
+  //SEG172 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@20->assertType#0] -- register_copy 
+  //SEG173 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG174 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG175 [56] phi from testBinaryOperator::@20 to testBinaryOperator::@21 [phi:testBinaryOperator::@20->testBinaryOperator::@21]
+  b21_from_b20:
+    jmp b21
+  //SEG176 testBinaryOperator::@21
+  b21:
+  //SEG177 [57] call assertType 
+  //SEG178 [87] phi from testBinaryOperator::@21 to assertType [phi:testBinaryOperator::@21->assertType]
+  assertType_from_b21:
+  //SEG179 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@21->assertType#0] -- register_copy 
+  //SEG180 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG181 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG182 [58] phi from testBinaryOperator::@21 to testBinaryOperator::@22 [phi:testBinaryOperator::@21->testBinaryOperator::@22]
+  b22_from_b21:
+    jmp b22
+  //SEG183 testBinaryOperator::@22
+  b22:
+  //SEG184 [59] call assertType 
+  //SEG185 [87] phi from testBinaryOperator::@22 to assertType [phi:testBinaryOperator::@22->assertType]
+  assertType_from_b22:
+  //SEG186 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@22->assertType#0] -- register_copy 
+  //SEG187 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG188 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG189 [60] phi from testBinaryOperator::@22 to testBinaryOperator::@23 [phi:testBinaryOperator::@22->testBinaryOperator::@23]
+  b23_from_b22:
+    jmp b23
+  //SEG190 testBinaryOperator::@23
+  b23:
+  //SEG191 [61] call assertType 
+  //SEG192 [87] phi from testBinaryOperator::@23 to assertType [phi:testBinaryOperator::@23->assertType]
+  assertType_from_b23:
+  //SEG193 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@23->assertType#0] -- register_copy 
+  //SEG194 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG195 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+    jmp b24
+  //SEG196 testBinaryOperator::@24
+  b24:
+  //SEG197 [62] (byte) idx#40 ← ++ (byte) idx#108 -- vbuz1=_inc_vbuz1 
+    inc idx
+  //SEG198 [63] call assertType 
+  //SEG199 [87] phi from testBinaryOperator::@24 to assertType [phi:testBinaryOperator::@24->assertType]
+  assertType_from_b24:
+  //SEG200 [87] phi (byte) idx#105 = (byte) idx#40 [phi:testBinaryOperator::@24->assertType#0] -- register_copy 
+  //SEG201 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG202 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG203 [64] phi from testBinaryOperator::@24 to testBinaryOperator::@25 [phi:testBinaryOperator::@24->testBinaryOperator::@25]
+  b25_from_b24:
+    jmp b25
+  //SEG204 testBinaryOperator::@25
+  b25:
+  //SEG205 [65] call assertType 
+  //SEG206 [87] phi from testBinaryOperator::@25 to assertType [phi:testBinaryOperator::@25->assertType]
+  assertType_from_b25:
+  //SEG207 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@25->assertType#0] -- register_copy 
+  //SEG208 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG209 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG210 [66] phi from testBinaryOperator::@25 to testBinaryOperator::@26 [phi:testBinaryOperator::@25->testBinaryOperator::@26]
+  b26_from_b25:
+    jmp b26
+  //SEG211 testBinaryOperator::@26
+  b26:
+  //SEG212 [67] call assertType 
+  //SEG213 [87] phi from testBinaryOperator::@26 to assertType [phi:testBinaryOperator::@26->assertType]
+  assertType_from_b26:
+  //SEG214 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@26->assertType#0] -- register_copy 
+  //SEG215 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG216 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG217 [68] phi from testBinaryOperator::@26 to testBinaryOperator::@27 [phi:testBinaryOperator::@26->testBinaryOperator::@27]
+  b27_from_b26:
+    jmp b27
+  //SEG218 testBinaryOperator::@27
+  b27:
+  //SEG219 [69] call assertType 
+  //SEG220 [87] phi from testBinaryOperator::@27 to assertType [phi:testBinaryOperator::@27->assertType]
+  assertType_from_b27:
+  //SEG221 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@27->assertType#0] -- register_copy 
+  //SEG222 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG223 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG224 [70] phi from testBinaryOperator::@27 to testBinaryOperator::@28 [phi:testBinaryOperator::@27->testBinaryOperator::@28]
+  b28_from_b27:
+    jmp b28
+  //SEG225 testBinaryOperator::@28
+  b28:
+  //SEG226 [71] call assertType 
+  //SEG227 [87] phi from testBinaryOperator::@28 to assertType [phi:testBinaryOperator::@28->assertType]
+  assertType_from_b28:
+  //SEG228 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@28->assertType#0] -- register_copy 
+  //SEG229 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG230 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG231 [72] phi from testBinaryOperator::@28 to testBinaryOperator::@29 [phi:testBinaryOperator::@28->testBinaryOperator::@29]
+  b29_from_b28:
+    jmp b29
+  //SEG232 testBinaryOperator::@29
+  b29:
+  //SEG233 [73] call assertType 
+  //SEG234 [87] phi from testBinaryOperator::@29 to assertType [phi:testBinaryOperator::@29->assertType]
+  assertType_from_b29:
+  //SEG235 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@29->assertType#0] -- register_copy 
+  //SEG236 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG237 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+    jmp b30
+  //SEG238 testBinaryOperator::@30
+  b30:
+  //SEG239 [74] (byte) idx#47 ← ++ (byte) idx#108 -- vbuz1=_inc_vbuz1 
+    inc idx
+  //SEG240 [75] call assertType 
+  //SEG241 [87] phi from testBinaryOperator::@30 to assertType [phi:testBinaryOperator::@30->assertType]
+  assertType_from_b30:
+  //SEG242 [87] phi (byte) idx#105 = (byte) idx#47 [phi:testBinaryOperator::@30->assertType#0] -- register_copy 
+  //SEG243 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG244 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG245 [76] phi from testBinaryOperator::@30 to testBinaryOperator::@31 [phi:testBinaryOperator::@30->testBinaryOperator::@31]
+  b31_from_b30:
+    jmp b31
+  //SEG246 testBinaryOperator::@31
+  b31:
+  //SEG247 [77] call assertType 
+  //SEG248 [87] phi from testBinaryOperator::@31 to assertType [phi:testBinaryOperator::@31->assertType]
+  assertType_from_b31:
+  //SEG249 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@31->assertType#0] -- register_copy 
+  //SEG250 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG251 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG252 [78] phi from testBinaryOperator::@31 to testBinaryOperator::@32 [phi:testBinaryOperator::@31->testBinaryOperator::@32]
+  b32_from_b31:
+    jmp b32
+  //SEG253 testBinaryOperator::@32
+  b32:
+  //SEG254 [79] call assertType 
+  //SEG255 [87] phi from testBinaryOperator::@32 to assertType [phi:testBinaryOperator::@32->assertType]
+  assertType_from_b32:
+  //SEG256 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@32->assertType#0] -- register_copy 
+  //SEG257 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG258 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG259 [80] phi from testBinaryOperator::@32 to testBinaryOperator::@33 [phi:testBinaryOperator::@32->testBinaryOperator::@33]
+  b33_from_b32:
+    jmp b33
+  //SEG260 testBinaryOperator::@33
+  b33:
+  //SEG261 [81] call assertType 
+  //SEG262 [87] phi from testBinaryOperator::@33 to assertType [phi:testBinaryOperator::@33->assertType]
+  assertType_from_b33:
+  //SEG263 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@33->assertType#0] -- register_copy 
+  //SEG264 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG265 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG266 [82] phi from testBinaryOperator::@33 to testBinaryOperator::@34 [phi:testBinaryOperator::@33->testBinaryOperator::@34]
+  b34_from_b33:
+    jmp b34
+  //SEG267 testBinaryOperator::@34
+  b34:
+  //SEG268 [83] call assertType 
+  //SEG269 [87] phi from testBinaryOperator::@34 to assertType [phi:testBinaryOperator::@34->assertType]
+  assertType_from_b34:
+  //SEG270 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@34->assertType#0] -- register_copy 
+  //SEG271 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG272 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG273 [84] phi from testBinaryOperator::@34 to testBinaryOperator::@35 [phi:testBinaryOperator::@34->testBinaryOperator::@35]
+  b35_from_b34:
+    jmp b35
+  //SEG274 testBinaryOperator::@35
+  b35:
+  //SEG275 [85] call assertType 
+  //SEG276 [87] phi from testBinaryOperator::@35 to assertType [phi:testBinaryOperator::@35->assertType]
+  assertType_from_b35:
+  //SEG277 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@35->assertType#0] -- register_copy 
+  //SEG278 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG279 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+    jmp breturn
+  //SEG280 testBinaryOperator::@return
+  breturn:
+  //SEG281 [86] return 
+    rts
+}
+//SEG282 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte zeropage(4) t1, byte zeropage(5) t2)
+assertType: {
+    .label t1 = 4
+    .label t2 = 5
+  //SEG283 [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 -- vbuz1_eq_vbuz2_then_la1 
+    lda t1
+    cmp t2
+    beq b1
+    jmp b3
+  //SEG284 assertType::@3
+  b3:
+  //SEG285 [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 -- pbuc1_derefidx_vbuz1=vbuc2 
+    lda #RED
+    ldy idx
+    sta COLS,y
+    jmp b2
+  //SEG286 assertType::@2
+  b2:
+  //SEG287 [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 -- pbuc1_derefidx_vbuz1=vbuz2 
+    lda t1
+    ldy idx
+    sta SCREEN,y
+  //SEG288 [91] (byte) idx#108 ← ++ (byte) idx#105 -- vbuz1=_inc_vbuz1 
+    inc idx
+    jmp breturn
+  //SEG289 assertType::@return
+  breturn:
+  //SEG290 [92] return 
+    rts
+  //SEG291 assertType::@1
+  b1:
+  //SEG292 [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuz1=vbuc2 
+    lda #GREEN
+    ldy idx
+    sta COLS,y
+    jmp b2
+}
+//SEG293 testUnaryOperator
+testUnaryOperator: {
+  //SEG294 [95] call assertType 
+  //SEG295 [87] phi from testUnaryOperator to assertType [phi:testUnaryOperator->assertType]
+  assertType_from_testUnaryOperator:
+  //SEG296 [87] phi (byte) idx#105 = (byte) 0 [phi:testUnaryOperator->assertType#0] -- vbuz1=vbuc1 
+    lda #0
+    sta idx
+  //SEG297 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG298 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG299 [96] phi from testUnaryOperator to testUnaryOperator::@1 [phi:testUnaryOperator->testUnaryOperator::@1]
+  b1_from_testUnaryOperator:
+    jmp b1
+  //SEG300 testUnaryOperator::@1
+  b1:
+  //SEG301 [97] call assertType 
+  //SEG302 [87] phi from testUnaryOperator::@1 to assertType [phi:testUnaryOperator::@1->assertType]
+  assertType_from_b1:
+  //SEG303 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@1->assertType#0] -- register_copy 
+  //SEG304 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG305 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG306 [98] phi from testUnaryOperator::@1 to testUnaryOperator::@2 [phi:testUnaryOperator::@1->testUnaryOperator::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG307 testUnaryOperator::@2
+  b2:
+  //SEG308 [99] call assertType 
+  //SEG309 [87] phi from testUnaryOperator::@2 to assertType [phi:testUnaryOperator::@2->assertType]
+  assertType_from_b2:
+  //SEG310 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@2->assertType#0] -- register_copy 
+  //SEG311 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG312 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG313 [100] phi from testUnaryOperator::@2 to testUnaryOperator::@3 [phi:testUnaryOperator::@2->testUnaryOperator::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG314 testUnaryOperator::@3
+  b3:
+  //SEG315 [101] call assertType 
+  //SEG316 [87] phi from testUnaryOperator::@3 to assertType [phi:testUnaryOperator::@3->assertType]
+  assertType_from_b3:
+  //SEG317 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@3->assertType#0] -- register_copy 
+  //SEG318 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG319 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG320 [102] phi from testUnaryOperator::@3 to testUnaryOperator::@4 [phi:testUnaryOperator::@3->testUnaryOperator::@4]
+  b4_from_b3:
+    jmp b4
+  //SEG321 testUnaryOperator::@4
+  b4:
+  //SEG322 [103] call assertType 
+  //SEG323 [87] phi from testUnaryOperator::@4 to assertType [phi:testUnaryOperator::@4->assertType]
+  assertType_from_b4:
+  //SEG324 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@4->assertType#0] -- register_copy 
+  //SEG325 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG326 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG327 [104] phi from testUnaryOperator::@4 to testUnaryOperator::@5 [phi:testUnaryOperator::@4->testUnaryOperator::@5]
+  b5_from_b4:
+    jmp b5
+  //SEG328 testUnaryOperator::@5
+  b5:
+  //SEG329 [105] call assertType 
+  //SEG330 [87] phi from testUnaryOperator::@5 to assertType [phi:testUnaryOperator::@5->assertType]
+  assertType_from_b5:
+  //SEG331 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@5->assertType#0] -- register_copy 
+  //SEG332 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG333 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+    jmp breturn
+  //SEG334 testUnaryOperator::@return
+  breturn:
+  //SEG335 [106] return 
+    rts
+}
+
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [6] *((byte*) main::s#2) ← (byte) ' ' [ main::s#2 ] ( main:2 [ main::s#2 ] ) always clobbers reg byte a reg byte y 
+Statement [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 [ main::s#1 ] ( main:2 [ main::s#1 ] ) always clobbers reg byte a 
+Statement [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 [ assertType::t1#42 idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ assertType::t1#42 idx#105 ] ) always clobbers reg byte a 
+Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ assertType::t1#42 ]
+Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ]
+Statement [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 [ idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ idx#105 ] ) always clobbers reg byte a 
+Statement [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 [ assertType::t1#42 idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ assertType::t1#42 idx#105 ] ) always clobbers reg byte a 
+Statement [6] *((byte*) main::s#2) ← (byte) ' ' [ main::s#2 ] ( main:2 [ main::s#2 ] ) always clobbers reg byte a reg byte y 
+Statement [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 [ main::s#1 ] ( main:2 [ main::s#1 ] ) always clobbers reg byte a 
+Statement [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 [ assertType::t1#42 idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ assertType::t1#42 idx#105 ] ) always clobbers reg byte a 
+Statement [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 [ idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ idx#105 ] ) always clobbers reg byte a 
+Statement [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 [ assertType::t1#42 idx#105 ] ( main:2::testBinaryOperator:12::assertType:15 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:17 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:19 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:21 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:23 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:25 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:27 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:29 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:31 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:33 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:35 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:37 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:39 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:41 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:43 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:45 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:47 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:49 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:51 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:53 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:55 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:57 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:59 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:61 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:63 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:65 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:67 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:69 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:71 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:73 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:75 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:77 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:79 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:81 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:83 [ assertType::t1#42 idx#105 ] main:2::testBinaryOperator:12::assertType:85 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:95 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:97 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:99 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:101 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:103 [ assertType::t1#42 idx#105 ] main:2::testUnaryOperator:10::assertType:105 [ assertType::t1#42 idx#105 ] ) always clobbers reg byte a 
+Potential registers zp ZP_WORD:2 [ main::s#2 main::s#1 ] : zp ZP_WORD:2 , 
+Potential registers zp ZP_BYTE:4 [ assertType::t1#42 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , 
+Potential registers zp ZP_BYTE:5 [ assertType::t2#42 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y , 
+Potential registers zp ZP_BYTE:6 [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] : zp ZP_BYTE:6 , reg byte x , reg byte y , 
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [] 34.25: zp ZP_BYTE:6 [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] 
+Uplift Scope [main] 33: zp ZP_WORD:2 [ main::s#2 main::s#1 ] 
+Uplift Scope [assertType] 2: zp ZP_BYTE:5 [ assertType::t2#42 ] 1: zp ZP_BYTE:4 [ assertType::t1#42 ] 
+Uplift Scope [testUnaryOperator] 
+Uplift Scope [testBinaryOperator] 
+
+Uplifting [] best 1503 combination reg byte x [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ] 
+Uplifting [main] best 1503 combination zp ZP_WORD:2 [ main::s#2 main::s#1 ] 
+Uplifting [assertType] best 1375 combination zp ZP_BYTE:5 [ assertType::t2#42 ] reg byte y [ assertType::t1#42 ] 
+Uplifting [testUnaryOperator] best 1375 combination 
+Uplifting [testBinaryOperator] best 1375 combination 
+Attempting to uplift remaining variables inzp ZP_BYTE:5 [ assertType::t2#42 ]
+Uplifting [assertType] best 1375 combination zp ZP_BYTE:5 [ assertType::t2#42 ] 
+Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:4 [ assertType::t2#42 ]
+
+ASSEMBLER BEFORE OPTIMIZATION
+//SEG0 File Comments
+// Tests different integer literal types
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_BYTE = 1
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_WORD = 3
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_DWORD = 5
+  .const TYPEID_SIGNED_DWORD = 6
+  .const RED = 2
+  .const GREEN = 5
+  .label SCREEN = $400
+  .label COLS = $d800
+//SEG3 @begin
+bbegin:
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+b1_from_bbegin:
+  jmp b1
+//SEG5 @1
+b1:
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+main_from_b1:
+  jsr main
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+bend_from_b1:
+  jmp bend
+//SEG9 @end
+bend:
+//SEG10 main
+main: {
+    .label s = 2
+  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
+  b1_from_main:
+  //SEG12 [5] phi (byte*) main::s#2 = (const byte*) SCREEN#0 [phi:main->main::@1#0] -- pbuz1=pbuc1 
+    lda #<SCREEN
+    sta s
+    lda #>SCREEN
+    sta s+1
+    jmp b1
+  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
+  b1_from_b1:
+  //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy 
+    jmp b1
+  //SEG15 main::@1
+  b1:
+  //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 
+    lda #' '
+    ldy #0
+    sta (s),y
+  //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 
+    inc s
+    bne !+
+    inc s+1
+  !:
+  //SEG18 [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 
+    lda s+1
+    cmp #>SCREEN+$3e8
+    bcc b1_from_b1
+    bne !+
+    lda s
+    cmp #<SCREEN+$3e8
+    bcc b1_from_b1
+  !:
+  //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG20 main::@2
+  b2:
+  //SEG21 [10] call testUnaryOperator 
+  //SEG22 [94] phi from main::@2 to testUnaryOperator [phi:main::@2->testUnaryOperator]
+  testUnaryOperator_from_b2:
+    jsr testUnaryOperator
+  //SEG23 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG24 main::@3
+  b3:
+  //SEG25 [12] call testBinaryOperator 
+  //SEG26 [14] phi from main::@3 to testBinaryOperator [phi:main::@3->testBinaryOperator]
+  testBinaryOperator_from_b3:
+    jsr testBinaryOperator
+    jmp breturn
+  //SEG27 main::@return
+  breturn:
+  //SEG28 [13] return 
+    rts
+}
+//SEG29 testBinaryOperator
+testBinaryOperator: {
+  //SEG30 [15] call assertType 
+  //SEG31 [87] phi from testBinaryOperator to assertType [phi:testBinaryOperator->assertType]
+  assertType_from_testBinaryOperator:
+  //SEG32 [87] phi (byte) idx#105 = (byte) $28 [phi:testBinaryOperator->assertType#0] -- vbuxx=vbuc1 
+    ldx #$28
+  //SEG33 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG34 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG35 [16] phi from testBinaryOperator to testBinaryOperator::@1 [phi:testBinaryOperator->testBinaryOperator::@1]
+  b1_from_testBinaryOperator:
+    jmp b1
+  //SEG36 testBinaryOperator::@1
+  b1:
+  //SEG37 [17] call assertType 
+  //SEG38 [87] phi from testBinaryOperator::@1 to assertType [phi:testBinaryOperator::@1->assertType]
+  assertType_from_b1:
+  //SEG39 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@1->assertType#0] -- register_copy 
+  //SEG40 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG41 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG42 [18] phi from testBinaryOperator::@1 to testBinaryOperator::@2 [phi:testBinaryOperator::@1->testBinaryOperator::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG43 testBinaryOperator::@2
+  b2:
+  //SEG44 [19] call assertType 
+  //SEG45 [87] phi from testBinaryOperator::@2 to assertType [phi:testBinaryOperator::@2->assertType]
+  assertType_from_b2:
+  //SEG46 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@2->assertType#0] -- register_copy 
+  //SEG47 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG48 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG49 [20] phi from testBinaryOperator::@2 to testBinaryOperator::@3 [phi:testBinaryOperator::@2->testBinaryOperator::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG50 testBinaryOperator::@3
+  b3:
+  //SEG51 [21] call assertType 
+  //SEG52 [87] phi from testBinaryOperator::@3 to assertType [phi:testBinaryOperator::@3->assertType]
+  assertType_from_b3:
+  //SEG53 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@3->assertType#0] -- register_copy 
+  //SEG54 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG55 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG56 [22] phi from testBinaryOperator::@3 to testBinaryOperator::@4 [phi:testBinaryOperator::@3->testBinaryOperator::@4]
+  b4_from_b3:
+    jmp b4
+  //SEG57 testBinaryOperator::@4
+  b4:
+  //SEG58 [23] call assertType 
+  //SEG59 [87] phi from testBinaryOperator::@4 to assertType [phi:testBinaryOperator::@4->assertType]
+  assertType_from_b4:
+  //SEG60 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@4->assertType#0] -- register_copy 
+  //SEG61 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG62 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG63 [24] phi from testBinaryOperator::@4 to testBinaryOperator::@5 [phi:testBinaryOperator::@4->testBinaryOperator::@5]
+  b5_from_b4:
+    jmp b5
+  //SEG64 testBinaryOperator::@5
+  b5:
+  //SEG65 [25] call assertType 
+  //SEG66 [87] phi from testBinaryOperator::@5 to assertType [phi:testBinaryOperator::@5->assertType]
+  assertType_from_b5:
+  //SEG67 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@5->assertType#0] -- register_copy 
+  //SEG68 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG69 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+    jmp b6
+  //SEG70 testBinaryOperator::@6
+  b6:
+  //SEG71 [26] (byte) idx#19 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG72 [27] call assertType 
+  //SEG73 [87] phi from testBinaryOperator::@6 to assertType [phi:testBinaryOperator::@6->assertType]
+  assertType_from_b6:
+  //SEG74 [87] phi (byte) idx#105 = (byte) idx#19 [phi:testBinaryOperator::@6->assertType#0] -- register_copy 
+  //SEG75 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG76 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG77 [28] phi from testBinaryOperator::@6 to testBinaryOperator::@7 [phi:testBinaryOperator::@6->testBinaryOperator::@7]
+  b7_from_b6:
+    jmp b7
+  //SEG78 testBinaryOperator::@7
+  b7:
+  //SEG79 [29] call assertType 
+  //SEG80 [87] phi from testBinaryOperator::@7 to assertType [phi:testBinaryOperator::@7->assertType]
+  assertType_from_b7:
+  //SEG81 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@7->assertType#0] -- register_copy 
+  //SEG82 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG83 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_BYTE
+    jsr assertType
+  //SEG84 [30] phi from testBinaryOperator::@7 to testBinaryOperator::@8 [phi:testBinaryOperator::@7->testBinaryOperator::@8]
+  b8_from_b7:
+    jmp b8
+  //SEG85 testBinaryOperator::@8
+  b8:
+  //SEG86 [31] call assertType 
+  //SEG87 [87] phi from testBinaryOperator::@8 to assertType [phi:testBinaryOperator::@8->assertType]
+  assertType_from_b8:
+  //SEG88 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@8->assertType#0] -- register_copy 
+  //SEG89 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG90 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG91 [32] phi from testBinaryOperator::@8 to testBinaryOperator::@9 [phi:testBinaryOperator::@8->testBinaryOperator::@9]
+  b9_from_b8:
+    jmp b9
+  //SEG92 testBinaryOperator::@9
+  b9:
+  //SEG93 [33] call assertType 
+  //SEG94 [87] phi from testBinaryOperator::@9 to assertType [phi:testBinaryOperator::@9->assertType]
+  assertType_from_b9:
+  //SEG95 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@9->assertType#0] -- register_copy 
+  //SEG96 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG97 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG98 [34] phi from testBinaryOperator::@9 to testBinaryOperator::@10 [phi:testBinaryOperator::@9->testBinaryOperator::@10]
+  b10_from_b9:
+    jmp b10
+  //SEG99 testBinaryOperator::@10
+  b10:
+  //SEG100 [35] call assertType 
+  //SEG101 [87] phi from testBinaryOperator::@10 to assertType [phi:testBinaryOperator::@10->assertType]
+  assertType_from_b10:
+  //SEG102 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@10->assertType#0] -- register_copy 
+  //SEG103 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG104 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG105 [36] phi from testBinaryOperator::@10 to testBinaryOperator::@11 [phi:testBinaryOperator::@10->testBinaryOperator::@11]
+  b11_from_b10:
+    jmp b11
+  //SEG106 testBinaryOperator::@11
+  b11:
+  //SEG107 [37] call assertType 
+  //SEG108 [87] phi from testBinaryOperator::@11 to assertType [phi:testBinaryOperator::@11->assertType]
+  assertType_from_b11:
+  //SEG109 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@11->assertType#0] -- register_copy 
+  //SEG110 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG111 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+    jmp b12
+  //SEG112 testBinaryOperator::@12
+  b12:
+  //SEG113 [38] (byte) idx#26 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG114 [39] call assertType 
+  //SEG115 [87] phi from testBinaryOperator::@12 to assertType [phi:testBinaryOperator::@12->assertType]
+  assertType_from_b12:
+  //SEG116 [87] phi (byte) idx#105 = (byte) idx#26 [phi:testBinaryOperator::@12->assertType#0] -- register_copy 
+  //SEG117 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG118 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG119 [40] phi from testBinaryOperator::@12 to testBinaryOperator::@13 [phi:testBinaryOperator::@12->testBinaryOperator::@13]
+  b13_from_b12:
+    jmp b13
+  //SEG120 testBinaryOperator::@13
+  b13:
+  //SEG121 [41] call assertType 
+  //SEG122 [87] phi from testBinaryOperator::@13 to assertType [phi:testBinaryOperator::@13->assertType]
+  assertType_from_b13:
+  //SEG123 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@13->assertType#0] -- register_copy 
+  //SEG124 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG125 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG126 [42] phi from testBinaryOperator::@13 to testBinaryOperator::@14 [phi:testBinaryOperator::@13->testBinaryOperator::@14]
+  b14_from_b13:
+    jmp b14
+  //SEG127 testBinaryOperator::@14
+  b14:
+  //SEG128 [43] call assertType 
+  //SEG129 [87] phi from testBinaryOperator::@14 to assertType [phi:testBinaryOperator::@14->assertType]
+  assertType_from_b14:
+  //SEG130 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@14->assertType#0] -- register_copy 
+  //SEG131 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG132 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG133 [44] phi from testBinaryOperator::@14 to testBinaryOperator::@15 [phi:testBinaryOperator::@14->testBinaryOperator::@15]
+  b15_from_b14:
+    jmp b15
+  //SEG134 testBinaryOperator::@15
+  b15:
+  //SEG135 [45] call assertType 
+  //SEG136 [87] phi from testBinaryOperator::@15 to assertType [phi:testBinaryOperator::@15->assertType]
+  assertType_from_b15:
+  //SEG137 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@15->assertType#0] -- register_copy 
+  //SEG138 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG139 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG140 [46] phi from testBinaryOperator::@15 to testBinaryOperator::@16 [phi:testBinaryOperator::@15->testBinaryOperator::@16]
+  b16_from_b15:
+    jmp b16
+  //SEG141 testBinaryOperator::@16
+  b16:
+  //SEG142 [47] call assertType 
+  //SEG143 [87] phi from testBinaryOperator::@16 to assertType [phi:testBinaryOperator::@16->assertType]
+  assertType_from_b16:
+  //SEG144 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@16->assertType#0] -- register_copy 
+  //SEG145 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG146 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG147 [48] phi from testBinaryOperator::@16 to testBinaryOperator::@17 [phi:testBinaryOperator::@16->testBinaryOperator::@17]
+  b17_from_b16:
+    jmp b17
+  //SEG148 testBinaryOperator::@17
+  b17:
+  //SEG149 [49] call assertType 
+  //SEG150 [87] phi from testBinaryOperator::@17 to assertType [phi:testBinaryOperator::@17->assertType]
+  assertType_from_b17:
+  //SEG151 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@17->assertType#0] -- register_copy 
+  //SEG152 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG153 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG154 [50] phi from testBinaryOperator::@17 to testBinaryOperator::@18 [phi:testBinaryOperator::@17->testBinaryOperator::@18]
+  b18_from_b17:
+    jmp b18
+  //SEG155 testBinaryOperator::@18
+  b18:
+  //SEG156 [51] call assertType 
+  //SEG157 [87] phi from testBinaryOperator::@18 to assertType [phi:testBinaryOperator::@18->assertType]
+  assertType_from_b18:
+  //SEG158 [87] phi (byte) idx#105 = (byte) $50 [phi:testBinaryOperator::@18->assertType#0] -- vbuxx=vbuc1 
+    ldx #$50
+  //SEG159 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG160 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG161 [52] phi from testBinaryOperator::@18 to testBinaryOperator::@19 [phi:testBinaryOperator::@18->testBinaryOperator::@19]
+  b19_from_b18:
+    jmp b19
+  //SEG162 testBinaryOperator::@19
+  b19:
+  //SEG163 [53] call assertType 
+  //SEG164 [87] phi from testBinaryOperator::@19 to assertType [phi:testBinaryOperator::@19->assertType]
+  assertType_from_b19:
+  //SEG165 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@19->assertType#0] -- register_copy 
+  //SEG166 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG167 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG168 [54] phi from testBinaryOperator::@19 to testBinaryOperator::@20 [phi:testBinaryOperator::@19->testBinaryOperator::@20]
+  b20_from_b19:
+    jmp b20
+  //SEG169 testBinaryOperator::@20
+  b20:
+  //SEG170 [55] call assertType 
+  //SEG171 [87] phi from testBinaryOperator::@20 to assertType [phi:testBinaryOperator::@20->assertType]
+  assertType_from_b20:
+  //SEG172 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@20->assertType#0] -- register_copy 
+  //SEG173 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG174 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG175 [56] phi from testBinaryOperator::@20 to testBinaryOperator::@21 [phi:testBinaryOperator::@20->testBinaryOperator::@21]
+  b21_from_b20:
+    jmp b21
+  //SEG176 testBinaryOperator::@21
+  b21:
+  //SEG177 [57] call assertType 
+  //SEG178 [87] phi from testBinaryOperator::@21 to assertType [phi:testBinaryOperator::@21->assertType]
+  assertType_from_b21:
+  //SEG179 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@21->assertType#0] -- register_copy 
+  //SEG180 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG181 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG182 [58] phi from testBinaryOperator::@21 to testBinaryOperator::@22 [phi:testBinaryOperator::@21->testBinaryOperator::@22]
+  b22_from_b21:
+    jmp b22
+  //SEG183 testBinaryOperator::@22
+  b22:
+  //SEG184 [59] call assertType 
+  //SEG185 [87] phi from testBinaryOperator::@22 to assertType [phi:testBinaryOperator::@22->assertType]
+  assertType_from_b22:
+  //SEG186 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@22->assertType#0] -- register_copy 
+  //SEG187 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG188 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG189 [60] phi from testBinaryOperator::@22 to testBinaryOperator::@23 [phi:testBinaryOperator::@22->testBinaryOperator::@23]
+  b23_from_b22:
+    jmp b23
+  //SEG190 testBinaryOperator::@23
+  b23:
+  //SEG191 [61] call assertType 
+  //SEG192 [87] phi from testBinaryOperator::@23 to assertType [phi:testBinaryOperator::@23->assertType]
+  assertType_from_b23:
+  //SEG193 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@23->assertType#0] -- register_copy 
+  //SEG194 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG195 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+    jmp b24
+  //SEG196 testBinaryOperator::@24
+  b24:
+  //SEG197 [62] (byte) idx#40 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG198 [63] call assertType 
+  //SEG199 [87] phi from testBinaryOperator::@24 to assertType [phi:testBinaryOperator::@24->assertType]
+  assertType_from_b24:
+  //SEG200 [87] phi (byte) idx#105 = (byte) idx#40 [phi:testBinaryOperator::@24->assertType#0] -- register_copy 
+  //SEG201 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG202 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG203 [64] phi from testBinaryOperator::@24 to testBinaryOperator::@25 [phi:testBinaryOperator::@24->testBinaryOperator::@25]
+  b25_from_b24:
+    jmp b25
+  //SEG204 testBinaryOperator::@25
+  b25:
+  //SEG205 [65] call assertType 
+  //SEG206 [87] phi from testBinaryOperator::@25 to assertType [phi:testBinaryOperator::@25->assertType]
+  assertType_from_b25:
+  //SEG207 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@25->assertType#0] -- register_copy 
+  //SEG208 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG209 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG210 [66] phi from testBinaryOperator::@25 to testBinaryOperator::@26 [phi:testBinaryOperator::@25->testBinaryOperator::@26]
+  b26_from_b25:
+    jmp b26
+  //SEG211 testBinaryOperator::@26
+  b26:
+  //SEG212 [67] call assertType 
+  //SEG213 [87] phi from testBinaryOperator::@26 to assertType [phi:testBinaryOperator::@26->assertType]
+  assertType_from_b26:
+  //SEG214 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@26->assertType#0] -- register_copy 
+  //SEG215 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG216 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG217 [68] phi from testBinaryOperator::@26 to testBinaryOperator::@27 [phi:testBinaryOperator::@26->testBinaryOperator::@27]
+  b27_from_b26:
+    jmp b27
+  //SEG218 testBinaryOperator::@27
+  b27:
+  //SEG219 [69] call assertType 
+  //SEG220 [87] phi from testBinaryOperator::@27 to assertType [phi:testBinaryOperator::@27->assertType]
+  assertType_from_b27:
+  //SEG221 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@27->assertType#0] -- register_copy 
+  //SEG222 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG223 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG224 [70] phi from testBinaryOperator::@27 to testBinaryOperator::@28 [phi:testBinaryOperator::@27->testBinaryOperator::@28]
+  b28_from_b27:
+    jmp b28
+  //SEG225 testBinaryOperator::@28
+  b28:
+  //SEG226 [71] call assertType 
+  //SEG227 [87] phi from testBinaryOperator::@28 to assertType [phi:testBinaryOperator::@28->assertType]
+  assertType_from_b28:
+  //SEG228 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@28->assertType#0] -- register_copy 
+  //SEG229 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG230 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG231 [72] phi from testBinaryOperator::@28 to testBinaryOperator::@29 [phi:testBinaryOperator::@28->testBinaryOperator::@29]
+  b29_from_b28:
+    jmp b29
+  //SEG232 testBinaryOperator::@29
+  b29:
+  //SEG233 [73] call assertType 
+  //SEG234 [87] phi from testBinaryOperator::@29 to assertType [phi:testBinaryOperator::@29->assertType]
+  assertType_from_b29:
+  //SEG235 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@29->assertType#0] -- register_copy 
+  //SEG236 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG237 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+    jmp b30
+  //SEG238 testBinaryOperator::@30
+  b30:
+  //SEG239 [74] (byte) idx#47 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG240 [75] call assertType 
+  //SEG241 [87] phi from testBinaryOperator::@30 to assertType [phi:testBinaryOperator::@30->assertType]
+  assertType_from_b30:
+  //SEG242 [87] phi (byte) idx#105 = (byte) idx#47 [phi:testBinaryOperator::@30->assertType#0] -- register_copy 
+  //SEG243 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG244 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG245 [76] phi from testBinaryOperator::@30 to testBinaryOperator::@31 [phi:testBinaryOperator::@30->testBinaryOperator::@31]
+  b31_from_b30:
+    jmp b31
+  //SEG246 testBinaryOperator::@31
+  b31:
+  //SEG247 [77] call assertType 
+  //SEG248 [87] phi from testBinaryOperator::@31 to assertType [phi:testBinaryOperator::@31->assertType]
+  assertType_from_b31:
+  //SEG249 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@31->assertType#0] -- register_copy 
+  //SEG250 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG251 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG252 [78] phi from testBinaryOperator::@31 to testBinaryOperator::@32 [phi:testBinaryOperator::@31->testBinaryOperator::@32]
+  b32_from_b31:
+    jmp b32
+  //SEG253 testBinaryOperator::@32
+  b32:
+  //SEG254 [79] call assertType 
+  //SEG255 [87] phi from testBinaryOperator::@32 to assertType [phi:testBinaryOperator::@32->assertType]
+  assertType_from_b32:
+  //SEG256 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@32->assertType#0] -- register_copy 
+  //SEG257 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG258 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG259 [80] phi from testBinaryOperator::@32 to testBinaryOperator::@33 [phi:testBinaryOperator::@32->testBinaryOperator::@33]
+  b33_from_b32:
+    jmp b33
+  //SEG260 testBinaryOperator::@33
+  b33:
+  //SEG261 [81] call assertType 
+  //SEG262 [87] phi from testBinaryOperator::@33 to assertType [phi:testBinaryOperator::@33->assertType]
+  assertType_from_b33:
+  //SEG263 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@33->assertType#0] -- register_copy 
+  //SEG264 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG265 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG266 [82] phi from testBinaryOperator::@33 to testBinaryOperator::@34 [phi:testBinaryOperator::@33->testBinaryOperator::@34]
+  b34_from_b33:
+    jmp b34
+  //SEG267 testBinaryOperator::@34
+  b34:
+  //SEG268 [83] call assertType 
+  //SEG269 [87] phi from testBinaryOperator::@34 to assertType [phi:testBinaryOperator::@34->assertType]
+  assertType_from_b34:
+  //SEG270 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@34->assertType#0] -- register_copy 
+  //SEG271 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG272 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG273 [84] phi from testBinaryOperator::@34 to testBinaryOperator::@35 [phi:testBinaryOperator::@34->testBinaryOperator::@35]
+  b35_from_b34:
+    jmp b35
+  //SEG274 testBinaryOperator::@35
+  b35:
+  //SEG275 [85] call assertType 
+  //SEG276 [87] phi from testBinaryOperator::@35 to assertType [phi:testBinaryOperator::@35->assertType]
+  assertType_from_b35:
+  //SEG277 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@35->assertType#0] -- register_copy 
+  //SEG278 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG279 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+    jmp breturn
+  //SEG280 testBinaryOperator::@return
+  breturn:
+  //SEG281 [86] return 
+    rts
+}
+//SEG282 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(4) t2)
+assertType: {
+    .label t2 = 4
+  //SEG283 [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 
+    tya
+    cmp t2
+    beq b1
+    jmp b3
+  //SEG284 assertType::@3
+  b3:
+  //SEG285 [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #RED
+    sta COLS,x
+    jmp b2
+  //SEG286 assertType::@2
+  b2:
+  //SEG287 [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 -- pbuc1_derefidx_vbuxx=vbuyy 
+    tya
+    sta SCREEN,x
+  //SEG288 [91] (byte) idx#108 ← ++ (byte) idx#105 -- vbuxx=_inc_vbuxx 
+    inx
+    jmp breturn
+  //SEG289 assertType::@return
+  breturn:
+  //SEG290 [92] return 
+    rts
+  //SEG291 assertType::@1
+  b1:
+  //SEG292 [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #GREEN
+    sta COLS,x
+    jmp b2
+}
+//SEG293 testUnaryOperator
+testUnaryOperator: {
+  //SEG294 [95] call assertType 
+  //SEG295 [87] phi from testUnaryOperator to assertType [phi:testUnaryOperator->assertType]
+  assertType_from_testUnaryOperator:
+  //SEG296 [87] phi (byte) idx#105 = (byte) 0 [phi:testUnaryOperator->assertType#0] -- vbuxx=vbuc1 
+    ldx #0
+  //SEG297 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG298 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG299 [96] phi from testUnaryOperator to testUnaryOperator::@1 [phi:testUnaryOperator->testUnaryOperator::@1]
+  b1_from_testUnaryOperator:
+    jmp b1
+  //SEG300 testUnaryOperator::@1
+  b1:
+  //SEG301 [97] call assertType 
+  //SEG302 [87] phi from testUnaryOperator::@1 to assertType [phi:testUnaryOperator::@1->assertType]
+  assertType_from_b1:
+  //SEG303 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@1->assertType#0] -- register_copy 
+  //SEG304 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG305 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_BYTE
+    jsr assertType
+  //SEG306 [98] phi from testUnaryOperator::@1 to testUnaryOperator::@2 [phi:testUnaryOperator::@1->testUnaryOperator::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG307 testUnaryOperator::@2
+  b2:
+  //SEG308 [99] call assertType 
+  //SEG309 [87] phi from testUnaryOperator::@2 to assertType [phi:testUnaryOperator::@2->assertType]
+  assertType_from_b2:
+  //SEG310 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@2->assertType#0] -- register_copy 
+  //SEG311 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG312 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG313 [100] phi from testUnaryOperator::@2 to testUnaryOperator::@3 [phi:testUnaryOperator::@2->testUnaryOperator::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG314 testUnaryOperator::@3
+  b3:
+  //SEG315 [101] call assertType 
+  //SEG316 [87] phi from testUnaryOperator::@3 to assertType [phi:testUnaryOperator::@3->assertType]
+  assertType_from_b3:
+  //SEG317 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@3->assertType#0] -- register_copy 
+  //SEG318 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG319 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG320 [102] phi from testUnaryOperator::@3 to testUnaryOperator::@4 [phi:testUnaryOperator::@3->testUnaryOperator::@4]
+  b4_from_b3:
+    jmp b4
+  //SEG321 testUnaryOperator::@4
+  b4:
+  //SEG322 [103] call assertType 
+  //SEG323 [87] phi from testUnaryOperator::@4 to assertType [phi:testUnaryOperator::@4->assertType]
+  assertType_from_b4:
+  //SEG324 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@4->assertType#0] -- register_copy 
+  //SEG325 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG326 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG327 [104] phi from testUnaryOperator::@4 to testUnaryOperator::@5 [phi:testUnaryOperator::@4->testUnaryOperator::@5]
+  b5_from_b4:
+    jmp b5
+  //SEG328 testUnaryOperator::@5
+  b5:
+  //SEG329 [105] call assertType 
+  //SEG330 [87] phi from testUnaryOperator::@5 to assertType [phi:testUnaryOperator::@5->assertType]
+  assertType_from_b5:
+  //SEG331 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@5->assertType#0] -- register_copy 
+  //SEG332 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG333 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+    jmp breturn
+  //SEG334 testUnaryOperator::@return
+  breturn:
+  //SEG335 [106] return 
+    rts
+}
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp b1
+Removing instruction jmp bend
+Removing instruction jmp b1
+Removing instruction jmp b2
+Removing instruction jmp b3
+Removing instruction jmp breturn
+Removing instruction jmp b1
+Removing instruction jmp b2
+Removing instruction jmp b3
+Removing instruction jmp b4
+Removing instruction jmp b5
+Removing instruction jmp b6
+Removing instruction jmp b7
+Removing instruction jmp b8
+Removing instruction jmp b9
+Removing instruction jmp b10
+Removing instruction jmp b11
+Removing instruction jmp b12
+Removing instruction jmp b13
+Removing instruction jmp b14
+Removing instruction jmp b15
+Removing instruction jmp b16
+Removing instruction jmp b17
+Removing instruction jmp b18
+Removing instruction jmp b19
+Removing instruction jmp b20
+Removing instruction jmp b21
+Removing instruction jmp b22
+Removing instruction jmp b23
+Removing instruction jmp b24
+Removing instruction jmp b25
+Removing instruction jmp b26
+Removing instruction jmp b27
+Removing instruction jmp b28
+Removing instruction jmp b29
+Removing instruction jmp b30
+Removing instruction jmp b31
+Removing instruction jmp b32
+Removing instruction jmp b33
+Removing instruction jmp b34
+Removing instruction jmp b35
+Removing instruction jmp breturn
+Removing instruction jmp b3
+Removing instruction jmp b2
+Removing instruction jmp breturn
+Removing instruction jmp b1
+Removing instruction jmp b2
+Removing instruction jmp b3
+Removing instruction jmp b4
+Removing instruction jmp b5
+Removing instruction jmp breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing label b1_from_b1 with b1
+Replacing label b1_from_b1 with b1
+Removing instruction b1_from_bbegin:
+Removing instruction b1:
+Removing instruction main_from_b1:
+Removing instruction bend_from_b1:
+Removing instruction b1_from_b1:
+Removing instruction b2_from_b1:
+Removing instruction testUnaryOperator_from_b2:
+Removing instruction b3_from_b2:
+Removing instruction testBinaryOperator_from_b3:
+Removing instruction b1_from_testBinaryOperator:
+Removing instruction assertType_from_b1:
+Removing instruction b2_from_b1:
+Removing instruction assertType_from_b2:
+Removing instruction b3_from_b2:
+Removing instruction assertType_from_b3:
+Removing instruction b4_from_b3:
+Removing instruction assertType_from_b4:
+Removing instruction b5_from_b4:
+Removing instruction assertType_from_b5:
+Removing instruction b7_from_b6:
+Removing instruction assertType_from_b7:
+Removing instruction b8_from_b7:
+Removing instruction assertType_from_b8:
+Removing instruction b9_from_b8:
+Removing instruction assertType_from_b9:
+Removing instruction b10_from_b9:
+Removing instruction assertType_from_b10:
+Removing instruction b11_from_b10:
+Removing instruction assertType_from_b11:
+Removing instruction b13_from_b12:
+Removing instruction assertType_from_b13:
+Removing instruction b14_from_b13:
+Removing instruction assertType_from_b14:
+Removing instruction b15_from_b14:
+Removing instruction assertType_from_b15:
+Removing instruction b16_from_b15:
+Removing instruction assertType_from_b16:
+Removing instruction b17_from_b16:
+Removing instruction assertType_from_b17:
+Removing instruction b18_from_b17:
+Removing instruction assertType_from_b18:
+Removing instruction b19_from_b18:
+Removing instruction assertType_from_b19:
+Removing instruction b20_from_b19:
+Removing instruction assertType_from_b20:
+Removing instruction b21_from_b20:
+Removing instruction assertType_from_b21:
+Removing instruction b22_from_b21:
+Removing instruction assertType_from_b22:
+Removing instruction b23_from_b22:
+Removing instruction assertType_from_b23:
+Removing instruction b25_from_b24:
+Removing instruction assertType_from_b25:
+Removing instruction b26_from_b25:
+Removing instruction assertType_from_b26:
+Removing instruction b27_from_b26:
+Removing instruction assertType_from_b27:
+Removing instruction b28_from_b27:
+Removing instruction assertType_from_b28:
+Removing instruction b29_from_b28:
+Removing instruction assertType_from_b29:
+Removing instruction b31_from_b30:
+Removing instruction assertType_from_b31:
+Removing instruction b32_from_b31:
+Removing instruction assertType_from_b32:
+Removing instruction b33_from_b32:
+Removing instruction assertType_from_b33:
+Removing instruction b34_from_b33:
+Removing instruction assertType_from_b34:
+Removing instruction b35_from_b34:
+Removing instruction assertType_from_b35:
+Removing instruction b1_from_testUnaryOperator:
+Removing instruction assertType_from_b1:
+Removing instruction b2_from_b1:
+Removing instruction assertType_from_b2:
+Removing instruction b3_from_b2:
+Removing instruction assertType_from_b3:
+Removing instruction b4_from_b3:
+Removing instruction assertType_from_b4:
+Removing instruction b5_from_b4:
+Removing instruction assertType_from_b5:
+Succesful ASM optimization Pass5RedundantLabelElimination
+Removing instruction bend:
+Removing instruction b1_from_main:
+Removing instruction b2:
+Removing instruction b3:
+Removing instruction breturn:
+Removing instruction assertType_from_testBinaryOperator:
+Removing instruction b1:
+Removing instruction b2:
+Removing instruction b3:
+Removing instruction b4:
+Removing instruction b5:
+Removing instruction b6:
+Removing instruction assertType_from_b6:
+Removing instruction b7:
+Removing instruction b8:
+Removing instruction b9:
+Removing instruction b10:
+Removing instruction b11:
+Removing instruction b12:
+Removing instruction assertType_from_b12:
+Removing instruction b13:
+Removing instruction b14:
+Removing instruction b15:
+Removing instruction b16:
+Removing instruction b17:
+Removing instruction b18:
+Removing instruction b19:
+Removing instruction b20:
+Removing instruction b21:
+Removing instruction b22:
+Removing instruction b23:
+Removing instruction b24:
+Removing instruction assertType_from_b24:
+Removing instruction b25:
+Removing instruction b26:
+Removing instruction b27:
+Removing instruction b28:
+Removing instruction b29:
+Removing instruction b30:
+Removing instruction assertType_from_b30:
+Removing instruction b31:
+Removing instruction b32:
+Removing instruction b33:
+Removing instruction b34:
+Removing instruction b35:
+Removing instruction breturn:
+Removing instruction b3:
+Removing instruction breturn:
+Removing instruction assertType_from_testUnaryOperator:
+Removing instruction b1:
+Removing instruction b2:
+Removing instruction b3:
+Removing instruction b4:
+Removing instruction b5:
+Removing instruction breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+Updating BasicUpstart to call main directly
+Removing instruction jsr main
+Succesful ASM optimization Pass5SkipBegin
+Removing instruction jmp b1
+Succesful ASM optimization Pass5NextJumpElimination
+Removing instruction bbegin:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+(label) @1
+(label) @begin
+(label) @end
+(byte*) COLS
+(const byte*) COLS#0 COLS = ((byte*))(word) $d800
+(byte) GREEN
+(const byte) GREEN#0 GREEN = (byte) 5
+(byte) RED
+(const byte) RED#0 RED = (byte) 2
+(byte*) SCREEN
+(const byte*) SCREEN#0 SCREEN = ((byte*))(word) $400
+(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#42 reg byte y 1.0
+(byte) assertType::t2
+(byte) assertType::t2#42 t2 zp ZP_BYTE:4 2.0
+(byte) idx
+(byte) idx#105 reg byte x 17.200000000000003
+(byte) idx#108 reg byte x 1.0526315789473677
+(byte) idx#19 reg byte x 4.0
+(byte) idx#26 reg byte x 4.0
+(byte) idx#40 reg byte x 4.0
+(byte) idx#47 reg byte x 4.0
+(void()) main()
+(label) main::@1
+(label) main::@2
+(label) main::@3
+(label) main::@return
+(byte*) main::s
+(byte*) main::s#1 s zp ZP_WORD:2 16.5
+(byte*) main::s#2 s zp ZP_WORD:2 16.5
+(void()) testBinaryOperator()
+(label) testBinaryOperator::@1
+(label) testBinaryOperator::@10
+(label) testBinaryOperator::@11
+(label) testBinaryOperator::@12
+(label) testBinaryOperator::@13
+(label) testBinaryOperator::@14
+(label) testBinaryOperator::@15
+(label) testBinaryOperator::@16
+(label) testBinaryOperator::@17
+(label) testBinaryOperator::@18
+(label) testBinaryOperator::@19
+(label) testBinaryOperator::@2
+(label) testBinaryOperator::@20
+(label) testBinaryOperator::@21
+(label) testBinaryOperator::@22
+(label) testBinaryOperator::@23
+(label) testBinaryOperator::@24
+(label) testBinaryOperator::@25
+(label) testBinaryOperator::@26
+(label) testBinaryOperator::@27
+(label) testBinaryOperator::@28
+(label) testBinaryOperator::@29
+(label) testBinaryOperator::@3
+(label) testBinaryOperator::@30
+(label) testBinaryOperator::@31
+(label) testBinaryOperator::@32
+(label) testBinaryOperator::@33
+(label) testBinaryOperator::@34
+(label) testBinaryOperator::@35
+(label) testBinaryOperator::@4
+(label) testBinaryOperator::@5
+(label) testBinaryOperator::@6
+(label) testBinaryOperator::@7
+(label) testBinaryOperator::@8
+(label) testBinaryOperator::@9
+(label) testBinaryOperator::@return
+(void()) testUnaryOperator()
+(label) testUnaryOperator::@1
+(label) testUnaryOperator::@2
+(label) testUnaryOperator::@3
+(label) testUnaryOperator::@4
+(label) testUnaryOperator::@5
+(label) testUnaryOperator::@return
+
+zp ZP_WORD:2 [ main::s#2 main::s#1 ]
+reg byte y [ assertType::t1#42 ]
+zp ZP_BYTE:4 [ assertType::t2#42 ]
+reg byte x [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ]
+
+
+FINAL ASSEMBLER
+Score: 1159
+
+//SEG0 File Comments
+// Tests different integer literal types
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_BYTE = 1
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_WORD = 3
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_DWORD = 5
+  .const TYPEID_SIGNED_DWORD = 6
+  .const RED = 2
+  .const GREEN = 5
+  .label SCREEN = $400
+  .label COLS = $d800
+//SEG3 @begin
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+//SEG5 @1
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+//SEG9 @end
+//SEG10 main
+main: {
+    .label s = 2
+  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
+  //SEG12 [5] phi (byte*) main::s#2 = (const byte*) SCREEN#0 [phi:main->main::@1#0] -- pbuz1=pbuc1 
+    lda #<SCREEN
+    sta s
+    lda #>SCREEN
+    sta s+1
+  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
+  //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy 
+  //SEG15 main::@1
+  b1:
+  //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 
+    lda #' '
+    ldy #0
+    sta (s),y
+  //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 
+    inc s
+    bne !+
+    inc s+1
+  !:
+  //SEG18 [8] if((byte*) main::s#1<(const byte*) SCREEN#0+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 
+    lda s+1
+    cmp #>SCREEN+$3e8
+    bcc b1
+    bne !+
+    lda s
+    cmp #<SCREEN+$3e8
+    bcc b1
+  !:
+  //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  //SEG20 main::@2
+  //SEG21 [10] call testUnaryOperator 
+  //SEG22 [94] phi from main::@2 to testUnaryOperator [phi:main::@2->testUnaryOperator]
+    jsr testUnaryOperator
+  //SEG23 [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
+  //SEG24 main::@3
+  //SEG25 [12] call testBinaryOperator 
+  //SEG26 [14] phi from main::@3 to testBinaryOperator [phi:main::@3->testBinaryOperator]
+    jsr testBinaryOperator
+  //SEG27 main::@return
+  //SEG28 [13] return 
+    rts
+}
+//SEG29 testBinaryOperator
+testBinaryOperator: {
+  //SEG30 [15] call assertType 
+  //SEG31 [87] phi from testBinaryOperator to assertType [phi:testBinaryOperator->assertType]
+  //SEG32 [87] phi (byte) idx#105 = (byte) $28 [phi:testBinaryOperator->assertType#0] -- vbuxx=vbuc1 
+    ldx #$28
+  //SEG33 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG34 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG35 [16] phi from testBinaryOperator to testBinaryOperator::@1 [phi:testBinaryOperator->testBinaryOperator::@1]
+  //SEG36 testBinaryOperator::@1
+  //SEG37 [17] call assertType 
+  //SEG38 [87] phi from testBinaryOperator::@1 to assertType [phi:testBinaryOperator::@1->assertType]
+  //SEG39 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@1->assertType#0] -- register_copy 
+  //SEG40 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG41 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@1->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG42 [18] phi from testBinaryOperator::@1 to testBinaryOperator::@2 [phi:testBinaryOperator::@1->testBinaryOperator::@2]
+  //SEG43 testBinaryOperator::@2
+  //SEG44 [19] call assertType 
+  //SEG45 [87] phi from testBinaryOperator::@2 to assertType [phi:testBinaryOperator::@2->assertType]
+  //SEG46 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@2->assertType#0] -- register_copy 
+  //SEG47 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG48 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@2->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG49 [20] phi from testBinaryOperator::@2 to testBinaryOperator::@3 [phi:testBinaryOperator::@2->testBinaryOperator::@3]
+  //SEG50 testBinaryOperator::@3
+  //SEG51 [21] call assertType 
+  //SEG52 [87] phi from testBinaryOperator::@3 to assertType [phi:testBinaryOperator::@3->assertType]
+  //SEG53 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@3->assertType#0] -- register_copy 
+  //SEG54 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG55 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@3->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG56 [22] phi from testBinaryOperator::@3 to testBinaryOperator::@4 [phi:testBinaryOperator::@3->testBinaryOperator::@4]
+  //SEG57 testBinaryOperator::@4
+  //SEG58 [23] call assertType 
+  //SEG59 [87] phi from testBinaryOperator::@4 to assertType [phi:testBinaryOperator::@4->assertType]
+  //SEG60 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@4->assertType#0] -- register_copy 
+  //SEG61 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG62 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@4->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG63 [24] phi from testBinaryOperator::@4 to testBinaryOperator::@5 [phi:testBinaryOperator::@4->testBinaryOperator::@5]
+  //SEG64 testBinaryOperator::@5
+  //SEG65 [25] call assertType 
+  //SEG66 [87] phi from testBinaryOperator::@5 to assertType [phi:testBinaryOperator::@5->assertType]
+  //SEG67 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@5->assertType#0] -- register_copy 
+  //SEG68 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG69 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@5->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG70 testBinaryOperator::@6
+  //SEG71 [26] (byte) idx#19 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG72 [27] call assertType 
+  //SEG73 [87] phi from testBinaryOperator::@6 to assertType [phi:testBinaryOperator::@6->assertType]
+  //SEG74 [87] phi (byte) idx#105 = (byte) idx#19 [phi:testBinaryOperator::@6->assertType#0] -- register_copy 
+  //SEG75 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG76 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testBinaryOperator::@6->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG77 [28] phi from testBinaryOperator::@6 to testBinaryOperator::@7 [phi:testBinaryOperator::@6->testBinaryOperator::@7]
+  //SEG78 testBinaryOperator::@7
+  //SEG79 [29] call assertType 
+  //SEG80 [87] phi from testBinaryOperator::@7 to assertType [phi:testBinaryOperator::@7->assertType]
+  //SEG81 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@7->assertType#0] -- register_copy 
+  //SEG82 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG83 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testBinaryOperator::@7->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG84 [30] phi from testBinaryOperator::@7 to testBinaryOperator::@8 [phi:testBinaryOperator::@7->testBinaryOperator::@8]
+  //SEG85 testBinaryOperator::@8
+  //SEG86 [31] call assertType 
+  //SEG87 [87] phi from testBinaryOperator::@8 to assertType [phi:testBinaryOperator::@8->assertType]
+  //SEG88 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@8->assertType#0] -- register_copy 
+  //SEG89 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG90 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@8->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG91 [32] phi from testBinaryOperator::@8 to testBinaryOperator::@9 [phi:testBinaryOperator::@8->testBinaryOperator::@9]
+  //SEG92 testBinaryOperator::@9
+  //SEG93 [33] call assertType 
+  //SEG94 [87] phi from testBinaryOperator::@9 to assertType [phi:testBinaryOperator::@9->assertType]
+  //SEG95 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@9->assertType#0] -- register_copy 
+  //SEG96 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG97 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@9->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG98 [34] phi from testBinaryOperator::@9 to testBinaryOperator::@10 [phi:testBinaryOperator::@9->testBinaryOperator::@10]
+  //SEG99 testBinaryOperator::@10
+  //SEG100 [35] call assertType 
+  //SEG101 [87] phi from testBinaryOperator::@10 to assertType [phi:testBinaryOperator::@10->assertType]
+  //SEG102 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@10->assertType#0] -- register_copy 
+  //SEG103 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG104 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@10->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG105 [36] phi from testBinaryOperator::@10 to testBinaryOperator::@11 [phi:testBinaryOperator::@10->testBinaryOperator::@11]
+  //SEG106 testBinaryOperator::@11
+  //SEG107 [37] call assertType 
+  //SEG108 [87] phi from testBinaryOperator::@11 to assertType [phi:testBinaryOperator::@11->assertType]
+  //SEG109 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@11->assertType#0] -- register_copy 
+  //SEG110 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG111 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@11->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG112 testBinaryOperator::@12
+  //SEG113 [38] (byte) idx#26 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG114 [39] call assertType 
+  //SEG115 [87] phi from testBinaryOperator::@12 to assertType [phi:testBinaryOperator::@12->assertType]
+  //SEG116 [87] phi (byte) idx#105 = (byte) idx#26 [phi:testBinaryOperator::@12->assertType#0] -- register_copy 
+  //SEG117 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG118 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@12->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG119 [40] phi from testBinaryOperator::@12 to testBinaryOperator::@13 [phi:testBinaryOperator::@12->testBinaryOperator::@13]
+  //SEG120 testBinaryOperator::@13
+  //SEG121 [41] call assertType 
+  //SEG122 [87] phi from testBinaryOperator::@13 to assertType [phi:testBinaryOperator::@13->assertType]
+  //SEG123 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@13->assertType#0] -- register_copy 
+  //SEG124 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG125 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@13->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG126 [42] phi from testBinaryOperator::@13 to testBinaryOperator::@14 [phi:testBinaryOperator::@13->testBinaryOperator::@14]
+  //SEG127 testBinaryOperator::@14
+  //SEG128 [43] call assertType 
+  //SEG129 [87] phi from testBinaryOperator::@14 to assertType [phi:testBinaryOperator::@14->assertType]
+  //SEG130 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@14->assertType#0] -- register_copy 
+  //SEG131 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG132 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@14->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG133 [44] phi from testBinaryOperator::@14 to testBinaryOperator::@15 [phi:testBinaryOperator::@14->testBinaryOperator::@15]
+  //SEG134 testBinaryOperator::@15
+  //SEG135 [45] call assertType 
+  //SEG136 [87] phi from testBinaryOperator::@15 to assertType [phi:testBinaryOperator::@15->assertType]
+  //SEG137 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@15->assertType#0] -- register_copy 
+  //SEG138 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG139 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@15->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG140 [46] phi from testBinaryOperator::@15 to testBinaryOperator::@16 [phi:testBinaryOperator::@15->testBinaryOperator::@16]
+  //SEG141 testBinaryOperator::@16
+  //SEG142 [47] call assertType 
+  //SEG143 [87] phi from testBinaryOperator::@16 to assertType [phi:testBinaryOperator::@16->assertType]
+  //SEG144 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@16->assertType#0] -- register_copy 
+  //SEG145 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG146 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@16->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG147 [48] phi from testBinaryOperator::@16 to testBinaryOperator::@17 [phi:testBinaryOperator::@16->testBinaryOperator::@17]
+  //SEG148 testBinaryOperator::@17
+  //SEG149 [49] call assertType 
+  //SEG150 [87] phi from testBinaryOperator::@17 to assertType [phi:testBinaryOperator::@17->assertType]
+  //SEG151 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@17->assertType#0] -- register_copy 
+  //SEG152 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG153 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@17->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG154 [50] phi from testBinaryOperator::@17 to testBinaryOperator::@18 [phi:testBinaryOperator::@17->testBinaryOperator::@18]
+  //SEG155 testBinaryOperator::@18
+  //SEG156 [51] call assertType 
+  //SEG157 [87] phi from testBinaryOperator::@18 to assertType [phi:testBinaryOperator::@18->assertType]
+  //SEG158 [87] phi (byte) idx#105 = (byte) $50 [phi:testBinaryOperator::@18->assertType#0] -- vbuxx=vbuc1 
+    ldx #$50
+  //SEG159 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG160 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@18->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG161 [52] phi from testBinaryOperator::@18 to testBinaryOperator::@19 [phi:testBinaryOperator::@18->testBinaryOperator::@19]
+  //SEG162 testBinaryOperator::@19
+  //SEG163 [53] call assertType 
+  //SEG164 [87] phi from testBinaryOperator::@19 to assertType [phi:testBinaryOperator::@19->assertType]
+  //SEG165 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@19->assertType#0] -- register_copy 
+  //SEG166 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG167 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@19->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG168 [54] phi from testBinaryOperator::@19 to testBinaryOperator::@20 [phi:testBinaryOperator::@19->testBinaryOperator::@20]
+  //SEG169 testBinaryOperator::@20
+  //SEG170 [55] call assertType 
+  //SEG171 [87] phi from testBinaryOperator::@20 to assertType [phi:testBinaryOperator::@20->assertType]
+  //SEG172 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@20->assertType#0] -- register_copy 
+  //SEG173 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG174 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testBinaryOperator::@20->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG175 [56] phi from testBinaryOperator::@20 to testBinaryOperator::@21 [phi:testBinaryOperator::@20->testBinaryOperator::@21]
+  //SEG176 testBinaryOperator::@21
+  //SEG177 [57] call assertType 
+  //SEG178 [87] phi from testBinaryOperator::@21 to assertType [phi:testBinaryOperator::@21->assertType]
+  //SEG179 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@21->assertType#0] -- register_copy 
+  //SEG180 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG181 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testBinaryOperator::@21->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG182 [58] phi from testBinaryOperator::@21 to testBinaryOperator::@22 [phi:testBinaryOperator::@21->testBinaryOperator::@22]
+  //SEG183 testBinaryOperator::@22
+  //SEG184 [59] call assertType 
+  //SEG185 [87] phi from testBinaryOperator::@22 to assertType [phi:testBinaryOperator::@22->assertType]
+  //SEG186 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@22->assertType#0] -- register_copy 
+  //SEG187 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG188 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@22->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG189 [60] phi from testBinaryOperator::@22 to testBinaryOperator::@23 [phi:testBinaryOperator::@22->testBinaryOperator::@23]
+  //SEG190 testBinaryOperator::@23
+  //SEG191 [61] call assertType 
+  //SEG192 [87] phi from testBinaryOperator::@23 to assertType [phi:testBinaryOperator::@23->assertType]
+  //SEG193 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@23->assertType#0] -- register_copy 
+  //SEG194 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG195 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@23->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG196 testBinaryOperator::@24
+  //SEG197 [62] (byte) idx#40 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG198 [63] call assertType 
+  //SEG199 [87] phi from testBinaryOperator::@24 to assertType [phi:testBinaryOperator::@24->assertType]
+  //SEG200 [87] phi (byte) idx#105 = (byte) idx#40 [phi:testBinaryOperator::@24->assertType#0] -- register_copy 
+  //SEG201 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG202 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@24->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG203 [64] phi from testBinaryOperator::@24 to testBinaryOperator::@25 [phi:testBinaryOperator::@24->testBinaryOperator::@25]
+  //SEG204 testBinaryOperator::@25
+  //SEG205 [65] call assertType 
+  //SEG206 [87] phi from testBinaryOperator::@25 to assertType [phi:testBinaryOperator::@25->assertType]
+  //SEG207 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@25->assertType#0] -- register_copy 
+  //SEG208 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG209 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@25->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG210 [66] phi from testBinaryOperator::@25 to testBinaryOperator::@26 [phi:testBinaryOperator::@25->testBinaryOperator::@26]
+  //SEG211 testBinaryOperator::@26
+  //SEG212 [67] call assertType 
+  //SEG213 [87] phi from testBinaryOperator::@26 to assertType [phi:testBinaryOperator::@26->assertType]
+  //SEG214 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@26->assertType#0] -- register_copy 
+  //SEG215 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG216 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@26->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG217 [68] phi from testBinaryOperator::@26 to testBinaryOperator::@27 [phi:testBinaryOperator::@26->testBinaryOperator::@27]
+  //SEG218 testBinaryOperator::@27
+  //SEG219 [69] call assertType 
+  //SEG220 [87] phi from testBinaryOperator::@27 to assertType [phi:testBinaryOperator::@27->assertType]
+  //SEG221 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@27->assertType#0] -- register_copy 
+  //SEG222 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG223 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@27->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG224 [70] phi from testBinaryOperator::@27 to testBinaryOperator::@28 [phi:testBinaryOperator::@27->testBinaryOperator::@28]
+  //SEG225 testBinaryOperator::@28
+  //SEG226 [71] call assertType 
+  //SEG227 [87] phi from testBinaryOperator::@28 to assertType [phi:testBinaryOperator::@28->assertType]
+  //SEG228 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@28->assertType#0] -- register_copy 
+  //SEG229 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG230 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@28->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG231 [72] phi from testBinaryOperator::@28 to testBinaryOperator::@29 [phi:testBinaryOperator::@28->testBinaryOperator::@29]
+  //SEG232 testBinaryOperator::@29
+  //SEG233 [73] call assertType 
+  //SEG234 [87] phi from testBinaryOperator::@29 to assertType [phi:testBinaryOperator::@29->assertType]
+  //SEG235 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@29->assertType#0] -- register_copy 
+  //SEG236 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG237 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@29->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG238 testBinaryOperator::@30
+  //SEG239 [74] (byte) idx#47 ← ++ (byte) idx#108 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG240 [75] call assertType 
+  //SEG241 [87] phi from testBinaryOperator::@30 to assertType [phi:testBinaryOperator::@30->assertType]
+  //SEG242 [87] phi (byte) idx#105 = (byte) idx#47 [phi:testBinaryOperator::@30->assertType#0] -- register_copy 
+  //SEG243 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG244 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@30->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG245 [76] phi from testBinaryOperator::@30 to testBinaryOperator::@31 [phi:testBinaryOperator::@30->testBinaryOperator::@31]
+  //SEG246 testBinaryOperator::@31
+  //SEG247 [77] call assertType 
+  //SEG248 [87] phi from testBinaryOperator::@31 to assertType [phi:testBinaryOperator::@31->assertType]
+  //SEG249 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@31->assertType#0] -- register_copy 
+  //SEG250 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG251 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@31->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG252 [78] phi from testBinaryOperator::@31 to testBinaryOperator::@32 [phi:testBinaryOperator::@31->testBinaryOperator::@32]
+  //SEG253 testBinaryOperator::@32
+  //SEG254 [79] call assertType 
+  //SEG255 [87] phi from testBinaryOperator::@32 to assertType [phi:testBinaryOperator::@32->assertType]
+  //SEG256 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@32->assertType#0] -- register_copy 
+  //SEG257 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG258 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@32->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG259 [80] phi from testBinaryOperator::@32 to testBinaryOperator::@33 [phi:testBinaryOperator::@32->testBinaryOperator::@33]
+  //SEG260 testBinaryOperator::@33
+  //SEG261 [81] call assertType 
+  //SEG262 [87] phi from testBinaryOperator::@33 to assertType [phi:testBinaryOperator::@33->assertType]
+  //SEG263 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@33->assertType#0] -- register_copy 
+  //SEG264 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG265 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@33->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG266 [82] phi from testBinaryOperator::@33 to testBinaryOperator::@34 [phi:testBinaryOperator::@33->testBinaryOperator::@34]
+  //SEG267 testBinaryOperator::@34
+  //SEG268 [83] call assertType 
+  //SEG269 [87] phi from testBinaryOperator::@34 to assertType [phi:testBinaryOperator::@34->assertType]
+  //SEG270 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@34->assertType#0] -- register_copy 
+  //SEG271 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG272 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testBinaryOperator::@34->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG273 [84] phi from testBinaryOperator::@34 to testBinaryOperator::@35 [phi:testBinaryOperator::@34->testBinaryOperator::@35]
+  //SEG274 testBinaryOperator::@35
+  //SEG275 [85] call assertType 
+  //SEG276 [87] phi from testBinaryOperator::@35 to assertType [phi:testBinaryOperator::@35->assertType]
+  //SEG277 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testBinaryOperator::@35->assertType#0] -- register_copy 
+  //SEG278 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG279 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testBinaryOperator::@35->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG280 testBinaryOperator::@return
+  //SEG281 [86] return 
+    rts
+}
+//SEG282 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(4) t2)
+assertType: {
+    .label t2 = 4
+  //SEG283 [88] if((byte) assertType::t1#42==(byte) assertType::t2#42) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 
+    tya
+    cmp t2
+    beq b1
+  //SEG284 assertType::@3
+  //SEG285 [89] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #RED
+    sta COLS,x
+  //SEG286 assertType::@2
+  b2:
+  //SEG287 [90] *((const byte*) SCREEN#0 + (byte) idx#105) ← (byte) assertType::t1#42 -- pbuc1_derefidx_vbuxx=vbuyy 
+    tya
+    sta SCREEN,x
+  //SEG288 [91] (byte) idx#108 ← ++ (byte) idx#105 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG289 assertType::@return
+  //SEG290 [92] return 
+    rts
+  //SEG291 assertType::@1
+  b1:
+  //SEG292 [93] *((const byte*) COLS#0 + (byte) idx#105) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #GREEN
+    sta COLS,x
+    jmp b2
+}
+//SEG293 testUnaryOperator
+testUnaryOperator: {
+  //SEG294 [95] call assertType 
+  //SEG295 [87] phi from testUnaryOperator to assertType [phi:testUnaryOperator->assertType]
+  //SEG296 [87] phi (byte) idx#105 = (byte) 0 [phi:testUnaryOperator->assertType#0] -- vbuxx=vbuc1 
+    ldx #0
+  //SEG297 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG298 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_BYTE [phi:testUnaryOperator->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG299 [96] phi from testUnaryOperator to testUnaryOperator::@1 [phi:testUnaryOperator->testUnaryOperator::@1]
+  //SEG300 testUnaryOperator::@1
+  //SEG301 [97] call assertType 
+  //SEG302 [87] phi from testUnaryOperator::@1 to assertType [phi:testUnaryOperator::@1->assertType]
+  //SEG303 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@1->assertType#0] -- register_copy 
+  //SEG304 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG305 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_BYTE [phi:testUnaryOperator::@1->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG306 [98] phi from testUnaryOperator::@1 to testUnaryOperator::@2 [phi:testUnaryOperator::@1->testUnaryOperator::@2]
+  //SEG307 testUnaryOperator::@2
+  //SEG308 [99] call assertType 
+  //SEG309 [87] phi from testUnaryOperator::@2 to assertType [phi:testUnaryOperator::@2->assertType]
+  //SEG310 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@2->assertType#0] -- register_copy 
+  //SEG311 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG312 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_WORD [phi:testUnaryOperator::@2->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG313 [100] phi from testUnaryOperator::@2 to testUnaryOperator::@3 [phi:testUnaryOperator::@2->testUnaryOperator::@3]
+  //SEG314 testUnaryOperator::@3
+  //SEG315 [101] call assertType 
+  //SEG316 [87] phi from testUnaryOperator::@3 to assertType [phi:testUnaryOperator::@3->assertType]
+  //SEG317 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@3->assertType#0] -- register_copy 
+  //SEG318 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG319 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_WORD [phi:testUnaryOperator::@3->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG320 [102] phi from testUnaryOperator::@3 to testUnaryOperator::@4 [phi:testUnaryOperator::@3->testUnaryOperator::@4]
+  //SEG321 testUnaryOperator::@4
+  //SEG322 [103] call assertType 
+  //SEG323 [87] phi from testUnaryOperator::@4 to assertType [phi:testUnaryOperator::@4->assertType]
+  //SEG324 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@4->assertType#0] -- register_copy 
+  //SEG325 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG326 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_DWORD [phi:testUnaryOperator::@4->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG327 [104] phi from testUnaryOperator::@4 to testUnaryOperator::@5 [phi:testUnaryOperator::@4->testUnaryOperator::@5]
+  //SEG328 testUnaryOperator::@5
+  //SEG329 [105] call assertType 
+  //SEG330 [87] phi from testUnaryOperator::@5 to assertType [phi:testUnaryOperator::@5->assertType]
+  //SEG331 [87] phi (byte) idx#105 = (byte) idx#108 [phi:testUnaryOperator::@5->assertType#0] -- register_copy 
+  //SEG332 [87] phi (byte) assertType::t2#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG333 [87] phi (byte) assertType::t1#42 = (const byte) TYPEID_SIGNED_DWORD [phi:testUnaryOperator::@5->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG334 testUnaryOperator::@return
+  //SEG335 [106] return 
+    rts
+}
+
diff --git a/src/test/ref/int-conversion.sym b/src/test/ref/int-conversion.sym
new file mode 100644
index 000000000..c17ed3db6
--- /dev/null
+++ b/src/test/ref/int-conversion.sym
@@ -0,0 +1,90 @@
+(label) @1
+(label) @begin
+(label) @end
+(byte*) COLS
+(const byte*) COLS#0 COLS = ((byte*))(word) $d800
+(byte) GREEN
+(const byte) GREEN#0 GREEN = (byte) 5
+(byte) RED
+(const byte) RED#0 RED = (byte) 2
+(byte*) SCREEN
+(const byte*) SCREEN#0 SCREEN = ((byte*))(word) $400
+(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#42 reg byte y 1.0
+(byte) assertType::t2
+(byte) assertType::t2#42 t2 zp ZP_BYTE:4 2.0
+(byte) idx
+(byte) idx#105 reg byte x 17.200000000000003
+(byte) idx#108 reg byte x 1.0526315789473677
+(byte) idx#19 reg byte x 4.0
+(byte) idx#26 reg byte x 4.0
+(byte) idx#40 reg byte x 4.0
+(byte) idx#47 reg byte x 4.0
+(void()) main()
+(label) main::@1
+(label) main::@2
+(label) main::@3
+(label) main::@return
+(byte*) main::s
+(byte*) main::s#1 s zp ZP_WORD:2 16.5
+(byte*) main::s#2 s zp ZP_WORD:2 16.5
+(void()) testBinaryOperator()
+(label) testBinaryOperator::@1
+(label) testBinaryOperator::@10
+(label) testBinaryOperator::@11
+(label) testBinaryOperator::@12
+(label) testBinaryOperator::@13
+(label) testBinaryOperator::@14
+(label) testBinaryOperator::@15
+(label) testBinaryOperator::@16
+(label) testBinaryOperator::@17
+(label) testBinaryOperator::@18
+(label) testBinaryOperator::@19
+(label) testBinaryOperator::@2
+(label) testBinaryOperator::@20
+(label) testBinaryOperator::@21
+(label) testBinaryOperator::@22
+(label) testBinaryOperator::@23
+(label) testBinaryOperator::@24
+(label) testBinaryOperator::@25
+(label) testBinaryOperator::@26
+(label) testBinaryOperator::@27
+(label) testBinaryOperator::@28
+(label) testBinaryOperator::@29
+(label) testBinaryOperator::@3
+(label) testBinaryOperator::@30
+(label) testBinaryOperator::@31
+(label) testBinaryOperator::@32
+(label) testBinaryOperator::@33
+(label) testBinaryOperator::@34
+(label) testBinaryOperator::@35
+(label) testBinaryOperator::@4
+(label) testBinaryOperator::@5
+(label) testBinaryOperator::@6
+(label) testBinaryOperator::@7
+(label) testBinaryOperator::@8
+(label) testBinaryOperator::@9
+(label) testBinaryOperator::@return
+(void()) testUnaryOperator()
+(label) testUnaryOperator::@1
+(label) testUnaryOperator::@2
+(label) testUnaryOperator::@3
+(label) testUnaryOperator::@4
+(label) testUnaryOperator::@5
+(label) testUnaryOperator::@return
+
+zp ZP_WORD:2 [ main::s#2 main::s#1 ]
+reg byte y [ assertType::t1#42 ]
+zp ZP_BYTE:4 [ assertType::t2#42 ]
+reg byte x [ idx#105 idx#108 idx#26 idx#40 idx#47 idx#19 ]
diff --git a/src/test/ref/int-literals.asm b/src/test/ref/int-literals.asm
new file mode 100644
index 000000000..8f7755754
--- /dev/null
+++ b/src/test/ref/int-literals.asm
@@ -0,0 +1,122 @@
+// Tests different integer literal types
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .const TYPEID_BYTE = 1
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_WORD = 3
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_DWORD = 5
+  .const TYPEID_SIGNED_DWORD = 6
+  .const RED = 2
+  .const GREEN = 5
+main: {
+    .label s = 2
+    lda #<$400
+    sta s
+    lda #>$400
+    sta s+1
+  b1:
+    lda #' '
+    ldy #0
+    sta (s),y
+    inc s
+    bne !+
+    inc s+1
+  !:
+    lda s+1
+    cmp #>$400+$3e8
+    bcc b1
+    bne !+
+    lda s
+    cmp #<$400+$3e8
+    bcc b1
+  !:
+    jsr testSimpleTypes
+    rts
+}
+testSimpleTypes: {
+    ldx #0
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    rts
+}
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(4) t2)
+assertType: {
+    .label t2 = 4
+    tya
+    cmp t2
+    beq b1
+    lda #RED
+    sta $d800,x
+  b2:
+    tya
+    sta $400,x
+    inx
+    rts
+  b1:
+    lda #GREEN
+    sta $d800,x
+    jmp b2
+}
diff --git a/src/test/ref/int-literals.cfg b/src/test/ref/int-literals.cfg
new file mode 100644
index 000000000..eb00a0ab4
--- /dev/null
+++ b/src/test/ref/int-literals.cfg
@@ -0,0 +1,107 @@
+@begin: scope:[]  from
+  [0] phi()
+  to:@1
+@1: scope:[]  from @begin
+  [1] phi()
+  [2] call main 
+  to:@end
+@end: scope:[]  from @1
+  [3] phi()
+main: scope:[main]  from @1
+  [4] phi()
+  to:main::@1
+main::@1: scope:[main]  from main main::@1
+  [5] (byte*) main::s#2 ← phi( main/(byte*)(word) $400 main::@1/(byte*) main::s#1 )
+  [6] *((byte*) main::s#2) ← (byte) ' '
+  [7] (byte*) main::s#1 ← ++ (byte*) main::s#2
+  [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  [9] phi()
+  [10] call testSimpleTypes 
+  to:main::@return
+main::@return: scope:[main]  from main::@2
+  [11] return 
+  to:@return
+testSimpleTypes: scope:[testSimpleTypes]  from main::@2
+  [12] phi()
+  [13] call assertType 
+  to:testSimpleTypes::@1
+testSimpleTypes::@1: scope:[testSimpleTypes]  from testSimpleTypes
+  [14] phi()
+  [15] call assertType 
+  to:testSimpleTypes::@2
+testSimpleTypes::@2: scope:[testSimpleTypes]  from testSimpleTypes::@1
+  [16] phi()
+  [17] call assertType 
+  to:testSimpleTypes::@3
+testSimpleTypes::@3: scope:[testSimpleTypes]  from testSimpleTypes::@2
+  [18] phi()
+  [19] call assertType 
+  to:testSimpleTypes::@4
+testSimpleTypes::@4: scope:[testSimpleTypes]  from testSimpleTypes::@3
+  [20] phi()
+  [21] call assertType 
+  to:testSimpleTypes::@5
+testSimpleTypes::@5: scope:[testSimpleTypes]  from testSimpleTypes::@4
+  [22] phi()
+  [23] call assertType 
+  to:testSimpleTypes::@6
+testSimpleTypes::@6: scope:[testSimpleTypes]  from testSimpleTypes::@5
+  [24] phi()
+  [25] call assertType 
+  to:testSimpleTypes::@7
+testSimpleTypes::@7: scope:[testSimpleTypes]  from testSimpleTypes::@6
+  [26] phi()
+  [27] call assertType 
+  to:testSimpleTypes::@8
+testSimpleTypes::@8: scope:[testSimpleTypes]  from testSimpleTypes::@7
+  [28] phi()
+  [29] call assertType 
+  to:testSimpleTypes::@9
+testSimpleTypes::@9: scope:[testSimpleTypes]  from testSimpleTypes::@8
+  [30] phi()
+  [31] call assertType 
+  to:testSimpleTypes::@10
+testSimpleTypes::@10: scope:[testSimpleTypes]  from testSimpleTypes::@9
+  [32] phi()
+  [33] call assertType 
+  to:testSimpleTypes::@11
+testSimpleTypes::@11: scope:[testSimpleTypes]  from testSimpleTypes::@10
+  [34] phi()
+  [35] call assertType 
+  to:testSimpleTypes::@12
+testSimpleTypes::@12: scope:[testSimpleTypes]  from testSimpleTypes::@11
+  [36] phi()
+  [37] call assertType 
+  to:testSimpleTypes::@13
+testSimpleTypes::@13: scope:[testSimpleTypes]  from testSimpleTypes::@12
+  [38] phi()
+  [39] call assertType 
+  to:testSimpleTypes::@14
+testSimpleTypes::@14: scope:[testSimpleTypes]  from testSimpleTypes::@13
+  [40] phi()
+  [41] call assertType 
+  to:testSimpleTypes::@return
+testSimpleTypes::@return: scope:[testSimpleTypes]  from testSimpleTypes::@14
+  [42] return 
+  to:@return
+assertType: scope:[assertType]  from testSimpleTypes testSimpleTypes::@1 testSimpleTypes::@10 testSimpleTypes::@11 testSimpleTypes::@12 testSimpleTypes::@13 testSimpleTypes::@14 testSimpleTypes::@2 testSimpleTypes::@3 testSimpleTypes::@4 testSimpleTypes::@5 testSimpleTypes::@6 testSimpleTypes::@7 testSimpleTypes::@8 testSimpleTypes::@9
+  [43] (byte) idx#41 ← phi( testSimpleTypes/(byte) 0 testSimpleTypes::@1/(byte) idx#20 testSimpleTypes::@10/(byte) idx#20 testSimpleTypes::@11/(byte) idx#20 testSimpleTypes::@12/(byte) idx#20 testSimpleTypes::@13/(byte) idx#20 testSimpleTypes::@14/(byte) idx#20 testSimpleTypes::@2/(byte) idx#20 testSimpleTypes::@3/(byte) idx#20 testSimpleTypes::@4/(byte) idx#20 testSimpleTypes::@5/(byte) idx#20 testSimpleTypes::@6/(byte) idx#20 testSimpleTypes::@7/(byte) idx#20 testSimpleTypes::@8/(byte) idx#20 testSimpleTypes::@9/(byte) idx#20 )
+  [43] (byte) assertType::t2#15 ← phi( testSimpleTypes/(const byte) TYPEID_BYTE testSimpleTypes::@1/(const byte) TYPEID_BYTE testSimpleTypes::@10/(const byte) TYPEID_DWORD testSimpleTypes::@11/(const byte) TYPEID_DWORD testSimpleTypes::@12/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@13/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@14/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@2/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@3/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@4/(const byte) TYPEID_WORD testSimpleTypes::@5/(const byte) TYPEID_WORD testSimpleTypes::@6/(const byte) TYPEID_WORD testSimpleTypes::@7/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@8/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@9/(const byte) TYPEID_SIGNED_WORD )
+  [43] (byte) assertType::t1#15 ← phi( testSimpleTypes/(const byte) TYPEID_BYTE testSimpleTypes::@1/(const byte) TYPEID_BYTE testSimpleTypes::@10/(const byte) TYPEID_DWORD testSimpleTypes::@11/(const byte) TYPEID_DWORD testSimpleTypes::@12/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@13/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@14/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@2/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@3/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@4/(const byte) TYPEID_WORD testSimpleTypes::@5/(const byte) TYPEID_WORD testSimpleTypes::@6/(const byte) TYPEID_WORD testSimpleTypes::@7/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@8/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@9/(const byte) TYPEID_SIGNED_WORD )
+  [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1
+  to:assertType::@3
+assertType::@3: scope:[assertType]  from assertType
+  [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15
+  [47] (byte) idx#20 ← ++ (byte) idx#41
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  [48] return 
+  to:@return
+assertType::@1: scope:[assertType]  from assertType
+  [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0
+  to:assertType::@2
diff --git a/src/test/ref/int-literals.log b/src/test/ref/int-literals.log
new file mode 100644
index 000000000..4030e6548
--- /dev/null
+++ b/src/test/ref/int-literals.log
@@ -0,0 +1,1947 @@
+Resolving typeid() (byte~) testSimpleTypes::$0 ← typeid  (byte) $c
+Resolving typeid() (byte~) testSimpleTypes::$2 ← typeid  (byte) $c
+Resolving typeid() (byte~) testSimpleTypes::$4 ← typeid  (signed byte) $c
+Resolving typeid() (byte~) testSimpleTypes::$6 ← typeid  (signed byte) $c
+Resolving typeid() (byte~) testSimpleTypes::$8 ← typeid  (word) $c
+Resolving typeid() (byte~) testSimpleTypes::$10 ← typeid  (word) $c
+Resolving typeid() (byte~) testSimpleTypes::$12 ← typeid  (word) $c
+Resolving typeid() (byte~) testSimpleTypes::$14 ← typeid  (signed word) $c
+Resolving typeid() (byte~) testSimpleTypes::$16 ← typeid  (signed word) $c
+Resolving typeid() (byte~) testSimpleTypes::$18 ← typeid  (signed word) $c
+Resolving typeid() (byte~) testSimpleTypes::$20 ← typeid  (dword) $c
+Resolving typeid() (byte~) testSimpleTypes::$22 ← typeid  (dword) $c
+Resolving typeid() (byte~) testSimpleTypes::$24 ← typeid  (signed dword) $c
+Resolving typeid() (byte~) testSimpleTypes::$26 ← typeid  (signed dword) $c
+Resolving typeid() (byte~) testSimpleTypes::$28 ← typeid  (signed dword) $c
+Adding pointer type conversion cast (byte*) SCREEN in (byte*) SCREEN ← (word) $400
+Adding pointer type conversion cast (byte*) COLS in (byte*) COLS ← (word) $d800
+
+CONTROL FLOW GRAPH SSA
+@begin: scope:[]  from
+  (byte) RED#0 ← (byte) 2
+  (byte) GREEN#0 ← (byte) 5
+  (word) $0 ← (word) $400
+  (byte*) SCREEN#0 ← ((byte*)) (word) $0
+  (word) $1 ← (word) $d800
+  (byte*) COLS#0 ← ((byte*)) (word) $1
+  (byte) idx#0 ← (byte) 0
+  to:@3
+main: scope:[main]  from @3
+  (byte) idx#50 ← phi( @3/(byte) idx#48 )
+  (byte*) main::s#0 ← (byte*) SCREEN#0
+  to:main::@1
+main::@1: scope:[main]  from main main::@1
+  (byte) idx#49 ← phi( main/(byte) idx#50 main::@1/(byte) idx#49 )
+  (byte*) main::s#2 ← phi( main/(byte*) main::s#0 main::@1/(byte*) main::s#1 )
+  *((byte*) main::s#2) ← (byte) ' '
+  (byte*) main::s#1 ← ++ (byte*) main::s#2
+  (byte*~) main::$1 ← (byte*) SCREEN#0 + (word) $3e8
+  (bool~) main::$2 ← (byte*) main::s#1 < (byte*~) main::$1
+  if((bool~) main::$2) goto main::@1
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  (byte) idx#46 ← phi( main::@1/(byte) idx#49 )
+  call testSimpleTypes 
+  to:main::@3
+main::@3: scope:[main]  from main::@2
+  (byte) idx#23 ← phi( main::@2/(byte) idx#19 )
+  (byte) idx#1 ← (byte) idx#23
+  to:main::@return
+main::@return: scope:[main]  from main::@3
+  (byte) idx#24 ← phi( main::@3/(byte) idx#1 )
+  (byte) idx#2 ← (byte) idx#24
+  return 
+  to:@return
+testSimpleTypes: scope:[testSimpleTypes]  from main::@2
+  (byte) idx#3 ← (byte) 0
+  (byte~) testSimpleTypes::$0 ← (const byte) TYPEID_BYTE
+  (byte) assertType::t1#0 ← (byte~) testSimpleTypes::$0
+  (byte) assertType::t2#0 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:testSimpleTypes::@1
+testSimpleTypes::@1: scope:[testSimpleTypes]  from testSimpleTypes
+  (byte) idx#25 ← phi( testSimpleTypes/(byte) idx#21 )
+  (byte) idx#4 ← (byte) idx#25
+  (byte~) testSimpleTypes::$2 ← (const byte) TYPEID_BYTE
+  (byte) assertType::t1#1 ← (byte~) testSimpleTypes::$2
+  (byte) assertType::t2#1 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:testSimpleTypes::@2
+testSimpleTypes::@2: scope:[testSimpleTypes]  from testSimpleTypes::@1
+  (byte) idx#26 ← phi( testSimpleTypes::@1/(byte) idx#21 )
+  (byte) idx#5 ← (byte) idx#26
+  (byte~) testSimpleTypes::$4 ← (const byte) TYPEID_SIGNED_BYTE
+  (byte) assertType::t1#2 ← (byte~) testSimpleTypes::$4
+  (byte) assertType::t2#2 ← (const byte) TYPEID_SIGNED_BYTE
+  call assertType 
+  to:testSimpleTypes::@3
+testSimpleTypes::@3: scope:[testSimpleTypes]  from testSimpleTypes::@2
+  (byte) idx#27 ← phi( testSimpleTypes::@2/(byte) idx#21 )
+  (byte) idx#6 ← (byte) idx#27
+  (byte~) testSimpleTypes::$6 ← (const byte) TYPEID_SIGNED_BYTE
+  (byte) assertType::t1#3 ← (byte~) testSimpleTypes::$6
+  (byte) assertType::t2#3 ← (const byte) TYPEID_SIGNED_BYTE
+  call assertType 
+  to:testSimpleTypes::@4
+testSimpleTypes::@4: scope:[testSimpleTypes]  from testSimpleTypes::@3
+  (byte) idx#28 ← phi( testSimpleTypes::@3/(byte) idx#21 )
+  (byte) idx#7 ← (byte) idx#28
+  (byte~) testSimpleTypes::$8 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#4 ← (byte~) testSimpleTypes::$8
+  (byte) assertType::t2#4 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testSimpleTypes::@5
+testSimpleTypes::@5: scope:[testSimpleTypes]  from testSimpleTypes::@4
+  (byte) idx#29 ← phi( testSimpleTypes::@4/(byte) idx#21 )
+  (byte) idx#8 ← (byte) idx#29
+  (byte~) testSimpleTypes::$10 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#5 ← (byte~) testSimpleTypes::$10
+  (byte) assertType::t2#5 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testSimpleTypes::@6
+testSimpleTypes::@6: scope:[testSimpleTypes]  from testSimpleTypes::@5
+  (byte) idx#30 ← phi( testSimpleTypes::@5/(byte) idx#21 )
+  (byte) idx#9 ← (byte) idx#30
+  (byte~) testSimpleTypes::$12 ← (const byte) TYPEID_WORD
+  (byte) assertType::t1#6 ← (byte~) testSimpleTypes::$12
+  (byte) assertType::t2#6 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:testSimpleTypes::@7
+testSimpleTypes::@7: scope:[testSimpleTypes]  from testSimpleTypes::@6
+  (byte) idx#31 ← phi( testSimpleTypes::@6/(byte) idx#21 )
+  (byte) idx#10 ← (byte) idx#31
+  (byte~) testSimpleTypes::$14 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#7 ← (byte~) testSimpleTypes::$14
+  (byte) assertType::t2#7 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testSimpleTypes::@8
+testSimpleTypes::@8: scope:[testSimpleTypes]  from testSimpleTypes::@7
+  (byte) idx#32 ← phi( testSimpleTypes::@7/(byte) idx#21 )
+  (byte) idx#11 ← (byte) idx#32
+  (byte~) testSimpleTypes::$16 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#8 ← (byte~) testSimpleTypes::$16
+  (byte) assertType::t2#8 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testSimpleTypes::@9
+testSimpleTypes::@9: scope:[testSimpleTypes]  from testSimpleTypes::@8
+  (byte) idx#33 ← phi( testSimpleTypes::@8/(byte) idx#21 )
+  (byte) idx#12 ← (byte) idx#33
+  (byte~) testSimpleTypes::$18 ← (const byte) TYPEID_SIGNED_WORD
+  (byte) assertType::t1#9 ← (byte~) testSimpleTypes::$18
+  (byte) assertType::t2#9 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:testSimpleTypes::@10
+testSimpleTypes::@10: scope:[testSimpleTypes]  from testSimpleTypes::@9
+  (byte) idx#34 ← phi( testSimpleTypes::@9/(byte) idx#21 )
+  (byte) idx#13 ← (byte) idx#34
+  (byte~) testSimpleTypes::$20 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#10 ← (byte~) testSimpleTypes::$20
+  (byte) assertType::t2#10 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testSimpleTypes::@11
+testSimpleTypes::@11: scope:[testSimpleTypes]  from testSimpleTypes::@10
+  (byte) idx#35 ← phi( testSimpleTypes::@10/(byte) idx#21 )
+  (byte) idx#14 ← (byte) idx#35
+  (byte~) testSimpleTypes::$22 ← (const byte) TYPEID_DWORD
+  (byte) assertType::t1#11 ← (byte~) testSimpleTypes::$22
+  (byte) assertType::t2#11 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:testSimpleTypes::@12
+testSimpleTypes::@12: scope:[testSimpleTypes]  from testSimpleTypes::@11
+  (byte) idx#36 ← phi( testSimpleTypes::@11/(byte) idx#21 )
+  (byte) idx#15 ← (byte) idx#36
+  (byte~) testSimpleTypes::$24 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#12 ← (byte~) testSimpleTypes::$24
+  (byte) assertType::t2#12 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testSimpleTypes::@13
+testSimpleTypes::@13: scope:[testSimpleTypes]  from testSimpleTypes::@12
+  (byte) idx#37 ← phi( testSimpleTypes::@12/(byte) idx#21 )
+  (byte) idx#16 ← (byte) idx#37
+  (byte~) testSimpleTypes::$26 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#13 ← (byte~) testSimpleTypes::$26
+  (byte) assertType::t2#13 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testSimpleTypes::@14
+testSimpleTypes::@14: scope:[testSimpleTypes]  from testSimpleTypes::@13
+  (byte) idx#38 ← phi( testSimpleTypes::@13/(byte) idx#21 )
+  (byte) idx#17 ← (byte) idx#38
+  (byte~) testSimpleTypes::$28 ← (const byte) TYPEID_SIGNED_DWORD
+  (byte) assertType::t1#14 ← (byte~) testSimpleTypes::$28
+  (byte) assertType::t2#14 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:testSimpleTypes::@15
+testSimpleTypes::@15: scope:[testSimpleTypes]  from testSimpleTypes::@14
+  (byte) idx#39 ← phi( testSimpleTypes::@14/(byte) idx#21 )
+  (byte) idx#18 ← (byte) idx#39
+  to:testSimpleTypes::@return
+testSimpleTypes::@return: scope:[testSimpleTypes]  from testSimpleTypes::@15
+  (byte) idx#40 ← phi( testSimpleTypes::@15/(byte) idx#18 )
+  (byte) idx#19 ← (byte) idx#40
+  return 
+  to:@return
+assertType: scope:[assertType]  from testSimpleTypes testSimpleTypes::@1 testSimpleTypes::@10 testSimpleTypes::@11 testSimpleTypes::@12 testSimpleTypes::@13 testSimpleTypes::@14 testSimpleTypes::@2 testSimpleTypes::@3 testSimpleTypes::@4 testSimpleTypes::@5 testSimpleTypes::@6 testSimpleTypes::@7 testSimpleTypes::@8 testSimpleTypes::@9
+  (byte) idx#47 ← phi( testSimpleTypes/(byte) idx#3 testSimpleTypes::@1/(byte) idx#4 testSimpleTypes::@10/(byte) idx#13 testSimpleTypes::@11/(byte) idx#14 testSimpleTypes::@12/(byte) idx#15 testSimpleTypes::@13/(byte) idx#16 testSimpleTypes::@14/(byte) idx#17 testSimpleTypes::@2/(byte) idx#5 testSimpleTypes::@3/(byte) idx#6 testSimpleTypes::@4/(byte) idx#7 testSimpleTypes::@5/(byte) idx#8 testSimpleTypes::@6/(byte) idx#9 testSimpleTypes::@7/(byte) idx#10 testSimpleTypes::@8/(byte) idx#11 testSimpleTypes::@9/(byte) idx#12 )
+  (byte) assertType::t2#15 ← phi( testSimpleTypes/(byte) assertType::t2#0 testSimpleTypes::@1/(byte) assertType::t2#1 testSimpleTypes::@10/(byte) assertType::t2#10 testSimpleTypes::@11/(byte) assertType::t2#11 testSimpleTypes::@12/(byte) assertType::t2#12 testSimpleTypes::@13/(byte) assertType::t2#13 testSimpleTypes::@14/(byte) assertType::t2#14 testSimpleTypes::@2/(byte) assertType::t2#2 testSimpleTypes::@3/(byte) assertType::t2#3 testSimpleTypes::@4/(byte) assertType::t2#4 testSimpleTypes::@5/(byte) assertType::t2#5 testSimpleTypes::@6/(byte) assertType::t2#6 testSimpleTypes::@7/(byte) assertType::t2#7 testSimpleTypes::@8/(byte) assertType::t2#8 testSimpleTypes::@9/(byte) assertType::t2#9 )
+  (byte) assertType::t1#15 ← phi( testSimpleTypes/(byte) assertType::t1#0 testSimpleTypes::@1/(byte) assertType::t1#1 testSimpleTypes::@10/(byte) assertType::t1#10 testSimpleTypes::@11/(byte) assertType::t1#11 testSimpleTypes::@12/(byte) assertType::t1#12 testSimpleTypes::@13/(byte) assertType::t1#13 testSimpleTypes::@14/(byte) assertType::t1#14 testSimpleTypes::@2/(byte) assertType::t1#2 testSimpleTypes::@3/(byte) assertType::t1#3 testSimpleTypes::@4/(byte) assertType::t1#4 testSimpleTypes::@5/(byte) assertType::t1#5 testSimpleTypes::@6/(byte) assertType::t1#6 testSimpleTypes::@7/(byte) assertType::t1#7 testSimpleTypes::@8/(byte) assertType::t1#8 testSimpleTypes::@9/(byte) assertType::t1#9 )
+  (bool~) assertType::$0 ← (byte) assertType::t1#15 == (byte) assertType::t2#15
+  if((bool~) assertType::$0) goto assertType::@1
+  to:assertType::@3
+assertType::@1: scope:[assertType]  from assertType
+  (byte) assertType::t1#17 ← phi( assertType/(byte) assertType::t1#15 )
+  (byte) idx#41 ← phi( assertType/(byte) idx#47 )
+  *((byte*) COLS#0 + (byte) idx#41) ← (byte) GREEN#0
+  to:assertType::@2
+assertType::@3: scope:[assertType]  from assertType
+  (byte) assertType::t1#18 ← phi( assertType/(byte) assertType::t1#15 )
+  (byte) idx#42 ← phi( assertType/(byte) idx#47 )
+  *((byte*) COLS#0 + (byte) idx#42) ← (byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  (byte) idx#43 ← phi( assertType::@1/(byte) idx#41 assertType::@3/(byte) idx#42 )
+  (byte) assertType::t1#16 ← phi( assertType::@1/(byte) assertType::t1#17 assertType::@3/(byte) assertType::t1#18 )
+  *((byte*) SCREEN#0 + (byte) idx#43) ← (byte) assertType::t1#16
+  (byte) idx#20 ← ++ (byte) idx#43
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  (byte) idx#44 ← phi( assertType::@2/(byte) idx#20 )
+  (byte) idx#21 ← (byte) idx#44
+  return 
+  to:@return
+@3: scope:[]  from @begin
+  (byte) idx#48 ← phi( @begin/(byte) idx#0 )
+  call main 
+  to:@4
+@4: scope:[]  from @3
+  (byte) idx#45 ← phi( @3/(byte) idx#2 )
+  (byte) idx#22 ← (byte) idx#45
+  to:@end
+@end: scope:[]  from @4
+
+SYMBOL TABLE SSA
+(word) $0
+(word) $1
+(label) @3
+(label) @4
+(label) @begin
+(label) @end
+(byte*) COLS
+(byte*) COLS#0
+(byte) GREEN
+(byte) GREEN#0
+(byte) RED
+(byte) RED#0
+(byte*) SCREEN
+(byte*) SCREEN#0
+(const byte) TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(bool~) assertType::$0
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#0
+(byte) assertType::t1#1
+(byte) assertType::t1#10
+(byte) assertType::t1#11
+(byte) assertType::t1#12
+(byte) assertType::t1#13
+(byte) assertType::t1#14
+(byte) assertType::t1#15
+(byte) assertType::t1#16
+(byte) assertType::t1#17
+(byte) assertType::t1#18
+(byte) assertType::t1#2
+(byte) assertType::t1#3
+(byte) assertType::t1#4
+(byte) assertType::t1#5
+(byte) assertType::t1#6
+(byte) assertType::t1#7
+(byte) assertType::t1#8
+(byte) assertType::t1#9
+(byte) assertType::t2
+(byte) assertType::t2#0
+(byte) assertType::t2#1
+(byte) assertType::t2#10
+(byte) assertType::t2#11
+(byte) assertType::t2#12
+(byte) assertType::t2#13
+(byte) assertType::t2#14
+(byte) assertType::t2#15
+(byte) assertType::t2#2
+(byte) assertType::t2#3
+(byte) assertType::t2#4
+(byte) assertType::t2#5
+(byte) assertType::t2#6
+(byte) assertType::t2#7
+(byte) assertType::t2#8
+(byte) assertType::t2#9
+(byte) idx
+(byte) idx#0
+(byte) idx#1
+(byte) idx#10
+(byte) idx#11
+(byte) idx#12
+(byte) idx#13
+(byte) idx#14
+(byte) idx#15
+(byte) idx#16
+(byte) idx#17
+(byte) idx#18
+(byte) idx#19
+(byte) idx#2
+(byte) idx#20
+(byte) idx#21
+(byte) idx#22
+(byte) idx#23
+(byte) idx#24
+(byte) idx#25
+(byte) idx#26
+(byte) idx#27
+(byte) idx#28
+(byte) idx#29
+(byte) idx#3
+(byte) idx#30
+(byte) idx#31
+(byte) idx#32
+(byte) idx#33
+(byte) idx#34
+(byte) idx#35
+(byte) idx#36
+(byte) idx#37
+(byte) idx#38
+(byte) idx#39
+(byte) idx#4
+(byte) idx#40
+(byte) idx#41
+(byte) idx#42
+(byte) idx#43
+(byte) idx#44
+(byte) idx#45
+(byte) idx#46
+(byte) idx#47
+(byte) idx#48
+(byte) idx#49
+(byte) idx#5
+(byte) idx#50
+(byte) idx#6
+(byte) idx#7
+(byte) idx#8
+(byte) idx#9
+(void()) main()
+(byte*~) main::$1
+(bool~) main::$2
+(label) main::@1
+(label) main::@2
+(label) main::@3
+(label) main::@return
+(byte*) main::s
+(byte*) main::s#0
+(byte*) main::s#1
+(byte*) main::s#2
+(void()) testSimpleTypes()
+(byte~) testSimpleTypes::$0
+(byte~) testSimpleTypes::$10
+(byte~) testSimpleTypes::$12
+(byte~) testSimpleTypes::$14
+(byte~) testSimpleTypes::$16
+(byte~) testSimpleTypes::$18
+(byte~) testSimpleTypes::$2
+(byte~) testSimpleTypes::$20
+(byte~) testSimpleTypes::$22
+(byte~) testSimpleTypes::$24
+(byte~) testSimpleTypes::$26
+(byte~) testSimpleTypes::$28
+(byte~) testSimpleTypes::$4
+(byte~) testSimpleTypes::$6
+(byte~) testSimpleTypes::$8
+(label) testSimpleTypes::@1
+(label) testSimpleTypes::@10
+(label) testSimpleTypes::@11
+(label) testSimpleTypes::@12
+(label) testSimpleTypes::@13
+(label) testSimpleTypes::@14
+(label) testSimpleTypes::@15
+(label) testSimpleTypes::@2
+(label) testSimpleTypes::@3
+(label) testSimpleTypes::@4
+(label) testSimpleTypes::@5
+(label) testSimpleTypes::@6
+(label) testSimpleTypes::@7
+(label) testSimpleTypes::@8
+(label) testSimpleTypes::@9
+(label) testSimpleTypes::@return
+
+Alias (byte) idx#46 = (byte) idx#49 
+Alias (byte) idx#1 = (byte) idx#23 (byte) idx#24 (byte) idx#2 
+Alias (byte) assertType::t1#0 = (byte~) testSimpleTypes::$0 
+Alias (byte) idx#25 = (byte) idx#4 
+Alias (byte) assertType::t1#1 = (byte~) testSimpleTypes::$2 
+Alias (byte) idx#26 = (byte) idx#5 
+Alias (byte) assertType::t1#2 = (byte~) testSimpleTypes::$4 
+Alias (byte) idx#27 = (byte) idx#6 
+Alias (byte) assertType::t1#3 = (byte~) testSimpleTypes::$6 
+Alias (byte) idx#28 = (byte) idx#7 
+Alias (byte) assertType::t1#4 = (byte~) testSimpleTypes::$8 
+Alias (byte) idx#29 = (byte) idx#8 
+Alias (byte) assertType::t1#5 = (byte~) testSimpleTypes::$10 
+Alias (byte) idx#30 = (byte) idx#9 
+Alias (byte) assertType::t1#6 = (byte~) testSimpleTypes::$12 
+Alias (byte) idx#10 = (byte) idx#31 
+Alias (byte) assertType::t1#7 = (byte~) testSimpleTypes::$14 
+Alias (byte) idx#11 = (byte) idx#32 
+Alias (byte) assertType::t1#8 = (byte~) testSimpleTypes::$16 
+Alias (byte) idx#12 = (byte) idx#33 
+Alias (byte) assertType::t1#9 = (byte~) testSimpleTypes::$18 
+Alias (byte) idx#13 = (byte) idx#34 
+Alias (byte) assertType::t1#10 = (byte~) testSimpleTypes::$20 
+Alias (byte) idx#14 = (byte) idx#35 
+Alias (byte) assertType::t1#11 = (byte~) testSimpleTypes::$22 
+Alias (byte) idx#15 = (byte) idx#36 
+Alias (byte) assertType::t1#12 = (byte~) testSimpleTypes::$24 
+Alias (byte) idx#16 = (byte) idx#37 
+Alias (byte) assertType::t1#13 = (byte~) testSimpleTypes::$26 
+Alias (byte) idx#17 = (byte) idx#38 
+Alias (byte) assertType::t1#14 = (byte~) testSimpleTypes::$28 
+Alias (byte) idx#18 = (byte) idx#39 (byte) idx#40 (byte) idx#19 
+Alias (byte) idx#41 = (byte) idx#47 (byte) idx#42 
+Alias (byte) assertType::t1#15 = (byte) assertType::t1#17 (byte) assertType::t1#18 
+Alias (byte) idx#20 = (byte) idx#44 (byte) idx#21 
+Alias (byte) idx#0 = (byte) idx#48 
+Alias (byte) idx#22 = (byte) idx#45 
+Successful SSA optimization Pass2AliasElimination
+Alias (byte) assertType::t1#15 = (byte) assertType::t1#16 
+Alias (byte) idx#41 = (byte) idx#43 
+Successful SSA optimization Pass2AliasElimination
+Self Phi Eliminated (byte) idx#46
+Successful SSA optimization Pass2SelfPhiElimination
+Redundant Phi (byte) idx#50 (byte) idx#0
+Redundant Phi (byte) idx#46 (byte) idx#50
+Redundant Phi (byte) idx#1 (byte) idx#18
+Redundant Phi (byte) idx#25 (byte) idx#20
+Redundant Phi (byte) idx#26 (byte) idx#20
+Redundant Phi (byte) idx#27 (byte) idx#20
+Redundant Phi (byte) idx#28 (byte) idx#20
+Redundant Phi (byte) idx#29 (byte) idx#20
+Redundant Phi (byte) idx#30 (byte) idx#20
+Redundant Phi (byte) idx#10 (byte) idx#20
+Redundant Phi (byte) idx#11 (byte) idx#20
+Redundant Phi (byte) idx#12 (byte) idx#20
+Redundant Phi (byte) idx#13 (byte) idx#20
+Redundant Phi (byte) idx#14 (byte) idx#20
+Redundant Phi (byte) idx#15 (byte) idx#20
+Redundant Phi (byte) idx#16 (byte) idx#20
+Redundant Phi (byte) idx#17 (byte) idx#20
+Redundant Phi (byte) idx#18 (byte) idx#20
+Redundant Phi (byte) idx#22 (byte) idx#1
+Successful SSA optimization Pass2RedundantPhiElimination
+Simple Condition (bool~) main::$2 [14] if((byte*) main::s#1<(byte*~) main::$1) goto main::@1
+Simple Condition (bool~) assertType::$0 [118] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1
+Successful SSA optimization Pass2ConditionalJumpSimplification
+Constant (const byte) RED#0 = 2
+Constant (const byte) GREEN#0 = 5
+Constant (const word) $0 = $400
+Constant (const word) $1 = $d800
+Constant (const byte) idx#0 = 0
+Constant (const byte) idx#3 = 0
+Constant (const byte) assertType::t1#0 = TYPEID_BYTE
+Constant (const byte) assertType::t2#0 = TYPEID_BYTE
+Constant (const byte) assertType::t1#1 = TYPEID_BYTE
+Constant (const byte) assertType::t2#1 = TYPEID_BYTE
+Constant (const byte) assertType::t1#2 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t2#2 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t1#3 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t2#3 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t1#4 = TYPEID_WORD
+Constant (const byte) assertType::t2#4 = TYPEID_WORD
+Constant (const byte) assertType::t1#5 = TYPEID_WORD
+Constant (const byte) assertType::t2#5 = TYPEID_WORD
+Constant (const byte) assertType::t1#6 = TYPEID_WORD
+Constant (const byte) assertType::t2#6 = TYPEID_WORD
+Constant (const byte) assertType::t1#7 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#7 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#8 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#8 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#9 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#9 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t1#10 = TYPEID_DWORD
+Constant (const byte) assertType::t2#10 = TYPEID_DWORD
+Constant (const byte) assertType::t1#11 = TYPEID_DWORD
+Constant (const byte) assertType::t2#11 = TYPEID_DWORD
+Constant (const byte) assertType::t1#12 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#12 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#13 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#13 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t1#14 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#14 = TYPEID_SIGNED_DWORD
+Successful SSA optimization Pass2ConstantIdentification
+Eliminating unused constant (const byte) idx#0
+Successful SSA optimization PassNEliminateUnusedVars
+Eliminating Noop Cast (byte*) SCREEN#0 ← ((byte*)) (const word) $0
+Eliminating Noop Cast (byte*) COLS#0 ← ((byte*)) (const word) $1
+Successful SSA optimization Pass2NopCastElimination
+Culled Empty Block (label) main::@3
+Culled Empty Block (label) testSimpleTypes::@15
+Culled Empty Block (label) @4
+Successful SSA optimization Pass2CullEmptyBlocks
+Constant right-side identified [4] (byte*~) main::$1 ← (byte*)(const word) $0 + (word) $3e8
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte*) main::s#0 = (byte*)$0
+Constant (const byte*) main::$1 = (byte*)$0+$3e8
+Successful SSA optimization Pass2ConstantIdentification
+Inlining constant with var siblings (const byte*) main::s#0
+Inlining constant with var siblings (const byte) assertType::t1#0
+Inlining constant with var siblings (const byte) assertType::t2#0
+Inlining constant with var siblings (const byte) assertType::t1#1
+Inlining constant with var siblings (const byte) assertType::t2#1
+Inlining constant with var siblings (const byte) assertType::t1#2
+Inlining constant with var siblings (const byte) assertType::t2#2
+Inlining constant with var siblings (const byte) assertType::t1#3
+Inlining constant with var siblings (const byte) assertType::t2#3
+Inlining constant with var siblings (const byte) assertType::t1#4
+Inlining constant with var siblings (const byte) assertType::t2#4
+Inlining constant with var siblings (const byte) assertType::t1#5
+Inlining constant with var siblings (const byte) assertType::t2#5
+Inlining constant with var siblings (const byte) assertType::t1#6
+Inlining constant with var siblings (const byte) assertType::t2#6
+Inlining constant with var siblings (const byte) assertType::t1#7
+Inlining constant with var siblings (const byte) assertType::t2#7
+Inlining constant with var siblings (const byte) assertType::t1#8
+Inlining constant with var siblings (const byte) assertType::t2#8
+Inlining constant with var siblings (const byte) assertType::t1#9
+Inlining constant with var siblings (const byte) assertType::t2#9
+Inlining constant with var siblings (const byte) assertType::t1#10
+Inlining constant with var siblings (const byte) assertType::t2#10
+Inlining constant with var siblings (const byte) assertType::t1#11
+Inlining constant with var siblings (const byte) assertType::t2#11
+Inlining constant with var siblings (const byte) assertType::t1#12
+Inlining constant with var siblings (const byte) assertType::t2#12
+Inlining constant with var siblings (const byte) assertType::t1#13
+Inlining constant with var siblings (const byte) assertType::t2#13
+Inlining constant with var siblings (const byte) assertType::t1#14
+Inlining constant with var siblings (const byte) assertType::t2#14
+Inlining constant with var siblings (const byte) idx#3
+Constant inlined assertType::t2#5 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#6 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#6 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#7 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#7 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t1#8 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#8 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t1#9 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#9 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined $0 = (word) $400
+Constant inlined $1 = (word) $d800
+Constant inlined assertType::t2#11 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#10 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#13 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#12 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#14 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#0 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#0 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#1 = (const byte) TYPEID_BYTE
+Constant inlined idx#3 = (byte) 0
+Constant inlined assertType::t2#1 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#2 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t2#2 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t1#3 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t2#3 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t1#4 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#4 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#5 = (const byte) TYPEID_WORD
+Constant inlined main::s#0 = (byte*)(word) $400
+Constant inlined main::$1 = (byte*)(word) $400+(word) $3e8
+Constant inlined assertType::t1#10 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#12 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#11 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#14 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#13 = (const byte) TYPEID_SIGNED_DWORD
+Successful SSA optimization Pass2ConstantInlining
+Added new block during phi lifting main::@4(between main::@1 and main::@1)
+Adding NOP phi() at start of @begin
+Adding NOP phi() at start of @3
+Adding NOP phi() at start of @end
+Adding NOP phi() at start of main
+Adding NOP phi() at start of main::@2
+Adding NOP phi() at start of testSimpleTypes
+CALL GRAPH
+Calls in [] to main:2 
+Calls in [main] to testSimpleTypes:10 
+Calls in [testSimpleTypes] to assertType:14 assertType:16 assertType:18 assertType:20 assertType:22 assertType:24 assertType:26 assertType:28 assertType:30 assertType:32 assertType:34 assertType:36 assertType:38 assertType:40 assertType:42 
+
+Created 4 initial phi equivalence classes
+Coalesced [12] main::s#3 ← main::s#1
+Coalesced [15] idx#51 ← idx#20
+Coalesced (already) [17] idx#57 ← idx#20
+Coalesced (already) [19] idx#58 ← idx#20
+Coalesced (already) [21] idx#59 ← idx#20
+Coalesced (already) [23] idx#60 ← idx#20
+Coalesced (already) [25] idx#61 ← idx#20
+Coalesced (already) [27] idx#62 ← idx#20
+Coalesced (already) [29] idx#63 ← idx#20
+Coalesced (already) [31] idx#64 ← idx#20
+Coalesced (already) [33] idx#52 ← idx#20
+Coalesced (already) [35] idx#53 ← idx#20
+Coalesced (already) [37] idx#54 ← idx#20
+Coalesced (already) [39] idx#55 ← idx#20
+Coalesced (already) [41] idx#56 ← idx#20
+Coalesced down to 4 phi equivalence classes
+Culled Empty Block (label) main::@4
+Renumbering block @3 to @1
+Adding NOP phi() at start of @begin
+Adding NOP phi() at start of @1
+Adding NOP phi() at start of @end
+Adding NOP phi() at start of main
+Adding NOP phi() at start of main::@2
+Adding NOP phi() at start of testSimpleTypes
+Adding NOP phi() at start of testSimpleTypes::@1
+Adding NOP phi() at start of testSimpleTypes::@2
+Adding NOP phi() at start of testSimpleTypes::@3
+Adding NOP phi() at start of testSimpleTypes::@4
+Adding NOP phi() at start of testSimpleTypes::@5
+Adding NOP phi() at start of testSimpleTypes::@6
+Adding NOP phi() at start of testSimpleTypes::@7
+Adding NOP phi() at start of testSimpleTypes::@8
+Adding NOP phi() at start of testSimpleTypes::@9
+Adding NOP phi() at start of testSimpleTypes::@10
+Adding NOP phi() at start of testSimpleTypes::@11
+Adding NOP phi() at start of testSimpleTypes::@12
+Adding NOP phi() at start of testSimpleTypes::@13
+Adding NOP phi() at start of testSimpleTypes::@14
+
+FINAL CONTROL FLOW GRAPH
+@begin: scope:[]  from
+  [0] phi()
+  to:@1
+@1: scope:[]  from @begin
+  [1] phi()
+  [2] call main 
+  to:@end
+@end: scope:[]  from @1
+  [3] phi()
+main: scope:[main]  from @1
+  [4] phi()
+  to:main::@1
+main::@1: scope:[main]  from main main::@1
+  [5] (byte*) main::s#2 ← phi( main/(byte*)(word) $400 main::@1/(byte*) main::s#1 )
+  [6] *((byte*) main::s#2) ← (byte) ' '
+  [7] (byte*) main::s#1 ← ++ (byte*) main::s#2
+  [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  [9] phi()
+  [10] call testSimpleTypes 
+  to:main::@return
+main::@return: scope:[main]  from main::@2
+  [11] return 
+  to:@return
+testSimpleTypes: scope:[testSimpleTypes]  from main::@2
+  [12] phi()
+  [13] call assertType 
+  to:testSimpleTypes::@1
+testSimpleTypes::@1: scope:[testSimpleTypes]  from testSimpleTypes
+  [14] phi()
+  [15] call assertType 
+  to:testSimpleTypes::@2
+testSimpleTypes::@2: scope:[testSimpleTypes]  from testSimpleTypes::@1
+  [16] phi()
+  [17] call assertType 
+  to:testSimpleTypes::@3
+testSimpleTypes::@3: scope:[testSimpleTypes]  from testSimpleTypes::@2
+  [18] phi()
+  [19] call assertType 
+  to:testSimpleTypes::@4
+testSimpleTypes::@4: scope:[testSimpleTypes]  from testSimpleTypes::@3
+  [20] phi()
+  [21] call assertType 
+  to:testSimpleTypes::@5
+testSimpleTypes::@5: scope:[testSimpleTypes]  from testSimpleTypes::@4
+  [22] phi()
+  [23] call assertType 
+  to:testSimpleTypes::@6
+testSimpleTypes::@6: scope:[testSimpleTypes]  from testSimpleTypes::@5
+  [24] phi()
+  [25] call assertType 
+  to:testSimpleTypes::@7
+testSimpleTypes::@7: scope:[testSimpleTypes]  from testSimpleTypes::@6
+  [26] phi()
+  [27] call assertType 
+  to:testSimpleTypes::@8
+testSimpleTypes::@8: scope:[testSimpleTypes]  from testSimpleTypes::@7
+  [28] phi()
+  [29] call assertType 
+  to:testSimpleTypes::@9
+testSimpleTypes::@9: scope:[testSimpleTypes]  from testSimpleTypes::@8
+  [30] phi()
+  [31] call assertType 
+  to:testSimpleTypes::@10
+testSimpleTypes::@10: scope:[testSimpleTypes]  from testSimpleTypes::@9
+  [32] phi()
+  [33] call assertType 
+  to:testSimpleTypes::@11
+testSimpleTypes::@11: scope:[testSimpleTypes]  from testSimpleTypes::@10
+  [34] phi()
+  [35] call assertType 
+  to:testSimpleTypes::@12
+testSimpleTypes::@12: scope:[testSimpleTypes]  from testSimpleTypes::@11
+  [36] phi()
+  [37] call assertType 
+  to:testSimpleTypes::@13
+testSimpleTypes::@13: scope:[testSimpleTypes]  from testSimpleTypes::@12
+  [38] phi()
+  [39] call assertType 
+  to:testSimpleTypes::@14
+testSimpleTypes::@14: scope:[testSimpleTypes]  from testSimpleTypes::@13
+  [40] phi()
+  [41] call assertType 
+  to:testSimpleTypes::@return
+testSimpleTypes::@return: scope:[testSimpleTypes]  from testSimpleTypes::@14
+  [42] return 
+  to:@return
+assertType: scope:[assertType]  from testSimpleTypes testSimpleTypes::@1 testSimpleTypes::@10 testSimpleTypes::@11 testSimpleTypes::@12 testSimpleTypes::@13 testSimpleTypes::@14 testSimpleTypes::@2 testSimpleTypes::@3 testSimpleTypes::@4 testSimpleTypes::@5 testSimpleTypes::@6 testSimpleTypes::@7 testSimpleTypes::@8 testSimpleTypes::@9
+  [43] (byte) idx#41 ← phi( testSimpleTypes/(byte) 0 testSimpleTypes::@1/(byte) idx#20 testSimpleTypes::@10/(byte) idx#20 testSimpleTypes::@11/(byte) idx#20 testSimpleTypes::@12/(byte) idx#20 testSimpleTypes::@13/(byte) idx#20 testSimpleTypes::@14/(byte) idx#20 testSimpleTypes::@2/(byte) idx#20 testSimpleTypes::@3/(byte) idx#20 testSimpleTypes::@4/(byte) idx#20 testSimpleTypes::@5/(byte) idx#20 testSimpleTypes::@6/(byte) idx#20 testSimpleTypes::@7/(byte) idx#20 testSimpleTypes::@8/(byte) idx#20 testSimpleTypes::@9/(byte) idx#20 )
+  [43] (byte) assertType::t2#15 ← phi( testSimpleTypes/(const byte) TYPEID_BYTE testSimpleTypes::@1/(const byte) TYPEID_BYTE testSimpleTypes::@10/(const byte) TYPEID_DWORD testSimpleTypes::@11/(const byte) TYPEID_DWORD testSimpleTypes::@12/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@13/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@14/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@2/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@3/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@4/(const byte) TYPEID_WORD testSimpleTypes::@5/(const byte) TYPEID_WORD testSimpleTypes::@6/(const byte) TYPEID_WORD testSimpleTypes::@7/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@8/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@9/(const byte) TYPEID_SIGNED_WORD )
+  [43] (byte) assertType::t1#15 ← phi( testSimpleTypes/(const byte) TYPEID_BYTE testSimpleTypes::@1/(const byte) TYPEID_BYTE testSimpleTypes::@10/(const byte) TYPEID_DWORD testSimpleTypes::@11/(const byte) TYPEID_DWORD testSimpleTypes::@12/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@13/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@14/(const byte) TYPEID_SIGNED_DWORD testSimpleTypes::@2/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@3/(const byte) TYPEID_SIGNED_BYTE testSimpleTypes::@4/(const byte) TYPEID_WORD testSimpleTypes::@5/(const byte) TYPEID_WORD testSimpleTypes::@6/(const byte) TYPEID_WORD testSimpleTypes::@7/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@8/(const byte) TYPEID_SIGNED_WORD testSimpleTypes::@9/(const byte) TYPEID_SIGNED_WORD )
+  [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1
+  to:assertType::@3
+assertType::@3: scope:[assertType]  from assertType
+  [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15
+  [47] (byte) idx#20 ← ++ (byte) idx#41
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  [48] return 
+  to:@return
+assertType::@1: scope:[assertType]  from assertType
+  [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0
+  to:assertType::@2
+
+
+VARIABLE REGISTER WEIGHTS
+(byte*) COLS
+(byte) GREEN
+(byte) RED
+(byte*) SCREEN
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(byte) assertType::t1
+(byte) assertType::t1#15 1.0
+(byte) assertType::t2
+(byte) assertType::t2#15 2.0
+(byte) idx
+(byte) idx#20 0.9999999999999999
+(byte) idx#41 7.200000000000002
+(void()) main()
+(byte*) main::s
+(byte*) main::s#1 16.5
+(byte*) main::s#2 16.5
+(void()) testSimpleTypes()
+
+Initial phi equivalence classes
+[ main::s#2 main::s#1 ]
+[ assertType::t1#15 ]
+[ assertType::t2#15 ]
+[ idx#41 idx#20 ]
+Complete equivalence classes
+[ main::s#2 main::s#1 ]
+[ assertType::t1#15 ]
+[ assertType::t2#15 ]
+[ idx#41 idx#20 ]
+Allocated zp ZP_WORD:2 [ main::s#2 main::s#1 ]
+Allocated zp ZP_BYTE:4 [ assertType::t1#15 ]
+Allocated zp ZP_BYTE:5 [ assertType::t2#15 ]
+Allocated zp ZP_BYTE:6 [ idx#41 idx#20 ]
+
+INITIAL ASM
+//SEG0 File Comments
+// Tests different integer literal types
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_BYTE = 1
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_WORD = 3
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_DWORD = 5
+  .const TYPEID_SIGNED_DWORD = 6
+  .const RED = 2
+  .const GREEN = 5
+  .label idx = 6
+//SEG3 @begin
+bbegin:
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+b1_from_bbegin:
+  jmp b1
+//SEG5 @1
+b1:
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+main_from_b1:
+  jsr main
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+bend_from_b1:
+  jmp bend
+//SEG9 @end
+bend:
+//SEG10 main
+main: {
+    .label s = 2
+  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
+  b1_from_main:
+  //SEG12 [5] phi (byte*) main::s#2 = (byte*)(word) $400 [phi:main->main::@1#0] -- pbuz1=pbuc1 
+    lda #<$400
+    sta s
+    lda #>$400
+    sta s+1
+    jmp b1
+  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
+  b1_from_b1:
+  //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy 
+    jmp b1
+  //SEG15 main::@1
+  b1:
+  //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 
+    lda #' '
+    ldy #0
+    sta (s),y
+  //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 
+    inc s
+    bne !+
+    inc s+1
+  !:
+  //SEG18 [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 
+    lda s+1
+    cmp #>$400+$3e8
+    bcc b1_from_b1
+    bne !+
+    lda s
+    cmp #<$400+$3e8
+    bcc b1_from_b1
+  !:
+  //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG20 main::@2
+  b2:
+  //SEG21 [10] call testSimpleTypes 
+  //SEG22 [12] phi from main::@2 to testSimpleTypes [phi:main::@2->testSimpleTypes]
+  testSimpleTypes_from_b2:
+    jsr testSimpleTypes
+    jmp breturn
+  //SEG23 main::@return
+  breturn:
+  //SEG24 [11] return 
+    rts
+}
+//SEG25 testSimpleTypes
+testSimpleTypes: {
+  //SEG26 [13] call assertType 
+  //SEG27 [43] phi from testSimpleTypes to assertType [phi:testSimpleTypes->assertType]
+  assertType_from_testSimpleTypes:
+  //SEG28 [43] phi (byte) idx#41 = (byte) 0 [phi:testSimpleTypes->assertType#0] -- vbuz1=vbuc1 
+    lda #0
+    sta idx
+  //SEG29 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG30 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG31 [14] phi from testSimpleTypes to testSimpleTypes::@1 [phi:testSimpleTypes->testSimpleTypes::@1]
+  b1_from_testSimpleTypes:
+    jmp b1
+  //SEG32 testSimpleTypes::@1
+  b1:
+  //SEG33 [15] call assertType 
+  //SEG34 [43] phi from testSimpleTypes::@1 to assertType [phi:testSimpleTypes::@1->assertType]
+  assertType_from_b1:
+  //SEG35 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@1->assertType#0] -- register_copy 
+  //SEG36 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG37 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG38 [16] phi from testSimpleTypes::@1 to testSimpleTypes::@2 [phi:testSimpleTypes::@1->testSimpleTypes::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG39 testSimpleTypes::@2
+  b2:
+  //SEG40 [17] call assertType 
+  //SEG41 [43] phi from testSimpleTypes::@2 to assertType [phi:testSimpleTypes::@2->assertType]
+  assertType_from_b2:
+  //SEG42 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@2->assertType#0] -- register_copy 
+  //SEG43 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG44 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG45 [18] phi from testSimpleTypes::@2 to testSimpleTypes::@3 [phi:testSimpleTypes::@2->testSimpleTypes::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG46 testSimpleTypes::@3
+  b3:
+  //SEG47 [19] call assertType 
+  //SEG48 [43] phi from testSimpleTypes::@3 to assertType [phi:testSimpleTypes::@3->assertType]
+  assertType_from_b3:
+  //SEG49 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@3->assertType#0] -- register_copy 
+  //SEG50 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG51 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG52 [20] phi from testSimpleTypes::@3 to testSimpleTypes::@4 [phi:testSimpleTypes::@3->testSimpleTypes::@4]
+  b4_from_b3:
+    jmp b4
+  //SEG53 testSimpleTypes::@4
+  b4:
+  //SEG54 [21] call assertType 
+  //SEG55 [43] phi from testSimpleTypes::@4 to assertType [phi:testSimpleTypes::@4->assertType]
+  assertType_from_b4:
+  //SEG56 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@4->assertType#0] -- register_copy 
+  //SEG57 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG58 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG59 [22] phi from testSimpleTypes::@4 to testSimpleTypes::@5 [phi:testSimpleTypes::@4->testSimpleTypes::@5]
+  b5_from_b4:
+    jmp b5
+  //SEG60 testSimpleTypes::@5
+  b5:
+  //SEG61 [23] call assertType 
+  //SEG62 [43] phi from testSimpleTypes::@5 to assertType [phi:testSimpleTypes::@5->assertType]
+  assertType_from_b5:
+  //SEG63 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@5->assertType#0] -- register_copy 
+  //SEG64 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG65 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG66 [24] phi from testSimpleTypes::@5 to testSimpleTypes::@6 [phi:testSimpleTypes::@5->testSimpleTypes::@6]
+  b6_from_b5:
+    jmp b6
+  //SEG67 testSimpleTypes::@6
+  b6:
+  //SEG68 [25] call assertType 
+  //SEG69 [43] phi from testSimpleTypes::@6 to assertType [phi:testSimpleTypes::@6->assertType]
+  assertType_from_b6:
+  //SEG70 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@6->assertType#0] -- register_copy 
+  //SEG71 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG72 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG73 [26] phi from testSimpleTypes::@6 to testSimpleTypes::@7 [phi:testSimpleTypes::@6->testSimpleTypes::@7]
+  b7_from_b6:
+    jmp b7
+  //SEG74 testSimpleTypes::@7
+  b7:
+  //SEG75 [27] call assertType 
+  //SEG76 [43] phi from testSimpleTypes::@7 to assertType [phi:testSimpleTypes::@7->assertType]
+  assertType_from_b7:
+  //SEG77 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@7->assertType#0] -- register_copy 
+  //SEG78 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG79 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG80 [28] phi from testSimpleTypes::@7 to testSimpleTypes::@8 [phi:testSimpleTypes::@7->testSimpleTypes::@8]
+  b8_from_b7:
+    jmp b8
+  //SEG81 testSimpleTypes::@8
+  b8:
+  //SEG82 [29] call assertType 
+  //SEG83 [43] phi from testSimpleTypes::@8 to assertType [phi:testSimpleTypes::@8->assertType]
+  assertType_from_b8:
+  //SEG84 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@8->assertType#0] -- register_copy 
+  //SEG85 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG86 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG87 [30] phi from testSimpleTypes::@8 to testSimpleTypes::@9 [phi:testSimpleTypes::@8->testSimpleTypes::@9]
+  b9_from_b8:
+    jmp b9
+  //SEG88 testSimpleTypes::@9
+  b9:
+  //SEG89 [31] call assertType 
+  //SEG90 [43] phi from testSimpleTypes::@9 to assertType [phi:testSimpleTypes::@9->assertType]
+  assertType_from_b9:
+  //SEG91 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@9->assertType#0] -- register_copy 
+  //SEG92 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG93 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG94 [32] phi from testSimpleTypes::@9 to testSimpleTypes::@10 [phi:testSimpleTypes::@9->testSimpleTypes::@10]
+  b10_from_b9:
+    jmp b10
+  //SEG95 testSimpleTypes::@10
+  b10:
+  //SEG96 [33] call assertType 
+  //SEG97 [43] phi from testSimpleTypes::@10 to assertType [phi:testSimpleTypes::@10->assertType]
+  assertType_from_b10:
+  //SEG98 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@10->assertType#0] -- register_copy 
+  //SEG99 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG100 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG101 [34] phi from testSimpleTypes::@10 to testSimpleTypes::@11 [phi:testSimpleTypes::@10->testSimpleTypes::@11]
+  b11_from_b10:
+    jmp b11
+  //SEG102 testSimpleTypes::@11
+  b11:
+  //SEG103 [35] call assertType 
+  //SEG104 [43] phi from testSimpleTypes::@11 to assertType [phi:testSimpleTypes::@11->assertType]
+  assertType_from_b11:
+  //SEG105 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@11->assertType#0] -- register_copy 
+  //SEG106 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG107 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG108 [36] phi from testSimpleTypes::@11 to testSimpleTypes::@12 [phi:testSimpleTypes::@11->testSimpleTypes::@12]
+  b12_from_b11:
+    jmp b12
+  //SEG109 testSimpleTypes::@12
+  b12:
+  //SEG110 [37] call assertType 
+  //SEG111 [43] phi from testSimpleTypes::@12 to assertType [phi:testSimpleTypes::@12->assertType]
+  assertType_from_b12:
+  //SEG112 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@12->assertType#0] -- register_copy 
+  //SEG113 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG114 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG115 [38] phi from testSimpleTypes::@12 to testSimpleTypes::@13 [phi:testSimpleTypes::@12->testSimpleTypes::@13]
+  b13_from_b12:
+    jmp b13
+  //SEG116 testSimpleTypes::@13
+  b13:
+  //SEG117 [39] call assertType 
+  //SEG118 [43] phi from testSimpleTypes::@13 to assertType [phi:testSimpleTypes::@13->assertType]
+  assertType_from_b13:
+  //SEG119 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@13->assertType#0] -- register_copy 
+  //SEG120 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG121 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG122 [40] phi from testSimpleTypes::@13 to testSimpleTypes::@14 [phi:testSimpleTypes::@13->testSimpleTypes::@14]
+  b14_from_b13:
+    jmp b14
+  //SEG123 testSimpleTypes::@14
+  b14:
+  //SEG124 [41] call assertType 
+  //SEG125 [43] phi from testSimpleTypes::@14 to assertType [phi:testSimpleTypes::@14->assertType]
+  assertType_from_b14:
+  //SEG126 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@14->assertType#0] -- register_copy 
+  //SEG127 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG128 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+    jmp breturn
+  //SEG129 testSimpleTypes::@return
+  breturn:
+  //SEG130 [42] return 
+    rts
+}
+//SEG131 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte zeropage(4) t1, byte zeropage(5) t2)
+assertType: {
+    .label t1 = 4
+    .label t2 = 5
+  //SEG132 [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 -- vbuz1_eq_vbuz2_then_la1 
+    lda t1
+    cmp t2
+    beq b1
+    jmp b3
+  //SEG133 assertType::@3
+  b3:
+  //SEG134 [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 -- pbuc1_derefidx_vbuz1=vbuc2 
+    lda #RED
+    ldy idx
+    sta $d800,y
+    jmp b2
+  //SEG135 assertType::@2
+  b2:
+  //SEG136 [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 -- pbuc1_derefidx_vbuz1=vbuz2 
+    lda t1
+    ldy idx
+    sta $400,y
+  //SEG137 [47] (byte) idx#20 ← ++ (byte) idx#41 -- vbuz1=_inc_vbuz1 
+    inc idx
+    jmp breturn
+  //SEG138 assertType::@return
+  breturn:
+  //SEG139 [48] return 
+    rts
+  //SEG140 assertType::@1
+  b1:
+  //SEG141 [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuz1=vbuc2 
+    lda #GREEN
+    ldy idx
+    sta $d800,y
+    jmp b2
+}
+
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [6] *((byte*) main::s#2) ← (byte) ' ' [ main::s#2 ] ( main:2 [ main::s#2 ] ) always clobbers reg byte a reg byte y 
+Statement [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 [ main::s#1 ] ( main:2 [ main::s#1 ] ) always clobbers reg byte a 
+Statement [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 [ assertType::t1#15 idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ assertType::t1#15 idx#41 ] ) always clobbers reg byte a 
+Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ assertType::t1#15 ]
+Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ idx#41 idx#20 ]
+Statement [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 [ idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ idx#41 ] ) always clobbers reg byte a 
+Statement [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 [ assertType::t1#15 idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ assertType::t1#15 idx#41 ] ) always clobbers reg byte a 
+Statement [6] *((byte*) main::s#2) ← (byte) ' ' [ main::s#2 ] ( main:2 [ main::s#2 ] ) always clobbers reg byte a reg byte y 
+Statement [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 [ main::s#1 ] ( main:2 [ main::s#1 ] ) always clobbers reg byte a 
+Statement [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 [ assertType::t1#15 idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ assertType::t1#15 idx#41 ] ) always clobbers reg byte a 
+Statement [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 [ idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ idx#41 ] ) always clobbers reg byte a 
+Statement [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 [ assertType::t1#15 idx#41 ] ( main:2::testSimpleTypes:10::assertType:13 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:15 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:17 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:19 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:21 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:23 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:25 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:27 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:29 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:31 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:33 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:35 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:37 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:39 [ assertType::t1#15 idx#41 ] main:2::testSimpleTypes:10::assertType:41 [ assertType::t1#15 idx#41 ] ) always clobbers reg byte a 
+Potential registers zp ZP_WORD:2 [ main::s#2 main::s#1 ] : zp ZP_WORD:2 , 
+Potential registers zp ZP_BYTE:4 [ assertType::t1#15 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , 
+Potential registers zp ZP_BYTE:5 [ assertType::t2#15 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y , 
+Potential registers zp ZP_BYTE:6 [ idx#41 idx#20 ] : zp ZP_BYTE:6 , reg byte x , reg byte y , 
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [main] 33: zp ZP_WORD:2 [ main::s#2 main::s#1 ] 
+Uplift Scope [] 8.2: zp ZP_BYTE:6 [ idx#41 idx#20 ] 
+Uplift Scope [assertType] 2: zp ZP_BYTE:5 [ assertType::t2#15 ] 1: zp ZP_BYTE:4 [ assertType::t1#15 ] 
+Uplift Scope [testSimpleTypes] 
+
+Uplifting [main] best 978 combination zp ZP_WORD:2 [ main::s#2 main::s#1 ] 
+Uplifting [] best 963 combination reg byte x [ idx#41 idx#20 ] 
+Uplifting [assertType] best 916 combination zp ZP_BYTE:5 [ assertType::t2#15 ] reg byte y [ assertType::t1#15 ] 
+Uplifting [testSimpleTypes] best 916 combination 
+Attempting to uplift remaining variables inzp ZP_BYTE:5 [ assertType::t2#15 ]
+Uplifting [assertType] best 916 combination zp ZP_BYTE:5 [ assertType::t2#15 ] 
+Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:4 [ assertType::t2#15 ]
+
+ASSEMBLER BEFORE OPTIMIZATION
+//SEG0 File Comments
+// Tests different integer literal types
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_BYTE = 1
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_WORD = 3
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_DWORD = 5
+  .const TYPEID_SIGNED_DWORD = 6
+  .const RED = 2
+  .const GREEN = 5
+//SEG3 @begin
+bbegin:
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+b1_from_bbegin:
+  jmp b1
+//SEG5 @1
+b1:
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+main_from_b1:
+  jsr main
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+bend_from_b1:
+  jmp bend
+//SEG9 @end
+bend:
+//SEG10 main
+main: {
+    .label s = 2
+  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
+  b1_from_main:
+  //SEG12 [5] phi (byte*) main::s#2 = (byte*)(word) $400 [phi:main->main::@1#0] -- pbuz1=pbuc1 
+    lda #<$400
+    sta s
+    lda #>$400
+    sta s+1
+    jmp b1
+  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
+  b1_from_b1:
+  //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy 
+    jmp b1
+  //SEG15 main::@1
+  b1:
+  //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 
+    lda #' '
+    ldy #0
+    sta (s),y
+  //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 
+    inc s
+    bne !+
+    inc s+1
+  !:
+  //SEG18 [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 
+    lda s+1
+    cmp #>$400+$3e8
+    bcc b1_from_b1
+    bne !+
+    lda s
+    cmp #<$400+$3e8
+    bcc b1_from_b1
+  !:
+  //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG20 main::@2
+  b2:
+  //SEG21 [10] call testSimpleTypes 
+  //SEG22 [12] phi from main::@2 to testSimpleTypes [phi:main::@2->testSimpleTypes]
+  testSimpleTypes_from_b2:
+    jsr testSimpleTypes
+    jmp breturn
+  //SEG23 main::@return
+  breturn:
+  //SEG24 [11] return 
+    rts
+}
+//SEG25 testSimpleTypes
+testSimpleTypes: {
+  //SEG26 [13] call assertType 
+  //SEG27 [43] phi from testSimpleTypes to assertType [phi:testSimpleTypes->assertType]
+  assertType_from_testSimpleTypes:
+  //SEG28 [43] phi (byte) idx#41 = (byte) 0 [phi:testSimpleTypes->assertType#0] -- vbuxx=vbuc1 
+    ldx #0
+  //SEG29 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG30 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG31 [14] phi from testSimpleTypes to testSimpleTypes::@1 [phi:testSimpleTypes->testSimpleTypes::@1]
+  b1_from_testSimpleTypes:
+    jmp b1
+  //SEG32 testSimpleTypes::@1
+  b1:
+  //SEG33 [15] call assertType 
+  //SEG34 [43] phi from testSimpleTypes::@1 to assertType [phi:testSimpleTypes::@1->assertType]
+  assertType_from_b1:
+  //SEG35 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@1->assertType#0] -- register_copy 
+  //SEG36 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG37 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG38 [16] phi from testSimpleTypes::@1 to testSimpleTypes::@2 [phi:testSimpleTypes::@1->testSimpleTypes::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG39 testSimpleTypes::@2
+  b2:
+  //SEG40 [17] call assertType 
+  //SEG41 [43] phi from testSimpleTypes::@2 to assertType [phi:testSimpleTypes::@2->assertType]
+  assertType_from_b2:
+  //SEG42 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@2->assertType#0] -- register_copy 
+  //SEG43 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG44 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_BYTE
+    jsr assertType
+  //SEG45 [18] phi from testSimpleTypes::@2 to testSimpleTypes::@3 [phi:testSimpleTypes::@2->testSimpleTypes::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG46 testSimpleTypes::@3
+  b3:
+  //SEG47 [19] call assertType 
+  //SEG48 [43] phi from testSimpleTypes::@3 to assertType [phi:testSimpleTypes::@3->assertType]
+  assertType_from_b3:
+  //SEG49 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@3->assertType#0] -- register_copy 
+  //SEG50 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG51 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_BYTE
+    jsr assertType
+  //SEG52 [20] phi from testSimpleTypes::@3 to testSimpleTypes::@4 [phi:testSimpleTypes::@3->testSimpleTypes::@4]
+  b4_from_b3:
+    jmp b4
+  //SEG53 testSimpleTypes::@4
+  b4:
+  //SEG54 [21] call assertType 
+  //SEG55 [43] phi from testSimpleTypes::@4 to assertType [phi:testSimpleTypes::@4->assertType]
+  assertType_from_b4:
+  //SEG56 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@4->assertType#0] -- register_copy 
+  //SEG57 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG58 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG59 [22] phi from testSimpleTypes::@4 to testSimpleTypes::@5 [phi:testSimpleTypes::@4->testSimpleTypes::@5]
+  b5_from_b4:
+    jmp b5
+  //SEG60 testSimpleTypes::@5
+  b5:
+  //SEG61 [23] call assertType 
+  //SEG62 [43] phi from testSimpleTypes::@5 to assertType [phi:testSimpleTypes::@5->assertType]
+  assertType_from_b5:
+  //SEG63 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@5->assertType#0] -- register_copy 
+  //SEG64 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG65 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG66 [24] phi from testSimpleTypes::@5 to testSimpleTypes::@6 [phi:testSimpleTypes::@5->testSimpleTypes::@6]
+  b6_from_b5:
+    jmp b6
+  //SEG67 testSimpleTypes::@6
+  b6:
+  //SEG68 [25] call assertType 
+  //SEG69 [43] phi from testSimpleTypes::@6 to assertType [phi:testSimpleTypes::@6->assertType]
+  assertType_from_b6:
+  //SEG70 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@6->assertType#0] -- register_copy 
+  //SEG71 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG72 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG73 [26] phi from testSimpleTypes::@6 to testSimpleTypes::@7 [phi:testSimpleTypes::@6->testSimpleTypes::@7]
+  b7_from_b6:
+    jmp b7
+  //SEG74 testSimpleTypes::@7
+  b7:
+  //SEG75 [27] call assertType 
+  //SEG76 [43] phi from testSimpleTypes::@7 to assertType [phi:testSimpleTypes::@7->assertType]
+  assertType_from_b7:
+  //SEG77 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@7->assertType#0] -- register_copy 
+  //SEG78 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG79 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG80 [28] phi from testSimpleTypes::@7 to testSimpleTypes::@8 [phi:testSimpleTypes::@7->testSimpleTypes::@8]
+  b8_from_b7:
+    jmp b8
+  //SEG81 testSimpleTypes::@8
+  b8:
+  //SEG82 [29] call assertType 
+  //SEG83 [43] phi from testSimpleTypes::@8 to assertType [phi:testSimpleTypes::@8->assertType]
+  assertType_from_b8:
+  //SEG84 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@8->assertType#0] -- register_copy 
+  //SEG85 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG86 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG87 [30] phi from testSimpleTypes::@8 to testSimpleTypes::@9 [phi:testSimpleTypes::@8->testSimpleTypes::@9]
+  b9_from_b8:
+    jmp b9
+  //SEG88 testSimpleTypes::@9
+  b9:
+  //SEG89 [31] call assertType 
+  //SEG90 [43] phi from testSimpleTypes::@9 to assertType [phi:testSimpleTypes::@9->assertType]
+  assertType_from_b9:
+  //SEG91 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@9->assertType#0] -- register_copy 
+  //SEG92 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG93 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG94 [32] phi from testSimpleTypes::@9 to testSimpleTypes::@10 [phi:testSimpleTypes::@9->testSimpleTypes::@10]
+  b10_from_b9:
+    jmp b10
+  //SEG95 testSimpleTypes::@10
+  b10:
+  //SEG96 [33] call assertType 
+  //SEG97 [43] phi from testSimpleTypes::@10 to assertType [phi:testSimpleTypes::@10->assertType]
+  assertType_from_b10:
+  //SEG98 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@10->assertType#0] -- register_copy 
+  //SEG99 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG100 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG101 [34] phi from testSimpleTypes::@10 to testSimpleTypes::@11 [phi:testSimpleTypes::@10->testSimpleTypes::@11]
+  b11_from_b10:
+    jmp b11
+  //SEG102 testSimpleTypes::@11
+  b11:
+  //SEG103 [35] call assertType 
+  //SEG104 [43] phi from testSimpleTypes::@11 to assertType [phi:testSimpleTypes::@11->assertType]
+  assertType_from_b11:
+  //SEG105 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@11->assertType#0] -- register_copy 
+  //SEG106 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG107 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG108 [36] phi from testSimpleTypes::@11 to testSimpleTypes::@12 [phi:testSimpleTypes::@11->testSimpleTypes::@12]
+  b12_from_b11:
+    jmp b12
+  //SEG109 testSimpleTypes::@12
+  b12:
+  //SEG110 [37] call assertType 
+  //SEG111 [43] phi from testSimpleTypes::@12 to assertType [phi:testSimpleTypes::@12->assertType]
+  assertType_from_b12:
+  //SEG112 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@12->assertType#0] -- register_copy 
+  //SEG113 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG114 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG115 [38] phi from testSimpleTypes::@12 to testSimpleTypes::@13 [phi:testSimpleTypes::@12->testSimpleTypes::@13]
+  b13_from_b12:
+    jmp b13
+  //SEG116 testSimpleTypes::@13
+  b13:
+  //SEG117 [39] call assertType 
+  //SEG118 [43] phi from testSimpleTypes::@13 to assertType [phi:testSimpleTypes::@13->assertType]
+  assertType_from_b13:
+  //SEG119 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@13->assertType#0] -- register_copy 
+  //SEG120 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG121 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG122 [40] phi from testSimpleTypes::@13 to testSimpleTypes::@14 [phi:testSimpleTypes::@13->testSimpleTypes::@14]
+  b14_from_b13:
+    jmp b14
+  //SEG123 testSimpleTypes::@14
+  b14:
+  //SEG124 [41] call assertType 
+  //SEG125 [43] phi from testSimpleTypes::@14 to assertType [phi:testSimpleTypes::@14->assertType]
+  assertType_from_b14:
+  //SEG126 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@14->assertType#0] -- register_copy 
+  //SEG127 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG128 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+    jmp breturn
+  //SEG129 testSimpleTypes::@return
+  breturn:
+  //SEG130 [42] return 
+    rts
+}
+//SEG131 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(4) t2)
+assertType: {
+    .label t2 = 4
+  //SEG132 [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 
+    tya
+    cmp t2
+    beq b1
+    jmp b3
+  //SEG133 assertType::@3
+  b3:
+  //SEG134 [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #RED
+    sta $d800,x
+    jmp b2
+  //SEG135 assertType::@2
+  b2:
+  //SEG136 [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 -- pbuc1_derefidx_vbuxx=vbuyy 
+    tya
+    sta $400,x
+  //SEG137 [47] (byte) idx#20 ← ++ (byte) idx#41 -- vbuxx=_inc_vbuxx 
+    inx
+    jmp breturn
+  //SEG138 assertType::@return
+  breturn:
+  //SEG139 [48] return 
+    rts
+  //SEG140 assertType::@1
+  b1:
+  //SEG141 [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #GREEN
+    sta $d800,x
+    jmp b2
+}
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp b1
+Removing instruction jmp bend
+Removing instruction jmp b1
+Removing instruction jmp b2
+Removing instruction jmp breturn
+Removing instruction jmp b1
+Removing instruction jmp b2
+Removing instruction jmp b3
+Removing instruction jmp b4
+Removing instruction jmp b5
+Removing instruction jmp b6
+Removing instruction jmp b7
+Removing instruction jmp b8
+Removing instruction jmp b9
+Removing instruction jmp b10
+Removing instruction jmp b11
+Removing instruction jmp b12
+Removing instruction jmp b13
+Removing instruction jmp b14
+Removing instruction jmp breturn
+Removing instruction jmp b3
+Removing instruction jmp b2
+Removing instruction jmp breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY
+Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing label b1_from_b1 with b1
+Replacing label b1_from_b1 with b1
+Removing instruction b1_from_bbegin:
+Removing instruction b1:
+Removing instruction main_from_b1:
+Removing instruction bend_from_b1:
+Removing instruction b1_from_b1:
+Removing instruction b2_from_b1:
+Removing instruction testSimpleTypes_from_b2:
+Removing instruction b1_from_testSimpleTypes:
+Removing instruction assertType_from_b1:
+Removing instruction b2_from_b1:
+Removing instruction assertType_from_b2:
+Removing instruction b3_from_b2:
+Removing instruction assertType_from_b3:
+Removing instruction b4_from_b3:
+Removing instruction assertType_from_b4:
+Removing instruction b5_from_b4:
+Removing instruction assertType_from_b5:
+Removing instruction b6_from_b5:
+Removing instruction assertType_from_b6:
+Removing instruction b7_from_b6:
+Removing instruction assertType_from_b7:
+Removing instruction b8_from_b7:
+Removing instruction assertType_from_b8:
+Removing instruction b9_from_b8:
+Removing instruction assertType_from_b9:
+Removing instruction b10_from_b9:
+Removing instruction assertType_from_b10:
+Removing instruction b11_from_b10:
+Removing instruction assertType_from_b11:
+Removing instruction b12_from_b11:
+Removing instruction assertType_from_b12:
+Removing instruction b13_from_b12:
+Removing instruction assertType_from_b13:
+Removing instruction b14_from_b13:
+Removing instruction assertType_from_b14:
+Succesful ASM optimization Pass5RedundantLabelElimination
+Removing instruction bend:
+Removing instruction b1_from_main:
+Removing instruction b2:
+Removing instruction breturn:
+Removing instruction assertType_from_testSimpleTypes:
+Removing instruction b1:
+Removing instruction b2:
+Removing instruction b3:
+Removing instruction b4:
+Removing instruction b5:
+Removing instruction b6:
+Removing instruction b7:
+Removing instruction b8:
+Removing instruction b9:
+Removing instruction b10:
+Removing instruction b11:
+Removing instruction b12:
+Removing instruction b13:
+Removing instruction b14:
+Removing instruction breturn:
+Removing instruction b3:
+Removing instruction breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+Updating BasicUpstart to call main directly
+Removing instruction jsr main
+Succesful ASM optimization Pass5SkipBegin
+Removing instruction jmp b1
+Succesful ASM optimization Pass5NextJumpElimination
+Removing instruction bbegin:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+(label) @1
+(label) @begin
+(label) @end
+(byte*) COLS
+(byte) GREEN
+(const byte) GREEN#0 GREEN = (byte) 5
+(byte) RED
+(const byte) RED#0 RED = (byte) 2
+(byte*) SCREEN
+(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#15 reg byte y 1.0
+(byte) assertType::t2
+(byte) assertType::t2#15 t2 zp ZP_BYTE:4 2.0
+(byte) idx
+(byte) idx#20 reg byte x 0.9999999999999999
+(byte) idx#41 reg byte x 7.200000000000002
+(void()) main()
+(label) main::@1
+(label) main::@2
+(label) main::@return
+(byte*) main::s
+(byte*) main::s#1 s zp ZP_WORD:2 16.5
+(byte*) main::s#2 s zp ZP_WORD:2 16.5
+(void()) testSimpleTypes()
+(label) testSimpleTypes::@1
+(label) testSimpleTypes::@10
+(label) testSimpleTypes::@11
+(label) testSimpleTypes::@12
+(label) testSimpleTypes::@13
+(label) testSimpleTypes::@14
+(label) testSimpleTypes::@2
+(label) testSimpleTypes::@3
+(label) testSimpleTypes::@4
+(label) testSimpleTypes::@5
+(label) testSimpleTypes::@6
+(label) testSimpleTypes::@7
+(label) testSimpleTypes::@8
+(label) testSimpleTypes::@9
+(label) testSimpleTypes::@return
+
+zp ZP_WORD:2 [ main::s#2 main::s#1 ]
+reg byte y [ assertType::t1#15 ]
+zp ZP_BYTE:4 [ assertType::t2#15 ]
+reg byte x [ idx#41 idx#20 ]
+
+
+FINAL ASSEMBLER
+Score: 784
+
+//SEG0 File Comments
+// Tests different integer literal types
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_BYTE = 1
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_WORD = 3
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_DWORD = 5
+  .const TYPEID_SIGNED_DWORD = 6
+  .const RED = 2
+  .const GREEN = 5
+//SEG3 @begin
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+//SEG5 @1
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+//SEG9 @end
+//SEG10 main
+main: {
+    .label s = 2
+  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
+  //SEG12 [5] phi (byte*) main::s#2 = (byte*)(word) $400 [phi:main->main::@1#0] -- pbuz1=pbuc1 
+    lda #<$400
+    sta s
+    lda #>$400
+    sta s+1
+  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
+  //SEG14 [5] phi (byte*) main::s#2 = (byte*) main::s#1 [phi:main::@1->main::@1#0] -- register_copy 
+  //SEG15 main::@1
+  b1:
+  //SEG16 [6] *((byte*) main::s#2) ← (byte) ' ' -- _deref_pbuz1=vbuc1 
+    lda #' '
+    ldy #0
+    sta (s),y
+  //SEG17 [7] (byte*) main::s#1 ← ++ (byte*) main::s#2 -- pbuz1=_inc_pbuz1 
+    inc s
+    bne !+
+    inc s+1
+  !:
+  //SEG18 [8] if((byte*) main::s#1<(byte*)(word) $400+(word) $3e8) goto main::@1 -- pbuz1_lt_pbuc1_then_la1 
+    lda s+1
+    cmp #>$400+$3e8
+    bcc b1
+    bne !+
+    lda s
+    cmp #<$400+$3e8
+    bcc b1
+  !:
+  //SEG19 [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  //SEG20 main::@2
+  //SEG21 [10] call testSimpleTypes 
+  //SEG22 [12] phi from main::@2 to testSimpleTypes [phi:main::@2->testSimpleTypes]
+    jsr testSimpleTypes
+  //SEG23 main::@return
+  //SEG24 [11] return 
+    rts
+}
+//SEG25 testSimpleTypes
+testSimpleTypes: {
+  //SEG26 [13] call assertType 
+  //SEG27 [43] phi from testSimpleTypes to assertType [phi:testSimpleTypes->assertType]
+  //SEG28 [43] phi (byte) idx#41 = (byte) 0 [phi:testSimpleTypes->assertType#0] -- vbuxx=vbuc1 
+    ldx #0
+  //SEG29 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG30 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG31 [14] phi from testSimpleTypes to testSimpleTypes::@1 [phi:testSimpleTypes->testSimpleTypes::@1]
+  //SEG32 testSimpleTypes::@1
+  //SEG33 [15] call assertType 
+  //SEG34 [43] phi from testSimpleTypes::@1 to assertType [phi:testSimpleTypes::@1->assertType]
+  //SEG35 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@1->assertType#0] -- register_copy 
+  //SEG36 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG37 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_BYTE [phi:testSimpleTypes::@1->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG38 [16] phi from testSimpleTypes::@1 to testSimpleTypes::@2 [phi:testSimpleTypes::@1->testSimpleTypes::@2]
+  //SEG39 testSimpleTypes::@2
+  //SEG40 [17] call assertType 
+  //SEG41 [43] phi from testSimpleTypes::@2 to assertType [phi:testSimpleTypes::@2->assertType]
+  //SEG42 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@2->assertType#0] -- register_copy 
+  //SEG43 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG44 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@2->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG45 [18] phi from testSimpleTypes::@2 to testSimpleTypes::@3 [phi:testSimpleTypes::@2->testSimpleTypes::@3]
+  //SEG46 testSimpleTypes::@3
+  //SEG47 [19] call assertType 
+  //SEG48 [43] phi from testSimpleTypes::@3 to assertType [phi:testSimpleTypes::@3->assertType]
+  //SEG49 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@3->assertType#0] -- register_copy 
+  //SEG50 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG51 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_BYTE [phi:testSimpleTypes::@3->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG52 [20] phi from testSimpleTypes::@3 to testSimpleTypes::@4 [phi:testSimpleTypes::@3->testSimpleTypes::@4]
+  //SEG53 testSimpleTypes::@4
+  //SEG54 [21] call assertType 
+  //SEG55 [43] phi from testSimpleTypes::@4 to assertType [phi:testSimpleTypes::@4->assertType]
+  //SEG56 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@4->assertType#0] -- register_copy 
+  //SEG57 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG58 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@4->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG59 [22] phi from testSimpleTypes::@4 to testSimpleTypes::@5 [phi:testSimpleTypes::@4->testSimpleTypes::@5]
+  //SEG60 testSimpleTypes::@5
+  //SEG61 [23] call assertType 
+  //SEG62 [43] phi from testSimpleTypes::@5 to assertType [phi:testSimpleTypes::@5->assertType]
+  //SEG63 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@5->assertType#0] -- register_copy 
+  //SEG64 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG65 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@5->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG66 [24] phi from testSimpleTypes::@5 to testSimpleTypes::@6 [phi:testSimpleTypes::@5->testSimpleTypes::@6]
+  //SEG67 testSimpleTypes::@6
+  //SEG68 [25] call assertType 
+  //SEG69 [43] phi from testSimpleTypes::@6 to assertType [phi:testSimpleTypes::@6->assertType]
+  //SEG70 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@6->assertType#0] -- register_copy 
+  //SEG71 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG72 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_WORD [phi:testSimpleTypes::@6->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG73 [26] phi from testSimpleTypes::@6 to testSimpleTypes::@7 [phi:testSimpleTypes::@6->testSimpleTypes::@7]
+  //SEG74 testSimpleTypes::@7
+  //SEG75 [27] call assertType 
+  //SEG76 [43] phi from testSimpleTypes::@7 to assertType [phi:testSimpleTypes::@7->assertType]
+  //SEG77 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@7->assertType#0] -- register_copy 
+  //SEG78 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG79 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@7->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG80 [28] phi from testSimpleTypes::@7 to testSimpleTypes::@8 [phi:testSimpleTypes::@7->testSimpleTypes::@8]
+  //SEG81 testSimpleTypes::@8
+  //SEG82 [29] call assertType 
+  //SEG83 [43] phi from testSimpleTypes::@8 to assertType [phi:testSimpleTypes::@8->assertType]
+  //SEG84 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@8->assertType#0] -- register_copy 
+  //SEG85 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG86 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@8->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG87 [30] phi from testSimpleTypes::@8 to testSimpleTypes::@9 [phi:testSimpleTypes::@8->testSimpleTypes::@9]
+  //SEG88 testSimpleTypes::@9
+  //SEG89 [31] call assertType 
+  //SEG90 [43] phi from testSimpleTypes::@9 to assertType [phi:testSimpleTypes::@9->assertType]
+  //SEG91 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@9->assertType#0] -- register_copy 
+  //SEG92 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG93 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_WORD [phi:testSimpleTypes::@9->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG94 [32] phi from testSimpleTypes::@9 to testSimpleTypes::@10 [phi:testSimpleTypes::@9->testSimpleTypes::@10]
+  //SEG95 testSimpleTypes::@10
+  //SEG96 [33] call assertType 
+  //SEG97 [43] phi from testSimpleTypes::@10 to assertType [phi:testSimpleTypes::@10->assertType]
+  //SEG98 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@10->assertType#0] -- register_copy 
+  //SEG99 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG100 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@10->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG101 [34] phi from testSimpleTypes::@10 to testSimpleTypes::@11 [phi:testSimpleTypes::@10->testSimpleTypes::@11]
+  //SEG102 testSimpleTypes::@11
+  //SEG103 [35] call assertType 
+  //SEG104 [43] phi from testSimpleTypes::@11 to assertType [phi:testSimpleTypes::@11->assertType]
+  //SEG105 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@11->assertType#0] -- register_copy 
+  //SEG106 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG107 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_DWORD [phi:testSimpleTypes::@11->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG108 [36] phi from testSimpleTypes::@11 to testSimpleTypes::@12 [phi:testSimpleTypes::@11->testSimpleTypes::@12]
+  //SEG109 testSimpleTypes::@12
+  //SEG110 [37] call assertType 
+  //SEG111 [43] phi from testSimpleTypes::@12 to assertType [phi:testSimpleTypes::@12->assertType]
+  //SEG112 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@12->assertType#0] -- register_copy 
+  //SEG113 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG114 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@12->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG115 [38] phi from testSimpleTypes::@12 to testSimpleTypes::@13 [phi:testSimpleTypes::@12->testSimpleTypes::@13]
+  //SEG116 testSimpleTypes::@13
+  //SEG117 [39] call assertType 
+  //SEG118 [43] phi from testSimpleTypes::@13 to assertType [phi:testSimpleTypes::@13->assertType]
+  //SEG119 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@13->assertType#0] -- register_copy 
+  //SEG120 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG121 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@13->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG122 [40] phi from testSimpleTypes::@13 to testSimpleTypes::@14 [phi:testSimpleTypes::@13->testSimpleTypes::@14]
+  //SEG123 testSimpleTypes::@14
+  //SEG124 [41] call assertType 
+  //SEG125 [43] phi from testSimpleTypes::@14 to assertType [phi:testSimpleTypes::@14->assertType]
+  //SEG126 [43] phi (byte) idx#41 = (byte) idx#20 [phi:testSimpleTypes::@14->assertType#0] -- register_copy 
+  //SEG127 [43] phi (byte) assertType::t2#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG128 [43] phi (byte) assertType::t1#15 = (const byte) TYPEID_SIGNED_DWORD [phi:testSimpleTypes::@14->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG129 testSimpleTypes::@return
+  //SEG130 [42] return 
+    rts
+}
+//SEG131 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(4) t2)
+assertType: {
+    .label t2 = 4
+  //SEG132 [44] if((byte) assertType::t1#15==(byte) assertType::t2#15) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 
+    tya
+    cmp t2
+    beq b1
+  //SEG133 assertType::@3
+  //SEG134 [45] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #RED
+    sta $d800,x
+  //SEG135 assertType::@2
+  b2:
+  //SEG136 [46] *((byte*)(word) $400 + (byte) idx#41) ← (byte) assertType::t1#15 -- pbuc1_derefidx_vbuxx=vbuyy 
+    tya
+    sta $400,x
+  //SEG137 [47] (byte) idx#20 ← ++ (byte) idx#41 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG138 assertType::@return
+  //SEG139 [48] return 
+    rts
+  //SEG140 assertType::@1
+  b1:
+  //SEG141 [49] *((byte*)(word) $d800 + (byte) idx#41) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #GREEN
+    sta $d800,x
+    jmp b2
+}
+
diff --git a/src/test/ref/int-literals.sym b/src/test/ref/int-literals.sym
new file mode 100644
index 000000000..ea8cfda80
--- /dev/null
+++ b/src/test/ref/int-literals.sym
@@ -0,0 +1,55 @@
+(label) @1
+(label) @begin
+(label) @end
+(byte*) COLS
+(byte) GREEN
+(const byte) GREEN#0 GREEN = (byte) 5
+(byte) RED
+(const byte) RED#0 RED = (byte) 2
+(byte*) SCREEN
+(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#15 reg byte y 1.0
+(byte) assertType::t2
+(byte) assertType::t2#15 t2 zp ZP_BYTE:4 2.0
+(byte) idx
+(byte) idx#20 reg byte x 0.9999999999999999
+(byte) idx#41 reg byte x 7.200000000000002
+(void()) main()
+(label) main::@1
+(label) main::@2
+(label) main::@return
+(byte*) main::s
+(byte*) main::s#1 s zp ZP_WORD:2 16.5
+(byte*) main::s#2 s zp ZP_WORD:2 16.5
+(void()) testSimpleTypes()
+(label) testSimpleTypes::@1
+(label) testSimpleTypes::@10
+(label) testSimpleTypes::@11
+(label) testSimpleTypes::@12
+(label) testSimpleTypes::@13
+(label) testSimpleTypes::@14
+(label) testSimpleTypes::@2
+(label) testSimpleTypes::@3
+(label) testSimpleTypes::@4
+(label) testSimpleTypes::@5
+(label) testSimpleTypes::@6
+(label) testSimpleTypes::@7
+(label) testSimpleTypes::@8
+(label) testSimpleTypes::@9
+(label) testSimpleTypes::@return
+
+zp ZP_WORD:2 [ main::s#2 main::s#1 ]
+reg byte y [ assertType::t1#15 ]
+zp ZP_BYTE:4 [ assertType::t2#15 ]
+reg byte x [ idx#41 idx#20 ]
diff --git a/src/test/ref/number-conversion.asm b/src/test/ref/number-conversion.asm
new file mode 100644
index 000000000..17df64b44
--- /dev/null
+++ b/src/test/ref/number-conversion.asm
@@ -0,0 +1,180 @@
+// Tests conversion of numbers to correct int types
+// See https://gitlab.com/camelot/kickc/issues/181
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_SIGNED_DWORD = 6
+  .const TYPEID_BYTE = 1
+  .const TYPEID_WORD = 3
+  .const TYPEID_DWORD = 5
+  .const RED = 2
+  .const GREEN = 5
+main: {
+    ldx #0
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    ldx #$28
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    ldx #$50
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_BYTE
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_WORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    tay
+    jsr assertType
+    lda #TYPEID_DWORD
+    sta assertType.t2
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+    rts
+}
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(2) t2)
+assertType: {
+    .label t2 = 2
+    tya
+    cmp t2
+    beq b1
+    lda #RED
+    sta $d800,x
+  b2:
+    tya
+    sta $400,x
+    inx
+    rts
+  b1:
+    lda #GREEN
+    sta $d800,x
+    jmp b2
+}
diff --git a/src/test/ref/number-conversion.cfg b/src/test/ref/number-conversion.cfg
new file mode 100644
index 000000000..746b50917
--- /dev/null
+++ b/src/test/ref/number-conversion.cfg
@@ -0,0 +1,171 @@
+@begin: scope:[]  from
+  [0] phi()
+  to:@1
+@1: scope:[]  from @begin
+  [1] phi()
+  [2] call main 
+  to:@end
+@end: scope:[]  from @1
+  [3] phi()
+main: scope:[main]  from @1
+  [4] phi()
+  [5] call assertType 
+  to:main::@1
+main::@1: scope:[main]  from main
+  [6] phi()
+  [7] call assertType 
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  [8] phi()
+  [9] call assertType 
+  to:main::@3
+main::@3: scope:[main]  from main::@2
+  [10] phi()
+  [11] call assertType 
+  to:main::@4
+main::@4: scope:[main]  from main::@3
+  [12] phi()
+  [13] call assertType 
+  to:main::@5
+main::@5: scope:[main]  from main::@4
+  [14] phi()
+  [15] call assertType 
+  to:main::@6
+main::@6: scope:[main]  from main::@5
+  [16] phi()
+  [17] call assertType 
+  to:main::@7
+main::@7: scope:[main]  from main::@6
+  [18] phi()
+  [19] call assertType 
+  to:main::@8
+main::@8: scope:[main]  from main::@7
+  [20] phi()
+  [21] call assertType 
+  to:main::@9
+main::@9: scope:[main]  from main::@8
+  [22] phi()
+  [23] call assertType 
+  to:main::@10
+main::@10: scope:[main]  from main::@9
+  [24] phi()
+  [25] call assertType 
+  to:main::@11
+main::@11: scope:[main]  from main::@10
+  [26] phi()
+  [27] call assertType 
+  to:main::@12
+main::@12: scope:[main]  from main::@11
+  [28] phi()
+  [29] call assertType 
+  to:main::@13
+main::@13: scope:[main]  from main::@12
+  [30] phi()
+  [31] call assertType 
+  to:main::@14
+main::@14: scope:[main]  from main::@13
+  [32] phi()
+  [33] call assertType 
+  to:main::@15
+main::@15: scope:[main]  from main::@14
+  [34] phi()
+  [35] call assertType 
+  to:main::@16
+main::@16: scope:[main]  from main::@15
+  [36] phi()
+  [37] call assertType 
+  to:main::@17
+main::@17: scope:[main]  from main::@16
+  [38] phi()
+  [39] call assertType 
+  to:main::@18
+main::@18: scope:[main]  from main::@17
+  [40] phi()
+  [41] call assertType 
+  to:main::@19
+main::@19: scope:[main]  from main::@18
+  [42] phi()
+  [43] call assertType 
+  to:main::@20
+main::@20: scope:[main]  from main::@19
+  [44] phi()
+  [45] call assertType 
+  to:main::@21
+main::@21: scope:[main]  from main::@20
+  [46] phi()
+  [47] call assertType 
+  to:main::@22
+main::@22: scope:[main]  from main::@21
+  [48] phi()
+  [49] call assertType 
+  to:main::@23
+main::@23: scope:[main]  from main::@22
+  [50] phi()
+  [51] call assertType 
+  to:main::@24
+main::@24: scope:[main]  from main::@23
+  [52] phi()
+  [53] call assertType 
+  to:main::@25
+main::@25: scope:[main]  from main::@24
+  [54] phi()
+  [55] call assertType 
+  to:main::@26
+main::@26: scope:[main]  from main::@25
+  [56] phi()
+  [57] call assertType 
+  to:main::@27
+main::@27: scope:[main]  from main::@26
+  [58] phi()
+  [59] call assertType 
+  to:main::@28
+main::@28: scope:[main]  from main::@27
+  [60] phi()
+  [61] call assertType 
+  to:main::@29
+main::@29: scope:[main]  from main::@28
+  [62] phi()
+  [63] call assertType 
+  to:main::@30
+main::@30: scope:[main]  from main::@29
+  [64] phi()
+  [65] call assertType 
+  to:main::@31
+main::@31: scope:[main]  from main::@30
+  [66] phi()
+  [67] call assertType 
+  to:main::@32
+main::@32: scope:[main]  from main::@31
+  [68] phi()
+  [69] call assertType 
+  to:main::@33
+main::@33: scope:[main]  from main::@32
+  [70] phi()
+  [71] call assertType 
+  to:main::@34
+main::@34: scope:[main]  from main::@33
+  [72] phi()
+  [73] call assertType 
+  to:main::@return
+main::@return: scope:[main]  from main::@34
+  [74] return 
+  to:@return
+assertType: scope:[assertType]  from main main::@1 main::@10 main::@11 main::@12 main::@13 main::@14 main::@15 main::@16 main::@17 main::@18 main::@19 main::@2 main::@20 main::@21 main::@22 main::@23 main::@24 main::@25 main::@26 main::@27 main::@28 main::@29 main::@3 main::@30 main::@31 main::@32 main::@33 main::@34 main::@4 main::@5 main::@6 main::@7 main::@8 main::@9
+  [75] (byte) idx#79 ← phi( main/(byte) 0 main::@1/(byte) idx#40 main::@10/(byte) idx#40 main::@11/(byte) idx#40 main::@12/(byte) idx#40 main::@13/(byte) idx#40 main::@14/(byte) idx#40 main::@15/(byte) idx#40 main::@16/(byte) idx#40 main::@17/(byte) idx#40 main::@18/(byte) idx#40 main::@19/(byte) idx#40 main::@2/(byte) idx#40 main::@20/(byte) idx#40 main::@21/(byte) $50 main::@22/(byte) idx#40 main::@23/(byte) idx#40 main::@24/(byte) idx#40 main::@25/(byte) idx#40 main::@26/(byte) idx#40 main::@27/(byte) idx#40 main::@28/(byte) idx#40 main::@29/(byte) idx#40 main::@3/(byte) idx#40 main::@30/(byte) idx#40 main::@31/(byte) idx#40 main::@32/(byte) idx#40 main::@33/(byte) idx#40 main::@34/(byte) idx#40 main::@4/(byte) idx#40 main::@5/(byte) idx#40 main::@6/(byte) idx#40 main::@7/(byte) idx#40 main::@8/(byte) idx#40 main::@9/(byte) $28 )
+  [75] (byte) assertType::t2#35 ← phi( main/(const byte) TYPEID_SIGNED_BYTE main::@1/(const byte) TYPEID_SIGNED_WORD main::@10/(const byte) TYPEID_BYTE main::@11/(const byte) TYPEID_WORD main::@12/(const byte) TYPEID_WORD main::@13/(const byte) TYPEID_DWORD main::@14/(const byte) TYPEID_WORD main::@15/(const byte) TYPEID_WORD main::@16/(const byte) TYPEID_DWORD main::@17/(const byte) TYPEID_DWORD main::@18/(const byte) TYPEID_DWORD main::@19/(const byte) TYPEID_DWORD main::@2/(const byte) TYPEID_SIGNED_DWORD main::@20/(const byte) TYPEID_DWORD main::@21/(const byte) TYPEID_BYTE main::@22/(const byte) TYPEID_BYTE main::@23/(const byte) TYPEID_BYTE main::@24/(const byte) TYPEID_WORD main::@25/(const byte) TYPEID_WORD main::@26/(const byte) TYPEID_DWORD main::@27/(const byte) TYPEID_WORD main::@28/(const byte) TYPEID_WORD main::@29/(const byte) TYPEID_WORD main::@3/(const byte) TYPEID_SIGNED_WORD main::@30/(const byte) TYPEID_DWORD main::@31/(const byte) TYPEID_DWORD main::@32/(const byte) TYPEID_DWORD main::@33/(const byte) TYPEID_DWORD main::@34/(const byte) TYPEID_DWORD main::@4/(const byte) TYPEID_SIGNED_WORD main::@5/(const byte) TYPEID_SIGNED_DWORD main::@6/(const byte) TYPEID_SIGNED_DWORD main::@7/(const byte) TYPEID_SIGNED_DWORD main::@8/(const byte) TYPEID_SIGNED_DWORD main::@9/(const byte) TYPEID_BYTE )
+  [75] (byte) assertType::t1#35 ← phi( main/(const byte) TYPEID_SIGNED_BYTE main::@1/(const byte) TYPEID_SIGNED_WORD main::@10/(const byte) TYPEID_BYTE main::@11/(const byte) TYPEID_WORD main::@12/(const byte) TYPEID_WORD main::@13/(const byte) TYPEID_DWORD main::@14/(const byte) TYPEID_WORD main::@15/(const byte) TYPEID_WORD main::@16/(const byte) TYPEID_DWORD main::@17/(const byte) TYPEID_DWORD main::@18/(const byte) TYPEID_DWORD main::@19/(const byte) TYPEID_DWORD main::@2/(const byte) TYPEID_SIGNED_DWORD main::@20/(const byte) TYPEID_DWORD main::@21/(const byte) TYPEID_BYTE main::@22/(const byte) TYPEID_BYTE main::@23/(const byte) TYPEID_BYTE main::@24/(const byte) TYPEID_WORD main::@25/(const byte) TYPEID_WORD main::@26/(const byte) TYPEID_DWORD main::@27/(const byte) TYPEID_WORD main::@28/(const byte) TYPEID_WORD main::@29/(const byte) TYPEID_WORD main::@3/(const byte) TYPEID_SIGNED_WORD main::@30/(const byte) TYPEID_DWORD main::@31/(const byte) TYPEID_DWORD main::@32/(const byte) TYPEID_DWORD main::@33/(const byte) TYPEID_DWORD main::@34/(const byte) TYPEID_SIGNED_DWORD main::@4/(const byte) TYPEID_SIGNED_WORD main::@5/(const byte) TYPEID_SIGNED_DWORD main::@6/(const byte) TYPEID_SIGNED_DWORD main::@7/(const byte) TYPEID_SIGNED_DWORD main::@8/(const byte) TYPEID_SIGNED_DWORD main::@9/(const byte) TYPEID_BYTE )
+  [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1
+  to:assertType::@3
+assertType::@3: scope:[assertType]  from assertType
+  [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35
+  [79] (byte) idx#40 ← ++ (byte) idx#79
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  [80] return 
+  to:@return
+assertType::@1: scope:[assertType]  from assertType
+  [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0
+  to:assertType::@2
diff --git a/src/test/ref/number-conversion.log b/src/test/ref/number-conversion.log
new file mode 100644
index 000000000..72d68592f
--- /dev/null
+++ b/src/test/ref/number-conversion.log
@@ -0,0 +1,3609 @@
+Resolved forward reference idx to (byte) idx
+Resolved forward reference idx to (byte) idx
+Resolved forward reference idx to (byte) idx
+Adding pointer type conversion cast (byte*) SCREEN in (byte*) SCREEN ← (word) $400
+Adding pointer type conversion cast (byte*) COLS in (byte*) COLS ← (word) $d800
+
+CONTROL FLOW GRAPH SSA
+@begin: scope:[]  from
+  to:@1
+main: scope:[main]  from @2
+  (byte) idx#0 ← (byte) 0
+  (number~) main::$0 ← (signed byte) $c + (number) $c
+  (byte~) main::$1 ← typeid  (number~) main::$0
+  (byte) assertType::t1#0 ← (byte~) main::$1
+  (byte) assertType::t2#0 ← (const byte) TYPEID_SIGNED_BYTE
+  call assertType 
+  to:main::@1
+main::@1: scope:[main]  from main
+  (byte) idx#43 ← phi( main/(byte) idx#41 )
+  (byte) idx#1 ← (byte) idx#43
+  (number~) main::$3 ← (signed byte) $c + (number) $82
+  (byte~) main::$4 ← typeid  (number~) main::$3
+  (byte) assertType::t1#1 ← (byte~) main::$4
+  (byte) assertType::t2#1 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  (byte) idx#44 ← phi( main::@1/(byte) idx#41 )
+  (byte) idx#2 ← (byte) idx#44
+  (number~) main::$6 ← (signed byte) $c + (number) $80e8
+  (byte~) main::$7 ← typeid  (number~) main::$6
+  (byte) assertType::t1#2 ← (byte~) main::$7
+  (byte) assertType::t2#2 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:main::@3
+main::@3: scope:[main]  from main::@2
+  (byte) idx#45 ← phi( main::@2/(byte) idx#41 )
+  (byte) idx#3 ← (byte) idx#45
+  (number~) main::$9 ← (signed word) $c + (number) $c
+  (byte~) main::$10 ← typeid  (number~) main::$9
+  (byte) assertType::t1#3 ← (byte~) main::$10
+  (byte) assertType::t2#3 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:main::@4
+main::@4: scope:[main]  from main::@3
+  (byte) idx#46 ← phi( main::@3/(byte) idx#41 )
+  (byte) idx#4 ← (byte) idx#46
+  (number~) main::$12 ← (signed word) $c + (number) $82
+  (byte~) main::$13 ← typeid  (number~) main::$12
+  (byte) assertType::t1#4 ← (byte~) main::$13
+  (byte) assertType::t2#4 ← (const byte) TYPEID_SIGNED_WORD
+  call assertType 
+  to:main::@5
+main::@5: scope:[main]  from main::@4
+  (byte) idx#47 ← phi( main::@4/(byte) idx#41 )
+  (byte) idx#5 ← (byte) idx#47
+  (number~) main::$15 ← (signed word) $c + (number) $186a0
+  (byte~) main::$16 ← typeid  (number~) main::$15
+  (byte) assertType::t1#5 ← (byte~) main::$16
+  (byte) assertType::t2#5 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:main::@6
+main::@6: scope:[main]  from main::@5
+  (byte) idx#48 ← phi( main::@5/(byte) idx#41 )
+  (byte) idx#6 ← (byte) idx#48
+  (number~) main::$18 ← (signed dword) $c + (number) $c
+  (byte~) main::$19 ← typeid  (number~) main::$18
+  (byte) assertType::t1#6 ← (byte~) main::$19
+  (byte) assertType::t2#6 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:main::@7
+main::@7: scope:[main]  from main::@6
+  (byte) idx#49 ← phi( main::@6/(byte) idx#41 )
+  (byte) idx#7 ← (byte) idx#49
+  (number~) main::$21 ← (signed dword) $c + (number) $82
+  (byte~) main::$22 ← typeid  (number~) main::$21
+  (byte) assertType::t1#7 ← (byte~) main::$22
+  (byte) assertType::t2#7 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:main::@8
+main::@8: scope:[main]  from main::@7
+  (byte) idx#50 ← phi( main::@7/(byte) idx#41 )
+  (byte) idx#8 ← (byte) idx#50
+  (number~) main::$24 ← (signed dword) $c + (number) $186a0
+  (byte~) main::$25 ← typeid  (number~) main::$24
+  (byte) assertType::t1#8 ← (byte~) main::$25
+  (byte) assertType::t2#8 ← (const byte) TYPEID_SIGNED_DWORD
+  call assertType 
+  to:main::@9
+main::@9: scope:[main]  from main::@8
+  (byte) idx#51 ← phi( main::@8/(byte) idx#41 )
+  (byte) idx#9 ← (byte) idx#51
+  (byte) idx#10 ← (byte) $28
+  (number~) main::$27 ← (byte) $c + (number) $c
+  (byte~) main::$28 ← typeid  (number~) main::$27
+  (byte) assertType::t1#9 ← (byte~) main::$28
+  (byte) assertType::t2#9 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:main::@10
+main::@10: scope:[main]  from main::@9
+  (byte) idx#52 ← phi( main::@9/(byte) idx#41 )
+  (byte) idx#11 ← (byte) idx#52
+  (number~) main::$30 ← (byte) $c + (number) $fa
+  (byte~) main::$31 ← typeid  (number~) main::$30
+  (byte) assertType::t1#10 ← (byte~) main::$31
+  (byte) assertType::t2#10 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:main::@11
+main::@11: scope:[main]  from main::@10
+  (byte) idx#53 ← phi( main::@10/(byte) idx#41 )
+  (byte) idx#12 ← (byte) idx#53
+  (number~) main::$33 ← (byte) $c + (number) $12c
+  (byte~) main::$34 ← typeid  (number~) main::$33
+  (byte) assertType::t1#11 ← (byte~) main::$34
+  (byte) assertType::t2#11 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@12
+main::@12: scope:[main]  from main::@11
+  (byte) idx#54 ← phi( main::@11/(byte) idx#41 )
+  (byte) idx#13 ← (byte) idx#54
+  (number~) main::$36 ← (byte) $c + (number) $fffe
+  (byte~) main::$37 ← typeid  (number~) main::$36
+  (byte) assertType::t1#12 ← (byte~) main::$37
+  (byte) assertType::t2#12 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@13
+main::@13: scope:[main]  from main::@12
+  (byte) idx#55 ← phi( main::@12/(byte) idx#41 )
+  (byte) idx#14 ← (byte) idx#55
+  (number~) main::$39 ← (byte) $c + (number) $101d0
+  (byte~) main::$40 ← typeid  (number~) main::$39
+  (byte) assertType::t1#13 ← (byte~) main::$40
+  (byte) assertType::t2#13 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@14
+main::@14: scope:[main]  from main::@13
+  (byte) idx#56 ← phi( main::@13/(byte) idx#41 )
+  (byte) idx#15 ← (byte) idx#56
+  (number~) main::$42 ← (word) $c + (number) $c
+  (byte~) main::$43 ← typeid  (number~) main::$42
+  (byte) assertType::t1#14 ← (byte~) main::$43
+  (byte) assertType::t2#14 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@15
+main::@15: scope:[main]  from main::@14
+  (byte) idx#57 ← phi( main::@14/(byte) idx#41 )
+  (byte) idx#16 ← (byte) idx#57
+  (number~) main::$45 ← (word) $c + (number) $82
+  (byte~) main::$46 ← typeid  (number~) main::$45
+  (byte) assertType::t1#15 ← (byte~) main::$46
+  (byte) assertType::t2#15 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@16
+main::@16: scope:[main]  from main::@15
+  (byte) idx#58 ← phi( main::@15/(byte) idx#41 )
+  (byte) idx#17 ← (byte) idx#58
+  (number~) main::$48 ← (word) $c + (number) $101d0
+  (byte~) main::$49 ← typeid  (number~) main::$48
+  (byte) assertType::t1#16 ← (byte~) main::$49
+  (byte) assertType::t2#16 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@17
+main::@17: scope:[main]  from main::@16
+  (byte) idx#59 ← phi( main::@16/(byte) idx#41 )
+  (byte) idx#18 ← (byte) idx#59
+  (number~) main::$51 ← (dword) $c + (number) $c
+  (byte~) main::$52 ← typeid  (number~) main::$51
+  (byte) assertType::t1#17 ← (byte~) main::$52
+  (byte) assertType::t2#17 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@18
+main::@18: scope:[main]  from main::@17
+  (byte) idx#60 ← phi( main::@17/(byte) idx#41 )
+  (byte) idx#19 ← (byte) idx#60
+  (number~) main::$54 ← (dword) $c + (number) $82
+  (byte~) main::$55 ← typeid  (number~) main::$54
+  (byte) assertType::t1#18 ← (byte~) main::$55
+  (byte) assertType::t2#18 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@19
+main::@19: scope:[main]  from main::@18
+  (byte) idx#61 ← phi( main::@18/(byte) idx#41 )
+  (byte) idx#20 ← (byte) idx#61
+  (number~) main::$57 ← (dword) $c + (number) $101d0
+  (byte~) main::$58 ← typeid  (number~) main::$57
+  (byte) assertType::t1#19 ← (byte~) main::$58
+  (byte) assertType::t2#19 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@20
+main::@20: scope:[main]  from main::@19
+  (byte) idx#62 ← phi( main::@19/(byte) idx#41 )
+  (byte) idx#21 ← (byte) idx#62
+  (number~) main::$60 ← (byte) $c + (number) $b2d05e00
+  (byte~) main::$61 ← typeid  (number~) main::$60
+  (byte) assertType::t1#20 ← (byte~) main::$61
+  (byte) assertType::t2#20 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@21
+main::@21: scope:[main]  from main::@20
+  (byte) idx#63 ← phi( main::@20/(byte) idx#41 )
+  (byte) idx#22 ← (byte) idx#63
+  (byte) idx#23 ← (byte) $50
+  (number~) main::$63 ← - (number) $c
+  (number~) main::$64 ← (byte) $c + (number~) main::$63
+  (byte~) main::$65 ← typeid  (number~) main::$64
+  (byte) assertType::t1#21 ← (byte~) main::$65
+  (byte) assertType::t2#21 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:main::@22
+main::@22: scope:[main]  from main::@21
+  (byte) idx#64 ← phi( main::@21/(byte) idx#41 )
+  (byte) idx#24 ← (byte) idx#64
+  (number~) main::$67 ← - (number) $78
+  (number~) main::$68 ← (byte) $c + (number~) main::$67
+  (byte~) main::$69 ← typeid  (number~) main::$68
+  (byte) assertType::t1#22 ← (byte~) main::$69
+  (byte) assertType::t2#22 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:main::@23
+main::@23: scope:[main]  from main::@22
+  (byte) idx#65 ← phi( main::@22/(byte) idx#41 )
+  (byte) idx#25 ← (byte) idx#65
+  (number~) main::$71 ← - (number) $fa
+  (number~) main::$72 ← (byte) $c + (number~) main::$71
+  (byte~) main::$73 ← typeid  (number~) main::$72
+  (byte) assertType::t1#23 ← (byte~) main::$73
+  (byte) assertType::t2#23 ← (const byte) TYPEID_BYTE
+  call assertType 
+  to:main::@24
+main::@24: scope:[main]  from main::@23
+  (byte) idx#66 ← phi( main::@23/(byte) idx#41 )
+  (byte) idx#26 ← (byte) idx#66
+  (number~) main::$75 ← - (number) $104
+  (number~) main::$76 ← (byte) $c + (number~) main::$75
+  (byte~) main::$77 ← typeid  (number~) main::$76
+  (byte) assertType::t1#24 ← (byte~) main::$77
+  (byte) assertType::t2#24 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@25
+main::@25: scope:[main]  from main::@24
+  (byte) idx#67 ← phi( main::@24/(byte) idx#41 )
+  (byte) idx#27 ← (byte) idx#67
+  (number~) main::$79 ← - (number) $fde8
+  (number~) main::$80 ← (byte) $c + (number~) main::$79
+  (byte~) main::$81 ← typeid  (number~) main::$80
+  (byte) assertType::t1#25 ← (byte~) main::$81
+  (byte) assertType::t2#25 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@26
+main::@26: scope:[main]  from main::@25
+  (byte) idx#68 ← phi( main::@25/(byte) idx#41 )
+  (byte) idx#28 ← (byte) idx#68
+  (number~) main::$83 ← - (number) $101d0
+  (number~) main::$84 ← (byte) $c + (number~) main::$83
+  (byte~) main::$85 ← typeid  (number~) main::$84
+  (byte) assertType::t1#26 ← (byte~) main::$85
+  (byte) assertType::t2#26 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@27
+main::@27: scope:[main]  from main::@26
+  (byte) idx#69 ← phi( main::@26/(byte) idx#41 )
+  (byte) idx#29 ← (byte) idx#69
+  (number~) main::$87 ← - (number) $c
+  (number~) main::$88 ← (word) $c + (number~) main::$87
+  (byte~) main::$89 ← typeid  (number~) main::$88
+  (byte) assertType::t1#27 ← (byte~) main::$89
+  (byte) assertType::t2#27 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@28
+main::@28: scope:[main]  from main::@27
+  (byte) idx#70 ← phi( main::@27/(byte) idx#41 )
+  (byte) idx#30 ← (byte) idx#70
+  (number~) main::$91 ← - (number) $82
+  (number~) main::$92 ← (word) $c + (number~) main::$91
+  (byte~) main::$93 ← typeid  (number~) main::$92
+  (byte) assertType::t1#28 ← (byte~) main::$93
+  (byte) assertType::t2#28 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@29
+main::@29: scope:[main]  from main::@28
+  (byte) idx#71 ← phi( main::@28/(byte) idx#41 )
+  (byte) idx#31 ← (byte) idx#71
+  (number~) main::$95 ← - (number) $fde8
+  (number~) main::$96 ← (word) $c + (number~) main::$95
+  (byte~) main::$97 ← typeid  (number~) main::$96
+  (byte) assertType::t1#29 ← (byte~) main::$97
+  (byte) assertType::t2#29 ← (const byte) TYPEID_WORD
+  call assertType 
+  to:main::@30
+main::@30: scope:[main]  from main::@29
+  (byte) idx#72 ← phi( main::@29/(byte) idx#41 )
+  (byte) idx#32 ← (byte) idx#72
+  (number~) main::$99 ← - (number) $101d0
+  (number~) main::$100 ← (word) $c + (number~) main::$99
+  (byte~) main::$101 ← typeid  (number~) main::$100
+  (byte) assertType::t1#30 ← (byte~) main::$101
+  (byte) assertType::t2#30 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@31
+main::@31: scope:[main]  from main::@30
+  (byte) idx#73 ← phi( main::@30/(byte) idx#41 )
+  (byte) idx#33 ← (byte) idx#73
+  (number~) main::$103 ← - (number) $c
+  (number~) main::$104 ← (dword) $c + (number~) main::$103
+  (byte~) main::$105 ← typeid  (number~) main::$104
+  (byte) assertType::t1#31 ← (byte~) main::$105
+  (byte) assertType::t2#31 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@32
+main::@32: scope:[main]  from main::@31
+  (byte) idx#74 ← phi( main::@31/(byte) idx#41 )
+  (byte) idx#34 ← (byte) idx#74
+  (number~) main::$107 ← - (number) $82
+  (number~) main::$108 ← (dword) $c + (number~) main::$107
+  (byte~) main::$109 ← typeid  (number~) main::$108
+  (byte) assertType::t1#32 ← (byte~) main::$109
+  (byte) assertType::t2#32 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@33
+main::@33: scope:[main]  from main::@32
+  (byte) idx#75 ← phi( main::@32/(byte) idx#41 )
+  (byte) idx#35 ← (byte) idx#75
+  (number~) main::$111 ← - (number) $101d0
+  (number~) main::$112 ← (dword) $c + (number~) main::$111
+  (byte~) main::$113 ← typeid  (number~) main::$112
+  (byte) assertType::t1#33 ← (byte~) main::$113
+  (byte) assertType::t2#33 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@34
+main::@34: scope:[main]  from main::@33
+  (byte) idx#76 ← phi( main::@33/(byte) idx#41 )
+  (byte) idx#36 ← (byte) idx#76
+  (number~) main::$115 ← - (number) $7d2b7500
+  (number~) main::$116 ← (signed byte) $c + (number~) main::$115
+  (byte~) main::$117 ← typeid  (number~) main::$116
+  (byte) assertType::t1#34 ← (byte~) main::$117
+  (byte) assertType::t2#34 ← (const byte) TYPEID_DWORD
+  call assertType 
+  to:main::@35
+main::@35: scope:[main]  from main::@34
+  (byte) idx#77 ← phi( main::@34/(byte) idx#41 )
+  (byte) idx#37 ← (byte) idx#77
+  to:main::@return
+main::@return: scope:[main]  from main::@35
+  (byte) idx#78 ← phi( main::@35/(byte) idx#37 )
+  (byte) idx#38 ← (byte) idx#78
+  return 
+  to:@return
+@1: scope:[]  from @begin
+  (byte) RED#0 ← (byte) 2
+  (byte) GREEN#0 ← (byte) 5
+  (word) $0 ← (word) $400
+  (byte*) SCREEN#0 ← ((byte*)) (word) $0
+  (word) $1 ← (word) $d800
+  (byte*) COLS#0 ← ((byte*)) (word) $1
+  (byte) idx#39 ← (byte) 0
+  to:@2
+assertType: scope:[assertType]  from main main::@1 main::@10 main::@11 main::@12 main::@13 main::@14 main::@15 main::@16 main::@17 main::@18 main::@19 main::@2 main::@20 main::@21 main::@22 main::@23 main::@24 main::@25 main::@26 main::@27 main::@28 main::@29 main::@3 main::@30 main::@31 main::@32 main::@33 main::@34 main::@4 main::@5 main::@6 main::@7 main::@8 main::@9
+  (byte) idx#84 ← phi( main/(byte) idx#0 main::@1/(byte) idx#1 main::@10/(byte) idx#11 main::@11/(byte) idx#12 main::@12/(byte) idx#13 main::@13/(byte) idx#14 main::@14/(byte) idx#15 main::@15/(byte) idx#16 main::@16/(byte) idx#17 main::@17/(byte) idx#18 main::@18/(byte) idx#19 main::@19/(byte) idx#20 main::@2/(byte) idx#2 main::@20/(byte) idx#21 main::@21/(byte) idx#23 main::@22/(byte) idx#24 main::@23/(byte) idx#25 main::@24/(byte) idx#26 main::@25/(byte) idx#27 main::@26/(byte) idx#28 main::@27/(byte) idx#29 main::@28/(byte) idx#30 main::@29/(byte) idx#31 main::@3/(byte) idx#3 main::@30/(byte) idx#32 main::@31/(byte) idx#33 main::@32/(byte) idx#34 main::@33/(byte) idx#35 main::@34/(byte) idx#36 main::@4/(byte) idx#4 main::@5/(byte) idx#5 main::@6/(byte) idx#6 main::@7/(byte) idx#7 main::@8/(byte) idx#8 main::@9/(byte) idx#10 )
+  (byte) assertType::t2#35 ← phi( main/(byte) assertType::t2#0 main::@1/(byte) assertType::t2#1 main::@10/(byte) assertType::t2#10 main::@11/(byte) assertType::t2#11 main::@12/(byte) assertType::t2#12 main::@13/(byte) assertType::t2#13 main::@14/(byte) assertType::t2#14 main::@15/(byte) assertType::t2#15 main::@16/(byte) assertType::t2#16 main::@17/(byte) assertType::t2#17 main::@18/(byte) assertType::t2#18 main::@19/(byte) assertType::t2#19 main::@2/(byte) assertType::t2#2 main::@20/(byte) assertType::t2#20 main::@21/(byte) assertType::t2#21 main::@22/(byte) assertType::t2#22 main::@23/(byte) assertType::t2#23 main::@24/(byte) assertType::t2#24 main::@25/(byte) assertType::t2#25 main::@26/(byte) assertType::t2#26 main::@27/(byte) assertType::t2#27 main::@28/(byte) assertType::t2#28 main::@29/(byte) assertType::t2#29 main::@3/(byte) assertType::t2#3 main::@30/(byte) assertType::t2#30 main::@31/(byte) assertType::t2#31 main::@32/(byte) assertType::t2#32 main::@33/(byte) assertType::t2#33 main::@34/(byte) assertType::t2#34 main::@4/(byte) assertType::t2#4 main::@5/(byte) assertType::t2#5 main::@6/(byte) assertType::t2#6 main::@7/(byte) assertType::t2#7 main::@8/(byte) assertType::t2#8 main::@9/(byte) assertType::t2#9 )
+  (byte) assertType::t1#35 ← phi( main/(byte) assertType::t1#0 main::@1/(byte) assertType::t1#1 main::@10/(byte) assertType::t1#10 main::@11/(byte) assertType::t1#11 main::@12/(byte) assertType::t1#12 main::@13/(byte) assertType::t1#13 main::@14/(byte) assertType::t1#14 main::@15/(byte) assertType::t1#15 main::@16/(byte) assertType::t1#16 main::@17/(byte) assertType::t1#17 main::@18/(byte) assertType::t1#18 main::@19/(byte) assertType::t1#19 main::@2/(byte) assertType::t1#2 main::@20/(byte) assertType::t1#20 main::@21/(byte) assertType::t1#21 main::@22/(byte) assertType::t1#22 main::@23/(byte) assertType::t1#23 main::@24/(byte) assertType::t1#24 main::@25/(byte) assertType::t1#25 main::@26/(byte) assertType::t1#26 main::@27/(byte) assertType::t1#27 main::@28/(byte) assertType::t1#28 main::@29/(byte) assertType::t1#29 main::@3/(byte) assertType::t1#3 main::@30/(byte) assertType::t1#30 main::@31/(byte) assertType::t1#31 main::@32/(byte) assertType::t1#32 main::@33/(byte) assertType::t1#33 main::@34/(byte) assertType::t1#34 main::@4/(byte) assertType::t1#4 main::@5/(byte) assertType::t1#5 main::@6/(byte) assertType::t1#6 main::@7/(byte) assertType::t1#7 main::@8/(byte) assertType::t1#8 main::@9/(byte) assertType::t1#9 )
+  (bool~) assertType::$0 ← (byte) assertType::t1#35 == (byte) assertType::t2#35
+  if((bool~) assertType::$0) goto assertType::@1
+  to:assertType::@3
+assertType::@1: scope:[assertType]  from assertType
+  (byte) assertType::t1#37 ← phi( assertType/(byte) assertType::t1#35 )
+  (byte) idx#79 ← phi( assertType/(byte) idx#84 )
+  *((byte*) COLS#0 + (byte) idx#79) ← (byte) GREEN#0
+  to:assertType::@2
+assertType::@3: scope:[assertType]  from assertType
+  (byte) assertType::t1#38 ← phi( assertType/(byte) assertType::t1#35 )
+  (byte) idx#80 ← phi( assertType/(byte) idx#84 )
+  *((byte*) COLS#0 + (byte) idx#80) ← (byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  (byte) idx#81 ← phi( assertType::@1/(byte) idx#79 assertType::@3/(byte) idx#80 )
+  (byte) assertType::t1#36 ← phi( assertType::@1/(byte) assertType::t1#37 assertType::@3/(byte) assertType::t1#38 )
+  *((byte*) SCREEN#0 + (byte) idx#81) ← (byte) assertType::t1#36
+  (byte) idx#40 ← ++ (byte) idx#81
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  (byte) idx#82 ← phi( assertType::@2/(byte) idx#40 )
+  (byte) idx#41 ← (byte) idx#82
+  return 
+  to:@return
+@2: scope:[]  from @1
+  (byte) idx#85 ← phi( @1/(byte) idx#39 )
+  call main 
+  to:@3
+@3: scope:[]  from @2
+  (byte) idx#83 ← phi( @2/(byte) idx#38 )
+  (byte) idx#42 ← (byte) idx#83
+  to:@end
+@end: scope:[]  from @3
+
+SYMBOL TABLE SSA
+(word) $0
+(word) $1
+(label) @1
+(label) @2
+(label) @3
+(label) @begin
+(label) @end
+(byte*) COLS
+(byte*) COLS#0
+(byte) GREEN
+(byte) GREEN#0
+(byte) RED
+(byte) RED#0
+(byte*) SCREEN
+(byte*) SCREEN#0
+(const byte) TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(bool~) assertType::$0
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#0
+(byte) assertType::t1#1
+(byte) assertType::t1#10
+(byte) assertType::t1#11
+(byte) assertType::t1#12
+(byte) assertType::t1#13
+(byte) assertType::t1#14
+(byte) assertType::t1#15
+(byte) assertType::t1#16
+(byte) assertType::t1#17
+(byte) assertType::t1#18
+(byte) assertType::t1#19
+(byte) assertType::t1#2
+(byte) assertType::t1#20
+(byte) assertType::t1#21
+(byte) assertType::t1#22
+(byte) assertType::t1#23
+(byte) assertType::t1#24
+(byte) assertType::t1#25
+(byte) assertType::t1#26
+(byte) assertType::t1#27
+(byte) assertType::t1#28
+(byte) assertType::t1#29
+(byte) assertType::t1#3
+(byte) assertType::t1#30
+(byte) assertType::t1#31
+(byte) assertType::t1#32
+(byte) assertType::t1#33
+(byte) assertType::t1#34
+(byte) assertType::t1#35
+(byte) assertType::t1#36
+(byte) assertType::t1#37
+(byte) assertType::t1#38
+(byte) assertType::t1#4
+(byte) assertType::t1#5
+(byte) assertType::t1#6
+(byte) assertType::t1#7
+(byte) assertType::t1#8
+(byte) assertType::t1#9
+(byte) assertType::t2
+(byte) assertType::t2#0
+(byte) assertType::t2#1
+(byte) assertType::t2#10
+(byte) assertType::t2#11
+(byte) assertType::t2#12
+(byte) assertType::t2#13
+(byte) assertType::t2#14
+(byte) assertType::t2#15
+(byte) assertType::t2#16
+(byte) assertType::t2#17
+(byte) assertType::t2#18
+(byte) assertType::t2#19
+(byte) assertType::t2#2
+(byte) assertType::t2#20
+(byte) assertType::t2#21
+(byte) assertType::t2#22
+(byte) assertType::t2#23
+(byte) assertType::t2#24
+(byte) assertType::t2#25
+(byte) assertType::t2#26
+(byte) assertType::t2#27
+(byte) assertType::t2#28
+(byte) assertType::t2#29
+(byte) assertType::t2#3
+(byte) assertType::t2#30
+(byte) assertType::t2#31
+(byte) assertType::t2#32
+(byte) assertType::t2#33
+(byte) assertType::t2#34
+(byte) assertType::t2#35
+(byte) assertType::t2#4
+(byte) assertType::t2#5
+(byte) assertType::t2#6
+(byte) assertType::t2#7
+(byte) assertType::t2#8
+(byte) assertType::t2#9
+(byte) idx
+(byte) idx#0
+(byte) idx#1
+(byte) idx#10
+(byte) idx#11
+(byte) idx#12
+(byte) idx#13
+(byte) idx#14
+(byte) idx#15
+(byte) idx#16
+(byte) idx#17
+(byte) idx#18
+(byte) idx#19
+(byte) idx#2
+(byte) idx#20
+(byte) idx#21
+(byte) idx#22
+(byte) idx#23
+(byte) idx#24
+(byte) idx#25
+(byte) idx#26
+(byte) idx#27
+(byte) idx#28
+(byte) idx#29
+(byte) idx#3
+(byte) idx#30
+(byte) idx#31
+(byte) idx#32
+(byte) idx#33
+(byte) idx#34
+(byte) idx#35
+(byte) idx#36
+(byte) idx#37
+(byte) idx#38
+(byte) idx#39
+(byte) idx#4
+(byte) idx#40
+(byte) idx#41
+(byte) idx#42
+(byte) idx#43
+(byte) idx#44
+(byte) idx#45
+(byte) idx#46
+(byte) idx#47
+(byte) idx#48
+(byte) idx#49
+(byte) idx#5
+(byte) idx#50
+(byte) idx#51
+(byte) idx#52
+(byte) idx#53
+(byte) idx#54
+(byte) idx#55
+(byte) idx#56
+(byte) idx#57
+(byte) idx#58
+(byte) idx#59
+(byte) idx#6
+(byte) idx#60
+(byte) idx#61
+(byte) idx#62
+(byte) idx#63
+(byte) idx#64
+(byte) idx#65
+(byte) idx#66
+(byte) idx#67
+(byte) idx#68
+(byte) idx#69
+(byte) idx#7
+(byte) idx#70
+(byte) idx#71
+(byte) idx#72
+(byte) idx#73
+(byte) idx#74
+(byte) idx#75
+(byte) idx#76
+(byte) idx#77
+(byte) idx#78
+(byte) idx#79
+(byte) idx#8
+(byte) idx#80
+(byte) idx#81
+(byte) idx#82
+(byte) idx#83
+(byte) idx#84
+(byte) idx#85
+(byte) idx#9
+(void()) main()
+(number~) main::$0
+(byte~) main::$1
+(byte~) main::$10
+(number~) main::$100
+(byte~) main::$101
+(number~) main::$103
+(number~) main::$104
+(byte~) main::$105
+(number~) main::$107
+(number~) main::$108
+(byte~) main::$109
+(number~) main::$111
+(number~) main::$112
+(byte~) main::$113
+(number~) main::$115
+(number~) main::$116
+(byte~) main::$117
+(number~) main::$12
+(byte~) main::$13
+(number~) main::$15
+(byte~) main::$16
+(number~) main::$18
+(byte~) main::$19
+(number~) main::$21
+(byte~) main::$22
+(number~) main::$24
+(byte~) main::$25
+(number~) main::$27
+(byte~) main::$28
+(number~) main::$3
+(number~) main::$30
+(byte~) main::$31
+(number~) main::$33
+(byte~) main::$34
+(number~) main::$36
+(byte~) main::$37
+(number~) main::$39
+(byte~) main::$4
+(byte~) main::$40
+(number~) main::$42
+(byte~) main::$43
+(number~) main::$45
+(byte~) main::$46
+(number~) main::$48
+(byte~) main::$49
+(number~) main::$51
+(byte~) main::$52
+(number~) main::$54
+(byte~) main::$55
+(number~) main::$57
+(byte~) main::$58
+(number~) main::$6
+(number~) main::$60
+(byte~) main::$61
+(number~) main::$63
+(number~) main::$64
+(byte~) main::$65
+(number~) main::$67
+(number~) main::$68
+(byte~) main::$69
+(byte~) main::$7
+(number~) main::$71
+(number~) main::$72
+(byte~) main::$73
+(number~) main::$75
+(number~) main::$76
+(byte~) main::$77
+(number~) main::$79
+(number~) main::$80
+(byte~) main::$81
+(number~) main::$83
+(number~) main::$84
+(byte~) main::$85
+(number~) main::$87
+(number~) main::$88
+(byte~) main::$89
+(number~) main::$9
+(number~) main::$91
+(number~) main::$92
+(byte~) main::$93
+(number~) main::$95
+(number~) main::$96
+(byte~) main::$97
+(number~) main::$99
+(label) main::@1
+(label) main::@10
+(label) main::@11
+(label) main::@12
+(label) main::@13
+(label) main::@14
+(label) main::@15
+(label) main::@16
+(label) main::@17
+(label) main::@18
+(label) main::@19
+(label) main::@2
+(label) main::@20
+(label) main::@21
+(label) main::@22
+(label) main::@23
+(label) main::@24
+(label) main::@25
+(label) main::@26
+(label) main::@27
+(label) main::@28
+(label) main::@29
+(label) main::@3
+(label) main::@30
+(label) main::@31
+(label) main::@32
+(label) main::@33
+(label) main::@34
+(label) main::@35
+(label) main::@4
+(label) main::@5
+(label) main::@6
+(label) main::@7
+(label) main::@8
+(label) main::@9
+(label) main::@return
+
+Adding number conversion cast (signed byte) $c in (number~) main::$0 ← (signed byte) $c + (number) $c
+Adding number conversion cast (signed word) $c in (number~) main::$3 ← (signed byte) $c + (number) $82
+Adding number conversion cast (signed word) $82 in (number~) main::$3 ← (signed word)(signed byte) $c + (number) $82
+Adding number conversion cast (signed dword) $c in (number~) main::$6 ← (signed byte) $c + (number) $80e8
+Adding number conversion cast (signed dword) $80e8 in (number~) main::$6 ← (signed dword)(signed byte) $c + (number) $80e8
+Adding number conversion cast (signed word) $c in (number~) main::$9 ← (signed word) $c + (number) $c
+Adding number conversion cast (signed word) $82 in (number~) main::$12 ← (signed word) $c + (number) $82
+Adding number conversion cast (signed dword) $c in (number~) main::$15 ← (signed word) $c + (number) $186a0
+Adding number conversion cast (signed dword) $186a0 in (number~) main::$15 ← (signed dword)(signed word) $c + (number) $186a0
+Adding number conversion cast (signed dword) $c in (number~) main::$18 ← (signed dword) $c + (number) $c
+Adding number conversion cast (signed dword) $82 in (number~) main::$21 ← (signed dword) $c + (number) $82
+Adding number conversion cast (signed dword) $186a0 in (number~) main::$24 ← (signed dword) $c + (number) $186a0
+Adding number conversion cast (byte) $c in (number~) main::$27 ← (byte) $c + (number) $c
+Adding number conversion cast (byte) $fa in (number~) main::$30 ← (byte) $c + (number) $fa
+Adding number conversion cast (word) $c in (number~) main::$33 ← (byte) $c + (number) $12c
+Adding number conversion cast (word) $12c in (number~) main::$33 ← (word)(byte) $c + (number) $12c
+Adding number conversion cast (word) $c in (number~) main::$36 ← (byte) $c + (number) $fffe
+Adding number conversion cast (word) $fffe in (number~) main::$36 ← (word)(byte) $c + (number) $fffe
+Adding number conversion cast (dword) $c in (number~) main::$39 ← (byte) $c + (number) $101d0
+Adding number conversion cast (dword) $101d0 in (number~) main::$39 ← (dword)(byte) $c + (number) $101d0
+Adding number conversion cast (word) $c in (number~) main::$42 ← (word) $c + (number) $c
+Adding number conversion cast (word) $82 in (number~) main::$45 ← (word) $c + (number) $82
+Adding number conversion cast (dword) $c in (number~) main::$48 ← (word) $c + (number) $101d0
+Adding number conversion cast (dword) $101d0 in (number~) main::$48 ← (dword)(word) $c + (number) $101d0
+Adding number conversion cast (dword) $c in (number~) main::$51 ← (dword) $c + (number) $c
+Adding number conversion cast (dword) $82 in (number~) main::$54 ← (dword) $c + (number) $82
+Adding number conversion cast (dword) $101d0 in (number~) main::$57 ← (dword) $c + (number) $101d0
+Adding number conversion cast (dword) $c in (number~) main::$60 ← (byte) $c + (number) $b2d05e00
+Adding number conversion cast (dword) $b2d05e00 in (number~) main::$60 ← (dword)(byte) $c + (number) $b2d05e00
+Inferred type updated to signed byte in (number~) main::$0 ← (signed byte) $c + (signed byte)(number) $c
+Inferred type updated to signed word in (number~) main::$3 ← (signed word)(signed byte) $c + (signed word)(number) $82
+Inferred type updated to signed dword in (number~) main::$6 ← (signed dword)(signed byte) $c + (signed dword)(number) $80e8
+Inferred type updated to signed word in (number~) main::$9 ← (signed word) $c + (signed word)(number) $c
+Inferred type updated to signed word in (number~) main::$12 ← (signed word) $c + (signed word)(number) $82
+Inferred type updated to signed dword in (number~) main::$15 ← (signed dword)(signed word) $c + (signed dword)(number) $186a0
+Inferred type updated to signed dword in (number~) main::$18 ← (signed dword) $c + (signed dword)(number) $c
+Inferred type updated to signed dword in (number~) main::$21 ← (signed dword) $c + (signed dword)(number) $82
+Inferred type updated to signed dword in (number~) main::$24 ← (signed dword) $c + (signed dword)(number) $186a0
+Inferred type updated to byte in (number~) main::$27 ← (byte) $c + (byte)(number) $c
+Inferred type updated to byte in (number~) main::$30 ← (byte) $c + (byte)(number) $fa
+Inferred type updated to word in (number~) main::$33 ← (word)(byte) $c + (word)(number) $12c
+Inferred type updated to word in (number~) main::$36 ← (word)(byte) $c + (word)(number) $fffe
+Inferred type updated to dword in (number~) main::$39 ← (dword)(byte) $c + (dword)(number) $101d0
+Inferred type updated to word in (number~) main::$42 ← (word) $c + (word)(number) $c
+Inferred type updated to word in (number~) main::$45 ← (word) $c + (word)(number) $82
+Inferred type updated to dword in (number~) main::$48 ← (dword)(word) $c + (dword)(number) $101d0
+Inferred type updated to dword in (number~) main::$51 ← (dword) $c + (dword)(number) $c
+Inferred type updated to dword in (number~) main::$54 ← (dword) $c + (dword)(number) $82
+Inferred type updated to dword in (number~) main::$57 ← (dword) $c + (dword)(number) $101d0
+Inferred type updated to dword in (number~) main::$60 ← (dword)(byte) $c + (dword)(number) $b2d05e00
+Resolving typeid() (byte~) main::$1 ← typeid  (signed byte~) main::$0
+Resolving typeid() (byte~) main::$4 ← typeid  (signed word~) main::$3
+Resolving typeid() (byte~) main::$7 ← typeid  (signed dword~) main::$6
+Resolving typeid() (byte~) main::$10 ← typeid  (signed word~) main::$9
+Resolving typeid() (byte~) main::$13 ← typeid  (signed word~) main::$12
+Resolving typeid() (byte~) main::$16 ← typeid  (signed dword~) main::$15
+Resolving typeid() (byte~) main::$19 ← typeid  (signed dword~) main::$18
+Resolving typeid() (byte~) main::$22 ← typeid  (signed dword~) main::$21
+Resolving typeid() (byte~) main::$25 ← typeid  (signed dword~) main::$24
+Resolving typeid() (byte~) main::$28 ← typeid  (byte~) main::$27
+Resolving typeid() (byte~) main::$31 ← typeid  (byte~) main::$30
+Resolving typeid() (byte~) main::$34 ← typeid  (word~) main::$33
+Resolving typeid() (byte~) main::$37 ← typeid  (word~) main::$36
+Resolving typeid() (byte~) main::$40 ← typeid  (dword~) main::$39
+Resolving typeid() (byte~) main::$43 ← typeid  (word~) main::$42
+Resolving typeid() (byte~) main::$46 ← typeid  (word~) main::$45
+Resolving typeid() (byte~) main::$49 ← typeid  (dword~) main::$48
+Resolving typeid() (byte~) main::$52 ← typeid  (dword~) main::$51
+Resolving typeid() (byte~) main::$55 ← typeid  (dword~) main::$54
+Resolving typeid() (byte~) main::$58 ← typeid  (dword~) main::$57
+Resolving typeid() (byte~) main::$61 ← typeid  (dword~) main::$60
+Successful SSA optimization PassNTypeIdSimplification
+Alias (byte) assertType::t1#0 = (byte~) main::$1 
+Alias (byte) idx#1 = (byte) idx#43 
+Alias (byte) assertType::t1#1 = (byte~) main::$4 
+Alias (byte) idx#2 = (byte) idx#44 
+Alias (byte) assertType::t1#2 = (byte~) main::$7 
+Alias (byte) idx#3 = (byte) idx#45 
+Alias (byte) assertType::t1#3 = (byte~) main::$10 
+Alias (byte) idx#4 = (byte) idx#46 
+Alias (byte) assertType::t1#4 = (byte~) main::$13 
+Alias (byte) idx#47 = (byte) idx#5 
+Alias (byte) assertType::t1#5 = (byte~) main::$16 
+Alias (byte) idx#48 = (byte) idx#6 
+Alias (byte) assertType::t1#6 = (byte~) main::$19 
+Alias (byte) idx#49 = (byte) idx#7 
+Alias (byte) assertType::t1#7 = (byte~) main::$22 
+Alias (byte) idx#50 = (byte) idx#8 
+Alias (byte) assertType::t1#8 = (byte~) main::$25 
+Alias (byte) idx#51 = (byte) idx#9 
+Alias (byte) assertType::t1#9 = (byte~) main::$28 
+Alias (byte) idx#11 = (byte) idx#52 
+Alias (byte) assertType::t1#10 = (byte~) main::$31 
+Alias (byte) idx#12 = (byte) idx#53 
+Alias (byte) assertType::t1#11 = (byte~) main::$34 
+Alias (byte) idx#13 = (byte) idx#54 
+Alias (byte) assertType::t1#12 = (byte~) main::$37 
+Alias (byte) idx#14 = (byte) idx#55 
+Alias (byte) assertType::t1#13 = (byte~) main::$40 
+Alias (byte) idx#15 = (byte) idx#56 
+Alias (byte) assertType::t1#14 = (byte~) main::$43 
+Alias (byte) idx#16 = (byte) idx#57 
+Alias (byte) assertType::t1#15 = (byte~) main::$46 
+Alias (byte) idx#17 = (byte) idx#58 
+Alias (byte) assertType::t1#16 = (byte~) main::$49 
+Alias (byte) idx#18 = (byte) idx#59 
+Alias (byte) assertType::t1#17 = (byte~) main::$52 
+Alias (byte) idx#19 = (byte) idx#60 
+Alias (byte) assertType::t1#18 = (byte~) main::$55 
+Alias (byte) idx#20 = (byte) idx#61 
+Alias (byte) assertType::t1#19 = (byte~) main::$58 
+Alias (byte) idx#21 = (byte) idx#62 
+Alias (byte) assertType::t1#20 = (byte~) main::$61 
+Alias (byte) idx#22 = (byte) idx#63 
+Alias (byte) assertType::t1#21 = (byte~) main::$65 
+Alias (byte) idx#24 = (byte) idx#64 
+Alias (byte) assertType::t1#22 = (byte~) main::$69 
+Alias (byte) idx#25 = (byte) idx#65 
+Alias (byte) assertType::t1#23 = (byte~) main::$73 
+Alias (byte) idx#26 = (byte) idx#66 
+Alias (byte) assertType::t1#24 = (byte~) main::$77 
+Alias (byte) idx#27 = (byte) idx#67 
+Alias (byte) assertType::t1#25 = (byte~) main::$81 
+Alias (byte) idx#28 = (byte) idx#68 
+Alias (byte) assertType::t1#26 = (byte~) main::$85 
+Alias (byte) idx#29 = (byte) idx#69 
+Alias (byte) assertType::t1#27 = (byte~) main::$89 
+Alias (byte) idx#30 = (byte) idx#70 
+Alias (byte) assertType::t1#28 = (byte~) main::$93 
+Alias (byte) idx#31 = (byte) idx#71 
+Alias (byte) assertType::t1#29 = (byte~) main::$97 
+Alias (byte) idx#32 = (byte) idx#72 
+Alias (byte) assertType::t1#30 = (byte~) main::$101 
+Alias (byte) idx#33 = (byte) idx#73 
+Alias (byte) assertType::t1#31 = (byte~) main::$105 
+Alias (byte) idx#34 = (byte) idx#74 
+Alias (byte) assertType::t1#32 = (byte~) main::$109 
+Alias (byte) idx#35 = (byte) idx#75 
+Alias (byte) assertType::t1#33 = (byte~) main::$113 
+Alias (byte) idx#36 = (byte) idx#76 
+Alias (byte) assertType::t1#34 = (byte~) main::$117 
+Alias (byte) idx#37 = (byte) idx#77 (byte) idx#78 (byte) idx#38 
+Alias (byte) idx#79 = (byte) idx#84 (byte) idx#80 
+Alias (byte) assertType::t1#35 = (byte) assertType::t1#37 (byte) assertType::t1#38 
+Alias (byte) idx#40 = (byte) idx#82 (byte) idx#41 
+Alias (byte) idx#39 = (byte) idx#85 
+Alias (byte) idx#42 = (byte) idx#83 
+Successful SSA optimization Pass2AliasElimination
+Alias (byte) assertType::t1#35 = (byte) assertType::t1#36 
+Alias (byte) idx#79 = (byte) idx#81 
+Successful SSA optimization Pass2AliasElimination
+Redundant Phi (byte) idx#1 (byte) idx#40
+Redundant Phi (byte) idx#2 (byte) idx#40
+Redundant Phi (byte) idx#3 (byte) idx#40
+Redundant Phi (byte) idx#4 (byte) idx#40
+Redundant Phi (byte) idx#47 (byte) idx#40
+Redundant Phi (byte) idx#48 (byte) idx#40
+Redundant Phi (byte) idx#49 (byte) idx#40
+Redundant Phi (byte) idx#50 (byte) idx#40
+Redundant Phi (byte) idx#51 (byte) idx#40
+Redundant Phi (byte) idx#11 (byte) idx#40
+Redundant Phi (byte) idx#12 (byte) idx#40
+Redundant Phi (byte) idx#13 (byte) idx#40
+Redundant Phi (byte) idx#14 (byte) idx#40
+Redundant Phi (byte) idx#15 (byte) idx#40
+Redundant Phi (byte) idx#16 (byte) idx#40
+Redundant Phi (byte) idx#17 (byte) idx#40
+Redundant Phi (byte) idx#18 (byte) idx#40
+Redundant Phi (byte) idx#19 (byte) idx#40
+Redundant Phi (byte) idx#20 (byte) idx#40
+Redundant Phi (byte) idx#21 (byte) idx#40
+Redundant Phi (byte) idx#22 (byte) idx#40
+Redundant Phi (byte) idx#24 (byte) idx#40
+Redundant Phi (byte) idx#25 (byte) idx#40
+Redundant Phi (byte) idx#26 (byte) idx#40
+Redundant Phi (byte) idx#27 (byte) idx#40
+Redundant Phi (byte) idx#28 (byte) idx#40
+Redundant Phi (byte) idx#29 (byte) idx#40
+Redundant Phi (byte) idx#30 (byte) idx#40
+Redundant Phi (byte) idx#31 (byte) idx#40
+Redundant Phi (byte) idx#32 (byte) idx#40
+Redundant Phi (byte) idx#33 (byte) idx#40
+Redundant Phi (byte) idx#34 (byte) idx#40
+Redundant Phi (byte) idx#35 (byte) idx#40
+Redundant Phi (byte) idx#36 (byte) idx#40
+Redundant Phi (byte) idx#37 (byte) idx#40
+Redundant Phi (byte) idx#42 (byte) idx#37
+Successful SSA optimization Pass2RedundantPhiElimination
+Simple Condition (bool~) assertType::$0 [274] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1
+Successful SSA optimization Pass2ConditionalJumpSimplification
+Constant right-side identified [1] (signed byte~) main::$0 ← (signed byte) $c + (signed byte)(number) $c
+Constant right-side identified [8] (signed word~) main::$3 ← (signed word)(signed byte) $c + (signed word)(number) $82
+Constant right-side identified [15] (signed dword~) main::$6 ← (signed dword)(signed byte) $c + (signed dword)(number) $80e8
+Constant right-side identified [22] (signed word~) main::$9 ← (signed word) $c + (signed word)(number) $c
+Constant right-side identified [29] (signed word~) main::$12 ← (signed word) $c + (signed word)(number) $82
+Constant right-side identified [36] (signed dword~) main::$15 ← (signed dword)(signed word) $c + (signed dword)(number) $186a0
+Constant right-side identified [43] (signed dword~) main::$18 ← (signed dword) $c + (signed dword)(number) $c
+Constant right-side identified [50] (signed dword~) main::$21 ← (signed dword) $c + (signed dword)(number) $82
+Constant right-side identified [57] (signed dword~) main::$24 ← (signed dword) $c + (signed dword)(number) $186a0
+Constant right-side identified [65] (byte~) main::$27 ← (byte) $c + (byte)(number) $c
+Constant right-side identified [72] (byte~) main::$30 ← (byte) $c + (byte)(number) $fa
+Constant right-side identified [79] (word~) main::$33 ← (word)(byte) $c + (word)(number) $12c
+Constant right-side identified [86] (word~) main::$36 ← (word)(byte) $c + (word)(number) $fffe
+Constant right-side identified [93] (dword~) main::$39 ← (dword)(byte) $c + (dword)(number) $101d0
+Constant right-side identified [100] (word~) main::$42 ← (word) $c + (word)(number) $c
+Constant right-side identified [107] (word~) main::$45 ← (word) $c + (word)(number) $82
+Constant right-side identified [114] (dword~) main::$48 ← (dword)(word) $c + (dword)(number) $101d0
+Constant right-side identified [121] (dword~) main::$51 ← (dword) $c + (dword)(number) $c
+Constant right-side identified [128] (dword~) main::$54 ← (dword) $c + (dword)(number) $82
+Constant right-side identified [135] (dword~) main::$57 ← (dword) $c + (dword)(number) $101d0
+Constant right-side identified [142] (dword~) main::$60 ← (dword)(byte) $c + (dword)(number) $b2d05e00
+Constant right-side identified [150] (number~) main::$63 ← - (number) $c
+Constant right-side identified [158] (number~) main::$67 ← - (number) $78
+Constant right-side identified [166] (number~) main::$71 ← - (number) $fa
+Constant right-side identified [174] (number~) main::$75 ← - (number) $104
+Constant right-side identified [182] (number~) main::$79 ← - (number) $fde8
+Constant right-side identified [190] (number~) main::$83 ← - (number) $101d0
+Constant right-side identified [198] (number~) main::$87 ← - (number) $c
+Constant right-side identified [206] (number~) main::$91 ← - (number) $82
+Constant right-side identified [214] (number~) main::$95 ← - (number) $fde8
+Constant right-side identified [222] (number~) main::$99 ← - (number) $101d0
+Constant right-side identified [230] (number~) main::$103 ← - (number) $c
+Constant right-side identified [238] (number~) main::$107 ← - (number) $82
+Constant right-side identified [246] (number~) main::$111 ← - (number) $101d0
+Constant right-side identified [254] (number~) main::$115 ← - (number) $7d2b7500
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) idx#0 = 0
+Constant (const signed byte) main::$0 = $c+(signed byte)$c
+Constant (const byte) assertType::t1#0 = TYPEID_SIGNED_BYTE
+Constant (const byte) assertType::t2#0 = TYPEID_SIGNED_BYTE
+Constant (const signed word) main::$3 = (signed word)$c+(signed word)$82
+Constant (const byte) assertType::t1#1 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#1 = TYPEID_SIGNED_WORD
+Constant (const signed dword) main::$6 = (signed dword)$c+(signed dword)$80e8
+Constant (const byte) assertType::t1#2 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#2 = TYPEID_SIGNED_DWORD
+Constant (const signed word) main::$9 = $c+(signed word)$c
+Constant (const byte) assertType::t1#3 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#3 = TYPEID_SIGNED_WORD
+Constant (const signed word) main::$12 = $c+(signed word)$82
+Constant (const byte) assertType::t1#4 = TYPEID_SIGNED_WORD
+Constant (const byte) assertType::t2#4 = TYPEID_SIGNED_WORD
+Constant (const signed dword) main::$15 = (signed dword)$c+(signed dword)$186a0
+Constant (const byte) assertType::t1#5 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#5 = TYPEID_SIGNED_DWORD
+Constant (const signed dword) main::$18 = $c+(signed dword)$c
+Constant (const byte) assertType::t1#6 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#6 = TYPEID_SIGNED_DWORD
+Constant (const signed dword) main::$21 = $c+(signed dword)$82
+Constant (const byte) assertType::t1#7 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#7 = TYPEID_SIGNED_DWORD
+Constant (const signed dword) main::$24 = $c+(signed dword)$186a0
+Constant (const byte) assertType::t1#8 = TYPEID_SIGNED_DWORD
+Constant (const byte) assertType::t2#8 = TYPEID_SIGNED_DWORD
+Constant (const byte) idx#10 = $28
+Constant (const byte) main::$27 = $c+(byte)$c
+Constant (const byte) assertType::t1#9 = TYPEID_BYTE
+Constant (const byte) assertType::t2#9 = TYPEID_BYTE
+Constant (const byte) main::$30 = $c+(byte)$fa
+Constant (const byte) assertType::t1#10 = TYPEID_BYTE
+Constant (const byte) assertType::t2#10 = TYPEID_BYTE
+Constant (const word) main::$33 = (word)$c+(word)$12c
+Constant (const byte) assertType::t1#11 = TYPEID_WORD
+Constant (const byte) assertType::t2#11 = TYPEID_WORD
+Constant (const word) main::$36 = (word)$c+(word)$fffe
+Constant (const byte) assertType::t1#12 = TYPEID_WORD
+Constant (const byte) assertType::t2#12 = TYPEID_WORD
+Constant (const dword) main::$39 = (dword)$c+(dword)$101d0
+Constant (const byte) assertType::t1#13 = TYPEID_DWORD
+Constant (const byte) assertType::t2#13 = TYPEID_DWORD
+Constant (const word) main::$42 = $c+(word)$c
+Constant (const byte) assertType::t1#14 = TYPEID_WORD
+Constant (const byte) assertType::t2#14 = TYPEID_WORD
+Constant (const word) main::$45 = $c+(word)$82
+Constant (const byte) assertType::t1#15 = TYPEID_WORD
+Constant (const byte) assertType::t2#15 = TYPEID_WORD
+Constant (const dword) main::$48 = (dword)$c+(dword)$101d0
+Constant (const byte) assertType::t1#16 = TYPEID_DWORD
+Constant (const byte) assertType::t2#16 = TYPEID_DWORD
+Constant (const dword) main::$51 = $c+(dword)$c
+Constant (const byte) assertType::t1#17 = TYPEID_DWORD
+Constant (const byte) assertType::t2#17 = TYPEID_DWORD
+Constant (const dword) main::$54 = $c+(dword)$82
+Constant (const byte) assertType::t1#18 = TYPEID_DWORD
+Constant (const byte) assertType::t2#18 = TYPEID_DWORD
+Constant (const dword) main::$57 = $c+(dword)$101d0
+Constant (const byte) assertType::t1#19 = TYPEID_DWORD
+Constant (const byte) assertType::t2#19 = TYPEID_DWORD
+Constant (const dword) main::$60 = (dword)$c+(dword)$b2d05e00
+Constant (const byte) assertType::t1#20 = TYPEID_DWORD
+Constant (const byte) assertType::t2#20 = TYPEID_DWORD
+Constant (const byte) idx#23 = $50
+Constant (const number) main::$63 = -$c
+Constant (const byte) assertType::t2#21 = TYPEID_BYTE
+Constant (const number) main::$67 = -$78
+Constant (const byte) assertType::t2#22 = TYPEID_BYTE
+Constant (const number) main::$71 = -$fa
+Constant (const byte) assertType::t2#23 = TYPEID_BYTE
+Constant (const number) main::$75 = -$104
+Constant (const byte) assertType::t2#24 = TYPEID_WORD
+Constant (const number) main::$79 = -$fde8
+Constant (const byte) assertType::t2#25 = TYPEID_WORD
+Constant (const number) main::$83 = -$101d0
+Constant (const byte) assertType::t2#26 = TYPEID_DWORD
+Constant (const number) main::$87 = -$c
+Constant (const byte) assertType::t2#27 = TYPEID_WORD
+Constant (const number) main::$91 = -$82
+Constant (const byte) assertType::t2#28 = TYPEID_WORD
+Constant (const number) main::$95 = -$fde8
+Constant (const byte) assertType::t2#29 = TYPEID_WORD
+Constant (const number) main::$99 = -$101d0
+Constant (const byte) assertType::t2#30 = TYPEID_DWORD
+Constant (const number) main::$103 = -$c
+Constant (const byte) assertType::t2#31 = TYPEID_DWORD
+Constant (const number) main::$107 = -$82
+Constant (const byte) assertType::t2#32 = TYPEID_DWORD
+Constant (const number) main::$111 = -$101d0
+Constant (const byte) assertType::t2#33 = TYPEID_DWORD
+Constant (const number) main::$115 = -$7d2b7500
+Constant (const byte) assertType::t2#34 = TYPEID_DWORD
+Constant (const byte) RED#0 = 2
+Constant (const byte) GREEN#0 = 5
+Constant (const word) $0 = $400
+Constant (const word) $1 = $d800
+Constant (const byte) idx#39 = 0
+Successful SSA optimization Pass2ConstantIdentification
+Eliminating unused constant (const signed byte) main::$0
+Eliminating unused constant (const signed word) main::$3
+Eliminating unused constant (const signed dword) main::$6
+Eliminating unused constant (const signed word) main::$9
+Eliminating unused constant (const signed word) main::$12
+Eliminating unused constant (const signed dword) main::$15
+Eliminating unused constant (const signed dword) main::$18
+Eliminating unused constant (const signed dword) main::$21
+Eliminating unused constant (const signed dword) main::$24
+Eliminating unused constant (const byte) main::$27
+Eliminating unused constant (const byte) main::$30
+Eliminating unused constant (const word) main::$33
+Eliminating unused constant (const word) main::$36
+Eliminating unused constant (const dword) main::$39
+Eliminating unused constant (const word) main::$42
+Eliminating unused constant (const word) main::$45
+Eliminating unused constant (const dword) main::$48
+Eliminating unused constant (const dword) main::$51
+Eliminating unused constant (const dword) main::$54
+Eliminating unused constant (const dword) main::$57
+Eliminating unused constant (const dword) main::$60
+Eliminating unused constant (const byte) idx#39
+Successful SSA optimization PassNEliminateUnusedVars
+Eliminating Noop Cast (byte*) SCREEN#0 ← ((byte*)) (const word) $0
+Eliminating Noop Cast (byte*) COLS#0 ← ((byte*)) (const word) $1
+Successful SSA optimization Pass2NopCastElimination
+Adding number conversion cast (byte) main::$63 in (number~) main::$64 ← (byte) $c + (const number) main::$63
+Adding number conversion cast (byte) main::$67 in (number~) main::$68 ← (byte) $c + (const number) main::$67
+Adding number conversion cast (byte) main::$71 in (number~) main::$72 ← (byte) $c + (const number) main::$71
+Adding number conversion cast (word) $c in (number~) main::$76 ← (byte) $c + (const number) main::$75
+Adding number conversion cast (word) main::$75 in (number~) main::$76 ← (word)(byte) $c + (const number) main::$75
+Adding number conversion cast (word) $c in (number~) main::$80 ← (byte) $c + (const number) main::$79
+Adding number conversion cast (word) main::$79 in (number~) main::$80 ← (word)(byte) $c + (const number) main::$79
+Adding number conversion cast (dword) $c in (number~) main::$84 ← (byte) $c + (const number) main::$83
+Adding number conversion cast (dword) main::$83 in (number~) main::$84 ← (dword)(byte) $c + (const number) main::$83
+Adding number conversion cast (word) main::$87 in (number~) main::$88 ← (word) $c + (const number) main::$87
+Adding number conversion cast (word) main::$91 in (number~) main::$92 ← (word) $c + (const number) main::$91
+Adding number conversion cast (word) main::$95 in (number~) main::$96 ← (word) $c + (const number) main::$95
+Adding number conversion cast (dword) $c in (number~) main::$100 ← (word) $c + (const number) main::$99
+Adding number conversion cast (dword) main::$99 in (number~) main::$100 ← (dword)(word) $c + (const number) main::$99
+Adding number conversion cast (dword) main::$103 in (number~) main::$104 ← (dword) $c + (const number) main::$103
+Adding number conversion cast (dword) main::$107 in (number~) main::$108 ← (dword) $c + (const number) main::$107
+Adding number conversion cast (dword) main::$111 in (number~) main::$112 ← (dword) $c + (const number) main::$111
+Adding number conversion cast (signed dword) $c in (number~) main::$116 ← (signed byte) $c + (const number) main::$115
+Adding number conversion cast (signed dword) main::$115 in (number~) main::$116 ← (signed dword)(signed byte) $c + (const number) main::$115
+Inferred type updated to byte in (number~) main::$64 ← (byte) $c + (byte)(const number) main::$63
+Inferred type updated to byte in (number~) main::$68 ← (byte) $c + (byte)(const number) main::$67
+Inferred type updated to byte in (number~) main::$72 ← (byte) $c + (byte)(const number) main::$71
+Inferred type updated to word in (number~) main::$76 ← (word)(byte) $c + (word)(const number) main::$75
+Inferred type updated to word in (number~) main::$80 ← (word)(byte) $c + (word)(const number) main::$79
+Inferred type updated to dword in (number~) main::$84 ← (dword)(byte) $c + (dword)(const number) main::$83
+Inferred type updated to word in (number~) main::$88 ← (word) $c + (word)(const number) main::$87
+Inferred type updated to word in (number~) main::$92 ← (word) $c + (word)(const number) main::$91
+Inferred type updated to word in (number~) main::$96 ← (word) $c + (word)(const number) main::$95
+Inferred type updated to dword in (number~) main::$100 ← (dword)(word) $c + (dword)(const number) main::$99
+Inferred type updated to dword in (number~) main::$104 ← (dword) $c + (dword)(const number) main::$103
+Inferred type updated to dword in (number~) main::$108 ← (dword) $c + (dword)(const number) main::$107
+Inferred type updated to dword in (number~) main::$112 ← (dword) $c + (dword)(const number) main::$111
+Inferred type updated to signed dword in (number~) main::$116 ← (signed dword)(signed byte) $c + (signed dword)(const number) main::$115
+Resolving typeid() (byte) assertType::t1#21 ← typeid  (byte~) main::$64
+Resolving typeid() (byte) assertType::t1#22 ← typeid  (byte~) main::$68
+Resolving typeid() (byte) assertType::t1#23 ← typeid  (byte~) main::$72
+Resolving typeid() (byte) assertType::t1#24 ← typeid  (word~) main::$76
+Resolving typeid() (byte) assertType::t1#25 ← typeid  (word~) main::$80
+Resolving typeid() (byte) assertType::t1#26 ← typeid  (dword~) main::$84
+Resolving typeid() (byte) assertType::t1#27 ← typeid  (word~) main::$88
+Resolving typeid() (byte) assertType::t1#28 ← typeid  (word~) main::$92
+Resolving typeid() (byte) assertType::t1#29 ← typeid  (word~) main::$96
+Resolving typeid() (byte) assertType::t1#30 ← typeid  (dword~) main::$100
+Resolving typeid() (byte) assertType::t1#31 ← typeid  (dword~) main::$104
+Resolving typeid() (byte) assertType::t1#32 ← typeid  (dword~) main::$108
+Resolving typeid() (byte) assertType::t1#33 ← typeid  (dword~) main::$112
+Resolving typeid() (byte) assertType::t1#34 ← typeid  (signed dword~) main::$116
+Successful SSA optimization PassNTypeIdSimplification
+Culled Empty Block (label) main::@35
+Culled Empty Block (label) @1
+Culled Empty Block (label) @3
+Successful SSA optimization Pass2CullEmptyBlocks
+Constant right-side identified [21] (byte~) main::$64 ← (byte) $c + (byte)(const number) main::$63
+Constant right-side identified [24] (byte~) main::$68 ← (byte) $c + (byte)(const number) main::$67
+Constant right-side identified [27] (byte~) main::$72 ← (byte) $c + (byte)(const number) main::$71
+Constant right-side identified [30] (word~) main::$76 ← (word)(byte) $c + (word)(const number) main::$75
+Constant right-side identified [33] (word~) main::$80 ← (word)(byte) $c + (word)(const number) main::$79
+Constant right-side identified [36] (dword~) main::$84 ← (dword)(byte) $c + (dword)(const number) main::$83
+Constant right-side identified [39] (word~) main::$88 ← (word) $c + (word)(const number) main::$87
+Constant right-side identified [42] (word~) main::$92 ← (word) $c + (word)(const number) main::$91
+Constant right-side identified [45] (word~) main::$96 ← (word) $c + (word)(const number) main::$95
+Constant right-side identified [48] (dword~) main::$100 ← (dword)(word) $c + (dword)(const number) main::$99
+Constant right-side identified [51] (dword~) main::$104 ← (dword) $c + (dword)(const number) main::$103
+Constant right-side identified [54] (dword~) main::$108 ← (dword) $c + (dword)(const number) main::$107
+Constant right-side identified [57] (dword~) main::$112 ← (dword) $c + (dword)(const number) main::$111
+Constant right-side identified [60] (signed dword~) main::$116 ← (signed dword)(signed byte) $c + (signed dword)(const number) main::$115
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) main::$64 = $c+(byte)main::$63
+Constant (const byte) assertType::t1#21 = TYPEID_BYTE
+Constant (const byte) main::$68 = $c+(byte)main::$67
+Constant (const byte) assertType::t1#22 = TYPEID_BYTE
+Constant (const byte) main::$72 = $c+(byte)main::$71
+Constant (const byte) assertType::t1#23 = TYPEID_BYTE
+Constant (const word) main::$76 = (word)$c+(word)main::$75
+Constant (const byte) assertType::t1#24 = TYPEID_WORD
+Constant (const word) main::$80 = (word)$c+(word)main::$79
+Constant (const byte) assertType::t1#25 = TYPEID_WORD
+Constant (const dword) main::$84 = (dword)$c+(dword)main::$83
+Constant (const byte) assertType::t1#26 = TYPEID_DWORD
+Constant (const word) main::$88 = $c+(word)main::$87
+Constant (const byte) assertType::t1#27 = TYPEID_WORD
+Constant (const word) main::$92 = $c+(word)main::$91
+Constant (const byte) assertType::t1#28 = TYPEID_WORD
+Constant (const word) main::$96 = $c+(word)main::$95
+Constant (const byte) assertType::t1#29 = TYPEID_WORD
+Constant (const dword) main::$100 = (dword)$c+(dword)main::$99
+Constant (const byte) assertType::t1#30 = TYPEID_DWORD
+Constant (const dword) main::$104 = $c+(dword)main::$103
+Constant (const byte) assertType::t1#31 = TYPEID_DWORD
+Constant (const dword) main::$108 = $c+(dword)main::$107
+Constant (const byte) assertType::t1#32 = TYPEID_DWORD
+Constant (const dword) main::$112 = $c+(dword)main::$111
+Constant (const byte) assertType::t1#33 = TYPEID_DWORD
+Constant (const signed dword) main::$116 = (signed dword)$c+(signed dword)main::$115
+Constant (const byte) assertType::t1#34 = TYPEID_SIGNED_DWORD
+Successful SSA optimization Pass2ConstantIdentification
+Eliminating unused constant (const byte) main::$64
+Eliminating unused constant (const byte) main::$68
+Eliminating unused constant (const byte) main::$72
+Eliminating unused constant (const word) main::$76
+Eliminating unused constant (const word) main::$80
+Eliminating unused constant (const dword) main::$84
+Eliminating unused constant (const word) main::$88
+Eliminating unused constant (const word) main::$92
+Eliminating unused constant (const word) main::$96
+Eliminating unused constant (const dword) main::$100
+Eliminating unused constant (const dword) main::$104
+Eliminating unused constant (const dword) main::$108
+Eliminating unused constant (const dword) main::$112
+Eliminating unused constant (const signed dword) main::$116
+Successful SSA optimization PassNEliminateUnusedVars
+Eliminating unused constant (const number) main::$63
+Eliminating unused constant (const number) main::$67
+Eliminating unused constant (const number) main::$71
+Eliminating unused constant (const number) main::$75
+Eliminating unused constant (const number) main::$79
+Eliminating unused constant (const number) main::$83
+Eliminating unused constant (const number) main::$87
+Eliminating unused constant (const number) main::$91
+Eliminating unused constant (const number) main::$95
+Eliminating unused constant (const number) main::$99
+Eliminating unused constant (const number) main::$103
+Eliminating unused constant (const number) main::$107
+Eliminating unused constant (const number) main::$111
+Eliminating unused constant (const number) main::$115
+Successful SSA optimization PassNEliminateUnusedVars
+Inlining constant with var siblings (const byte) assertType::t1#0
+Inlining constant with var siblings (const byte) assertType::t2#0
+Inlining constant with var siblings (const byte) assertType::t1#1
+Inlining constant with var siblings (const byte) assertType::t2#1
+Inlining constant with var siblings (const byte) assertType::t1#2
+Inlining constant with var siblings (const byte) assertType::t2#2
+Inlining constant with var siblings (const byte) assertType::t1#3
+Inlining constant with var siblings (const byte) assertType::t2#3
+Inlining constant with var siblings (const byte) assertType::t1#4
+Inlining constant with var siblings (const byte) assertType::t2#4
+Inlining constant with var siblings (const byte) assertType::t1#5
+Inlining constant with var siblings (const byte) assertType::t2#5
+Inlining constant with var siblings (const byte) assertType::t1#6
+Inlining constant with var siblings (const byte) assertType::t2#6
+Inlining constant with var siblings (const byte) assertType::t1#7
+Inlining constant with var siblings (const byte) assertType::t2#7
+Inlining constant with var siblings (const byte) assertType::t1#8
+Inlining constant with var siblings (const byte) assertType::t2#8
+Inlining constant with var siblings (const byte) assertType::t1#9
+Inlining constant with var siblings (const byte) assertType::t2#9
+Inlining constant with var siblings (const byte) assertType::t1#10
+Inlining constant with var siblings (const byte) assertType::t2#10
+Inlining constant with var siblings (const byte) assertType::t1#11
+Inlining constant with var siblings (const byte) assertType::t2#11
+Inlining constant with var siblings (const byte) assertType::t1#12
+Inlining constant with var siblings (const byte) assertType::t2#12
+Inlining constant with var siblings (const byte) assertType::t1#13
+Inlining constant with var siblings (const byte) assertType::t2#13
+Inlining constant with var siblings (const byte) assertType::t1#14
+Inlining constant with var siblings (const byte) assertType::t2#14
+Inlining constant with var siblings (const byte) assertType::t1#15
+Inlining constant with var siblings (const byte) assertType::t2#15
+Inlining constant with var siblings (const byte) assertType::t1#16
+Inlining constant with var siblings (const byte) assertType::t2#16
+Inlining constant with var siblings (const byte) assertType::t1#17
+Inlining constant with var siblings (const byte) assertType::t2#17
+Inlining constant with var siblings (const byte) assertType::t1#18
+Inlining constant with var siblings (const byte) assertType::t2#18
+Inlining constant with var siblings (const byte) assertType::t1#19
+Inlining constant with var siblings (const byte) assertType::t2#19
+Inlining constant with var siblings (const byte) assertType::t1#20
+Inlining constant with var siblings (const byte) assertType::t2#20
+Inlining constant with var siblings (const byte) assertType::t2#21
+Inlining constant with var siblings (const byte) assertType::t2#22
+Inlining constant with var siblings (const byte) assertType::t2#23
+Inlining constant with var siblings (const byte) assertType::t2#24
+Inlining constant with var siblings (const byte) assertType::t2#25
+Inlining constant with var siblings (const byte) assertType::t2#26
+Inlining constant with var siblings (const byte) assertType::t2#27
+Inlining constant with var siblings (const byte) assertType::t2#28
+Inlining constant with var siblings (const byte) assertType::t2#29
+Inlining constant with var siblings (const byte) assertType::t2#30
+Inlining constant with var siblings (const byte) assertType::t2#31
+Inlining constant with var siblings (const byte) assertType::t2#32
+Inlining constant with var siblings (const byte) assertType::t2#33
+Inlining constant with var siblings (const byte) assertType::t2#34
+Inlining constant with var siblings (const byte) assertType::t1#21
+Inlining constant with var siblings (const byte) assertType::t1#22
+Inlining constant with var siblings (const byte) assertType::t1#23
+Inlining constant with var siblings (const byte) assertType::t1#24
+Inlining constant with var siblings (const byte) assertType::t1#25
+Inlining constant with var siblings (const byte) assertType::t1#26
+Inlining constant with var siblings (const byte) assertType::t1#27
+Inlining constant with var siblings (const byte) assertType::t1#28
+Inlining constant with var siblings (const byte) assertType::t1#29
+Inlining constant with var siblings (const byte) assertType::t1#30
+Inlining constant with var siblings (const byte) assertType::t1#31
+Inlining constant with var siblings (const byte) assertType::t1#32
+Inlining constant with var siblings (const byte) assertType::t1#33
+Inlining constant with var siblings (const byte) assertType::t1#34
+Inlining constant with var siblings (const byte) idx#0
+Inlining constant with var siblings (const byte) idx#10
+Inlining constant with var siblings (const byte) idx#23
+Constant inlined assertType::t2#5 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#6 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#7 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#8 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#9 = (const byte) TYPEID_BYTE
+Constant inlined $0 = (word) $400
+Constant inlined $1 = (word) $d800
+Constant inlined assertType::t2#31 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#30 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#33 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#21 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#20 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#32 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#23 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#34 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#22 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#25 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#24 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#27 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#0 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t1#26 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#1 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t1#29 = (const byte) TYPEID_WORD
+Constant inlined idx#0 = (byte) 0
+Constant inlined assertType::t2#2 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#28 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#3 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#4 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined idx#23 = (byte) $50
+Constant inlined assertType::t2#20 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#10 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#22 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#21 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#12 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#24 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#11 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#23 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t1#14 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#26 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#13 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#25 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#16 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#28 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#15 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#27 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#18 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#17 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#29 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#19 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#6 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined idx#10 = (byte) $28
+Constant inlined assertType::t1#7 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#8 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#9 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#11 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#10 = (const byte) TYPEID_BYTE
+Constant inlined assertType::t2#13 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t2#12 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#15 = (const byte) TYPEID_WORD
+Constant inlined assertType::t2#14 = (const byte) TYPEID_WORD
+Constant inlined assertType::t1#0 = (const byte) TYPEID_SIGNED_BYTE
+Constant inlined assertType::t2#17 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#1 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#16 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#2 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t2#19 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#3 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t2#18 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#4 = (const byte) TYPEID_SIGNED_WORD
+Constant inlined assertType::t1#5 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#30 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#32 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#31 = (const byte) TYPEID_DWORD
+Constant inlined assertType::t1#34 = (const byte) TYPEID_SIGNED_DWORD
+Constant inlined assertType::t1#33 = (const byte) TYPEID_DWORD
+Successful SSA optimization Pass2ConstantInlining
+Adding NOP phi() at start of @begin
+Adding NOP phi() at start of @2
+Adding NOP phi() at start of @end
+Adding NOP phi() at start of main
+Adding NOP phi() at start of main::@9
+Adding NOP phi() at start of main::@21
+CALL GRAPH
+Calls in [] to main:2 
+Calls in [main] to assertType:5 assertType:7 assertType:9 assertType:11 assertType:13 assertType:15 assertType:17 assertType:19 assertType:21 assertType:23 assertType:25 assertType:27 assertType:29 assertType:31 assertType:33 assertType:35 assertType:37 assertType:39 assertType:41 assertType:43 assertType:45 assertType:47 assertType:49 assertType:51 assertType:53 assertType:55 assertType:57 assertType:59 assertType:61 assertType:63 assertType:65 assertType:67 assertType:69 assertType:71 assertType:73 
+
+Created 3 initial phi equivalence classes
+Coalesced [6] idx#86 ← idx#40
+Coalesced (already) [8] idx#97 ← idx#40
+Coalesced (already) [10] idx#107 ← idx#40
+Coalesced (already) [12] idx#113 ← idx#40
+Coalesced (already) [14] idx#114 ← idx#40
+Coalesced (already) [16] idx#115 ← idx#40
+Coalesced (already) [18] idx#116 ← idx#40
+Coalesced (already) [20] idx#117 ← idx#40
+Coalesced (already) [24] idx#87 ← idx#40
+Coalesced (already) [26] idx#88 ← idx#40
+Coalesced (already) [28] idx#89 ← idx#40
+Coalesced (already) [30] idx#90 ← idx#40
+Coalesced (already) [32] idx#91 ← idx#40
+Coalesced (already) [34] idx#92 ← idx#40
+Coalesced (already) [36] idx#93 ← idx#40
+Coalesced (already) [38] idx#94 ← idx#40
+Coalesced (already) [40] idx#95 ← idx#40
+Coalesced (already) [42] idx#96 ← idx#40
+Coalesced (already) [44] idx#98 ← idx#40
+Coalesced (already) [48] idx#99 ← idx#40
+Coalesced (already) [50] idx#100 ← idx#40
+Coalesced (already) [52] idx#101 ← idx#40
+Coalesced (already) [54] idx#102 ← idx#40
+Coalesced (already) [56] idx#103 ← idx#40
+Coalesced (already) [58] idx#104 ← idx#40
+Coalesced (already) [60] idx#105 ← idx#40
+Coalesced (already) [62] idx#106 ← idx#40
+Coalesced (already) [64] idx#108 ← idx#40
+Coalesced (already) [66] idx#109 ← idx#40
+Coalesced (already) [68] idx#110 ← idx#40
+Coalesced (already) [70] idx#111 ← idx#40
+Coalesced (already) [72] idx#112 ← idx#40
+Coalesced down to 3 phi equivalence classes
+Renumbering block @2 to @1
+Adding NOP phi() at start of @begin
+Adding NOP phi() at start of @1
+Adding NOP phi() at start of @end
+Adding NOP phi() at start of main
+Adding NOP phi() at start of main::@1
+Adding NOP phi() at start of main::@2
+Adding NOP phi() at start of main::@3
+Adding NOP phi() at start of main::@4
+Adding NOP phi() at start of main::@5
+Adding NOP phi() at start of main::@6
+Adding NOP phi() at start of main::@7
+Adding NOP phi() at start of main::@8
+Adding NOP phi() at start of main::@9
+Adding NOP phi() at start of main::@10
+Adding NOP phi() at start of main::@11
+Adding NOP phi() at start of main::@12
+Adding NOP phi() at start of main::@13
+Adding NOP phi() at start of main::@14
+Adding NOP phi() at start of main::@15
+Adding NOP phi() at start of main::@16
+Adding NOP phi() at start of main::@17
+Adding NOP phi() at start of main::@18
+Adding NOP phi() at start of main::@19
+Adding NOP phi() at start of main::@20
+Adding NOP phi() at start of main::@21
+Adding NOP phi() at start of main::@22
+Adding NOP phi() at start of main::@23
+Adding NOP phi() at start of main::@24
+Adding NOP phi() at start of main::@25
+Adding NOP phi() at start of main::@26
+Adding NOP phi() at start of main::@27
+Adding NOP phi() at start of main::@28
+Adding NOP phi() at start of main::@29
+Adding NOP phi() at start of main::@30
+Adding NOP phi() at start of main::@31
+Adding NOP phi() at start of main::@32
+Adding NOP phi() at start of main::@33
+Adding NOP phi() at start of main::@34
+
+FINAL CONTROL FLOW GRAPH
+@begin: scope:[]  from
+  [0] phi()
+  to:@1
+@1: scope:[]  from @begin
+  [1] phi()
+  [2] call main 
+  to:@end
+@end: scope:[]  from @1
+  [3] phi()
+main: scope:[main]  from @1
+  [4] phi()
+  [5] call assertType 
+  to:main::@1
+main::@1: scope:[main]  from main
+  [6] phi()
+  [7] call assertType 
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  [8] phi()
+  [9] call assertType 
+  to:main::@3
+main::@3: scope:[main]  from main::@2
+  [10] phi()
+  [11] call assertType 
+  to:main::@4
+main::@4: scope:[main]  from main::@3
+  [12] phi()
+  [13] call assertType 
+  to:main::@5
+main::@5: scope:[main]  from main::@4
+  [14] phi()
+  [15] call assertType 
+  to:main::@6
+main::@6: scope:[main]  from main::@5
+  [16] phi()
+  [17] call assertType 
+  to:main::@7
+main::@7: scope:[main]  from main::@6
+  [18] phi()
+  [19] call assertType 
+  to:main::@8
+main::@8: scope:[main]  from main::@7
+  [20] phi()
+  [21] call assertType 
+  to:main::@9
+main::@9: scope:[main]  from main::@8
+  [22] phi()
+  [23] call assertType 
+  to:main::@10
+main::@10: scope:[main]  from main::@9
+  [24] phi()
+  [25] call assertType 
+  to:main::@11
+main::@11: scope:[main]  from main::@10
+  [26] phi()
+  [27] call assertType 
+  to:main::@12
+main::@12: scope:[main]  from main::@11
+  [28] phi()
+  [29] call assertType 
+  to:main::@13
+main::@13: scope:[main]  from main::@12
+  [30] phi()
+  [31] call assertType 
+  to:main::@14
+main::@14: scope:[main]  from main::@13
+  [32] phi()
+  [33] call assertType 
+  to:main::@15
+main::@15: scope:[main]  from main::@14
+  [34] phi()
+  [35] call assertType 
+  to:main::@16
+main::@16: scope:[main]  from main::@15
+  [36] phi()
+  [37] call assertType 
+  to:main::@17
+main::@17: scope:[main]  from main::@16
+  [38] phi()
+  [39] call assertType 
+  to:main::@18
+main::@18: scope:[main]  from main::@17
+  [40] phi()
+  [41] call assertType 
+  to:main::@19
+main::@19: scope:[main]  from main::@18
+  [42] phi()
+  [43] call assertType 
+  to:main::@20
+main::@20: scope:[main]  from main::@19
+  [44] phi()
+  [45] call assertType 
+  to:main::@21
+main::@21: scope:[main]  from main::@20
+  [46] phi()
+  [47] call assertType 
+  to:main::@22
+main::@22: scope:[main]  from main::@21
+  [48] phi()
+  [49] call assertType 
+  to:main::@23
+main::@23: scope:[main]  from main::@22
+  [50] phi()
+  [51] call assertType 
+  to:main::@24
+main::@24: scope:[main]  from main::@23
+  [52] phi()
+  [53] call assertType 
+  to:main::@25
+main::@25: scope:[main]  from main::@24
+  [54] phi()
+  [55] call assertType 
+  to:main::@26
+main::@26: scope:[main]  from main::@25
+  [56] phi()
+  [57] call assertType 
+  to:main::@27
+main::@27: scope:[main]  from main::@26
+  [58] phi()
+  [59] call assertType 
+  to:main::@28
+main::@28: scope:[main]  from main::@27
+  [60] phi()
+  [61] call assertType 
+  to:main::@29
+main::@29: scope:[main]  from main::@28
+  [62] phi()
+  [63] call assertType 
+  to:main::@30
+main::@30: scope:[main]  from main::@29
+  [64] phi()
+  [65] call assertType 
+  to:main::@31
+main::@31: scope:[main]  from main::@30
+  [66] phi()
+  [67] call assertType 
+  to:main::@32
+main::@32: scope:[main]  from main::@31
+  [68] phi()
+  [69] call assertType 
+  to:main::@33
+main::@33: scope:[main]  from main::@32
+  [70] phi()
+  [71] call assertType 
+  to:main::@34
+main::@34: scope:[main]  from main::@33
+  [72] phi()
+  [73] call assertType 
+  to:main::@return
+main::@return: scope:[main]  from main::@34
+  [74] return 
+  to:@return
+assertType: scope:[assertType]  from main main::@1 main::@10 main::@11 main::@12 main::@13 main::@14 main::@15 main::@16 main::@17 main::@18 main::@19 main::@2 main::@20 main::@21 main::@22 main::@23 main::@24 main::@25 main::@26 main::@27 main::@28 main::@29 main::@3 main::@30 main::@31 main::@32 main::@33 main::@34 main::@4 main::@5 main::@6 main::@7 main::@8 main::@9
+  [75] (byte) idx#79 ← phi( main/(byte) 0 main::@1/(byte) idx#40 main::@10/(byte) idx#40 main::@11/(byte) idx#40 main::@12/(byte) idx#40 main::@13/(byte) idx#40 main::@14/(byte) idx#40 main::@15/(byte) idx#40 main::@16/(byte) idx#40 main::@17/(byte) idx#40 main::@18/(byte) idx#40 main::@19/(byte) idx#40 main::@2/(byte) idx#40 main::@20/(byte) idx#40 main::@21/(byte) $50 main::@22/(byte) idx#40 main::@23/(byte) idx#40 main::@24/(byte) idx#40 main::@25/(byte) idx#40 main::@26/(byte) idx#40 main::@27/(byte) idx#40 main::@28/(byte) idx#40 main::@29/(byte) idx#40 main::@3/(byte) idx#40 main::@30/(byte) idx#40 main::@31/(byte) idx#40 main::@32/(byte) idx#40 main::@33/(byte) idx#40 main::@34/(byte) idx#40 main::@4/(byte) idx#40 main::@5/(byte) idx#40 main::@6/(byte) idx#40 main::@7/(byte) idx#40 main::@8/(byte) idx#40 main::@9/(byte) $28 )
+  [75] (byte) assertType::t2#35 ← phi( main/(const byte) TYPEID_SIGNED_BYTE main::@1/(const byte) TYPEID_SIGNED_WORD main::@10/(const byte) TYPEID_BYTE main::@11/(const byte) TYPEID_WORD main::@12/(const byte) TYPEID_WORD main::@13/(const byte) TYPEID_DWORD main::@14/(const byte) TYPEID_WORD main::@15/(const byte) TYPEID_WORD main::@16/(const byte) TYPEID_DWORD main::@17/(const byte) TYPEID_DWORD main::@18/(const byte) TYPEID_DWORD main::@19/(const byte) TYPEID_DWORD main::@2/(const byte) TYPEID_SIGNED_DWORD main::@20/(const byte) TYPEID_DWORD main::@21/(const byte) TYPEID_BYTE main::@22/(const byte) TYPEID_BYTE main::@23/(const byte) TYPEID_BYTE main::@24/(const byte) TYPEID_WORD main::@25/(const byte) TYPEID_WORD main::@26/(const byte) TYPEID_DWORD main::@27/(const byte) TYPEID_WORD main::@28/(const byte) TYPEID_WORD main::@29/(const byte) TYPEID_WORD main::@3/(const byte) TYPEID_SIGNED_WORD main::@30/(const byte) TYPEID_DWORD main::@31/(const byte) TYPEID_DWORD main::@32/(const byte) TYPEID_DWORD main::@33/(const byte) TYPEID_DWORD main::@34/(const byte) TYPEID_DWORD main::@4/(const byte) TYPEID_SIGNED_WORD main::@5/(const byte) TYPEID_SIGNED_DWORD main::@6/(const byte) TYPEID_SIGNED_DWORD main::@7/(const byte) TYPEID_SIGNED_DWORD main::@8/(const byte) TYPEID_SIGNED_DWORD main::@9/(const byte) TYPEID_BYTE )
+  [75] (byte) assertType::t1#35 ← phi( main/(const byte) TYPEID_SIGNED_BYTE main::@1/(const byte) TYPEID_SIGNED_WORD main::@10/(const byte) TYPEID_BYTE main::@11/(const byte) TYPEID_WORD main::@12/(const byte) TYPEID_WORD main::@13/(const byte) TYPEID_DWORD main::@14/(const byte) TYPEID_WORD main::@15/(const byte) TYPEID_WORD main::@16/(const byte) TYPEID_DWORD main::@17/(const byte) TYPEID_DWORD main::@18/(const byte) TYPEID_DWORD main::@19/(const byte) TYPEID_DWORD main::@2/(const byte) TYPEID_SIGNED_DWORD main::@20/(const byte) TYPEID_DWORD main::@21/(const byte) TYPEID_BYTE main::@22/(const byte) TYPEID_BYTE main::@23/(const byte) TYPEID_BYTE main::@24/(const byte) TYPEID_WORD main::@25/(const byte) TYPEID_WORD main::@26/(const byte) TYPEID_DWORD main::@27/(const byte) TYPEID_WORD main::@28/(const byte) TYPEID_WORD main::@29/(const byte) TYPEID_WORD main::@3/(const byte) TYPEID_SIGNED_WORD main::@30/(const byte) TYPEID_DWORD main::@31/(const byte) TYPEID_DWORD main::@32/(const byte) TYPEID_DWORD main::@33/(const byte) TYPEID_DWORD main::@34/(const byte) TYPEID_SIGNED_DWORD main::@4/(const byte) TYPEID_SIGNED_WORD main::@5/(const byte) TYPEID_SIGNED_DWORD main::@6/(const byte) TYPEID_SIGNED_DWORD main::@7/(const byte) TYPEID_SIGNED_DWORD main::@8/(const byte) TYPEID_SIGNED_DWORD main::@9/(const byte) TYPEID_BYTE )
+  [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1
+  to:assertType::@3
+assertType::@3: scope:[assertType]  from assertType
+  [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0
+  to:assertType::@2
+assertType::@2: scope:[assertType]  from assertType::@1 assertType::@3
+  [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35
+  [79] (byte) idx#40 ← ++ (byte) idx#79
+  to:assertType::@return
+assertType::@return: scope:[assertType]  from assertType::@2
+  [80] return 
+  to:@return
+assertType::@1: scope:[assertType]  from assertType
+  [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0
+  to:assertType::@2
+
+
+VARIABLE REGISTER WEIGHTS
+(byte*) COLS
+(byte) GREEN
+(byte) RED
+(byte*) SCREEN
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(byte) assertType::t1
+(byte) assertType::t1#35 1.0
+(byte) assertType::t2
+(byte) assertType::t2#35 2.0
+(byte) idx
+(byte) idx#40 0.9999999999999993
+(byte) idx#79 14.400000000000007
+(void()) main()
+
+Initial phi equivalence classes
+[ assertType::t1#35 ]
+[ assertType::t2#35 ]
+[ idx#79 idx#40 ]
+Complete equivalence classes
+[ assertType::t1#35 ]
+[ assertType::t2#35 ]
+[ idx#79 idx#40 ]
+Allocated zp ZP_BYTE:2 [ assertType::t1#35 ]
+Allocated zp ZP_BYTE:3 [ assertType::t2#35 ]
+Allocated zp ZP_BYTE:4 [ idx#79 idx#40 ]
+
+INITIAL ASM
+//SEG0 File Comments
+// Tests conversion of numbers to correct int types
+// See https://gitlab.com/camelot/kickc/issues/181
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_SIGNED_DWORD = 6
+  .const TYPEID_BYTE = 1
+  .const TYPEID_WORD = 3
+  .const TYPEID_DWORD = 5
+  .const RED = 2
+  .const GREEN = 5
+  .label idx = 4
+//SEG3 @begin
+bbegin:
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+b1_from_bbegin:
+  jmp b1
+//SEG5 @1
+b1:
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+main_from_b1:
+  jsr main
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+bend_from_b1:
+  jmp bend
+//SEG9 @end
+bend:
+//SEG10 main
+main: {
+  //SEG11 [5] call assertType 
+  //SEG12 [75] phi from main to assertType [phi:main->assertType]
+  assertType_from_main:
+  //SEG13 [75] phi (byte) idx#79 = (byte) 0 [phi:main->assertType#0] -- vbuz1=vbuc1 
+    lda #0
+    sta idx
+  //SEG14 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG15 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG16 [6] phi from main to main::@1 [phi:main->main::@1]
+  b1_from_main:
+    jmp b1
+  //SEG17 main::@1
+  b1:
+  //SEG18 [7] call assertType 
+  //SEG19 [75] phi from main::@1 to assertType [phi:main::@1->assertType]
+  assertType_from_b1:
+  //SEG20 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@1->assertType#0] -- register_copy 
+  //SEG21 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG22 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG23 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG24 main::@2
+  b2:
+  //SEG25 [9] call assertType 
+  //SEG26 [75] phi from main::@2 to assertType [phi:main::@2->assertType]
+  assertType_from_b2:
+  //SEG27 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@2->assertType#0] -- register_copy 
+  //SEG28 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG29 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG30 [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG31 main::@3
+  b3:
+  //SEG32 [11] call assertType 
+  //SEG33 [75] phi from main::@3 to assertType [phi:main::@3->assertType]
+  assertType_from_b3:
+  //SEG34 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@3->assertType#0] -- register_copy 
+  //SEG35 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG36 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG37 [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4]
+  b4_from_b3:
+    jmp b4
+  //SEG38 main::@4
+  b4:
+  //SEG39 [13] call assertType 
+  //SEG40 [75] phi from main::@4 to assertType [phi:main::@4->assertType]
+  assertType_from_b4:
+  //SEG41 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@4->assertType#0] -- register_copy 
+  //SEG42 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG43 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG44 [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5]
+  b5_from_b4:
+    jmp b5
+  //SEG45 main::@5
+  b5:
+  //SEG46 [15] call assertType 
+  //SEG47 [75] phi from main::@5 to assertType [phi:main::@5->assertType]
+  assertType_from_b5:
+  //SEG48 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@5->assertType#0] -- register_copy 
+  //SEG49 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG50 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG51 [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
+  b6_from_b5:
+    jmp b6
+  //SEG52 main::@6
+  b6:
+  //SEG53 [17] call assertType 
+  //SEG54 [75] phi from main::@6 to assertType [phi:main::@6->assertType]
+  assertType_from_b6:
+  //SEG55 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@6->assertType#0] -- register_copy 
+  //SEG56 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG57 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG58 [18] phi from main::@6 to main::@7 [phi:main::@6->main::@7]
+  b7_from_b6:
+    jmp b7
+  //SEG59 main::@7
+  b7:
+  //SEG60 [19] call assertType 
+  //SEG61 [75] phi from main::@7 to assertType [phi:main::@7->assertType]
+  assertType_from_b7:
+  //SEG62 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@7->assertType#0] -- register_copy 
+  //SEG63 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG64 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG65 [20] phi from main::@7 to main::@8 [phi:main::@7->main::@8]
+  b8_from_b7:
+    jmp b8
+  //SEG66 main::@8
+  b8:
+  //SEG67 [21] call assertType 
+  //SEG68 [75] phi from main::@8 to assertType [phi:main::@8->assertType]
+  assertType_from_b8:
+  //SEG69 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@8->assertType#0] -- register_copy 
+  //SEG70 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG71 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG72 [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
+  b9_from_b8:
+    jmp b9
+  //SEG73 main::@9
+  b9:
+  //SEG74 [23] call assertType 
+  //SEG75 [75] phi from main::@9 to assertType [phi:main::@9->assertType]
+  assertType_from_b9:
+  //SEG76 [75] phi (byte) idx#79 = (byte) $28 [phi:main::@9->assertType#0] -- vbuz1=vbuc1 
+    lda #$28
+    sta idx
+  //SEG77 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG78 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG79 [24] phi from main::@9 to main::@10 [phi:main::@9->main::@10]
+  b10_from_b9:
+    jmp b10
+  //SEG80 main::@10
+  b10:
+  //SEG81 [25] call assertType 
+  //SEG82 [75] phi from main::@10 to assertType [phi:main::@10->assertType]
+  assertType_from_b10:
+  //SEG83 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@10->assertType#0] -- register_copy 
+  //SEG84 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG85 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG86 [26] phi from main::@10 to main::@11 [phi:main::@10->main::@11]
+  b11_from_b10:
+    jmp b11
+  //SEG87 main::@11
+  b11:
+  //SEG88 [27] call assertType 
+  //SEG89 [75] phi from main::@11 to assertType [phi:main::@11->assertType]
+  assertType_from_b11:
+  //SEG90 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@11->assertType#0] -- register_copy 
+  //SEG91 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG92 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG93 [28] phi from main::@11 to main::@12 [phi:main::@11->main::@12]
+  b12_from_b11:
+    jmp b12
+  //SEG94 main::@12
+  b12:
+  //SEG95 [29] call assertType 
+  //SEG96 [75] phi from main::@12 to assertType [phi:main::@12->assertType]
+  assertType_from_b12:
+  //SEG97 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@12->assertType#0] -- register_copy 
+  //SEG98 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG99 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG100 [30] phi from main::@12 to main::@13 [phi:main::@12->main::@13]
+  b13_from_b12:
+    jmp b13
+  //SEG101 main::@13
+  b13:
+  //SEG102 [31] call assertType 
+  //SEG103 [75] phi from main::@13 to assertType [phi:main::@13->assertType]
+  assertType_from_b13:
+  //SEG104 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@13->assertType#0] -- register_copy 
+  //SEG105 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG106 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG107 [32] phi from main::@13 to main::@14 [phi:main::@13->main::@14]
+  b14_from_b13:
+    jmp b14
+  //SEG108 main::@14
+  b14:
+  //SEG109 [33] call assertType 
+  //SEG110 [75] phi from main::@14 to assertType [phi:main::@14->assertType]
+  assertType_from_b14:
+  //SEG111 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@14->assertType#0] -- register_copy 
+  //SEG112 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG113 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG114 [34] phi from main::@14 to main::@15 [phi:main::@14->main::@15]
+  b15_from_b14:
+    jmp b15
+  //SEG115 main::@15
+  b15:
+  //SEG116 [35] call assertType 
+  //SEG117 [75] phi from main::@15 to assertType [phi:main::@15->assertType]
+  assertType_from_b15:
+  //SEG118 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@15->assertType#0] -- register_copy 
+  //SEG119 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG120 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG121 [36] phi from main::@15 to main::@16 [phi:main::@15->main::@16]
+  b16_from_b15:
+    jmp b16
+  //SEG122 main::@16
+  b16:
+  //SEG123 [37] call assertType 
+  //SEG124 [75] phi from main::@16 to assertType [phi:main::@16->assertType]
+  assertType_from_b16:
+  //SEG125 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@16->assertType#0] -- register_copy 
+  //SEG126 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG127 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG128 [38] phi from main::@16 to main::@17 [phi:main::@16->main::@17]
+  b17_from_b16:
+    jmp b17
+  //SEG129 main::@17
+  b17:
+  //SEG130 [39] call assertType 
+  //SEG131 [75] phi from main::@17 to assertType [phi:main::@17->assertType]
+  assertType_from_b17:
+  //SEG132 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@17->assertType#0] -- register_copy 
+  //SEG133 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG134 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG135 [40] phi from main::@17 to main::@18 [phi:main::@17->main::@18]
+  b18_from_b17:
+    jmp b18
+  //SEG136 main::@18
+  b18:
+  //SEG137 [41] call assertType 
+  //SEG138 [75] phi from main::@18 to assertType [phi:main::@18->assertType]
+  assertType_from_b18:
+  //SEG139 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@18->assertType#0] -- register_copy 
+  //SEG140 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG141 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG142 [42] phi from main::@18 to main::@19 [phi:main::@18->main::@19]
+  b19_from_b18:
+    jmp b19
+  //SEG143 main::@19
+  b19:
+  //SEG144 [43] call assertType 
+  //SEG145 [75] phi from main::@19 to assertType [phi:main::@19->assertType]
+  assertType_from_b19:
+  //SEG146 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@19->assertType#0] -- register_copy 
+  //SEG147 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG148 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG149 [44] phi from main::@19 to main::@20 [phi:main::@19->main::@20]
+  b20_from_b19:
+    jmp b20
+  //SEG150 main::@20
+  b20:
+  //SEG151 [45] call assertType 
+  //SEG152 [75] phi from main::@20 to assertType [phi:main::@20->assertType]
+  assertType_from_b20:
+  //SEG153 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@20->assertType#0] -- register_copy 
+  //SEG154 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG155 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG156 [46] phi from main::@20 to main::@21 [phi:main::@20->main::@21]
+  b21_from_b20:
+    jmp b21
+  //SEG157 main::@21
+  b21:
+  //SEG158 [47] call assertType 
+  //SEG159 [75] phi from main::@21 to assertType [phi:main::@21->assertType]
+  assertType_from_b21:
+  //SEG160 [75] phi (byte) idx#79 = (byte) $50 [phi:main::@21->assertType#0] -- vbuz1=vbuc1 
+    lda #$50
+    sta idx
+  //SEG161 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG162 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG163 [48] phi from main::@21 to main::@22 [phi:main::@21->main::@22]
+  b22_from_b21:
+    jmp b22
+  //SEG164 main::@22
+  b22:
+  //SEG165 [49] call assertType 
+  //SEG166 [75] phi from main::@22 to assertType [phi:main::@22->assertType]
+  assertType_from_b22:
+  //SEG167 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@22->assertType#0] -- register_copy 
+  //SEG168 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG169 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG170 [50] phi from main::@22 to main::@23 [phi:main::@22->main::@23]
+  b23_from_b22:
+    jmp b23
+  //SEG171 main::@23
+  b23:
+  //SEG172 [51] call assertType 
+  //SEG173 [75] phi from main::@23 to assertType [phi:main::@23->assertType]
+  assertType_from_b23:
+  //SEG174 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@23->assertType#0] -- register_copy 
+  //SEG175 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG176 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t1
+    jsr assertType
+  //SEG177 [52] phi from main::@23 to main::@24 [phi:main::@23->main::@24]
+  b24_from_b23:
+    jmp b24
+  //SEG178 main::@24
+  b24:
+  //SEG179 [53] call assertType 
+  //SEG180 [75] phi from main::@24 to assertType [phi:main::@24->assertType]
+  assertType_from_b24:
+  //SEG181 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@24->assertType#0] -- register_copy 
+  //SEG182 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG183 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG184 [54] phi from main::@24 to main::@25 [phi:main::@24->main::@25]
+  b25_from_b24:
+    jmp b25
+  //SEG185 main::@25
+  b25:
+  //SEG186 [55] call assertType 
+  //SEG187 [75] phi from main::@25 to assertType [phi:main::@25->assertType]
+  assertType_from_b25:
+  //SEG188 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@25->assertType#0] -- register_copy 
+  //SEG189 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG190 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG191 [56] phi from main::@25 to main::@26 [phi:main::@25->main::@26]
+  b26_from_b25:
+    jmp b26
+  //SEG192 main::@26
+  b26:
+  //SEG193 [57] call assertType 
+  //SEG194 [75] phi from main::@26 to assertType [phi:main::@26->assertType]
+  assertType_from_b26:
+  //SEG195 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@26->assertType#0] -- register_copy 
+  //SEG196 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG197 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG198 [58] phi from main::@26 to main::@27 [phi:main::@26->main::@27]
+  b27_from_b26:
+    jmp b27
+  //SEG199 main::@27
+  b27:
+  //SEG200 [59] call assertType 
+  //SEG201 [75] phi from main::@27 to assertType [phi:main::@27->assertType]
+  assertType_from_b27:
+  //SEG202 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@27->assertType#0] -- register_copy 
+  //SEG203 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG204 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG205 [60] phi from main::@27 to main::@28 [phi:main::@27->main::@28]
+  b28_from_b27:
+    jmp b28
+  //SEG206 main::@28
+  b28:
+  //SEG207 [61] call assertType 
+  //SEG208 [75] phi from main::@28 to assertType [phi:main::@28->assertType]
+  assertType_from_b28:
+  //SEG209 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@28->assertType#0] -- register_copy 
+  //SEG210 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG211 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG212 [62] phi from main::@28 to main::@29 [phi:main::@28->main::@29]
+  b29_from_b28:
+    jmp b29
+  //SEG213 main::@29
+  b29:
+  //SEG214 [63] call assertType 
+  //SEG215 [75] phi from main::@29 to assertType [phi:main::@29->assertType]
+  assertType_from_b29:
+  //SEG216 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@29->assertType#0] -- register_copy 
+  //SEG217 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG218 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t1
+    jsr assertType
+  //SEG219 [64] phi from main::@29 to main::@30 [phi:main::@29->main::@30]
+  b30_from_b29:
+    jmp b30
+  //SEG220 main::@30
+  b30:
+  //SEG221 [65] call assertType 
+  //SEG222 [75] phi from main::@30 to assertType [phi:main::@30->assertType]
+  assertType_from_b30:
+  //SEG223 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@30->assertType#0] -- register_copy 
+  //SEG224 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG225 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG226 [66] phi from main::@30 to main::@31 [phi:main::@30->main::@31]
+  b31_from_b30:
+    jmp b31
+  //SEG227 main::@31
+  b31:
+  //SEG228 [67] call assertType 
+  //SEG229 [75] phi from main::@31 to assertType [phi:main::@31->assertType]
+  assertType_from_b31:
+  //SEG230 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@31->assertType#0] -- register_copy 
+  //SEG231 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG232 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG233 [68] phi from main::@31 to main::@32 [phi:main::@31->main::@32]
+  b32_from_b31:
+    jmp b32
+  //SEG234 main::@32
+  b32:
+  //SEG235 [69] call assertType 
+  //SEG236 [75] phi from main::@32 to assertType [phi:main::@32->assertType]
+  assertType_from_b32:
+  //SEG237 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@32->assertType#0] -- register_copy 
+  //SEG238 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG239 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG240 [70] phi from main::@32 to main::@33 [phi:main::@32->main::@33]
+  b33_from_b32:
+    jmp b33
+  //SEG241 main::@33
+  b33:
+  //SEG242 [71] call assertType 
+  //SEG243 [75] phi from main::@33 to assertType [phi:main::@33->assertType]
+  assertType_from_b33:
+  //SEG244 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@33->assertType#0] -- register_copy 
+  //SEG245 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG246 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t1
+    jsr assertType
+  //SEG247 [72] phi from main::@33 to main::@34 [phi:main::@33->main::@34]
+  b34_from_b33:
+    jmp b34
+  //SEG248 main::@34
+  b34:
+  //SEG249 [73] call assertType 
+  //SEG250 [75] phi from main::@34 to assertType [phi:main::@34->assertType]
+  assertType_from_b34:
+  //SEG251 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@34->assertType#0] -- register_copy 
+  //SEG252 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@34->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG253 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@34->assertType#2] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t1
+    jsr assertType
+    jmp breturn
+  //SEG254 main::@return
+  breturn:
+  //SEG255 [74] return 
+    rts
+}
+//SEG256 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte zeropage(2) t1, byte zeropage(3) t2)
+assertType: {
+    .label t1 = 2
+    .label t2 = 3
+  //SEG257 [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 -- vbuz1_eq_vbuz2_then_la1 
+    lda t1
+    cmp t2
+    beq b1
+    jmp b3
+  //SEG258 assertType::@3
+  b3:
+  //SEG259 [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 -- pbuc1_derefidx_vbuz1=vbuc2 
+    lda #RED
+    ldy idx
+    sta $d800,y
+    jmp b2
+  //SEG260 assertType::@2
+  b2:
+  //SEG261 [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 -- pbuc1_derefidx_vbuz1=vbuz2 
+    lda t1
+    ldy idx
+    sta $400,y
+  //SEG262 [79] (byte) idx#40 ← ++ (byte) idx#79 -- vbuz1=_inc_vbuz1 
+    inc idx
+    jmp breturn
+  //SEG263 assertType::@return
+  breturn:
+  //SEG264 [80] return 
+    rts
+  //SEG265 assertType::@1
+  b1:
+  //SEG266 [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuz1=vbuc2 
+    lda #GREEN
+    ldy idx
+    sta $d800,y
+    jmp b2
+}
+
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 [ assertType::t1#35 idx#79 ] ( main:2::assertType:5 [ assertType::t1#35 idx#79 ] main:2::assertType:7 [ assertType::t1#35 idx#79 ] main:2::assertType:9 [ assertType::t1#35 idx#79 ] main:2::assertType:11 [ assertType::t1#35 idx#79 ] main:2::assertType:13 [ assertType::t1#35 idx#79 ] main:2::assertType:15 [ assertType::t1#35 idx#79 ] main:2::assertType:17 [ assertType::t1#35 idx#79 ] main:2::assertType:19 [ assertType::t1#35 idx#79 ] main:2::assertType:21 [ assertType::t1#35 idx#79 ] main:2::assertType:23 [ assertType::t1#35 idx#79 ] main:2::assertType:25 [ assertType::t1#35 idx#79 ] main:2::assertType:27 [ assertType::t1#35 idx#79 ] main:2::assertType:29 [ assertType::t1#35 idx#79 ] main:2::assertType:31 [ assertType::t1#35 idx#79 ] main:2::assertType:33 [ assertType::t1#35 idx#79 ] main:2::assertType:35 [ assertType::t1#35 idx#79 ] main:2::assertType:37 [ assertType::t1#35 idx#79 ] main:2::assertType:39 [ assertType::t1#35 idx#79 ] main:2::assertType:41 [ assertType::t1#35 idx#79 ] main:2::assertType:43 [ assertType::t1#35 idx#79 ] main:2::assertType:45 [ assertType::t1#35 idx#79 ] main:2::assertType:47 [ assertType::t1#35 idx#79 ] main:2::assertType:49 [ assertType::t1#35 idx#79 ] main:2::assertType:51 [ assertType::t1#35 idx#79 ] main:2::assertType:53 [ assertType::t1#35 idx#79 ] main:2::assertType:55 [ assertType::t1#35 idx#79 ] main:2::assertType:57 [ assertType::t1#35 idx#79 ] main:2::assertType:59 [ assertType::t1#35 idx#79 ] main:2::assertType:61 [ assertType::t1#35 idx#79 ] main:2::assertType:63 [ assertType::t1#35 idx#79 ] main:2::assertType:65 [ assertType::t1#35 idx#79 ] main:2::assertType:67 [ assertType::t1#35 idx#79 ] main:2::assertType:69 [ assertType::t1#35 idx#79 ] main:2::assertType:71 [ assertType::t1#35 idx#79 ] main:2::assertType:73 [ assertType::t1#35 idx#79 ] ) always clobbers reg byte a 
+Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ assertType::t1#35 ]
+Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ idx#79 idx#40 ]
+Statement [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 [ idx#79 ] ( main:2::assertType:5 [ idx#79 ] main:2::assertType:7 [ idx#79 ] main:2::assertType:9 [ idx#79 ] main:2::assertType:11 [ idx#79 ] main:2::assertType:13 [ idx#79 ] main:2::assertType:15 [ idx#79 ] main:2::assertType:17 [ idx#79 ] main:2::assertType:19 [ idx#79 ] main:2::assertType:21 [ idx#79 ] main:2::assertType:23 [ idx#79 ] main:2::assertType:25 [ idx#79 ] main:2::assertType:27 [ idx#79 ] main:2::assertType:29 [ idx#79 ] main:2::assertType:31 [ idx#79 ] main:2::assertType:33 [ idx#79 ] main:2::assertType:35 [ idx#79 ] main:2::assertType:37 [ idx#79 ] main:2::assertType:39 [ idx#79 ] main:2::assertType:41 [ idx#79 ] main:2::assertType:43 [ idx#79 ] main:2::assertType:45 [ idx#79 ] main:2::assertType:47 [ idx#79 ] main:2::assertType:49 [ idx#79 ] main:2::assertType:51 [ idx#79 ] main:2::assertType:53 [ idx#79 ] main:2::assertType:55 [ idx#79 ] main:2::assertType:57 [ idx#79 ] main:2::assertType:59 [ idx#79 ] main:2::assertType:61 [ idx#79 ] main:2::assertType:63 [ idx#79 ] main:2::assertType:65 [ idx#79 ] main:2::assertType:67 [ idx#79 ] main:2::assertType:69 [ idx#79 ] main:2::assertType:71 [ idx#79 ] main:2::assertType:73 [ idx#79 ] ) always clobbers reg byte a 
+Statement [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 [ assertType::t1#35 idx#79 ] ( main:2::assertType:5 [ assertType::t1#35 idx#79 ] main:2::assertType:7 [ assertType::t1#35 idx#79 ] main:2::assertType:9 [ assertType::t1#35 idx#79 ] main:2::assertType:11 [ assertType::t1#35 idx#79 ] main:2::assertType:13 [ assertType::t1#35 idx#79 ] main:2::assertType:15 [ assertType::t1#35 idx#79 ] main:2::assertType:17 [ assertType::t1#35 idx#79 ] main:2::assertType:19 [ assertType::t1#35 idx#79 ] main:2::assertType:21 [ assertType::t1#35 idx#79 ] main:2::assertType:23 [ assertType::t1#35 idx#79 ] main:2::assertType:25 [ assertType::t1#35 idx#79 ] main:2::assertType:27 [ assertType::t1#35 idx#79 ] main:2::assertType:29 [ assertType::t1#35 idx#79 ] main:2::assertType:31 [ assertType::t1#35 idx#79 ] main:2::assertType:33 [ assertType::t1#35 idx#79 ] main:2::assertType:35 [ assertType::t1#35 idx#79 ] main:2::assertType:37 [ assertType::t1#35 idx#79 ] main:2::assertType:39 [ assertType::t1#35 idx#79 ] main:2::assertType:41 [ assertType::t1#35 idx#79 ] main:2::assertType:43 [ assertType::t1#35 idx#79 ] main:2::assertType:45 [ assertType::t1#35 idx#79 ] main:2::assertType:47 [ assertType::t1#35 idx#79 ] main:2::assertType:49 [ assertType::t1#35 idx#79 ] main:2::assertType:51 [ assertType::t1#35 idx#79 ] main:2::assertType:53 [ assertType::t1#35 idx#79 ] main:2::assertType:55 [ assertType::t1#35 idx#79 ] main:2::assertType:57 [ assertType::t1#35 idx#79 ] main:2::assertType:59 [ assertType::t1#35 idx#79 ] main:2::assertType:61 [ assertType::t1#35 idx#79 ] main:2::assertType:63 [ assertType::t1#35 idx#79 ] main:2::assertType:65 [ assertType::t1#35 idx#79 ] main:2::assertType:67 [ assertType::t1#35 idx#79 ] main:2::assertType:69 [ assertType::t1#35 idx#79 ] main:2::assertType:71 [ assertType::t1#35 idx#79 ] main:2::assertType:73 [ assertType::t1#35 idx#79 ] ) always clobbers reg byte a 
+Statement [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 [ assertType::t1#35 idx#79 ] ( main:2::assertType:5 [ assertType::t1#35 idx#79 ] main:2::assertType:7 [ assertType::t1#35 idx#79 ] main:2::assertType:9 [ assertType::t1#35 idx#79 ] main:2::assertType:11 [ assertType::t1#35 idx#79 ] main:2::assertType:13 [ assertType::t1#35 idx#79 ] main:2::assertType:15 [ assertType::t1#35 idx#79 ] main:2::assertType:17 [ assertType::t1#35 idx#79 ] main:2::assertType:19 [ assertType::t1#35 idx#79 ] main:2::assertType:21 [ assertType::t1#35 idx#79 ] main:2::assertType:23 [ assertType::t1#35 idx#79 ] main:2::assertType:25 [ assertType::t1#35 idx#79 ] main:2::assertType:27 [ assertType::t1#35 idx#79 ] main:2::assertType:29 [ assertType::t1#35 idx#79 ] main:2::assertType:31 [ assertType::t1#35 idx#79 ] main:2::assertType:33 [ assertType::t1#35 idx#79 ] main:2::assertType:35 [ assertType::t1#35 idx#79 ] main:2::assertType:37 [ assertType::t1#35 idx#79 ] main:2::assertType:39 [ assertType::t1#35 idx#79 ] main:2::assertType:41 [ assertType::t1#35 idx#79 ] main:2::assertType:43 [ assertType::t1#35 idx#79 ] main:2::assertType:45 [ assertType::t1#35 idx#79 ] main:2::assertType:47 [ assertType::t1#35 idx#79 ] main:2::assertType:49 [ assertType::t1#35 idx#79 ] main:2::assertType:51 [ assertType::t1#35 idx#79 ] main:2::assertType:53 [ assertType::t1#35 idx#79 ] main:2::assertType:55 [ assertType::t1#35 idx#79 ] main:2::assertType:57 [ assertType::t1#35 idx#79 ] main:2::assertType:59 [ assertType::t1#35 idx#79 ] main:2::assertType:61 [ assertType::t1#35 idx#79 ] main:2::assertType:63 [ assertType::t1#35 idx#79 ] main:2::assertType:65 [ assertType::t1#35 idx#79 ] main:2::assertType:67 [ assertType::t1#35 idx#79 ] main:2::assertType:69 [ assertType::t1#35 idx#79 ] main:2::assertType:71 [ assertType::t1#35 idx#79 ] main:2::assertType:73 [ assertType::t1#35 idx#79 ] ) always clobbers reg byte a 
+Statement [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 [ idx#79 ] ( main:2::assertType:5 [ idx#79 ] main:2::assertType:7 [ idx#79 ] main:2::assertType:9 [ idx#79 ] main:2::assertType:11 [ idx#79 ] main:2::assertType:13 [ idx#79 ] main:2::assertType:15 [ idx#79 ] main:2::assertType:17 [ idx#79 ] main:2::assertType:19 [ idx#79 ] main:2::assertType:21 [ idx#79 ] main:2::assertType:23 [ idx#79 ] main:2::assertType:25 [ idx#79 ] main:2::assertType:27 [ idx#79 ] main:2::assertType:29 [ idx#79 ] main:2::assertType:31 [ idx#79 ] main:2::assertType:33 [ idx#79 ] main:2::assertType:35 [ idx#79 ] main:2::assertType:37 [ idx#79 ] main:2::assertType:39 [ idx#79 ] main:2::assertType:41 [ idx#79 ] main:2::assertType:43 [ idx#79 ] main:2::assertType:45 [ idx#79 ] main:2::assertType:47 [ idx#79 ] main:2::assertType:49 [ idx#79 ] main:2::assertType:51 [ idx#79 ] main:2::assertType:53 [ idx#79 ] main:2::assertType:55 [ idx#79 ] main:2::assertType:57 [ idx#79 ] main:2::assertType:59 [ idx#79 ] main:2::assertType:61 [ idx#79 ] main:2::assertType:63 [ idx#79 ] main:2::assertType:65 [ idx#79 ] main:2::assertType:67 [ idx#79 ] main:2::assertType:69 [ idx#79 ] main:2::assertType:71 [ idx#79 ] main:2::assertType:73 [ idx#79 ] ) always clobbers reg byte a 
+Statement [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 [ assertType::t1#35 idx#79 ] ( main:2::assertType:5 [ assertType::t1#35 idx#79 ] main:2::assertType:7 [ assertType::t1#35 idx#79 ] main:2::assertType:9 [ assertType::t1#35 idx#79 ] main:2::assertType:11 [ assertType::t1#35 idx#79 ] main:2::assertType:13 [ assertType::t1#35 idx#79 ] main:2::assertType:15 [ assertType::t1#35 idx#79 ] main:2::assertType:17 [ assertType::t1#35 idx#79 ] main:2::assertType:19 [ assertType::t1#35 idx#79 ] main:2::assertType:21 [ assertType::t1#35 idx#79 ] main:2::assertType:23 [ assertType::t1#35 idx#79 ] main:2::assertType:25 [ assertType::t1#35 idx#79 ] main:2::assertType:27 [ assertType::t1#35 idx#79 ] main:2::assertType:29 [ assertType::t1#35 idx#79 ] main:2::assertType:31 [ assertType::t1#35 idx#79 ] main:2::assertType:33 [ assertType::t1#35 idx#79 ] main:2::assertType:35 [ assertType::t1#35 idx#79 ] main:2::assertType:37 [ assertType::t1#35 idx#79 ] main:2::assertType:39 [ assertType::t1#35 idx#79 ] main:2::assertType:41 [ assertType::t1#35 idx#79 ] main:2::assertType:43 [ assertType::t1#35 idx#79 ] main:2::assertType:45 [ assertType::t1#35 idx#79 ] main:2::assertType:47 [ assertType::t1#35 idx#79 ] main:2::assertType:49 [ assertType::t1#35 idx#79 ] main:2::assertType:51 [ assertType::t1#35 idx#79 ] main:2::assertType:53 [ assertType::t1#35 idx#79 ] main:2::assertType:55 [ assertType::t1#35 idx#79 ] main:2::assertType:57 [ assertType::t1#35 idx#79 ] main:2::assertType:59 [ assertType::t1#35 idx#79 ] main:2::assertType:61 [ assertType::t1#35 idx#79 ] main:2::assertType:63 [ assertType::t1#35 idx#79 ] main:2::assertType:65 [ assertType::t1#35 idx#79 ] main:2::assertType:67 [ assertType::t1#35 idx#79 ] main:2::assertType:69 [ assertType::t1#35 idx#79 ] main:2::assertType:71 [ assertType::t1#35 idx#79 ] main:2::assertType:73 [ assertType::t1#35 idx#79 ] ) always clobbers reg byte a 
+Potential registers zp ZP_BYTE:2 [ assertType::t1#35 ] : zp ZP_BYTE:2 , reg byte x , reg byte y , 
+Potential registers zp ZP_BYTE:3 [ assertType::t2#35 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y , 
+Potential registers zp ZP_BYTE:4 [ idx#79 idx#40 ] : zp ZP_BYTE:4 , reg byte x , reg byte y , 
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [] 15.4: zp ZP_BYTE:4 [ idx#79 idx#40 ] 
+Uplift Scope [assertType] 2: zp ZP_BYTE:3 [ assertType::t2#35 ] 1: zp ZP_BYTE:2 [ assertType::t1#35 ] 
+Uplift Scope [main] 
+
+Uplifting [] best 739 combination reg byte x [ idx#79 idx#40 ] 
+Uplifting [assertType] best 632 combination zp ZP_BYTE:3 [ assertType::t2#35 ] reg byte y [ assertType::t1#35 ] 
+Uplifting [main] best 632 combination 
+Attempting to uplift remaining variables inzp ZP_BYTE:3 [ assertType::t2#35 ]
+Uplifting [assertType] best 632 combination zp ZP_BYTE:3 [ assertType::t2#35 ] 
+Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ assertType::t2#35 ]
+
+ASSEMBLER BEFORE OPTIMIZATION
+//SEG0 File Comments
+// Tests conversion of numbers to correct int types
+// See https://gitlab.com/camelot/kickc/issues/181
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_SIGNED_DWORD = 6
+  .const TYPEID_BYTE = 1
+  .const TYPEID_WORD = 3
+  .const TYPEID_DWORD = 5
+  .const RED = 2
+  .const GREEN = 5
+//SEG3 @begin
+bbegin:
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+b1_from_bbegin:
+  jmp b1
+//SEG5 @1
+b1:
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+main_from_b1:
+  jsr main
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+bend_from_b1:
+  jmp bend
+//SEG9 @end
+bend:
+//SEG10 main
+main: {
+  //SEG11 [5] call assertType 
+  //SEG12 [75] phi from main to assertType [phi:main->assertType]
+  assertType_from_main:
+  //SEG13 [75] phi (byte) idx#79 = (byte) 0 [phi:main->assertType#0] -- vbuxx=vbuc1 
+    ldx #0
+  //SEG14 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG15 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_BYTE
+    jsr assertType
+  //SEG16 [6] phi from main to main::@1 [phi:main->main::@1]
+  b1_from_main:
+    jmp b1
+  //SEG17 main::@1
+  b1:
+  //SEG18 [7] call assertType 
+  //SEG19 [75] phi from main::@1 to assertType [phi:main::@1->assertType]
+  assertType_from_b1:
+  //SEG20 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@1->assertType#0] -- register_copy 
+  //SEG21 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG22 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG23 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  b2_from_b1:
+    jmp b2
+  //SEG24 main::@2
+  b2:
+  //SEG25 [9] call assertType 
+  //SEG26 [75] phi from main::@2 to assertType [phi:main::@2->assertType]
+  assertType_from_b2:
+  //SEG27 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@2->assertType#0] -- register_copy 
+  //SEG28 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG29 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG30 [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
+  b3_from_b2:
+    jmp b3
+  //SEG31 main::@3
+  b3:
+  //SEG32 [11] call assertType 
+  //SEG33 [75] phi from main::@3 to assertType [phi:main::@3->assertType]
+  assertType_from_b3:
+  //SEG34 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@3->assertType#0] -- register_copy 
+  //SEG35 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG36 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG37 [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4]
+  b4_from_b3:
+    jmp b4
+  //SEG38 main::@4
+  b4:
+  //SEG39 [13] call assertType 
+  //SEG40 [75] phi from main::@4 to assertType [phi:main::@4->assertType]
+  assertType_from_b4:
+  //SEG41 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@4->assertType#0] -- register_copy 
+  //SEG42 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG43 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_WORD
+    jsr assertType
+  //SEG44 [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5]
+  b5_from_b4:
+    jmp b5
+  //SEG45 main::@5
+  b5:
+  //SEG46 [15] call assertType 
+  //SEG47 [75] phi from main::@5 to assertType [phi:main::@5->assertType]
+  assertType_from_b5:
+  //SEG48 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@5->assertType#0] -- register_copy 
+  //SEG49 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG50 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG51 [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
+  b6_from_b5:
+    jmp b6
+  //SEG52 main::@6
+  b6:
+  //SEG53 [17] call assertType 
+  //SEG54 [75] phi from main::@6 to assertType [phi:main::@6->assertType]
+  assertType_from_b6:
+  //SEG55 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@6->assertType#0] -- register_copy 
+  //SEG56 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG57 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG58 [18] phi from main::@6 to main::@7 [phi:main::@6->main::@7]
+  b7_from_b6:
+    jmp b7
+  //SEG59 main::@7
+  b7:
+  //SEG60 [19] call assertType 
+  //SEG61 [75] phi from main::@7 to assertType [phi:main::@7->assertType]
+  assertType_from_b7:
+  //SEG62 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@7->assertType#0] -- register_copy 
+  //SEG63 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG64 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG65 [20] phi from main::@7 to main::@8 [phi:main::@7->main::@8]
+  b8_from_b7:
+    jmp b8
+  //SEG66 main::@8
+  b8:
+  //SEG67 [21] call assertType 
+  //SEG68 [75] phi from main::@8 to assertType [phi:main::@8->assertType]
+  assertType_from_b8:
+  //SEG69 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@8->assertType#0] -- register_copy 
+  //SEG70 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG71 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG72 [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
+  b9_from_b8:
+    jmp b9
+  //SEG73 main::@9
+  b9:
+  //SEG74 [23] call assertType 
+  //SEG75 [75] phi from main::@9 to assertType [phi:main::@9->assertType]
+  assertType_from_b9:
+  //SEG76 [75] phi (byte) idx#79 = (byte) $28 [phi:main::@9->assertType#0] -- vbuxx=vbuc1 
+    ldx #$28
+  //SEG77 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG78 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG79 [24] phi from main::@9 to main::@10 [phi:main::@9->main::@10]
+  b10_from_b9:
+    jmp b10
+  //SEG80 main::@10
+  b10:
+  //SEG81 [25] call assertType 
+  //SEG82 [75] phi from main::@10 to assertType [phi:main::@10->assertType]
+  assertType_from_b10:
+  //SEG83 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@10->assertType#0] -- register_copy 
+  //SEG84 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG85 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG86 [26] phi from main::@10 to main::@11 [phi:main::@10->main::@11]
+  b11_from_b10:
+    jmp b11
+  //SEG87 main::@11
+  b11:
+  //SEG88 [27] call assertType 
+  //SEG89 [75] phi from main::@11 to assertType [phi:main::@11->assertType]
+  assertType_from_b11:
+  //SEG90 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@11->assertType#0] -- register_copy 
+  //SEG91 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG92 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG93 [28] phi from main::@11 to main::@12 [phi:main::@11->main::@12]
+  b12_from_b11:
+    jmp b12
+  //SEG94 main::@12
+  b12:
+  //SEG95 [29] call assertType 
+  //SEG96 [75] phi from main::@12 to assertType [phi:main::@12->assertType]
+  assertType_from_b12:
+  //SEG97 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@12->assertType#0] -- register_copy 
+  //SEG98 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG99 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG100 [30] phi from main::@12 to main::@13 [phi:main::@12->main::@13]
+  b13_from_b12:
+    jmp b13
+  //SEG101 main::@13
+  b13:
+  //SEG102 [31] call assertType 
+  //SEG103 [75] phi from main::@13 to assertType [phi:main::@13->assertType]
+  assertType_from_b13:
+  //SEG104 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@13->assertType#0] -- register_copy 
+  //SEG105 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG106 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG107 [32] phi from main::@13 to main::@14 [phi:main::@13->main::@14]
+  b14_from_b13:
+    jmp b14
+  //SEG108 main::@14
+  b14:
+  //SEG109 [33] call assertType 
+  //SEG110 [75] phi from main::@14 to assertType [phi:main::@14->assertType]
+  assertType_from_b14:
+  //SEG111 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@14->assertType#0] -- register_copy 
+  //SEG112 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG113 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG114 [34] phi from main::@14 to main::@15 [phi:main::@14->main::@15]
+  b15_from_b14:
+    jmp b15
+  //SEG115 main::@15
+  b15:
+  //SEG116 [35] call assertType 
+  //SEG117 [75] phi from main::@15 to assertType [phi:main::@15->assertType]
+  assertType_from_b15:
+  //SEG118 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@15->assertType#0] -- register_copy 
+  //SEG119 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG120 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG121 [36] phi from main::@15 to main::@16 [phi:main::@15->main::@16]
+  b16_from_b15:
+    jmp b16
+  //SEG122 main::@16
+  b16:
+  //SEG123 [37] call assertType 
+  //SEG124 [75] phi from main::@16 to assertType [phi:main::@16->assertType]
+  assertType_from_b16:
+  //SEG125 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@16->assertType#0] -- register_copy 
+  //SEG126 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG127 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG128 [38] phi from main::@16 to main::@17 [phi:main::@16->main::@17]
+  b17_from_b16:
+    jmp b17
+  //SEG129 main::@17
+  b17:
+  //SEG130 [39] call assertType 
+  //SEG131 [75] phi from main::@17 to assertType [phi:main::@17->assertType]
+  assertType_from_b17:
+  //SEG132 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@17->assertType#0] -- register_copy 
+  //SEG133 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG134 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG135 [40] phi from main::@17 to main::@18 [phi:main::@17->main::@18]
+  b18_from_b17:
+    jmp b18
+  //SEG136 main::@18
+  b18:
+  //SEG137 [41] call assertType 
+  //SEG138 [75] phi from main::@18 to assertType [phi:main::@18->assertType]
+  assertType_from_b18:
+  //SEG139 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@18->assertType#0] -- register_copy 
+  //SEG140 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG141 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG142 [42] phi from main::@18 to main::@19 [phi:main::@18->main::@19]
+  b19_from_b18:
+    jmp b19
+  //SEG143 main::@19
+  b19:
+  //SEG144 [43] call assertType 
+  //SEG145 [75] phi from main::@19 to assertType [phi:main::@19->assertType]
+  assertType_from_b19:
+  //SEG146 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@19->assertType#0] -- register_copy 
+  //SEG147 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG148 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG149 [44] phi from main::@19 to main::@20 [phi:main::@19->main::@20]
+  b20_from_b19:
+    jmp b20
+  //SEG150 main::@20
+  b20:
+  //SEG151 [45] call assertType 
+  //SEG152 [75] phi from main::@20 to assertType [phi:main::@20->assertType]
+  assertType_from_b20:
+  //SEG153 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@20->assertType#0] -- register_copy 
+  //SEG154 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG155 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG156 [46] phi from main::@20 to main::@21 [phi:main::@20->main::@21]
+  b21_from_b20:
+    jmp b21
+  //SEG157 main::@21
+  b21:
+  //SEG158 [47] call assertType 
+  //SEG159 [75] phi from main::@21 to assertType [phi:main::@21->assertType]
+  assertType_from_b21:
+  //SEG160 [75] phi (byte) idx#79 = (byte) $50 [phi:main::@21->assertType#0] -- vbuxx=vbuc1 
+    ldx #$50
+  //SEG161 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG162 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG163 [48] phi from main::@21 to main::@22 [phi:main::@21->main::@22]
+  b22_from_b21:
+    jmp b22
+  //SEG164 main::@22
+  b22:
+  //SEG165 [49] call assertType 
+  //SEG166 [75] phi from main::@22 to assertType [phi:main::@22->assertType]
+  assertType_from_b22:
+  //SEG167 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@22->assertType#0] -- register_copy 
+  //SEG168 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG169 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG170 [50] phi from main::@22 to main::@23 [phi:main::@22->main::@23]
+  b23_from_b22:
+    jmp b23
+  //SEG171 main::@23
+  b23:
+  //SEG172 [51] call assertType 
+  //SEG173 [75] phi from main::@23 to assertType [phi:main::@23->assertType]
+  assertType_from_b23:
+  //SEG174 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@23->assertType#0] -- register_copy 
+  //SEG175 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG176 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_BYTE
+    jsr assertType
+  //SEG177 [52] phi from main::@23 to main::@24 [phi:main::@23->main::@24]
+  b24_from_b23:
+    jmp b24
+  //SEG178 main::@24
+  b24:
+  //SEG179 [53] call assertType 
+  //SEG180 [75] phi from main::@24 to assertType [phi:main::@24->assertType]
+  assertType_from_b24:
+  //SEG181 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@24->assertType#0] -- register_copy 
+  //SEG182 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG183 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG184 [54] phi from main::@24 to main::@25 [phi:main::@24->main::@25]
+  b25_from_b24:
+    jmp b25
+  //SEG185 main::@25
+  b25:
+  //SEG186 [55] call assertType 
+  //SEG187 [75] phi from main::@25 to assertType [phi:main::@25->assertType]
+  assertType_from_b25:
+  //SEG188 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@25->assertType#0] -- register_copy 
+  //SEG189 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG190 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG191 [56] phi from main::@25 to main::@26 [phi:main::@25->main::@26]
+  b26_from_b25:
+    jmp b26
+  //SEG192 main::@26
+  b26:
+  //SEG193 [57] call assertType 
+  //SEG194 [75] phi from main::@26 to assertType [phi:main::@26->assertType]
+  assertType_from_b26:
+  //SEG195 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@26->assertType#0] -- register_copy 
+  //SEG196 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG197 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG198 [58] phi from main::@26 to main::@27 [phi:main::@26->main::@27]
+  b27_from_b26:
+    jmp b27
+  //SEG199 main::@27
+  b27:
+  //SEG200 [59] call assertType 
+  //SEG201 [75] phi from main::@27 to assertType [phi:main::@27->assertType]
+  assertType_from_b27:
+  //SEG202 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@27->assertType#0] -- register_copy 
+  //SEG203 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG204 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG205 [60] phi from main::@27 to main::@28 [phi:main::@27->main::@28]
+  b28_from_b27:
+    jmp b28
+  //SEG206 main::@28
+  b28:
+  //SEG207 [61] call assertType 
+  //SEG208 [75] phi from main::@28 to assertType [phi:main::@28->assertType]
+  assertType_from_b28:
+  //SEG209 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@28->assertType#0] -- register_copy 
+  //SEG210 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG211 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG212 [62] phi from main::@28 to main::@29 [phi:main::@28->main::@29]
+  b29_from_b28:
+    jmp b29
+  //SEG213 main::@29
+  b29:
+  //SEG214 [63] call assertType 
+  //SEG215 [75] phi from main::@29 to assertType [phi:main::@29->assertType]
+  assertType_from_b29:
+  //SEG216 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@29->assertType#0] -- register_copy 
+  //SEG217 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG218 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_WORD
+    jsr assertType
+  //SEG219 [64] phi from main::@29 to main::@30 [phi:main::@29->main::@30]
+  b30_from_b29:
+    jmp b30
+  //SEG220 main::@30
+  b30:
+  //SEG221 [65] call assertType 
+  //SEG222 [75] phi from main::@30 to assertType [phi:main::@30->assertType]
+  assertType_from_b30:
+  //SEG223 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@30->assertType#0] -- register_copy 
+  //SEG224 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG225 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG226 [66] phi from main::@30 to main::@31 [phi:main::@30->main::@31]
+  b31_from_b30:
+    jmp b31
+  //SEG227 main::@31
+  b31:
+  //SEG228 [67] call assertType 
+  //SEG229 [75] phi from main::@31 to assertType [phi:main::@31->assertType]
+  assertType_from_b31:
+  //SEG230 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@31->assertType#0] -- register_copy 
+  //SEG231 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG232 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG233 [68] phi from main::@31 to main::@32 [phi:main::@31->main::@32]
+  b32_from_b31:
+    jmp b32
+  //SEG234 main::@32
+  b32:
+  //SEG235 [69] call assertType 
+  //SEG236 [75] phi from main::@32 to assertType [phi:main::@32->assertType]
+  assertType_from_b32:
+  //SEG237 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@32->assertType#0] -- register_copy 
+  //SEG238 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG239 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG240 [70] phi from main::@32 to main::@33 [phi:main::@32->main::@33]
+  b33_from_b32:
+    jmp b33
+  //SEG241 main::@33
+  b33:
+  //SEG242 [71] call assertType 
+  //SEG243 [75] phi from main::@33 to assertType [phi:main::@33->assertType]
+  assertType_from_b33:
+  //SEG244 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@33->assertType#0] -- register_copy 
+  //SEG245 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG246 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_DWORD
+    jsr assertType
+  //SEG247 [72] phi from main::@33 to main::@34 [phi:main::@33->main::@34]
+  b34_from_b33:
+    jmp b34
+  //SEG248 main::@34
+  b34:
+  //SEG249 [73] call assertType 
+  //SEG250 [75] phi from main::@34 to assertType [phi:main::@34->assertType]
+  assertType_from_b34:
+  //SEG251 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@34->assertType#0] -- register_copy 
+  //SEG252 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@34->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG253 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@34->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+    jmp breturn
+  //SEG254 main::@return
+  breturn:
+  //SEG255 [74] return 
+    rts
+}
+//SEG256 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(2) t2)
+assertType: {
+    .label t2 = 2
+  //SEG257 [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 
+    tya
+    cmp t2
+    beq b1
+    jmp b3
+  //SEG258 assertType::@3
+  b3:
+  //SEG259 [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #RED
+    sta $d800,x
+    jmp b2
+  //SEG260 assertType::@2
+  b2:
+  //SEG261 [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 -- pbuc1_derefidx_vbuxx=vbuyy 
+    tya
+    sta $400,x
+  //SEG262 [79] (byte) idx#40 ← ++ (byte) idx#79 -- vbuxx=_inc_vbuxx 
+    inx
+    jmp breturn
+  //SEG263 assertType::@return
+  breturn:
+  //SEG264 [80] return 
+    rts
+  //SEG265 assertType::@1
+  b1:
+  //SEG266 [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #GREEN
+    sta $d800,x
+    jmp b2
+}
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp b1
+Removing instruction jmp bend
+Removing instruction jmp b1
+Removing instruction jmp b2
+Removing instruction jmp b3
+Removing instruction jmp b4
+Removing instruction jmp b5
+Removing instruction jmp b6
+Removing instruction jmp b7
+Removing instruction jmp b8
+Removing instruction jmp b9
+Removing instruction jmp b10
+Removing instruction jmp b11
+Removing instruction jmp b12
+Removing instruction jmp b13
+Removing instruction jmp b14
+Removing instruction jmp b15
+Removing instruction jmp b16
+Removing instruction jmp b17
+Removing instruction jmp b18
+Removing instruction jmp b19
+Removing instruction jmp b20
+Removing instruction jmp b21
+Removing instruction jmp b22
+Removing instruction jmp b23
+Removing instruction jmp b24
+Removing instruction jmp b25
+Removing instruction jmp b26
+Removing instruction jmp b27
+Removing instruction jmp b28
+Removing instruction jmp b29
+Removing instruction jmp b30
+Removing instruction jmp b31
+Removing instruction jmp b32
+Removing instruction jmp b33
+Removing instruction jmp b34
+Removing instruction jmp breturn
+Removing instruction jmp b3
+Removing instruction jmp b2
+Removing instruction jmp breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Replacing instruction ldy #TYPEID_SIGNED_BYTE with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_WORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_SIGNED_DWORD with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_BYTE with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_WORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Replacing instruction ldy #TYPEID_DWORD with TAY
+Removing instruction b1_from_bbegin:
+Removing instruction b1:
+Removing instruction main_from_b1:
+Removing instruction bend_from_b1:
+Removing instruction b1_from_main:
+Removing instruction assertType_from_b1:
+Removing instruction b2_from_b1:
+Removing instruction assertType_from_b2:
+Removing instruction b3_from_b2:
+Removing instruction assertType_from_b3:
+Removing instruction b4_from_b3:
+Removing instruction assertType_from_b4:
+Removing instruction b5_from_b4:
+Removing instruction assertType_from_b5:
+Removing instruction b6_from_b5:
+Removing instruction assertType_from_b6:
+Removing instruction b7_from_b6:
+Removing instruction assertType_from_b7:
+Removing instruction b8_from_b7:
+Removing instruction assertType_from_b8:
+Removing instruction b9_from_b8:
+Removing instruction assertType_from_b9:
+Removing instruction b10_from_b9:
+Removing instruction assertType_from_b10:
+Removing instruction b11_from_b10:
+Removing instruction assertType_from_b11:
+Removing instruction b12_from_b11:
+Removing instruction assertType_from_b12:
+Removing instruction b13_from_b12:
+Removing instruction assertType_from_b13:
+Removing instruction b14_from_b13:
+Removing instruction assertType_from_b14:
+Removing instruction b15_from_b14:
+Removing instruction assertType_from_b15:
+Removing instruction b16_from_b15:
+Removing instruction assertType_from_b16:
+Removing instruction b17_from_b16:
+Removing instruction assertType_from_b17:
+Removing instruction b18_from_b17:
+Removing instruction assertType_from_b18:
+Removing instruction b19_from_b18:
+Removing instruction assertType_from_b19:
+Removing instruction b20_from_b19:
+Removing instruction assertType_from_b20:
+Removing instruction b21_from_b20:
+Removing instruction assertType_from_b21:
+Removing instruction b22_from_b21:
+Removing instruction assertType_from_b22:
+Removing instruction b23_from_b22:
+Removing instruction assertType_from_b23:
+Removing instruction b24_from_b23:
+Removing instruction assertType_from_b24:
+Removing instruction b25_from_b24:
+Removing instruction assertType_from_b25:
+Removing instruction b26_from_b25:
+Removing instruction assertType_from_b26:
+Removing instruction b27_from_b26:
+Removing instruction assertType_from_b27:
+Removing instruction b28_from_b27:
+Removing instruction assertType_from_b28:
+Removing instruction b29_from_b28:
+Removing instruction assertType_from_b29:
+Removing instruction b30_from_b29:
+Removing instruction assertType_from_b30:
+Removing instruction b31_from_b30:
+Removing instruction assertType_from_b31:
+Removing instruction b32_from_b31:
+Removing instruction assertType_from_b32:
+Removing instruction b33_from_b32:
+Removing instruction assertType_from_b33:
+Removing instruction b34_from_b33:
+Removing instruction assertType_from_b34:
+Succesful ASM optimization Pass5RedundantLabelElimination
+Removing instruction bend:
+Removing instruction assertType_from_main:
+Removing instruction b1:
+Removing instruction b2:
+Removing instruction b3:
+Removing instruction b4:
+Removing instruction b5:
+Removing instruction b6:
+Removing instruction b7:
+Removing instruction b8:
+Removing instruction b9:
+Removing instruction b10:
+Removing instruction b11:
+Removing instruction b12:
+Removing instruction b13:
+Removing instruction b14:
+Removing instruction b15:
+Removing instruction b16:
+Removing instruction b17:
+Removing instruction b18:
+Removing instruction b19:
+Removing instruction b20:
+Removing instruction b21:
+Removing instruction b22:
+Removing instruction b23:
+Removing instruction b24:
+Removing instruction b25:
+Removing instruction b26:
+Removing instruction b27:
+Removing instruction b28:
+Removing instruction b29:
+Removing instruction b30:
+Removing instruction b31:
+Removing instruction b32:
+Removing instruction b33:
+Removing instruction b34:
+Removing instruction breturn:
+Removing instruction b3:
+Removing instruction breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+Updating BasicUpstart to call main directly
+Removing instruction jsr main
+Succesful ASM optimization Pass5SkipBegin
+Removing instruction bbegin:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+(label) @1
+(label) @begin
+(label) @end
+(byte*) COLS
+(byte) GREEN
+(const byte) GREEN#0 GREEN = (byte) 5
+(byte) RED
+(const byte) RED#0 RED = (byte) 2
+(byte*) SCREEN
+(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#35 reg byte y 1.0
+(byte) assertType::t2
+(byte) assertType::t2#35 t2 zp ZP_BYTE:2 2.0
+(byte) idx
+(byte) idx#40 reg byte x 0.9999999999999993
+(byte) idx#79 reg byte x 14.400000000000007
+(void()) main()
+(label) main::@1
+(label) main::@10
+(label) main::@11
+(label) main::@12
+(label) main::@13
+(label) main::@14
+(label) main::@15
+(label) main::@16
+(label) main::@17
+(label) main::@18
+(label) main::@19
+(label) main::@2
+(label) main::@20
+(label) main::@21
+(label) main::@22
+(label) main::@23
+(label) main::@24
+(label) main::@25
+(label) main::@26
+(label) main::@27
+(label) main::@28
+(label) main::@29
+(label) main::@3
+(label) main::@30
+(label) main::@31
+(label) main::@32
+(label) main::@33
+(label) main::@34
+(label) main::@4
+(label) main::@5
+(label) main::@6
+(label) main::@7
+(label) main::@8
+(label) main::@9
+(label) main::@return
+
+reg byte y [ assertType::t1#35 ]
+zp ZP_BYTE:2 [ assertType::t2#35 ]
+reg byte x [ idx#79 idx#40 ]
+
+
+FINAL ASSEMBLER
+Score: 506
+
+//SEG0 File Comments
+// Tests conversion of numbers to correct int types
+// See https://gitlab.com/camelot/kickc/issues/181
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+  .const TYPEID_SIGNED_BYTE = 2
+  .const TYPEID_SIGNED_WORD = 4
+  .const TYPEID_SIGNED_DWORD = 6
+  .const TYPEID_BYTE = 1
+  .const TYPEID_WORD = 3
+  .const TYPEID_DWORD = 5
+  .const RED = 2
+  .const GREEN = 5
+//SEG3 @begin
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+//SEG5 @1
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+//SEG9 @end
+//SEG10 main
+main: {
+  //SEG11 [5] call assertType 
+  //SEG12 [75] phi from main to assertType [phi:main->assertType]
+  //SEG13 [75] phi (byte) idx#79 = (byte) 0 [phi:main->assertType#0] -- vbuxx=vbuc1 
+    ldx #0
+  //SEG14 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_BYTE
+    sta assertType.t2
+  //SEG15 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_BYTE [phi:main->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG16 [6] phi from main to main::@1 [phi:main->main::@1]
+  //SEG17 main::@1
+  //SEG18 [7] call assertType 
+  //SEG19 [75] phi from main::@1 to assertType [phi:main::@1->assertType]
+  //SEG20 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@1->assertType#0] -- register_copy 
+  //SEG21 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG22 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@1->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG23 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
+  //SEG24 main::@2
+  //SEG25 [9] call assertType 
+  //SEG26 [75] phi from main::@2 to assertType [phi:main::@2->assertType]
+  //SEG27 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@2->assertType#0] -- register_copy 
+  //SEG28 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG29 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@2->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG30 [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
+  //SEG31 main::@3
+  //SEG32 [11] call assertType 
+  //SEG33 [75] phi from main::@3 to assertType [phi:main::@3->assertType]
+  //SEG34 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@3->assertType#0] -- register_copy 
+  //SEG35 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG36 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@3->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG37 [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4]
+  //SEG38 main::@4
+  //SEG39 [13] call assertType 
+  //SEG40 [75] phi from main::@4 to assertType [phi:main::@4->assertType]
+  //SEG41 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@4->assertType#0] -- register_copy 
+  //SEG42 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_WORD
+    sta assertType.t2
+  //SEG43 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_WORD [phi:main::@4->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG44 [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5]
+  //SEG45 main::@5
+  //SEG46 [15] call assertType 
+  //SEG47 [75] phi from main::@5 to assertType [phi:main::@5->assertType]
+  //SEG48 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@5->assertType#0] -- register_copy 
+  //SEG49 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG50 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@5->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG51 [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
+  //SEG52 main::@6
+  //SEG53 [17] call assertType 
+  //SEG54 [75] phi from main::@6 to assertType [phi:main::@6->assertType]
+  //SEG55 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@6->assertType#0] -- register_copy 
+  //SEG56 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG57 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@6->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG58 [18] phi from main::@6 to main::@7 [phi:main::@6->main::@7]
+  //SEG59 main::@7
+  //SEG60 [19] call assertType 
+  //SEG61 [75] phi from main::@7 to assertType [phi:main::@7->assertType]
+  //SEG62 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@7->assertType#0] -- register_copy 
+  //SEG63 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG64 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@7->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG65 [20] phi from main::@7 to main::@8 [phi:main::@7->main::@8]
+  //SEG66 main::@8
+  //SEG67 [21] call assertType 
+  //SEG68 [75] phi from main::@8 to assertType [phi:main::@8->assertType]
+  //SEG69 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@8->assertType#0] -- register_copy 
+  //SEG70 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_SIGNED_DWORD
+    sta assertType.t2
+  //SEG71 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@8->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG72 [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
+  //SEG73 main::@9
+  //SEG74 [23] call assertType 
+  //SEG75 [75] phi from main::@9 to assertType [phi:main::@9->assertType]
+  //SEG76 [75] phi (byte) idx#79 = (byte) $28 [phi:main::@9->assertType#0] -- vbuxx=vbuc1 
+    ldx #$28
+  //SEG77 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG78 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@9->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG79 [24] phi from main::@9 to main::@10 [phi:main::@9->main::@10]
+  //SEG80 main::@10
+  //SEG81 [25] call assertType 
+  //SEG82 [75] phi from main::@10 to assertType [phi:main::@10->assertType]
+  //SEG83 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@10->assertType#0] -- register_copy 
+  //SEG84 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG85 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@10->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG86 [26] phi from main::@10 to main::@11 [phi:main::@10->main::@11]
+  //SEG87 main::@11
+  //SEG88 [27] call assertType 
+  //SEG89 [75] phi from main::@11 to assertType [phi:main::@11->assertType]
+  //SEG90 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@11->assertType#0] -- register_copy 
+  //SEG91 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG92 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@11->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG93 [28] phi from main::@11 to main::@12 [phi:main::@11->main::@12]
+  //SEG94 main::@12
+  //SEG95 [29] call assertType 
+  //SEG96 [75] phi from main::@12 to assertType [phi:main::@12->assertType]
+  //SEG97 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@12->assertType#0] -- register_copy 
+  //SEG98 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG99 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@12->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG100 [30] phi from main::@12 to main::@13 [phi:main::@12->main::@13]
+  //SEG101 main::@13
+  //SEG102 [31] call assertType 
+  //SEG103 [75] phi from main::@13 to assertType [phi:main::@13->assertType]
+  //SEG104 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@13->assertType#0] -- register_copy 
+  //SEG105 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG106 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@13->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG107 [32] phi from main::@13 to main::@14 [phi:main::@13->main::@14]
+  //SEG108 main::@14
+  //SEG109 [33] call assertType 
+  //SEG110 [75] phi from main::@14 to assertType [phi:main::@14->assertType]
+  //SEG111 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@14->assertType#0] -- register_copy 
+  //SEG112 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG113 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@14->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG114 [34] phi from main::@14 to main::@15 [phi:main::@14->main::@15]
+  //SEG115 main::@15
+  //SEG116 [35] call assertType 
+  //SEG117 [75] phi from main::@15 to assertType [phi:main::@15->assertType]
+  //SEG118 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@15->assertType#0] -- register_copy 
+  //SEG119 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG120 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@15->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG121 [36] phi from main::@15 to main::@16 [phi:main::@15->main::@16]
+  //SEG122 main::@16
+  //SEG123 [37] call assertType 
+  //SEG124 [75] phi from main::@16 to assertType [phi:main::@16->assertType]
+  //SEG125 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@16->assertType#0] -- register_copy 
+  //SEG126 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG127 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@16->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG128 [38] phi from main::@16 to main::@17 [phi:main::@16->main::@17]
+  //SEG129 main::@17
+  //SEG130 [39] call assertType 
+  //SEG131 [75] phi from main::@17 to assertType [phi:main::@17->assertType]
+  //SEG132 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@17->assertType#0] -- register_copy 
+  //SEG133 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG134 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@17->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG135 [40] phi from main::@17 to main::@18 [phi:main::@17->main::@18]
+  //SEG136 main::@18
+  //SEG137 [41] call assertType 
+  //SEG138 [75] phi from main::@18 to assertType [phi:main::@18->assertType]
+  //SEG139 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@18->assertType#0] -- register_copy 
+  //SEG140 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG141 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@18->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG142 [42] phi from main::@18 to main::@19 [phi:main::@18->main::@19]
+  //SEG143 main::@19
+  //SEG144 [43] call assertType 
+  //SEG145 [75] phi from main::@19 to assertType [phi:main::@19->assertType]
+  //SEG146 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@19->assertType#0] -- register_copy 
+  //SEG147 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG148 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@19->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG149 [44] phi from main::@19 to main::@20 [phi:main::@19->main::@20]
+  //SEG150 main::@20
+  //SEG151 [45] call assertType 
+  //SEG152 [75] phi from main::@20 to assertType [phi:main::@20->assertType]
+  //SEG153 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@20->assertType#0] -- register_copy 
+  //SEG154 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG155 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@20->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG156 [46] phi from main::@20 to main::@21 [phi:main::@20->main::@21]
+  //SEG157 main::@21
+  //SEG158 [47] call assertType 
+  //SEG159 [75] phi from main::@21 to assertType [phi:main::@21->assertType]
+  //SEG160 [75] phi (byte) idx#79 = (byte) $50 [phi:main::@21->assertType#0] -- vbuxx=vbuc1 
+    ldx #$50
+  //SEG161 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG162 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@21->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG163 [48] phi from main::@21 to main::@22 [phi:main::@21->main::@22]
+  //SEG164 main::@22
+  //SEG165 [49] call assertType 
+  //SEG166 [75] phi from main::@22 to assertType [phi:main::@22->assertType]
+  //SEG167 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@22->assertType#0] -- register_copy 
+  //SEG168 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG169 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@22->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG170 [50] phi from main::@22 to main::@23 [phi:main::@22->main::@23]
+  //SEG171 main::@23
+  //SEG172 [51] call assertType 
+  //SEG173 [75] phi from main::@23 to assertType [phi:main::@23->assertType]
+  //SEG174 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@23->assertType#0] -- register_copy 
+  //SEG175 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_BYTE
+    sta assertType.t2
+  //SEG176 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_BYTE [phi:main::@23->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG177 [52] phi from main::@23 to main::@24 [phi:main::@23->main::@24]
+  //SEG178 main::@24
+  //SEG179 [53] call assertType 
+  //SEG180 [75] phi from main::@24 to assertType [phi:main::@24->assertType]
+  //SEG181 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@24->assertType#0] -- register_copy 
+  //SEG182 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG183 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@24->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG184 [54] phi from main::@24 to main::@25 [phi:main::@24->main::@25]
+  //SEG185 main::@25
+  //SEG186 [55] call assertType 
+  //SEG187 [75] phi from main::@25 to assertType [phi:main::@25->assertType]
+  //SEG188 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@25->assertType#0] -- register_copy 
+  //SEG189 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG190 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@25->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG191 [56] phi from main::@25 to main::@26 [phi:main::@25->main::@26]
+  //SEG192 main::@26
+  //SEG193 [57] call assertType 
+  //SEG194 [75] phi from main::@26 to assertType [phi:main::@26->assertType]
+  //SEG195 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@26->assertType#0] -- register_copy 
+  //SEG196 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG197 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@26->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG198 [58] phi from main::@26 to main::@27 [phi:main::@26->main::@27]
+  //SEG199 main::@27
+  //SEG200 [59] call assertType 
+  //SEG201 [75] phi from main::@27 to assertType [phi:main::@27->assertType]
+  //SEG202 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@27->assertType#0] -- register_copy 
+  //SEG203 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG204 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@27->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG205 [60] phi from main::@27 to main::@28 [phi:main::@27->main::@28]
+  //SEG206 main::@28
+  //SEG207 [61] call assertType 
+  //SEG208 [75] phi from main::@28 to assertType [phi:main::@28->assertType]
+  //SEG209 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@28->assertType#0] -- register_copy 
+  //SEG210 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG211 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@28->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG212 [62] phi from main::@28 to main::@29 [phi:main::@28->main::@29]
+  //SEG213 main::@29
+  //SEG214 [63] call assertType 
+  //SEG215 [75] phi from main::@29 to assertType [phi:main::@29->assertType]
+  //SEG216 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@29->assertType#0] -- register_copy 
+  //SEG217 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_WORD
+    sta assertType.t2
+  //SEG218 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_WORD [phi:main::@29->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG219 [64] phi from main::@29 to main::@30 [phi:main::@29->main::@30]
+  //SEG220 main::@30
+  //SEG221 [65] call assertType 
+  //SEG222 [75] phi from main::@30 to assertType [phi:main::@30->assertType]
+  //SEG223 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@30->assertType#0] -- register_copy 
+  //SEG224 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG225 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@30->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG226 [66] phi from main::@30 to main::@31 [phi:main::@30->main::@31]
+  //SEG227 main::@31
+  //SEG228 [67] call assertType 
+  //SEG229 [75] phi from main::@31 to assertType [phi:main::@31->assertType]
+  //SEG230 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@31->assertType#0] -- register_copy 
+  //SEG231 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG232 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@31->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG233 [68] phi from main::@31 to main::@32 [phi:main::@31->main::@32]
+  //SEG234 main::@32
+  //SEG235 [69] call assertType 
+  //SEG236 [75] phi from main::@32 to assertType [phi:main::@32->assertType]
+  //SEG237 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@32->assertType#0] -- register_copy 
+  //SEG238 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG239 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@32->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG240 [70] phi from main::@32 to main::@33 [phi:main::@32->main::@33]
+  //SEG241 main::@33
+  //SEG242 [71] call assertType 
+  //SEG243 [75] phi from main::@33 to assertType [phi:main::@33->assertType]
+  //SEG244 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@33->assertType#0] -- register_copy 
+  //SEG245 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG246 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_DWORD [phi:main::@33->assertType#2] -- vbuyy=vbuc1 
+    tay
+    jsr assertType
+  //SEG247 [72] phi from main::@33 to main::@34 [phi:main::@33->main::@34]
+  //SEG248 main::@34
+  //SEG249 [73] call assertType 
+  //SEG250 [75] phi from main::@34 to assertType [phi:main::@34->assertType]
+  //SEG251 [75] phi (byte) idx#79 = (byte) idx#40 [phi:main::@34->assertType#0] -- register_copy 
+  //SEG252 [75] phi (byte) assertType::t2#35 = (const byte) TYPEID_DWORD [phi:main::@34->assertType#1] -- vbuz1=vbuc1 
+    lda #TYPEID_DWORD
+    sta assertType.t2
+  //SEG253 [75] phi (byte) assertType::t1#35 = (const byte) TYPEID_SIGNED_DWORD [phi:main::@34->assertType#2] -- vbuyy=vbuc1 
+    ldy #TYPEID_SIGNED_DWORD
+    jsr assertType
+  //SEG254 main::@return
+  //SEG255 [74] return 
+    rts
+}
+//SEG256 assertType
+// Check that the two passed type IDs are equal.
+// Shows a letter symbolizing t1
+// If they are equal the letter is green - if not it is red.
+// assertType(byte register(Y) t1, byte zeropage(2) t2)
+assertType: {
+    .label t2 = 2
+  //SEG257 [76] if((byte) assertType::t1#35==(byte) assertType::t2#35) goto assertType::@1 -- vbuyy_eq_vbuz1_then_la1 
+    tya
+    cmp t2
+    beq b1
+  //SEG258 assertType::@3
+  //SEG259 [77] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) RED#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #RED
+    sta $d800,x
+  //SEG260 assertType::@2
+  b2:
+  //SEG261 [78] *((byte*)(word) $400 + (byte) idx#79) ← (byte) assertType::t1#35 -- pbuc1_derefidx_vbuxx=vbuyy 
+    tya
+    sta $400,x
+  //SEG262 [79] (byte) idx#40 ← ++ (byte) idx#79 -- vbuxx=_inc_vbuxx 
+    inx
+  //SEG263 assertType::@return
+  //SEG264 [80] return 
+    rts
+  //SEG265 assertType::@1
+  b1:
+  //SEG266 [81] *((byte*)(word) $d800 + (byte) idx#79) ← (const byte) GREEN#0 -- pbuc1_derefidx_vbuxx=vbuc2 
+    lda #GREEN
+    sta $d800,x
+    jmp b2
+}
+
diff --git a/src/test/ref/number-conversion.sym b/src/test/ref/number-conversion.sym
new file mode 100644
index 000000000..78d7bc585
--- /dev/null
+++ b/src/test/ref/number-conversion.sym
@@ -0,0 +1,67 @@
+(label) @1
+(label) @begin
+(label) @end
+(byte*) COLS
+(byte) GREEN
+(const byte) GREEN#0 GREEN = (byte) 5
+(byte) RED
+(const byte) RED#0 RED = (byte) 2
+(byte*) SCREEN
+(const byte) TYPEID_BYTE TYPEID_BYTE = (number) 1
+(const byte) TYPEID_DWORD TYPEID_DWORD = (number) 5
+(const byte) TYPEID_SIGNED_BYTE TYPEID_SIGNED_BYTE = (number) 2
+(const byte) TYPEID_SIGNED_DWORD TYPEID_SIGNED_DWORD = (number) 6
+(const byte) TYPEID_SIGNED_WORD TYPEID_SIGNED_WORD = (number) 4
+(const byte) TYPEID_WORD TYPEID_WORD = (number) 3
+(void()) assertType((byte) assertType::t1 , (byte) assertType::t2)
+(label) assertType::@1
+(label) assertType::@2
+(label) assertType::@3
+(label) assertType::@return
+(byte) assertType::t1
+(byte) assertType::t1#35 reg byte y 1.0
+(byte) assertType::t2
+(byte) assertType::t2#35 t2 zp ZP_BYTE:2 2.0
+(byte) idx
+(byte) idx#40 reg byte x 0.9999999999999993
+(byte) idx#79 reg byte x 14.400000000000007
+(void()) main()
+(label) main::@1
+(label) main::@10
+(label) main::@11
+(label) main::@12
+(label) main::@13
+(label) main::@14
+(label) main::@15
+(label) main::@16
+(label) main::@17
+(label) main::@18
+(label) main::@19
+(label) main::@2
+(label) main::@20
+(label) main::@21
+(label) main::@22
+(label) main::@23
+(label) main::@24
+(label) main::@25
+(label) main::@26
+(label) main::@27
+(label) main::@28
+(label) main::@29
+(label) main::@3
+(label) main::@30
+(label) main::@31
+(label) main::@32
+(label) main::@33
+(label) main::@34
+(label) main::@4
+(label) main::@5
+(label) main::@6
+(label) main::@7
+(label) main::@8
+(label) main::@9
+(label) main::@return
+
+reg byte y [ assertType::t1#35 ]
+zp ZP_BYTE:2 [ assertType::t2#35 ]
+reg byte x [ idx#79 idx#40 ]
diff --git a/src/test/ref/number-type.asm b/src/test/ref/number-type.asm
new file mode 100644
index 000000000..8944e6dbf
--- /dev/null
+++ b/src/test/ref/number-type.asm
@@ -0,0 +1,69 @@
+// Tests the number type used for constant expressions
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    jsr testBytes
+    jsr testSBytes
+    rts
+}
+testSBytes: {
+    // Constant values resolvable to signed bytes
+    .label SCREEN = $428
+    lda #-$c
+    sta SCREEN
+    lda #-6-6
+    sta SCREEN+1
+    lda #-$12+6
+    sta SCREEN+2
+    lda #-$714+$708
+    sta SCREEN+3
+    lda #-1-2-3-6
+    sta SCREEN+4
+    lda #-2*6
+    sta SCREEN+5
+    lda #-3<<2
+    sta SCREEN+6
+    lda #-$18>>1
+    sta SCREEN+7
+    lda #-4&-9
+    sta SCREEN+8
+    lda #-$10|-$fc
+    sta SCREEN+9
+    lda #(-2-2)*$f/5
+    sta SCREEN+$a
+    lda #$ff&$1000-$c
+    sta SCREEN+$b
+    rts
+}
+testBytes: {
+    // Constant values resolvable to bytes
+    .label SCREEN = $400
+    lda #$c
+    sta SCREEN
+    lda #6+6
+    sta SCREEN+1
+    lda #$12-6
+    sta SCREEN+2
+    lda #$714-$708
+    sta SCREEN+3
+    lda #1+2+3+6
+    sta SCREEN+4
+    lda #2*6
+    sta SCREEN+5
+    lda #3<<2
+    sta SCREEN+6
+    lda #$18>>1
+    sta SCREEN+7
+    lda #$f&$1c
+    sta SCREEN+8
+    lda #4|8
+    sta SCREEN+9
+    lda #5^9
+    sta SCREEN+$a
+    lda #(2+2)*$f/5
+    sta SCREEN+$b
+    lda #$ff&$1000+$c
+    sta SCREEN+$c
+    rts
+}
diff --git a/src/test/ref/number-type.cfg b/src/test/ref/number-type.cfg
new file mode 100644
index 000000000..11a77d0ae
--- /dev/null
+++ b/src/test/ref/number-type.cfg
@@ -0,0 +1,55 @@
+@begin: scope:[]  from
+  [0] phi()
+  to:@1
+@1: scope:[]  from @begin
+  [1] phi()
+  [2] call main 
+  to:@end
+@end: scope:[]  from @1
+  [3] phi()
+main: scope:[main]  from @1
+  [4] phi()
+  [5] call testBytes 
+  to:main::@1
+main::@1: scope:[main]  from main
+  [6] phi()
+  [7] call testSBytes 
+  to:main::@return
+main::@return: scope:[main]  from main::@1
+  [8] return 
+  to:@return
+testSBytes: scope:[testSBytes]  from main::@1
+  [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c
+  [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6
+  [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6
+  [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708
+  [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6
+  [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6
+  [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2
+  [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1
+  [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9
+  [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc
+  [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5
+  [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c
+  to:testSBytes::@return
+testSBytes::@return: scope:[testSBytes]  from testSBytes
+  [21] return 
+  to:@return
+testBytes: scope:[testBytes]  from main
+  [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c
+  [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6
+  [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6
+  [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708
+  [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6
+  [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6
+  [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2
+  [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1
+  [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c
+  [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8
+  [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9
+  [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5
+  [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c
+  to:testBytes::@return
+testBytes::@return: scope:[testBytes]  from testBytes
+  [35] return 
+  to:@return
diff --git a/src/test/ref/number-type.log b/src/test/ref/number-type.log
new file mode 100644
index 000000000..55a8e6375
--- /dev/null
+++ b/src/test/ref/number-type.log
@@ -0,0 +1,1204 @@
+Adding pointer type conversion cast (byte*) testBytes::SCREEN in (byte*) testBytes::SCREEN ← (number) $400
+Adding pointer type conversion cast (signed byte*) testSBytes::SCREEN in (signed byte*) testSBytes::SCREEN ← (number) $428
+
+CONTROL FLOW GRAPH SSA
+@begin: scope:[]  from
+  to:@3
+main: scope:[main]  from @3
+  call testBytes 
+  to:main::@1
+main::@1: scope:[main]  from main
+  call testSBytes 
+  to:main::@2
+main::@2: scope:[main]  from main::@1
+  to:main::@return
+main::@return: scope:[main]  from main::@2
+  return 
+  to:@return
+testBytes: scope:[testBytes]  from main
+  (number) testBytes::$17 ← (number) $400
+  (byte*) testBytes::SCREEN#0 ← ((byte*)) (number) testBytes::$17
+  (byte) testBytes::idx#0 ← (number) 0
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#0) ← (number) $c
+  (byte) testBytes::idx#1 ← ++ (byte) testBytes::idx#0
+  (number~) testBytes::$0 ← (number) 6 + (number) 6
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#1) ← (number~) testBytes::$0
+  (byte) testBytes::idx#2 ← ++ (byte) testBytes::idx#1
+  (number~) testBytes::$1 ← (number) $12 - (number) 6
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#2) ← (number~) testBytes::$1
+  (byte) testBytes::idx#3 ← ++ (byte) testBytes::idx#2
+  (number~) testBytes::$2 ← (number) $714 - (number) $708
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#3) ← (number~) testBytes::$2
+  (byte) testBytes::idx#4 ← ++ (byte) testBytes::idx#3
+  (number~) testBytes::$3 ← (number) 1 + (number) 2
+  (number~) testBytes::$4 ← (number~) testBytes::$3 + (number) 3
+  (number~) testBytes::$5 ← (number~) testBytes::$4 + (number) 6
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#4) ← (number~) testBytes::$5
+  (byte) testBytes::idx#5 ← ++ (byte) testBytes::idx#4
+  (number~) testBytes::$6 ← (number) 2 * (number) 6
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#5) ← (number~) testBytes::$6
+  (byte) testBytes::idx#6 ← ++ (byte) testBytes::idx#5
+  (number~) testBytes::$7 ← (number) 3 << (number) 2
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#6) ← (number~) testBytes::$7
+  (byte) testBytes::idx#7 ← ++ (byte) testBytes::idx#6
+  (number~) testBytes::$8 ← (number) $18 >> (number) 1
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#7) ← (number~) testBytes::$8
+  (byte) testBytes::idx#8 ← ++ (byte) testBytes::idx#7
+  (number~) testBytes::$9 ← (number) $f & (number) $1c
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#8) ← (number~) testBytes::$9
+  (byte) testBytes::idx#9 ← ++ (byte) testBytes::idx#8
+  (number~) testBytes::$10 ← (number) 4 | (number) 8
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#9) ← (number~) testBytes::$10
+  (byte) testBytes::idx#10 ← ++ (byte) testBytes::idx#9
+  (number~) testBytes::$11 ← (number) 5 ^ (number) 9
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#10) ← (number~) testBytes::$11
+  (byte) testBytes::idx#11 ← ++ (byte) testBytes::idx#10
+  (number~) testBytes::$12 ← (number) 2 + (number) 2
+  (number~) testBytes::$13 ← (number) $f / (number) 5
+  (number~) testBytes::$14 ← (number~) testBytes::$12 * (number~) testBytes::$13
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#11) ← (number~) testBytes::$14
+  (byte) testBytes::idx#12 ← ++ (byte) testBytes::idx#11
+  (number~) testBytes::$15 ← (number) $1000 + (number) $c
+  (byte~) testBytes::$16 ← ((byte)) (number~) testBytes::$15
+  *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#12) ← (byte~) testBytes::$16
+  (byte) testBytes::idx#13 ← ++ (byte) testBytes::idx#12
+  to:testBytes::@return
+testBytes::@return: scope:[testBytes]  from testBytes
+  return 
+  to:@return
+testSBytes: scope:[testSBytes]  from main::@1
+  (number) testSBytes::$29 ← (number) $428
+  (signed byte*) testSBytes::SCREEN#0 ← ((signed byte*)) (number) testSBytes::$29
+  (byte) testSBytes::idx#0 ← (number) 0
+  (number~) testSBytes::$0 ← - (number) $c
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#0) ← (number~) testSBytes::$0
+  (byte) testSBytes::idx#1 ← ++ (byte) testSBytes::idx#0
+  (number~) testSBytes::$1 ← - (number) 6
+  (number~) testSBytes::$2 ← (number~) testSBytes::$1 - (number) 6
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#1) ← (number~) testSBytes::$2
+  (byte) testSBytes::idx#2 ← ++ (byte) testSBytes::idx#1
+  (number~) testSBytes::$3 ← - (number) $12
+  (number~) testSBytes::$4 ← (number~) testSBytes::$3 + (number) 6
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#2) ← (number~) testSBytes::$4
+  (byte) testSBytes::idx#3 ← ++ (byte) testSBytes::idx#2
+  (number~) testSBytes::$5 ← - (number) $714
+  (number~) testSBytes::$6 ← (number~) testSBytes::$5 + (number) $708
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#3) ← (number~) testSBytes::$6
+  (byte) testSBytes::idx#4 ← ++ (byte) testSBytes::idx#3
+  (number~) testSBytes::$7 ← - (number) 1
+  (number~) testSBytes::$8 ← (number~) testSBytes::$7 - (number) 2
+  (number~) testSBytes::$9 ← (number~) testSBytes::$8 - (number) 3
+  (number~) testSBytes::$10 ← (number~) testSBytes::$9 - (number) 6
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#4) ← (number~) testSBytes::$10
+  (byte) testSBytes::idx#5 ← ++ (byte) testSBytes::idx#4
+  (number~) testSBytes::$11 ← - (number) 2
+  (number~) testSBytes::$12 ← (number~) testSBytes::$11 * (number) 6
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#5) ← (number~) testSBytes::$12
+  (byte) testSBytes::idx#6 ← ++ (byte) testSBytes::idx#5
+  (number~) testSBytes::$13 ← - (number) 3
+  (number~) testSBytes::$14 ← (number~) testSBytes::$13 << (number) 2
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#6) ← (number~) testSBytes::$14
+  (byte) testSBytes::idx#7 ← ++ (byte) testSBytes::idx#6
+  (number~) testSBytes::$15 ← - (number) $18
+  (number~) testSBytes::$16 ← (number~) testSBytes::$15 >> (number) 1
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#7) ← (number~) testSBytes::$16
+  (byte) testSBytes::idx#8 ← ++ (byte) testSBytes::idx#7
+  (number~) testSBytes::$17 ← - (number) 4
+  (number~) testSBytes::$18 ← - (number) 9
+  (number~) testSBytes::$19 ← (number~) testSBytes::$17 & (number~) testSBytes::$18
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#8) ← (number~) testSBytes::$19
+  (byte) testSBytes::idx#9 ← ++ (byte) testSBytes::idx#8
+  (number~) testSBytes::$20 ← - (number) $10
+  (number~) testSBytes::$21 ← - (number) $fc
+  (number~) testSBytes::$22 ← (number~) testSBytes::$20 | (number~) testSBytes::$21
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#9) ← (number~) testSBytes::$22
+  (byte) testSBytes::idx#10 ← ++ (byte) testSBytes::idx#9
+  (number~) testSBytes::$23 ← - (number) 2
+  (number~) testSBytes::$24 ← (number~) testSBytes::$23 - (number) 2
+  (number~) testSBytes::$25 ← (number) $f / (number) 5
+  (number~) testSBytes::$26 ← (number~) testSBytes::$24 * (number~) testSBytes::$25
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#10) ← (number~) testSBytes::$26
+  (byte) testSBytes::idx#11 ← ++ (byte) testSBytes::idx#10
+  (number~) testSBytes::$27 ← (number) $1000 - (number) $c
+  (signed byte~) testSBytes::$28 ← ((signed byte)) (number~) testSBytes::$27
+  *((signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#11) ← (signed byte~) testSBytes::$28
+  (byte) testSBytes::idx#12 ← ++ (byte) testSBytes::idx#11
+  to:testSBytes::@return
+testSBytes::@return: scope:[testSBytes]  from testSBytes
+  return 
+  to:@return
+@3: scope:[]  from @begin
+  call main 
+  to:@4
+@4: scope:[]  from @3
+  to:@end
+@end: scope:[]  from @4
+
+SYMBOL TABLE SSA
+(label) @3
+(label) @4
+(label) @begin
+(label) @end
+(void()) main()
+(label) main::@1
+(label) main::@2
+(label) main::@return
+(void()) testBytes()
+(number~) testBytes::$0
+(number~) testBytes::$1
+(number~) testBytes::$10
+(number~) testBytes::$11
+(number~) testBytes::$12
+(number~) testBytes::$13
+(number~) testBytes::$14
+(number~) testBytes::$15
+(byte~) testBytes::$16
+(number) testBytes::$17
+(number~) testBytes::$2
+(number~) testBytes::$3
+(number~) testBytes::$4
+(number~) testBytes::$5
+(number~) testBytes::$6
+(number~) testBytes::$7
+(number~) testBytes::$8
+(number~) testBytes::$9
+(label) testBytes::@return
+(byte*) testBytes::SCREEN
+(byte*) testBytes::SCREEN#0
+(byte) testBytes::idx
+(byte) testBytes::idx#0
+(byte) testBytes::idx#1
+(byte) testBytes::idx#10
+(byte) testBytes::idx#11
+(byte) testBytes::idx#12
+(byte) testBytes::idx#13
+(byte) testBytes::idx#2
+(byte) testBytes::idx#3
+(byte) testBytes::idx#4
+(byte) testBytes::idx#5
+(byte) testBytes::idx#6
+(byte) testBytes::idx#7
+(byte) testBytes::idx#8
+(byte) testBytes::idx#9
+(void()) testSBytes()
+(number~) testSBytes::$0
+(number~) testSBytes::$1
+(number~) testSBytes::$10
+(number~) testSBytes::$11
+(number~) testSBytes::$12
+(number~) testSBytes::$13
+(number~) testSBytes::$14
+(number~) testSBytes::$15
+(number~) testSBytes::$16
+(number~) testSBytes::$17
+(number~) testSBytes::$18
+(number~) testSBytes::$19
+(number~) testSBytes::$2
+(number~) testSBytes::$20
+(number~) testSBytes::$21
+(number~) testSBytes::$22
+(number~) testSBytes::$23
+(number~) testSBytes::$24
+(number~) testSBytes::$25
+(number~) testSBytes::$26
+(number~) testSBytes::$27
+(signed byte~) testSBytes::$28
+(number) testSBytes::$29
+(number~) testSBytes::$3
+(number~) testSBytes::$4
+(number~) testSBytes::$5
+(number~) testSBytes::$6
+(number~) testSBytes::$7
+(number~) testSBytes::$8
+(number~) testSBytes::$9
+(label) testSBytes::@return
+(signed byte*) testSBytes::SCREEN
+(signed byte*) testSBytes::SCREEN#0
+(byte) testSBytes::idx
+(byte) testSBytes::idx#0
+(byte) testSBytes::idx#1
+(byte) testSBytes::idx#10
+(byte) testSBytes::idx#11
+(byte) testSBytes::idx#12
+(byte) testSBytes::idx#2
+(byte) testSBytes::idx#3
+(byte) testSBytes::idx#4
+(byte) testSBytes::idx#5
+(byte) testSBytes::idx#6
+(byte) testSBytes::idx#7
+(byte) testSBytes::idx#8
+(byte) testSBytes::idx#9
+
+Adding number conversion cast (byte) 0 in (byte) testBytes::idx#0 ← (number) 0
+Adding number conversion cast (byte) $c in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#0) ← (number) $c
+Adding number conversion cast (byte) 0 in (byte) testSBytes::idx#0 ← (number) 0
+Culled Empty Block (label) main::@2
+Culled Empty Block (label) @4
+Successful SSA optimization Pass2CullEmptyBlocks
+Constant right-side identified [5] (byte) testBytes::idx#0 ← ((byte)) (number) 0
+Constant right-side identified [6] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#0) ← ((byte)) (number) $c
+Constant right-side identified [8] (number~) testBytes::$0 ← (number) 6 + (number) 6
+Constant right-side identified [11] (number~) testBytes::$1 ← (number) $12 - (number) 6
+Constant right-side identified [14] (number~) testBytes::$2 ← (number) $714 - (number) $708
+Constant right-side identified [17] (number~) testBytes::$3 ← (number) 1 + (number) 2
+Constant right-side identified [22] (number~) testBytes::$6 ← (number) 2 * (number) 6
+Constant right-side identified [25] (number~) testBytes::$7 ← (number) 3 << (number) 2
+Constant right-side identified [28] (number~) testBytes::$8 ← (number) $18 >> (number) 1
+Constant right-side identified [31] (number~) testBytes::$9 ← (number) $f & (number) $1c
+Constant right-side identified [34] (number~) testBytes::$10 ← (number) 4 | (number) 8
+Constant right-side identified [37] (number~) testBytes::$11 ← (number) 5 ^ (number) 9
+Constant right-side identified [40] (number~) testBytes::$12 ← (number) 2 + (number) 2
+Constant right-side identified [41] (number~) testBytes::$13 ← (number) $f / (number) 5
+Constant right-side identified [45] (number~) testBytes::$15 ← (number) $1000 + (number) $c
+Constant right-side identified [52] (byte) testSBytes::idx#0 ← ((byte)) (number) 0
+Constant right-side identified [53] (number~) testSBytes::$0 ← - (number) $c
+Constant right-side identified [56] (number~) testSBytes::$1 ← - (number) 6
+Constant right-side identified [60] (number~) testSBytes::$3 ← - (number) $12
+Constant right-side identified [64] (number~) testSBytes::$5 ← - (number) $714
+Constant right-side identified [68] (number~) testSBytes::$7 ← - (number) 1
+Constant right-side identified [74] (number~) testSBytes::$11 ← - (number) 2
+Constant right-side identified [78] (number~) testSBytes::$13 ← - (number) 3
+Constant right-side identified [82] (number~) testSBytes::$15 ← - (number) $18
+Constant right-side identified [86] (number~) testSBytes::$17 ← - (number) 4
+Constant right-side identified [87] (number~) testSBytes::$18 ← - (number) 9
+Constant right-side identified [91] (number~) testSBytes::$20 ← - (number) $10
+Constant right-side identified [92] (number~) testSBytes::$21 ← - (number) $fc
+Constant right-side identified [96] (number~) testSBytes::$23 ← - (number) 2
+Constant right-side identified [98] (number~) testSBytes::$25 ← (number) $f / (number) 5
+Constant right-side identified [102] (number~) testSBytes::$27 ← (number) $1000 - (number) $c
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const number) testBytes::$17 = $400
+Constant (const byte) testBytes::idx#0 = ((byte))0
+Constant (const number) testBytes::$0 = 6+6
+Constant (const number) testBytes::$1 = $12-6
+Constant (const number) testBytes::$2 = $714-$708
+Constant (const number) testBytes::$3 = 1+2
+Constant (const number) testBytes::$6 = 2*6
+Constant (const number) testBytes::$7 = 3<<2
+Constant (const number) testBytes::$8 = $18>>1
+Constant (const number) testBytes::$9 = $f&$1c
+Constant (const number) testBytes::$10 = 4|8
+Constant (const number) testBytes::$11 = 5^9
+Constant (const number) testBytes::$12 = 2+2
+Constant (const number) testBytes::$13 = $f/5
+Constant (const number) testBytes::$15 = $1000+$c
+Constant (const number) testSBytes::$29 = $428
+Constant (const byte) testSBytes::idx#0 = ((byte))0
+Constant (const number) testSBytes::$0 = -$c
+Constant (const number) testSBytes::$1 = -6
+Constant (const number) testSBytes::$3 = -$12
+Constant (const number) testSBytes::$5 = -$714
+Constant (const number) testSBytes::$7 = -1
+Constant (const number) testSBytes::$11 = -2
+Constant (const number) testSBytes::$13 = -3
+Constant (const number) testSBytes::$15 = -$18
+Constant (const number) testSBytes::$17 = -4
+Constant (const number) testSBytes::$18 = -9
+Constant (const number) testSBytes::$20 = -$10
+Constant (const number) testSBytes::$21 = -$fc
+Constant (const number) testSBytes::$23 = -2
+Constant (const number) testSBytes::$25 = $f/5
+Constant (const number) testSBytes::$27 = $1000-$c
+Successful SSA optimization Pass2ConstantIdentification
+Eliminating unused variable (byte) testBytes::idx#13 and assignment [33] (byte) testBytes::idx#13 ← ++ (byte) testBytes::idx#12
+Eliminating unused variable (byte) testSBytes::idx#12 and assignment [73] (byte) testSBytes::idx#12 ← ++ (byte) testSBytes::idx#11
+Successful SSA optimization PassNEliminateUnusedVars
+Simplifying constant integer cast $c
+Adding number conversion cast (byte) testBytes::$0 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#1) ← (const number) testBytes::$0
+Adding number conversion cast (byte) testBytes::$1 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#2) ← (const number) testBytes::$1
+Adding number conversion cast (byte) testBytes::$2 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#3) ← (const number) testBytes::$2
+Adding number conversion cast (byte) testBytes::$6 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#5) ← (const number) testBytes::$6
+Adding number conversion cast (byte) testBytes::$7 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#6) ← (const number) testBytes::$7
+Adding number conversion cast (byte) testBytes::$8 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#7) ← (const number) testBytes::$8
+Adding number conversion cast (byte) testBytes::$9 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#8) ← (const number) testBytes::$9
+Adding number conversion cast (byte) testBytes::$10 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#9) ← (const number) testBytes::$10
+Adding number conversion cast (byte) testBytes::$11 in *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#10) ← (const number) testBytes::$11
+Adding number conversion cast (signed byte) testSBytes::$0 in *((signed byte*) testSBytes::SCREEN#0 + (const byte) testSBytes::idx#0) ← (const number) testSBytes::$0
+Constant right-side identified [3] (byte*) testBytes::SCREEN#0 ← ((byte*)) (const number) testBytes::$17
+Constant right-side identified [5] (byte) testBytes::idx#1 ← ++ (const byte) testBytes::idx#0
+Constant right-side identified [6] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#1) ← ((byte)) (const number) testBytes::$0
+Constant right-side identified [8] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#2) ← ((byte)) (const number) testBytes::$1
+Constant right-side identified [10] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#3) ← ((byte)) (const number) testBytes::$2
+Constant right-side identified [12] (number~) testBytes::$4 ← (const number) testBytes::$3 + (number) 3
+Constant right-side identified [16] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#5) ← ((byte)) (const number) testBytes::$6
+Constant right-side identified [18] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#6) ← ((byte)) (const number) testBytes::$7
+Constant right-side identified [20] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#7) ← ((byte)) (const number) testBytes::$8
+Constant right-side identified [22] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#8) ← ((byte)) (const number) testBytes::$9
+Constant right-side identified [24] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#9) ← ((byte)) (const number) testBytes::$10
+Constant right-side identified [26] *((byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#10) ← ((byte)) (const number) testBytes::$11
+Constant right-side identified [28] (number~) testBytes::$14 ← (const number) testBytes::$12 * (const number) testBytes::$13
+Constant right-side identified [31] (byte~) testBytes::$16 ← ((byte)) (const number) testBytes::$15
+Constant right-side identified [34] (signed byte*) testSBytes::SCREEN#0 ← ((signed byte*)) (const number) testSBytes::$29
+Constant right-side identified [35] *((signed byte*) testSBytes::SCREEN#0 + (const byte) testSBytes::idx#0) ← ((signed byte)) (const number) testSBytes::$0
+Constant right-side identified [36] (byte) testSBytes::idx#1 ← ++ (const byte) testSBytes::idx#0
+Constant right-side identified [37] (number~) testSBytes::$2 ← (const number) testSBytes::$1 - (number) 6
+Constant right-side identified [40] (number~) testSBytes::$4 ← (const number) testSBytes::$3 + (number) 6
+Constant right-side identified [43] (number~) testSBytes::$6 ← (const number) testSBytes::$5 + (number) $708
+Constant right-side identified [46] (number~) testSBytes::$8 ← (const number) testSBytes::$7 - (number) 2
+Constant right-side identified [51] (number~) testSBytes::$12 ← (const number) testSBytes::$11 * (number) 6
+Constant right-side identified [54] (number~) testSBytes::$14 ← (const number) testSBytes::$13 << (number) 2
+Constant right-side identified [57] (number~) testSBytes::$16 ← (const number) testSBytes::$15 >> (number) 1
+Constant right-side identified [60] (number~) testSBytes::$19 ← (const number) testSBytes::$17 & (const number) testSBytes::$18
+Constant right-side identified [63] (number~) testSBytes::$22 ← (const number) testSBytes::$20 | (const number) testSBytes::$21
+Constant right-side identified [66] (number~) testSBytes::$24 ← (const number) testSBytes::$23 - (number) 2
+Constant right-side identified [70] (signed byte~) testSBytes::$28 ← ((signed byte)) (const number) testSBytes::$27
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte*) testBytes::SCREEN#0 = ((byte*))testBytes::$17
+Constant (const byte) testBytes::idx#1 = ++testBytes::idx#0
+Constant (const number) testBytes::$4 = testBytes::$3+3
+Constant (const number) testBytes::$14 = testBytes::$12*testBytes::$13
+Constant (const byte) testBytes::$16 = ((byte))testBytes::$15
+Constant (const signed byte*) testSBytes::SCREEN#0 = ((signed byte*))testSBytes::$29
+Constant (const byte) testSBytes::idx#1 = ++testSBytes::idx#0
+Constant (const number) testSBytes::$2 = testSBytes::$1-6
+Constant (const number) testSBytes::$4 = testSBytes::$3+6
+Constant (const number) testSBytes::$6 = testSBytes::$5+$708
+Constant (const number) testSBytes::$8 = testSBytes::$7-2
+Constant (const number) testSBytes::$12 = testSBytes::$11*6
+Constant (const number) testSBytes::$14 = testSBytes::$13<<2
+Constant (const number) testSBytes::$16 = testSBytes::$15>>1
+Constant (const number) testSBytes::$19 = testSBytes::$17&testSBytes::$18
+Constant (const number) testSBytes::$22 = testSBytes::$20|testSBytes::$21
+Constant (const number) testSBytes::$24 = testSBytes::$23-2
+Constant (const signed byte) testSBytes::$28 = ((signed byte))testSBytes::$27
+Successful SSA optimization Pass2ConstantIdentification
+Adding number conversion cast (byte) testBytes::$14 in *((const byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#11) ← (const number) testBytes::$14
+Adding number conversion cast (signed byte) testSBytes::$2 in *((const signed byte*) testSBytes::SCREEN#0 + (const byte) testSBytes::idx#1) ← (const number) testSBytes::$2
+Adding number conversion cast (signed byte) testSBytes::$4 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#2) ← (const number) testSBytes::$4
+Adding number conversion cast (signed byte) testSBytes::$6 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#3) ← (const number) testSBytes::$6
+Adding number conversion cast (signed byte) testSBytes::$12 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#5) ← (const number) testSBytes::$12
+Adding number conversion cast (signed byte) testSBytes::$14 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#6) ← (const number) testSBytes::$14
+Adding number conversion cast (signed byte) testSBytes::$16 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#7) ← (const number) testSBytes::$16
+Adding number conversion cast (signed byte) testSBytes::$19 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#8) ← (const number) testSBytes::$19
+Adding number conversion cast (signed byte) testSBytes::$22 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#9) ← (const number) testSBytes::$22
+Constant right-side identified [5] (byte) testBytes::idx#2 ← ++ (const byte) testBytes::idx#1
+Constant right-side identified [10] (number~) testBytes::$5 ← (const number) testBytes::$4 + (number) 6
+Constant right-side identified [25] *((const byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#11) ← ((byte)) (const number) testBytes::$14
+Constant right-side identified [30] *((const signed byte*) testSBytes::SCREEN#0 + (const byte) testSBytes::idx#1) ← ((signed byte)) (const number) testSBytes::$2
+Constant right-side identified [31] (byte) testSBytes::idx#2 ← ++ (const byte) testSBytes::idx#1
+Constant right-side identified [32] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#2) ← ((signed byte)) (const number) testSBytes::$4
+Constant right-side identified [34] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#3) ← ((signed byte)) (const number) testSBytes::$6
+Constant right-side identified [36] (number~) testSBytes::$9 ← (const number) testSBytes::$8 - (number) 3
+Constant right-side identified [40] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#5) ← ((signed byte)) (const number) testSBytes::$12
+Constant right-side identified [42] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#6) ← ((signed byte)) (const number) testSBytes::$14
+Constant right-side identified [44] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#7) ← ((signed byte)) (const number) testSBytes::$16
+Constant right-side identified [46] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#8) ← ((signed byte)) (const number) testSBytes::$19
+Constant right-side identified [48] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#9) ← ((signed byte)) (const number) testSBytes::$22
+Constant right-side identified [50] (number~) testSBytes::$26 ← (const number) testSBytes::$24 * (const number) testSBytes::$25
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#2 = ++testBytes::idx#1
+Constant (const number) testBytes::$5 = testBytes::$4+6
+Constant (const byte) testSBytes::idx#2 = ++testSBytes::idx#1
+Constant (const number) testSBytes::$9 = testSBytes::$8-3
+Constant (const number) testSBytes::$26 = testSBytes::$24*testSBytes::$25
+Successful SSA optimization Pass2ConstantIdentification
+Adding number conversion cast (byte) testBytes::$5 in *((const byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#4) ← (const number) testBytes::$5
+Adding number conversion cast (signed byte) testSBytes::$26 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#10) ← (const number) testSBytes::$26
+Constant right-side identified [6] (byte) testBytes::idx#3 ← ++ (const byte) testBytes::idx#2
+Constant right-side identified [9] *((const byte*) testBytes::SCREEN#0 + (byte) testBytes::idx#4) ← ((byte)) (const number) testBytes::$5
+Constant right-side identified [30] (byte) testSBytes::idx#3 ← ++ (const byte) testSBytes::idx#2
+Constant right-side identified [33] (number~) testSBytes::$10 ← (const number) testSBytes::$9 - (number) 6
+Constant right-side identified [46] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#10) ← ((signed byte)) (const number) testSBytes::$26
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#3 = ++testBytes::idx#2
+Constant (const byte) testSBytes::idx#3 = ++testSBytes::idx#2
+Constant (const number) testSBytes::$10 = testSBytes::$9-6
+Successful SSA optimization Pass2ConstantIdentification
+Adding number conversion cast (signed byte) testSBytes::$10 in *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#4) ← (const number) testSBytes::$10
+Constant right-side identified [7] (byte) testBytes::idx#4 ← ++ (const byte) testBytes::idx#3
+Constant right-side identified [30] (byte) testSBytes::idx#4 ← ++ (const byte) testSBytes::idx#3
+Constant right-side identified [31] *((const signed byte*) testSBytes::SCREEN#0 + (byte) testSBytes::idx#4) ← ((signed byte)) (const number) testSBytes::$10
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#4 = ++testBytes::idx#3
+Constant (const byte) testSBytes::idx#4 = ++testSBytes::idx#3
+Successful SSA optimization Pass2ConstantIdentification
+Constant right-side identified [8] (byte) testBytes::idx#5 ← ++ (const byte) testBytes::idx#4
+Constant right-side identified [30] (byte) testSBytes::idx#5 ← ++ (const byte) testSBytes::idx#4
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#5 = ++testBytes::idx#4
+Constant (const byte) testSBytes::idx#5 = ++testSBytes::idx#4
+Successful SSA optimization Pass2ConstantIdentification
+Constant right-side identified [9] (byte) testBytes::idx#6 ← ++ (const byte) testBytes::idx#5
+Constant right-side identified [30] (byte) testSBytes::idx#6 ← ++ (const byte) testSBytes::idx#5
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#6 = ++testBytes::idx#5
+Constant (const byte) testSBytes::idx#6 = ++testSBytes::idx#5
+Successful SSA optimization Pass2ConstantIdentification
+Constant right-side identified [10] (byte) testBytes::idx#7 ← ++ (const byte) testBytes::idx#6
+Constant right-side identified [30] (byte) testSBytes::idx#7 ← ++ (const byte) testSBytes::idx#6
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#7 = ++testBytes::idx#6
+Constant (const byte) testSBytes::idx#7 = ++testSBytes::idx#6
+Successful SSA optimization Pass2ConstantIdentification
+Constant right-side identified [11] (byte) testBytes::idx#8 ← ++ (const byte) testBytes::idx#7
+Constant right-side identified [30] (byte) testSBytes::idx#8 ← ++ (const byte) testSBytes::idx#7
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#8 = ++testBytes::idx#7
+Constant (const byte) testSBytes::idx#8 = ++testSBytes::idx#7
+Successful SSA optimization Pass2ConstantIdentification
+Constant right-side identified [12] (byte) testBytes::idx#9 ← ++ (const byte) testBytes::idx#8
+Constant right-side identified [30] (byte) testSBytes::idx#9 ← ++ (const byte) testSBytes::idx#8
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#9 = ++testBytes::idx#8
+Constant (const byte) testSBytes::idx#9 = ++testSBytes::idx#8
+Successful SSA optimization Pass2ConstantIdentification
+Constant right-side identified [13] (byte) testBytes::idx#10 ← ++ (const byte) testBytes::idx#9
+Constant right-side identified [30] (byte) testSBytes::idx#10 ← ++ (const byte) testSBytes::idx#9
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#10 = ++testBytes::idx#9
+Constant (const byte) testSBytes::idx#10 = ++testSBytes::idx#9
+Successful SSA optimization Pass2ConstantIdentification
+Constant right-side identified [14] (byte) testBytes::idx#11 ← ++ (const byte) testBytes::idx#10
+Constant right-side identified [30] (byte) testSBytes::idx#11 ← ++ (const byte) testSBytes::idx#10
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#11 = ++testBytes::idx#10
+Constant (const byte) testSBytes::idx#11 = ++testSBytes::idx#10
+Successful SSA optimization Pass2ConstantIdentification
+Constant right-side identified [15] (byte) testBytes::idx#12 ← ++ (const byte) testBytes::idx#11
+Successful SSA optimization Pass2ConstantRValueConsolidation
+Constant (const byte) testBytes::idx#12 = ++testBytes::idx#11
+Successful SSA optimization Pass2ConstantIdentification
+Inlining constant with different constant siblings (const byte) testBytes::idx#0
+Inlining constant with different constant siblings (const byte) testBytes::idx#1
+Inlining constant with different constant siblings (const byte) testBytes::idx#2
+Inlining constant with different constant siblings (const byte) testBytes::idx#3
+Inlining constant with different constant siblings (const byte) testBytes::idx#4
+Inlining constant with different constant siblings (const byte) testBytes::idx#5
+Inlining constant with different constant siblings (const byte) testBytes::idx#6
+Inlining constant with different constant siblings (const byte) testBytes::idx#7
+Inlining constant with different constant siblings (const byte) testBytes::idx#8
+Inlining constant with different constant siblings (const byte) testBytes::idx#9
+Inlining constant with different constant siblings (const byte) testBytes::idx#10
+Inlining constant with different constant siblings (const byte) testBytes::idx#11
+Inlining constant with different constant siblings (const byte) testBytes::idx#12
+Inlining constant with different constant siblings (const byte) testSBytes::idx#0
+Inlining constant with different constant siblings (const byte) testSBytes::idx#1
+Inlining constant with different constant siblings (const byte) testSBytes::idx#2
+Inlining constant with different constant siblings (const byte) testSBytes::idx#3
+Inlining constant with different constant siblings (const byte) testSBytes::idx#4
+Inlining constant with different constant siblings (const byte) testSBytes::idx#5
+Inlining constant with different constant siblings (const byte) testSBytes::idx#6
+Inlining constant with different constant siblings (const byte) testSBytes::idx#7
+Inlining constant with different constant siblings (const byte) testSBytes::idx#8
+Inlining constant with different constant siblings (const byte) testSBytes::idx#9
+Inlining constant with different constant siblings (const byte) testSBytes::idx#10
+Inlining constant with different constant siblings (const byte) testSBytes::idx#11
+Constant inlined testBytes::idx#5 = ++++++++++((byte))(number) 0
+Constant inlined testBytes::idx#6 = ++++++++++++((byte))(number) 0
+Constant inlined testBytes::idx#3 = ++++++((byte))(number) 0
+Constant inlined testBytes::idx#4 = ++++++++((byte))(number) 0
+Constant inlined testBytes::idx#1 = ++((byte))(number) 0
+Constant inlined testBytes::idx#2 = ++++((byte))(number) 0
+Constant inlined testBytes::idx#0 = ((byte))(number) 0
+Constant inlined testBytes::idx#9 = ++++++++++++++++++((byte))(number) 0
+Constant inlined testBytes::idx#7 = ++++++++++++++((byte))(number) 0
+Constant inlined testBytes::idx#8 = ++++++++++++++++((byte))(number) 0
+Constant inlined testSBytes::$28 = ((signed byte))(number) $1000-(number) $c
+Constant inlined testSBytes::$29 = (number) $428
+Constant inlined testSBytes::$7 = -(number) 1
+Constant inlined testSBytes::$6 = -(number) $714+(number) $708
+Constant inlined testSBytes::$9 = -(number) 1-(number) 2-(number) 3
+Constant inlined testSBytes::$8 = -(number) 1-(number) 2
+Constant inlined testSBytes::$3 = -(number) $12
+Constant inlined testSBytes::$2 = -(number) 6-(number) 6
+Constant inlined testSBytes::$5 = -(number) $714
+Constant inlined testSBytes::$4 = -(number) $12+(number) 6
+Constant inlined testSBytes::$1 = -(number) 6
+Constant inlined testSBytes::$0 = -(number) $c
+Constant inlined testSBytes::$13 = -(number) 3
+Constant inlined testSBytes::$14 = -(number) 3<<(number) 2
+Constant inlined testSBytes::$15 = -(number) $18
+Constant inlined testSBytes::$16 = -(number) $18>>(number) 1
+Constant inlined testSBytes::$10 = -(number) 1-(number) 2-(number) 3-(number) 6
+Constant inlined testSBytes::$11 = -(number) 2
+Constant inlined testSBytes::$12 = -(number) 2*(number) 6
+Constant inlined testBytes::idx#12 = ++++++++++++++++++++++++((byte))(number) 0
+Constant inlined testBytes::$2 = (number) $714-(number) $708
+Constant inlined testBytes::$14 = (number) 2+(number) 2*(number) $f/(number) 5
+Constant inlined testSBytes::$24 = -(number) 2-(number) 2
+Constant inlined testBytes::idx#11 = ++++++++++++++++++++++((byte))(number) 0
+Constant inlined testBytes::$1 = (number) $12-(number) 6
+Constant inlined testBytes::$15 = (number) $1000+(number) $c
+Constant inlined testSBytes::$25 = (number) $f/(number) 5
+Constant inlined testBytes::idx#10 = ++++++++++++++++++++((byte))(number) 0
+Constant inlined testBytes::$0 = (number) 6+(number) 6
+Constant inlined testBytes::$12 = (number) 2+(number) 2
+Constant inlined testSBytes::$26 = -(number) 2-(number) 2*(number) $f/(number) 5
+Constant inlined testBytes::$13 = (number) $f/(number) 5
+Constant inlined testSBytes::$27 = (number) $1000-(number) $c
+Constant inlined testBytes::$10 = (number) 4|(number) 8
+Constant inlined testSBytes::$20 = -(number) $10
+Constant inlined testBytes::$11 = (number) 5^(number) 9
+Constant inlined testSBytes::$21 = -(number) $fc
+Constant inlined testSBytes::$22 = -(number) $10|-(number) $fc
+Constant inlined testSBytes::$23 = -(number) 2
+Constant inlined testBytes::$9 = (number) $f&(number) $1c
+Constant inlined testBytes::$8 = (number) $18>>(number) 1
+Constant inlined testBytes::$7 = (number) 3<<(number) 2
+Constant inlined testSBytes::idx#10 = ++++++++++++++++++++((byte))(number) 0
+Constant inlined testBytes::$6 = (number) 2*(number) 6
+Constant inlined testBytes::$5 = (number) 1+(number) 2+(number) 3+(number) 6
+Constant inlined testBytes::$4 = (number) 1+(number) 2+(number) 3
+Constant inlined testBytes::$3 = (number) 1+(number) 2
+Constant inlined testSBytes::idx#9 = ++++++++++++++++++((byte))(number) 0
+Constant inlined testSBytes::idx#11 = ++++++++++++++++++++++((byte))(number) 0
+Constant inlined testSBytes::idx#8 = ++++++++++++++++((byte))(number) 0
+Constant inlined testSBytes::idx#5 = ++++++++++((byte))(number) 0
+Constant inlined testSBytes::idx#4 = ++++++++((byte))(number) 0
+Constant inlined testSBytes::idx#7 = ++++++++++++++((byte))(number) 0
+Constant inlined testSBytes::idx#6 = ++++++++++++((byte))(number) 0
+Constant inlined testSBytes::$17 = -(number) 4
+Constant inlined testSBytes::idx#1 = ++((byte))(number) 0
+Constant inlined testSBytes::$18 = -(number) 9
+Constant inlined testSBytes::idx#0 = ((byte))(number) 0
+Constant inlined testBytes::$16 = ((byte))(number) $1000+(number) $c
+Constant inlined testSBytes::$19 = -(number) 4&-(number) 9
+Constant inlined testSBytes::idx#3 = ++++++((byte))(number) 0
+Constant inlined testBytes::$17 = (number) $400
+Constant inlined testSBytes::idx#2 = ++++((byte))(number) 0
+Successful SSA optimization Pass2ConstantInlining
+Consolidated array index constant in *(testBytes::SCREEN#0+((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++++++++((byte))0)
+Consolidated array index constant in *(testBytes::SCREEN#0+++++++++++++++++++++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++++++++((byte))0)
+Consolidated array index constant in *(testSBytes::SCREEN#0+++++++++++++++++++++++((byte))0)
+Successful SSA optimization Pass2ConstantAdditionElimination
+Simplifying constant integer cast 0
+Simplifying constant integer cast 0
+Simplifying constant integer cast 0
+Simplifying constant integer cast 0
+Simplifying constant plus zero testBytes::SCREEN#0+0
+Simplifying constant integer increment ++0
+Simplifying constant integer increment ++0
+Simplifying constant integer increment ++1
+Simplifying constant integer increment ++2
+Simplifying constant integer increment ++3
+Simplifying constant integer increment ++4
+Simplifying constant integer increment ++5
+Simplifying constant integer increment ++6
+Simplifying constant integer increment ++7
+Simplifying constant integer increment ++8
+Simplifying constant integer increment ++9
+Simplifying constant integer increment ++$a
+Simplifying constant plus zero testSBytes::SCREEN#0+0
+Simplifying constant integer increment ++0
+Simplifying constant integer increment ++0
+Simplifying constant integer increment ++1
+Simplifying constant integer increment ++2
+Simplifying constant integer increment ++3
+Simplifying constant integer increment ++4
+Simplifying constant integer increment ++5
+Simplifying constant integer increment ++6
+Simplifying constant integer increment ++7
+Simplifying constant integer increment ++8
+Simplifying constant integer increment ++9
+Successful SSA optimization Pass2ConstantSimplification
+Simplifying constant integer increment ++1
+Simplifying constant integer increment ++2
+Simplifying constant integer increment ++3
+Simplifying constant integer increment ++4
+Simplifying constant integer increment ++5
+Simplifying constant integer increment ++6
+Simplifying constant integer increment ++7
+Simplifying constant integer increment ++8
+Simplifying constant integer increment ++9
+Simplifying constant integer increment ++$a
+Simplifying constant integer increment ++$b
+Simplifying constant integer increment ++1
+Simplifying constant integer increment ++2
+Simplifying constant integer increment ++3
+Simplifying constant integer increment ++4
+Simplifying constant integer increment ++5
+Simplifying constant integer increment ++6
+Simplifying constant integer increment ++7
+Simplifying constant integer increment ++8
+Simplifying constant integer increment ++9
+Simplifying constant integer increment ++$a
+Successful SSA optimization Pass2ConstantSimplification
+Adding NOP phi() at start of @begin
+Adding NOP phi() at start of @3
+Adding NOP phi() at start of @end
+Adding NOP phi() at start of main
+Adding NOP phi() at start of main::@1
+CALL GRAPH
+Calls in [] to main:2 
+Calls in [main] to testBytes:5 testSBytes:7 
+
+Created 0 initial phi equivalence classes
+Coalesced down to 0 phi equivalence classes
+Renumbering block @3 to @1
+Adding NOP phi() at start of @begin
+Adding NOP phi() at start of @1
+Adding NOP phi() at start of @end
+Adding NOP phi() at start of main
+Adding NOP phi() at start of main::@1
+
+FINAL CONTROL FLOW GRAPH
+@begin: scope:[]  from
+  [0] phi()
+  to:@1
+@1: scope:[]  from @begin
+  [1] phi()
+  [2] call main 
+  to:@end
+@end: scope:[]  from @1
+  [3] phi()
+main: scope:[main]  from @1
+  [4] phi()
+  [5] call testBytes 
+  to:main::@1
+main::@1: scope:[main]  from main
+  [6] phi()
+  [7] call testSBytes 
+  to:main::@return
+main::@return: scope:[main]  from main::@1
+  [8] return 
+  to:@return
+testSBytes: scope:[testSBytes]  from main::@1
+  [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c
+  [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6
+  [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6
+  [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708
+  [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6
+  [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6
+  [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2
+  [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1
+  [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9
+  [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc
+  [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5
+  [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c
+  to:testSBytes::@return
+testSBytes::@return: scope:[testSBytes]  from testSBytes
+  [21] return 
+  to:@return
+testBytes: scope:[testBytes]  from main
+  [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c
+  [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6
+  [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6
+  [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708
+  [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6
+  [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6
+  [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2
+  [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1
+  [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c
+  [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8
+  [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9
+  [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5
+  [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c
+  to:testBytes::@return
+testBytes::@return: scope:[testBytes]  from testBytes
+  [35] return 
+  to:@return
+
+
+VARIABLE REGISTER WEIGHTS
+(void()) main()
+(void()) testBytes()
+(byte*) testBytes::SCREEN
+(byte) testBytes::idx
+(void()) testSBytes()
+(signed byte*) testSBytes::SCREEN
+(byte) testSBytes::idx
+
+Initial phi equivalence classes
+Complete equivalence classes
+
+INITIAL ASM
+//SEG0 File Comments
+// Tests the number type used for constant expressions
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+//SEG3 @begin
+bbegin:
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+b1_from_bbegin:
+  jmp b1
+//SEG5 @1
+b1:
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+main_from_b1:
+  jsr main
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+bend_from_b1:
+  jmp bend
+//SEG9 @end
+bend:
+//SEG10 main
+main: {
+  //SEG11 [5] call testBytes 
+    jsr testBytes
+  //SEG12 [6] phi from main to main::@1 [phi:main->main::@1]
+  b1_from_main:
+    jmp b1
+  //SEG13 main::@1
+  b1:
+  //SEG14 [7] call testSBytes 
+    jsr testSBytes
+    jmp breturn
+  //SEG15 main::@return
+  breturn:
+  //SEG16 [8] return 
+    rts
+}
+//SEG17 testSBytes
+testSBytes: {
+    // Constant values resolvable to signed bytes
+    .label SCREEN = $428
+  //SEG18 [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c -- _deref_pbsc1=vbsc2 
+    lda #-$c
+    sta SCREEN
+  //SEG19 [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-6-6
+    sta SCREEN+1
+  //SEG20 [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-$12+6
+    sta SCREEN+2
+  //SEG21 [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 -- _deref_pbsc1=vbsc2 
+    lda #-$714+$708
+    sta SCREEN+3
+  //SEG22 [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-1-2-3-6
+    sta SCREEN+4
+  //SEG23 [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-2*6
+    sta SCREEN+5
+  //SEG24 [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 -- _deref_pbsc1=vbsc2 
+    lda #-3<<2
+    sta SCREEN+6
+  //SEG25 [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 -- _deref_pbsc1=vbsc2 
+    lda #-$18>>1
+    sta SCREEN+7
+  //SEG26 [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 -- _deref_pbsc1=vbsc2 
+    lda #-4&-9
+    sta SCREEN+8
+  //SEG27 [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc -- _deref_pbsc1=vbsc2 
+    lda #-$10|-$fc
+    sta SCREEN+9
+  //SEG28 [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 -- _deref_pbsc1=vbsc2 
+    lda #(-2-2)*$f/5
+    sta SCREEN+$a
+  //SEG29 [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c -- _deref_pbsc1=vbsc2 
+    lda #$ff&$1000-$c
+    sta SCREEN+$b
+    jmp breturn
+  //SEG30 testSBytes::@return
+  breturn:
+  //SEG31 [21] return 
+    rts
+}
+//SEG32 testBytes
+testBytes: {
+    // Constant values resolvable to bytes
+    .label SCREEN = $400
+  //SEG33 [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c -- _deref_pbuc1=vbuc2 
+    lda #$c
+    sta SCREEN
+  //SEG34 [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #6+6
+    sta SCREEN+1
+  //SEG35 [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #$12-6
+    sta SCREEN+2
+  //SEG36 [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 -- _deref_pbuc1=vbuc2 
+    lda #$714-$708
+    sta SCREEN+3
+  //SEG37 [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #1+2+3+6
+    sta SCREEN+4
+  //SEG38 [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #2*6
+    sta SCREEN+5
+  //SEG39 [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 -- _deref_pbuc1=vbuc2 
+    lda #3<<2
+    sta SCREEN+6
+  //SEG40 [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 -- _deref_pbuc1=vbuc2 
+    lda #$18>>1
+    sta SCREEN+7
+  //SEG41 [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c -- _deref_pbuc1=vbuc2 
+    lda #$f&$1c
+    sta SCREEN+8
+  //SEG42 [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 -- _deref_pbuc1=vbuc2 
+    lda #4|8
+    sta SCREEN+9
+  //SEG43 [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 -- _deref_pbuc1=vbuc2 
+    lda #5^9
+    sta SCREEN+$a
+  //SEG44 [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 -- _deref_pbuc1=vbuc2 
+    lda #(2+2)*$f/5
+    sta SCREEN+$b
+  //SEG45 [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c -- _deref_pbuc1=vbuc2 
+    lda #$ff&$1000+$c
+    sta SCREEN+$c
+    jmp breturn
+  //SEG46 testBytes::@return
+  breturn:
+  //SEG47 [35] return 
+    rts
+}
+
+REGISTER UPLIFT POTENTIAL REGISTERS
+Statement [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c [ ] ( main:2::testSBytes:7 [ ] ) always clobbers reg byte a 
+Statement [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+Statement [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c [ ] ( main:2::testBytes:5 [ ] ) always clobbers reg byte a 
+
+REGISTER UPLIFT SCOPES
+Uplift Scope [main] 
+Uplift Scope [testBytes] 
+Uplift Scope [testSBytes] 
+Uplift Scope [] 
+
+Uplifting [main] best 204 combination 
+Uplifting [testBytes] best 204 combination 
+Uplifting [testSBytes] best 204 combination 
+Uplifting [] best 204 combination 
+
+ASSEMBLER BEFORE OPTIMIZATION
+//SEG0 File Comments
+// Tests the number type used for constant expressions
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+//SEG3 @begin
+bbegin:
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+b1_from_bbegin:
+  jmp b1
+//SEG5 @1
+b1:
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+main_from_b1:
+  jsr main
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+bend_from_b1:
+  jmp bend
+//SEG9 @end
+bend:
+//SEG10 main
+main: {
+  //SEG11 [5] call testBytes 
+    jsr testBytes
+  //SEG12 [6] phi from main to main::@1 [phi:main->main::@1]
+  b1_from_main:
+    jmp b1
+  //SEG13 main::@1
+  b1:
+  //SEG14 [7] call testSBytes 
+    jsr testSBytes
+    jmp breturn
+  //SEG15 main::@return
+  breturn:
+  //SEG16 [8] return 
+    rts
+}
+//SEG17 testSBytes
+testSBytes: {
+    // Constant values resolvable to signed bytes
+    .label SCREEN = $428
+  //SEG18 [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c -- _deref_pbsc1=vbsc2 
+    lda #-$c
+    sta SCREEN
+  //SEG19 [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-6-6
+    sta SCREEN+1
+  //SEG20 [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-$12+6
+    sta SCREEN+2
+  //SEG21 [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 -- _deref_pbsc1=vbsc2 
+    lda #-$714+$708
+    sta SCREEN+3
+  //SEG22 [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-1-2-3-6
+    sta SCREEN+4
+  //SEG23 [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-2*6
+    sta SCREEN+5
+  //SEG24 [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 -- _deref_pbsc1=vbsc2 
+    lda #-3<<2
+    sta SCREEN+6
+  //SEG25 [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 -- _deref_pbsc1=vbsc2 
+    lda #-$18>>1
+    sta SCREEN+7
+  //SEG26 [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 -- _deref_pbsc1=vbsc2 
+    lda #-4&-9
+    sta SCREEN+8
+  //SEG27 [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc -- _deref_pbsc1=vbsc2 
+    lda #-$10|-$fc
+    sta SCREEN+9
+  //SEG28 [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 -- _deref_pbsc1=vbsc2 
+    lda #(-2-2)*$f/5
+    sta SCREEN+$a
+  //SEG29 [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c -- _deref_pbsc1=vbsc2 
+    lda #$ff&$1000-$c
+    sta SCREEN+$b
+    jmp breturn
+  //SEG30 testSBytes::@return
+  breturn:
+  //SEG31 [21] return 
+    rts
+}
+//SEG32 testBytes
+testBytes: {
+    // Constant values resolvable to bytes
+    .label SCREEN = $400
+  //SEG33 [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c -- _deref_pbuc1=vbuc2 
+    lda #$c
+    sta SCREEN
+  //SEG34 [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #6+6
+    sta SCREEN+1
+  //SEG35 [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #$12-6
+    sta SCREEN+2
+  //SEG36 [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 -- _deref_pbuc1=vbuc2 
+    lda #$714-$708
+    sta SCREEN+3
+  //SEG37 [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #1+2+3+6
+    sta SCREEN+4
+  //SEG38 [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #2*6
+    sta SCREEN+5
+  //SEG39 [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 -- _deref_pbuc1=vbuc2 
+    lda #3<<2
+    sta SCREEN+6
+  //SEG40 [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 -- _deref_pbuc1=vbuc2 
+    lda #$18>>1
+    sta SCREEN+7
+  //SEG41 [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c -- _deref_pbuc1=vbuc2 
+    lda #$f&$1c
+    sta SCREEN+8
+  //SEG42 [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 -- _deref_pbuc1=vbuc2 
+    lda #4|8
+    sta SCREEN+9
+  //SEG43 [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 -- _deref_pbuc1=vbuc2 
+    lda #5^9
+    sta SCREEN+$a
+  //SEG44 [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 -- _deref_pbuc1=vbuc2 
+    lda #(2+2)*$f/5
+    sta SCREEN+$b
+  //SEG45 [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c -- _deref_pbuc1=vbuc2 
+    lda #$ff&$1000+$c
+    sta SCREEN+$c
+    jmp breturn
+  //SEG46 testBytes::@return
+  breturn:
+  //SEG47 [35] return 
+    rts
+}
+
+ASSEMBLER OPTIMIZATIONS
+Removing instruction jmp b1
+Removing instruction jmp bend
+Removing instruction jmp b1
+Removing instruction jmp breturn
+Removing instruction jmp breturn
+Removing instruction jmp breturn
+Succesful ASM optimization Pass5NextJumpElimination
+Removing instruction b1_from_bbegin:
+Removing instruction b1:
+Removing instruction main_from_b1:
+Removing instruction bend_from_b1:
+Removing instruction b1_from_main:
+Succesful ASM optimization Pass5RedundantLabelElimination
+Removing instruction bend:
+Removing instruction b1:
+Removing instruction breturn:
+Removing instruction breturn:
+Removing instruction breturn:
+Succesful ASM optimization Pass5UnusedLabelElimination
+Updating BasicUpstart to call main directly
+Removing instruction jsr main
+Succesful ASM optimization Pass5SkipBegin
+Removing instruction bbegin:
+Succesful ASM optimization Pass5UnusedLabelElimination
+
+FINAL SYMBOL TABLE
+(label) @1
+(label) @begin
+(label) @end
+(void()) main()
+(label) main::@1
+(label) main::@return
+(void()) testBytes()
+(label) testBytes::@return
+(byte*) testBytes::SCREEN
+(const byte*) testBytes::SCREEN#0 SCREEN = ((byte*))(number) $400
+(byte) testBytes::idx
+(void()) testSBytes()
+(label) testSBytes::@return
+(signed byte*) testSBytes::SCREEN
+(const signed byte*) testSBytes::SCREEN#0 SCREEN = ((signed byte*))(number) $428
+(byte) testSBytes::idx
+
+
+
+FINAL ASSEMBLER
+Score: 180
+
+//SEG0 File Comments
+// Tests the number type used for constant expressions
+//SEG1 Basic Upstart
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+//SEG2 Global Constants & labels
+//SEG3 @begin
+//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
+//SEG5 @1
+//SEG6 [2] call main 
+//SEG7 [4] phi from @1 to main [phi:@1->main]
+//SEG8 [3] phi from @1 to @end [phi:@1->@end]
+//SEG9 @end
+//SEG10 main
+main: {
+  //SEG11 [5] call testBytes 
+    jsr testBytes
+  //SEG12 [6] phi from main to main::@1 [phi:main->main::@1]
+  //SEG13 main::@1
+  //SEG14 [7] call testSBytes 
+    jsr testSBytes
+  //SEG15 main::@return
+  //SEG16 [8] return 
+    rts
+}
+//SEG17 testSBytes
+testSBytes: {
+    // Constant values resolvable to signed bytes
+    .label SCREEN = $428
+  //SEG18 [9] *((const signed byte*) testSBytes::SCREEN#0) ← ((signed byte))-(number) $c -- _deref_pbsc1=vbsc2 
+    lda #-$c
+    sta SCREEN
+  //SEG19 [10] *((const signed byte*) testSBytes::SCREEN#0+(number) 1) ← ((signed byte))-(number) 6-(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-6-6
+    sta SCREEN+1
+  //SEG20 [11] *((const signed byte*) testSBytes::SCREEN#0+(number) 2) ← ((signed byte))-(number) $12+(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-$12+6
+    sta SCREEN+2
+  //SEG21 [12] *((const signed byte*) testSBytes::SCREEN#0+(number) 3) ← ((signed byte))-(number) $714+(number) $708 -- _deref_pbsc1=vbsc2 
+    lda #-$714+$708
+    sta SCREEN+3
+  //SEG22 [13] *((const signed byte*) testSBytes::SCREEN#0+(number) 4) ← ((signed byte))-(number) 1-(number) 2-(number) 3-(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-1-2-3-6
+    sta SCREEN+4
+  //SEG23 [14] *((const signed byte*) testSBytes::SCREEN#0+(number) 5) ← ((signed byte))-(number) 2*(number) 6 -- _deref_pbsc1=vbsc2 
+    lda #-2*6
+    sta SCREEN+5
+  //SEG24 [15] *((const signed byte*) testSBytes::SCREEN#0+(number) 6) ← ((signed byte))-(number) 3<<(number) 2 -- _deref_pbsc1=vbsc2 
+    lda #-3<<2
+    sta SCREEN+6
+  //SEG25 [16] *((const signed byte*) testSBytes::SCREEN#0+(number) 7) ← ((signed byte))-(number) $18>>(number) 1 -- _deref_pbsc1=vbsc2 
+    lda #-$18>>1
+    sta SCREEN+7
+  //SEG26 [17] *((const signed byte*) testSBytes::SCREEN#0+(number) 8) ← ((signed byte))-(number) 4&-(number) 9 -- _deref_pbsc1=vbsc2 
+    lda #-4&-9
+    sta SCREEN+8
+  //SEG27 [18] *((const signed byte*) testSBytes::SCREEN#0+(number) 9) ← ((signed byte))-(number) $10|-(number) $fc -- _deref_pbsc1=vbsc2 
+    lda #-$10|-$fc
+    sta SCREEN+9
+  //SEG28 [19] *((const signed byte*) testSBytes::SCREEN#0+(number) $a) ← ((signed byte))-(number) 2-(number) 2*(number) $f/(number) 5 -- _deref_pbsc1=vbsc2 
+    lda #(-2-2)*$f/5
+    sta SCREEN+$a
+  //SEG29 [20] *((const signed byte*) testSBytes::SCREEN#0+(number) $b) ← ((signed byte))(number) $1000-(number) $c -- _deref_pbsc1=vbsc2 
+    lda #$ff&$1000-$c
+    sta SCREEN+$b
+  //SEG30 testSBytes::@return
+  //SEG31 [21] return 
+    rts
+}
+//SEG32 testBytes
+testBytes: {
+    // Constant values resolvable to bytes
+    .label SCREEN = $400
+  //SEG33 [22] *((const byte*) testBytes::SCREEN#0) ← (byte) $c -- _deref_pbuc1=vbuc2 
+    lda #$c
+    sta SCREEN
+  //SEG34 [23] *((const byte*) testBytes::SCREEN#0+(number) 1) ← ((byte))(number) 6+(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #6+6
+    sta SCREEN+1
+  //SEG35 [24] *((const byte*) testBytes::SCREEN#0+(number) 2) ← ((byte))(number) $12-(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #$12-6
+    sta SCREEN+2
+  //SEG36 [25] *((const byte*) testBytes::SCREEN#0+(number) 3) ← ((byte))(number) $714-(number) $708 -- _deref_pbuc1=vbuc2 
+    lda #$714-$708
+    sta SCREEN+3
+  //SEG37 [26] *((const byte*) testBytes::SCREEN#0+(number) 4) ← ((byte))(number) 1+(number) 2+(number) 3+(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #1+2+3+6
+    sta SCREEN+4
+  //SEG38 [27] *((const byte*) testBytes::SCREEN#0+(number) 5) ← ((byte))(number) 2*(number) 6 -- _deref_pbuc1=vbuc2 
+    lda #2*6
+    sta SCREEN+5
+  //SEG39 [28] *((const byte*) testBytes::SCREEN#0+(number) 6) ← ((byte))(number) 3<<(number) 2 -- _deref_pbuc1=vbuc2 
+    lda #3<<2
+    sta SCREEN+6
+  //SEG40 [29] *((const byte*) testBytes::SCREEN#0+(number) 7) ← ((byte))(number) $18>>(number) 1 -- _deref_pbuc1=vbuc2 
+    lda #$18>>1
+    sta SCREEN+7
+  //SEG41 [30] *((const byte*) testBytes::SCREEN#0+(number) 8) ← ((byte))(number) $f&(number) $1c -- _deref_pbuc1=vbuc2 
+    lda #$f&$1c
+    sta SCREEN+8
+  //SEG42 [31] *((const byte*) testBytes::SCREEN#0+(number) 9) ← ((byte))(number) 4|(number) 8 -- _deref_pbuc1=vbuc2 
+    lda #4|8
+    sta SCREEN+9
+  //SEG43 [32] *((const byte*) testBytes::SCREEN#0+(number) $a) ← ((byte))(number) 5^(number) 9 -- _deref_pbuc1=vbuc2 
+    lda #5^9
+    sta SCREEN+$a
+  //SEG44 [33] *((const byte*) testBytes::SCREEN#0+(number) $b) ← ((byte))(number) 2+(number) 2*(number) $f/(number) 5 -- _deref_pbuc1=vbuc2 
+    lda #(2+2)*$f/5
+    sta SCREEN+$b
+  //SEG45 [34] *((const byte*) testBytes::SCREEN#0+(number) $c) ← ((byte))(number) $1000+(number) $c -- _deref_pbuc1=vbuc2 
+    lda #$ff&$1000+$c
+    sta SCREEN+$c
+  //SEG46 testBytes::@return
+  //SEG47 [35] return 
+    rts
+}
+
diff --git a/src/test/ref/number-type.sym b/src/test/ref/number-type.sym
new file mode 100644
index 000000000..fa464be74
--- /dev/null
+++ b/src/test/ref/number-type.sym
@@ -0,0 +1,17 @@
+(label) @1
+(label) @begin
+(label) @end
+(void()) main()
+(label) main::@1
+(label) main::@return
+(void()) testBytes()
+(label) testBytes::@return
+(byte*) testBytes::SCREEN
+(const byte*) testBytes::SCREEN#0 SCREEN = ((byte*))(number) $400
+(byte) testBytes::idx
+(void()) testSBytes()
+(label) testSBytes::@return
+(signed byte*) testSBytes::SCREEN
+(const signed byte*) testSBytes::SCREEN#0 SCREEN = ((signed byte*))(number) $428
+(byte) testSBytes::idx
+

From b097b5c2c51a962d261979a523d8b230d01f4bcf Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 7 May 2019 01:46:23 +0200
Subject: [PATCH 10/93] Working on fixing test errors.

---
 .../iterator/ProgramExpressionBinary.java     | 28 +++++++++++--------
 .../iterator/ProgramExpressionIterator.java   |  2 ++
 .../kickc/model/values/ConstantPointer.java   |  8 ++----
 .../Pass2ConstantCastSimplification.java      | 17 +++++++----
 .../kickc/passes/Pass2InlineDerefIdx.java     |  2 +-
 src/test/kc/bitwise-not.kc                    |  2 +-
 6 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
index 655ca17e4..aac9a3cb5 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
@@ -44,12 +44,14 @@ public interface ProgramExpressionBinary extends ProgramExpression {
 
    /**
     * Adds a cast to the left operand
+    *
     * @param toType The toType to cast to
     */
    void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols);
 
    /**
     * Adds a cast to the right operand
+    *
     * @param toType The toType to cast to
     */
    void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols);
@@ -135,7 +137,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
 
       @Override
       public RValue getRight() {
-         if(assignment.getrValue1()==null && assignment.getOperator()==null) {
+         if(assignment.getrValue1() == null && assignment.getOperator() == null) {
             return assignment.getrValue2();
          } else {
             return new AssignmentRValue(assignment);
@@ -160,13 +162,9 @@ public interface ProgramExpressionBinary extends ProgramExpression {
 
       @Override
       public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
-         if(assignment.getrValue1()==null && assignment.getOperator()==null) {
-            //if(assignment.getrValue2() instanceof ConstantInteger) {
-            //   ((ConstantInteger) assignment.getrValue2()).setType(toType);
-            //}  else {
-               assignment.setOperator(Operators.getCastUnary(toType));
-            //}
-         }  else {
+         if(assignment.getrValue1() == null && assignment.getOperator() == null) {
+            assignment.setOperator(Operators.getCastUnary(toType));
+         } else {
             throw new InternalError("Not implemented!");
          }
       }
@@ -205,12 +203,20 @@ public interface ProgramExpressionBinary extends ProgramExpression {
 
       @Override
       public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
-         throw new InternalError("Not implemented!");
+         if(conditionalJump.getrValue1() instanceof ConstantValue) {
+            conditionalJump.setrValue1(new ConstantCastValue(toType, (ConstantValue) conditionalJump.getrValue1()));
+         } else {
+            throw new InternalError("Not implemented!");
+         }
       }
 
       @Override
       public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
-         throw new InternalError("Not implemented!");
+         if(conditionalJump.getrValue2() instanceof ConstantValue) {
+            conditionalJump.setrValue2(new ConstantCastValue(toType, (ConstantValue) conditionalJump.getrValue2()));
+         } else {
+            throw new InternalError("Not implemented!");
+         }
       }
 
 
@@ -226,7 +232,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
       }
 
       public ConstantBinary getConstantBinary() {
-         return (ConstantBinary)programValue.get();
+         return (ConstantBinary) programValue.get();
       }
 
       @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
index a8ae53aca..e525c101f 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
@@ -28,6 +28,8 @@ public class ProgramExpressionIterator {
       ProgramValueIterator.execute(program.getScope(), (programValue, currentStmt, stmtIt, currentBlock) -> {
          if(programValue.get() instanceof ConstantBinary) {
             handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), null, null, null);
+         } else if(programValue.get() instanceof ConstantUnary) {
+            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null);
          }
       });
 
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantPointer.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantPointer.java
index 452f3331c..dd8bf3940 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantPointer.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantPointer.java
@@ -5,7 +5,7 @@ import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
 
-/** Constant pointer (meaning it points to a constant location)*/
+/** Constant pointer (meaning it points to a constant location) */
 public class ConstantPointer implements ConstantEnumerable<Long> {
 
    /** The memory location pointed to. */
@@ -52,11 +52,7 @@ public class ConstantPointer implements ConstantEnumerable<Long> {
 
    @Override
    public String toString(Program program) {
-      if(program == null) {
-         return Long.toString(location);
-      } else {
-         return "(" + getType(program.getScope()).getTypeName() + ") " + Long.toString(location);
-      }
+      return "(" + getType().getTypeName() + ") " + Long.toString(location);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
index a40c02fd0..14f4f1028 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
@@ -1,13 +1,14 @@
 package dk.camelot64.kickc.passes;
 
 import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.iterator.ProgramExpression;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
 import dk.camelot64.kickc.model.operators.OperatorCast;
 import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
+import dk.camelot64.kickc.model.types.SymbolTypePointer;
 import dk.camelot64.kickc.model.values.ConstantInteger;
-import dk.camelot64.kickc.model.values.ConstantValue;
+import dk.camelot64.kickc.model.values.ConstantPointer;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -29,9 +30,15 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
                ConstantInteger constantInteger = (ConstantInteger) unary.getOperand();
                if(constantInteger.getType().equals(SymbolType.NUMBER)) {
                   SymbolType castType = operatorCast.getToType();
-                  ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
-                  programExpression.set(newConstInt);
-                  getLog().append("Simplifying constant integer cast "+newConstInt);
+                  if(castType instanceof SymbolTypeIntegerFixed ) {
+                     ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
+                     programExpression.set(newConstInt);
+                     getLog().append("Simplifying constant integer cast " + newConstInt.toString());
+                  }  else if(castType instanceof SymbolTypePointer) {
+                     ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType());
+                     programExpression.set(newConstPointer);
+                     getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
+                  }
                }
             }
          }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java
index dd7b0a85e..795d55117 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java
@@ -83,7 +83,7 @@ public class Pass2InlineDerefIdx extends Pass2SsaOptimization {
       } else if(derefAssignment.getOperator()==null) {
          return attemptInlineDeref(derefAssignment.getrValue2());
       } else if(derefAssignment.getOperator() instanceof OperatorCastPtr) {
-         throw new CompileError("Not implemented!");
+         //throw new CompileError("Not implemented!");
         //return attemptInlineDeref(derefAssignment.getrValue2());
         }
       return null;
diff --git a/src/test/kc/bitwise-not.kc b/src/test/kc/bitwise-not.kc
index 282da557c..1da5f5af6 100644
--- a/src/test/kc/bitwise-not.kc
+++ b/src/test/kc/bitwise-not.kc
@@ -1,7 +1,7 @@
 
 void main() {
     byte* SCREEN = $400;
-    *SCREEN = ~1;
+    *SCREEN = ~1ub;
 
     for(byte c : 1..26) {
         SCREEN[c] = ~c;

From 87e6fecb8f02f9c439465b09ce6d189d0acedaef Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 7 May 2019 09:19:50 +0200
Subject: [PATCH 11/93] Working on fixing test errors.

---
 .../kickc/passes/Pass2AssertTypeMatch.java          | 13 ++++++++++---
 .../java/dk/camelot64/kickc/test/TestPrograms.java  | 11 ++++++++---
 src/test/kc/helloworld0.kc                          |  8 ++++++++
 3 files changed, 26 insertions(+), 6 deletions(-)
 create mode 100644 src/test/kc/helloworld0.kc

diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
index 466599cf3..999188209 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
@@ -1,12 +1,15 @@
 package dk.camelot64.kickc.passes;
 
-import dk.camelot64.kickc.model.*;
-import dk.camelot64.kickc.model.statements.StatementConditionalJump;
-import dk.camelot64.kickc.model.values.LValue;
+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.StatementConditionalJump;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.types.SymbolTypePointer;
+import dk.camelot64.kickc.model.values.LValue;
 import dk.camelot64.kickc.model.values.RValue;
 
 /**
@@ -55,6 +58,10 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion {
          // L-value is still a number - constants are probably not done being identified & typed
          return;
       }
+      if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
+         // String value can be assigned into a pointer
+         return;
+      }
       // Types do not match
       getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false));
       throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource());
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index b77d09e82..29f794fb5 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,6 +32,11 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testHelloWorld0() throws IOException, URISyntaxException {
+      compileAndCompare("helloworld0", log());
+   }
+
    @Test
    public void testNumberConversion() throws IOException, URISyntaxException {
       compileAndCompare("number-conversion");
@@ -1879,9 +1884,9 @@ public class TestPrograms {
       boolean success = true;
       ReferenceHelper helper = new ReferenceHelperFolder(refPath);
       success &= helper.testOutput(fileName, ".asm", program.getAsm().toString(false));
-      success &= helper.testOutput(fileName, ".sym", program.getScope().getSymbolTableContents(program));
-      success &= helper.testOutput(fileName, ".cfg", program.getGraph().toString(program));
-      success &= helper.testOutput(fileName, ".log", program.getLog().toString());
+      //success &= helper.testOutput(fileName, ".sym", program.getScope().getSymbolTableContents(program));
+      //success &= helper.testOutput(fileName, ".cfg", program.getGraph().toString(program));
+      //success &= helper.testOutput(fileName, ".log", program.getLog().toString());
       if(!success) {
          //System.out.println("\nCOMPILE LOG");
          //System.out.println(program.getLog().toString());
diff --git a/src/test/kc/helloworld0.kc b/src/test/kc/helloworld0.kc
new file mode 100644
index 000000000..a70b62201
--- /dev/null
+++ b/src/test/kc/helloworld0.kc
@@ -0,0 +1,8 @@
+// Tests minimal hello world
+
+byte[] msg = "hello world";
+byte* SCREEN = 0x0400;
+
+void main() {
+    for( byte i: 0..11) SCREEN[i] = msg[i];
+}
\ No newline at end of file

From 47aa623f2525fea8585a20a4381eb3fd3555d14d Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 7 May 2019 18:52:01 +0200
Subject: [PATCH 12/93] Working on fixing test errors.

---
 .../model/types/SymbolTypeConversion.java     | 17 +++++-----
 .../kickc/model/types/SymbolTypeMatch.java    | 31 +++++++++++++++++++
 .../kickc/passes/Pass2AssertTypeMatch.java    | 14 ++-------
 .../passes/Pass2ConstantIdentification.java   | 16 +++++-----
 .../Pass2ConstantRValueConsolidation.java     |  2 +-
 .../passes/Pass2SizeOfSimplification.java     |  5 +--
 .../dk/camelot64/kickc/test/TestPrograms.java |  2 +-
 src/test/kc/helloworld0.kc                    |  2 +-
 8 files changed, 55 insertions(+), 34 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index 7b93fa1de..239f64417 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -11,11 +11,10 @@ import dk.camelot64.kickc.model.values.RValue;
 
 /**
  * Rules for converting integer types.
- *
+ * <p>
  * Integer conversion implements C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70
- *
+ * <p>
  * The special number type is converted as described here https://gitlab.com/camelot/kickc/issues/181
- * 
  */
 public class SymbolTypeConversion {
 
@@ -37,19 +36,19 @@ public class SymbolTypeConversion {
       if(type1.equals(type2))
          return type1;
       // C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword)
-      if(fixed1.isSigned()==fixed2.isSigned())
-         return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2;
+      if(fixed1.isSigned() == fixed2.isSigned())
+         return (fixed1.getBits() > fixed2.getBits()) ? fixed1 : fixed2;
       // C99 6.3.1.8 c. One is signed and one unsigned.
       // If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword).
       SymbolTypeIntegerFixed typeS, typeU;
       if(fixed1.isSigned()) {
          typeS = fixed1;
          typeU = fixed2;
-      }  else {
+      } else {
          typeS = fixed2;
          typeU = fixed1;
       }
-      if(typeS.getBits()>typeU.getBits())
+      if(typeS.getBits() > typeU.getBits())
          return typeS;
       // C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type.
       // The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value
@@ -59,6 +58,7 @@ public class SymbolTypeConversion {
 
    /**
     * Find the integer type that results from a binary operator according to the special number type conversion https://gitlab.com/camelot/kickc/issues/181
+    *
     * @param left The left value
     * @param right The right value
     * @param symbols The program scope symbols (used for looking up symbols and constants)
@@ -92,7 +92,8 @@ public class SymbolTypeConversion {
             fixedType = (SymbolTypeIntegerFixed) leftType;
          } else {
             // Binary operator combining number and non-integer
-            throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt);
+            return null;
+            //throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt);
          }
 
          if(numberVal instanceof ConstantValue) {
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java
new file mode 100644
index 000000000..b058abbb2
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java
@@ -0,0 +1,31 @@
+package dk.camelot64.kickc.model.types;
+
+/** Container for function checking if types of an assignment match up */
+public class SymbolTypeMatch {
+
+   /**
+    * Determines if the types of an assignment match up properly
+    * @param lValueType The type of the LValue
+    * @param rValueType The type of the RValue
+    * @return true if the types match up
+    */
+   public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) {
+      if(lValueType.equals(rValueType)) {
+         return true;
+      }
+      if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
+         // L-value is still a number - constants are probably not done being identified & typed
+         return true;
+      }
+      if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
+         // String value can be assigned into a pointer
+         return true;
+      }
+      if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && assignmentTypeMatch(((SymbolTypePointer) lValueType).getElementType(), ((SymbolTypePointer) rValueType).getElementType())) {
+         // Pointer types assigned from each other
+         // TODO: Maybe handle sizes
+         return true;
+      }
+      return false;
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
index 999188209..82c5fce43 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
@@ -8,7 +8,7 @@ import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementConditionalJump;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
+import dk.camelot64.kickc.model.types.SymbolTypeMatch;
 import dk.camelot64.kickc.model.values.LValue;
 import dk.camelot64.kickc.model.values.RValue;
 
@@ -51,17 +51,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion {
       LValue lValue = statement.getlValue();
       SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
       SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement);
-      if(lValueType.equals(rValueType)) {
-         return;
-      }
-      if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
-         // L-value is still a number - constants are probably not done being identified & typed
-         return;
-      }
-      if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
-         // String value can be assigned into a pointer
-         return;
-      }
+      if(SymbolTypeMatch.assignmentTypeMatch(lValueType, rValueType)) return;
       // Types do not match
       getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false));
       throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource());
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
index 0cde91c25..95e8e0229 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
@@ -15,11 +15,14 @@ import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.symbols.Scope;
 import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeArray;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.types.SymbolTypeMatch;
 import dk.camelot64.kickc.model.values.*;
 
-import java.util.*;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Compiler Pass propagating constants in expressions eliminating constant variables
@@ -69,24 +72,19 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
          ConstantValue constVal = constVarVal.getConstantValue();
          SymbolType valueType = SymbolTypeInference.inferType(getScope(), constVal);
          SymbolType variableType = variable.getType();
-         SymbolType constType = variableType;
 
-         if(!valueType.equals(variableType)) {
-            if(variableType.equals(valueType)) {
-               constType = variableType;
-            } else {
+         if(!SymbolTypeMatch.assignmentTypeMatch(variableType, valueType)) {
                throw new CompileError(
                      "Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) +
                            "\n value: (" + valueType.toString() + ") " + constVal.calculateLiteral(getScope()) +
                            "\n value definition: " + constVal.toString(getProgram())
                );
-            }
          }
 
          ConstantVar constantVar = new ConstantVar(
                variable.getName(),
                constScope,
-               constType,
+               variableType,
                constVal);
          constantVar.setDeclaredAlignment(variable.getDeclaredAlignment());
          constantVar.setDeclaredRegister(variable.getDeclaredRegister());
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
index a473bd5f8..eed062e60 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
@@ -16,7 +16,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Compiler Pass consolidating L-values that are constant into a single {@link ConstantValue}
+ * Compiler Pass consolidating R-values that are constant into a single {@link ConstantValue}
  */
 public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java
index e2c1e6f2c..3121da890 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2SizeOfSimplification.java
@@ -76,12 +76,12 @@ public class Pass2SizeOfSimplification extends Pass2SsaOptimization {
             SymbolTypeArray arrayType = (SymbolTypeArray) symbolType;
             RValue arraySize = arrayType.getSize();
             if(arraySize instanceof ConstantValue) {
-               getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
+               getLog().append("Resolving array sizeof() " + unary.toString(getProgram()));
                ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType());
                programValue.set(new ConstantBinary((ConstantValue) arraySize, Operators.MULTIPLY, sizeOfConstantVar));
                modified.set(true);
             } else if(constant.getValue() instanceof ConstantArrayList) {
-               getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
+               getLog().append("Resolving array sizeof() " + unary.toString(getProgram()));
                int size = ((ConstantArrayList) constant.getValue()).getElements().size();
                ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType());
                programValue.set(new ConstantBinary(new ConstantInteger((long) size), Operators.MULTIPLY, sizeOfConstantVar));
@@ -97,6 +97,7 @@ public class Pass2SizeOfSimplification extends Pass2SsaOptimization {
                if(stringLiteral instanceof ConstantString) {
                   ConstantString constString = (ConstantString) stringLiteral;
                   int length = constString.getString().length();
+                  getLog().append("Resolving string sizeof() " + unary.toString(getProgram()));
                   ConstantRef sizeOfChar = OperatorSizeOf.getSizeOfConstantVar(getScope(), SymbolType.BYTE);
                   programValue.set(new ConstantBinary(new ConstantInteger((long) length), Operators.MULTIPLY, sizeOfChar));
                   modified.set(true);
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 29f794fb5..422890f99 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -34,7 +34,7 @@ public class TestPrograms {
 
    @Test
    public void testHelloWorld0() throws IOException, URISyntaxException {
-      compileAndCompare("helloworld0", log());
+      compileAndCompare("helloworld0");
    }
 
    @Test
diff --git a/src/test/kc/helloworld0.kc b/src/test/kc/helloworld0.kc
index a70b62201..b3136af56 100644
--- a/src/test/kc/helloworld0.kc
+++ b/src/test/kc/helloworld0.kc
@@ -1,6 +1,6 @@
 // Tests minimal hello world
 
-byte[] msg = "hello world";
+byte[] msg = "hello world!";
 byte* SCREEN = 0x0400;
 
 void main() {

From 82729cb4d9488a0ebc2f80eaf5667015dddb319d Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 7 May 2019 21:03:26 +0200
Subject: [PATCH 13/93] Working on fixing test errors - 196/350 working.

---
 .../model/types/SymbolTypeConversion.java     |  9 +++++-
 .../Pass2ConstantCastSimplification.java      | 29 ++++++++++++++++++-
 .../passes/Pass2ConstantIdentification.java   |  6 ++++
 .../passes/PassNAddNumberTypeConversions.java |  6 ++--
 .../dk/camelot64/kickc/test/TestPrograms.java |  5 ++++
 src/test/kc/const-int-cast-problem.kc         |  8 +++++
 6 files changed, 58 insertions(+), 5 deletions(-)
 create mode 100644 src/test/kc/const-int-cast-problem.kc

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index 239f64417..15c35ad73 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -90,10 +90,17 @@ public class SymbolTypeConversion {
             // Right is the number type - left is the fixed type
             numberVal = right;
             fixedType = (SymbolTypeIntegerFixed) leftType;
+         } else if(SymbolType.NUMBER.equals(leftType) && rightType instanceof SymbolTypePointer) {
+            // Left is the number type - right is a pointer (effectively unsigned word)
+            numberVal = left;
+            fixedType = SymbolType.WORD;
+         } else if(SymbolType.NUMBER.equals(rightType) && leftType instanceof SymbolTypePointer) {
+            // Right is the number type - left is a pointer (effectively unsigned word)
+            numberVal = right;
+            fixedType = SymbolType.WORD;
          } else {
             // Binary operator combining number and non-integer
             return null;
-            //throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt);
          }
 
          if(numberVal instanceof ConstantValue) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
index 14f4f1028..893003447 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
@@ -3,10 +3,12 @@ package dk.camelot64.kickc.passes;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
+import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
 import dk.camelot64.kickc.model.operators.OperatorCast;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
+import dk.camelot64.kickc.model.values.ConstantCastValue;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantPointer;
 
@@ -28,21 +30,46 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
             ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression;
             if(unary.getOperand() instanceof ConstantInteger) {
                ConstantInteger constantInteger = (ConstantInteger) unary.getOperand();
-               if(constantInteger.getType().equals(SymbolType.NUMBER)) {
+               if(SymbolType.NUMBER.equals(constantInteger.getType())) {
                   SymbolType castType = operatorCast.getToType();
                   if(castType instanceof SymbolTypeIntegerFixed ) {
                      ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
                      programExpression.set(newConstInt);
                      getLog().append("Simplifying constant integer cast " + newConstInt.toString());
+                     optimized.set(true);
                   }  else if(castType instanceof SymbolTypePointer) {
                      ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType());
                      programExpression.set(newConstPointer);
                      getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
+                     optimized.set(true);
                   }
                }
             }
          }
       });
+      ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
+         if(programValue.get() instanceof ConstantCastValue) {
+            ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get();
+            if(constantCastValue.getValue() instanceof ConstantInteger) {
+               ConstantInteger constantInteger = (ConstantInteger) constantCastValue.getValue();
+               if(SymbolType.NUMBER.equals(constantInteger.getType())) {
+                  SymbolType castType = constantCastValue.getToType();
+                  if(castType instanceof SymbolTypeIntegerFixed ) {
+                     ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
+                     programValue.set(newConstInt);
+                     getLog().append("Simplifying constant integer cast " + newConstInt.toString());
+                     optimized.set(true);
+                  }  else if(castType instanceof SymbolTypePointer) {
+                     ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType());
+                     programValue.set(newConstPointer);
+                     getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
+                     optimized.set(true);
+                  }
+               }
+            }
+         }
+
+      });
       return optimized.get();
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
index 95e8e0229..d4df53443 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
@@ -73,6 +73,12 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
          SymbolType valueType = SymbolTypeInference.inferType(getScope(), constVal);
          SymbolType variableType = variable.getType();
 
+         if(!variableType.equals(SymbolType.NUMBER) && valueType.equals(SymbolType.NUMBER)) {
+            // Value is number - wait til it is cast to a proper type
+            constants.remove(constRef);
+            continue;
+         }
+
          if(!SymbolTypeMatch.assignmentTypeMatch(variableType, valueType)) {
                throw new CompileError(
                      "Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) +
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
index 39d15dc0c..16688948f 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeConversion;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.types.SymbolTypePointer;
 import dk.camelot64.kickc.model.values.RValue;
 
 /**
@@ -28,12 +29,12 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
             if(conversionType != null) {
                // Convert both left and right to the found type
                SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
-               if(!leftType.equals(conversionType)) {
+               if(!leftType.equals(conversionType) && !(leftType instanceof SymbolTypePointer)) {
                   getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
                   binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
                }
                SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
-               if(!rightType.equals(conversionType)) {
+               if(!rightType.equals(conversionType) && !(rightType instanceof SymbolTypePointer)) {
                   getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
                   binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
                }
@@ -43,5 +44,4 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
       return false;
    }
 
-
 }
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 422890f99..f9a125777 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -103,6 +103,11 @@ public class TestPrograms {
       compileAndCompare("type-signed");
    }
 
+   @Test
+   public void testConstIntCastProblem() throws IOException, URISyntaxException {
+      compileAndCompare("const-int-cast-problem");
+   }
+
    @Test
    public void testPointerPlus0() throws IOException, URISyntaxException {
       compileAndCompare("pointer-plus-0");
diff --git a/src/test/kc/const-int-cast-problem.kc b/src/test/kc/const-int-cast-problem.kc
new file mode 100644
index 000000000..01a8dea74
--- /dev/null
+++ b/src/test/kc/const-int-cast-problem.kc
@@ -0,0 +1,8 @@
+// Test a problem with converting casted constant numbers to fixed type constant integers
+const byte* SCREEN = $0400;
+
+void main() {
+    for( byte i: 121..122) {
+        SCREEN[i] = i>>4;
+    }
+}

From 44e9cff722d07a89dc389855ac059ba571b6f7f7 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 7 May 2019 21:53:08 +0200
Subject: [PATCH 14/93] Working on fixing test errors - 198/350 working.

---
 .../kickc/model/operators/OperatorGetHigh.java |  2 ++
 .../kickc/model/operators/OperatorGetLow.java  |  2 ++
 .../model/operators/OperatorShiftLeft.java     |  8 +++++++-
 .../model/operators/OperatorShiftRight.java    |  8 +++++++-
 .../model/types/SymbolTypeNumberInference.java | 18 ++++++++++++++----
 .../kickc/model/values/ConstantBinary.java     |  6 +++++-
 .../kickc/model/values/ConstantUnary.java      |  6 +++++-
 .../dk/camelot64/kickc/test/TestPrograms.java  |  5 +++++
 .../kc/examples/sinsprites/sinus-sprites.kc    |  2 +-
 src/test/kc/inline-kasm-resource.kc            |  2 +-
 src/test/kc/tod018-problem.kc                  |  9 +++++++++
 11 files changed, 58 insertions(+), 10 deletions(-)
 create mode 100644 src/test/kc/tod018-problem.kc

diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
index 2a76c569b..81aad2e0e 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
@@ -43,6 +43,8 @@ public class OperatorGetHigh extends OperatorUnary {
          return SymbolType.WORD;
       } else if(SymbolType.STRING.equals(operandType)) {
          return SymbolType.BYTE;
+      } else if(SymbolType.NUMBER.equals(operandType)) {
+         return SymbolType.NUMBER;
       }
       throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
index bd8d030f3..81fc490c0 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
@@ -43,6 +43,8 @@ public class OperatorGetLow extends OperatorUnary {
          return SymbolType.WORD;
       } else if(SymbolType.STRING.equals(operandType)) {
          return SymbolType.BYTE;
+      } else if(SymbolType.NUMBER.equals(operandType)) {
+         return SymbolType.NUMBER;
       }
       throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
index bb14a9cd1..c6c7f3f72 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
@@ -2,6 +2,8 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
+import dk.camelot64.kickc.model.types.SymbolTypeInteger;
 import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantInteger;
@@ -24,7 +26,11 @@ public class OperatorShiftLeft extends OperatorBinary {
 
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
-      return left;
+      if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
+         return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right);
+      } else {
+         return left;
+      }
    }
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
index 6b3adb2b7..dc9c66a69 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
@@ -2,6 +2,8 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
+import dk.camelot64.kickc.model.types.SymbolTypeInteger;
 import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -23,7 +25,11 @@ public class OperatorShiftRight extends OperatorBinary {
 
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
-      return left;
+      if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
+         return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right);
+      } else {
+         return left;
+      }
    }
 
 
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
index 4967f0bfa..acef7130b 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
@@ -48,8 +48,13 @@ public class SymbolTypeNumberInference {
          // Calculate resulting constant literal
          ConstantLiteral leftLiteral = leftValue.calculateLiteral(programScope);
          ConstantLiteral rightLiteral = rightValue.calculateLiteral(programScope);
-         ConstantLiteral constantLiteral = operator.calculateLiteral(leftLiteral, rightLiteral);
-         return inferTypes(programScope, constantLiteral);
+         ConstantLiteral literal = operator.calculateLiteral(leftLiteral, rightLiteral);
+         if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) {
+            SymbolType literalType = SymbolTypeInference.inferType(programScope, leftValue, operator, rightValue);
+            ((ConstantInteger) literal).setType(literalType);
+            throw new InternalError("Unexpected advanced literal type calculation!");
+         }
+         return inferTypes(programScope, literal);
       } else {
          throw new InternalError("Both operands must be number type.");
       }
@@ -64,8 +69,13 @@ public class SymbolTypeNumberInference {
       if(SymbolType.NUMBER.equals(constantValue.getType(programScope))) {
          // Calculate resulting constant literal
          ConstantLiteral operandLiteral = constantValue.calculateLiteral(programScope);
-         ConstantLiteral constantLiteral = operator.calculateLiteral(operandLiteral, programScope);
-         return inferTypes(programScope, constantLiteral);
+         ConstantLiteral literal = operator.calculateLiteral(operandLiteral, programScope);
+         if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) {
+            SymbolType literalType = SymbolTypeInference.inferType(programScope, operator, constantValue);
+            ((ConstantInteger) literal).setType(literalType);
+            throw new InternalError("Unexpected advanced literal type calculation!");
+         }
+         return inferTypes(programScope, literal);
       } else {
          throw new InternalError("Operand must be number type.");
       }
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java
index e15ed558a..df51994a4 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java
@@ -50,7 +50,11 @@ public class ConstantBinary implements ConstantValue {
 
    @Override
    public ConstantLiteral calculateLiteral(ProgramScope scope) {
-      return operator.calculateLiteral(left.calculateLiteral(scope), right.calculateLiteral(scope));
+      ConstantLiteral literal = operator.calculateLiteral(left.calculateLiteral(scope), right.calculateLiteral(scope));
+      if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(scope))) {
+         ((ConstantInteger) literal).setType(getType(scope));
+      }
+      return literal;
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java
index 80fc32871..a111b9c07 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java
@@ -38,7 +38,11 @@ public class ConstantUnary implements ConstantValue {
 
    @Override
    public ConstantLiteral calculateLiteral(ProgramScope scope) {
-      return operator.calculateLiteral(operand.calculateLiteral(scope), scope);
+      ConstantLiteral literal = operator.calculateLiteral(operand.calculateLiteral(scope), scope);
+      if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(scope))) {
+         ((ConstantInteger) literal).setType(getType(scope));
+      }
+      return literal;
    }
 
    @Override
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index f9a125777..6a0063197 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,6 +32,11 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testToD018Problem() throws IOException, URISyntaxException {
+      compileAndCompare("tod018-problem", log());
+   }
+
    @Test
    public void testHelloWorld0() throws IOException, URISyntaxException {
       compileAndCompare("helloworld0");
diff --git a/src/test/kc/examples/sinsprites/sinus-sprites.kc b/src/test/kc/examples/sinsprites/sinus-sprites.kc
index d27f76bb9..a81055760 100644
--- a/src/test/kc/examples/sinsprites/sinus-sprites.kc
+++ b/src/test/kc/examples/sinsprites/sinus-sprites.kc
@@ -104,7 +104,7 @@ void place_sprites() {
     *SPRITES_EXPAND_X = %01111111;
     *SPRITES_EXPAND_Y = %01111111;
     byte* sprites_ptr = SCREEN+$3f8;
-    byte spr_id = (byte)(sprites/$40);
+    byte spr_id = (byte)((word)sprites/$40);
     byte spr_x = 60;
     byte j2 = 0;
     byte col = $5;
diff --git a/src/test/kc/inline-kasm-resource.kc b/src/test/kc/inline-kasm-resource.kc
index 6b7bf9b32..a0d9b8593 100644
--- a/src/test/kc/inline-kasm-resource.kc
+++ b/src/test/kc/inline-kasm-resource.kc
@@ -14,7 +14,7 @@ const byte* SPRITES_XPOS = $d000;
 const byte* SPRITES_YPOS = $d001;
 
 void main() {
-    *(SCREEN+$3f8) = (byte)(SPRITE/$40);
+    *(SCREEN+$3f8) = (byte)((word)SPRITE/$40);
     *SPRITES_ENABLE = 1;
     *SPRITES_XPOS = 100;
     *SPRITES_YPOS = 100;
diff --git a/src/test/kc/tod018-problem.kc b/src/test/kc/tod018-problem.kc
new file mode 100644
index 000000000..cb6b2e5c7
--- /dev/null
+++ b/src/test/kc/tod018-problem.kc
@@ -0,0 +1,9 @@
+// Tests a problem with tod018 not calculating types correctly
+
+void main() {
+    const byte *D018 = 0xd018;
+    const byte* screen = 0x0400;
+    byte d018val = >((word)screen&$3fff);
+    *D018 = d018val;
+}
+

From cab95b6ba547a9204022ccfbb851676a797192f1 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 7 May 2019 22:08:59 +0200
Subject: [PATCH 15/93] Working on fixing test errors - 198/350 working.

---
 src/main/fragment/vduz1=_dword_vbuaa.asm            |  5 +++++
 src/main/fragment/vduz1=vduc1_plus_vduz2.asm        | 13 +++++++++++++
 src/main/fragment/vduz1=vduz1_plus_vduz2.asm        |  3 +--
 src/main/fragment/vduz1=vduz2_plus_vwuc1.asm        |  3 +--
 .../model/iterator/ProgramExpressionBinary.java     |  4 ++++
 5 files changed, 24 insertions(+), 4 deletions(-)
 create mode 100644 src/main/fragment/vduz1=_dword_vbuaa.asm
 create mode 100644 src/main/fragment/vduz1=vduc1_plus_vduz2.asm

diff --git a/src/main/fragment/vduz1=_dword_vbuaa.asm b/src/main/fragment/vduz1=_dword_vbuaa.asm
new file mode 100644
index 000000000..e1a56bd93
--- /dev/null
+++ b/src/main/fragment/vduz1=_dword_vbuaa.asm
@@ -0,0 +1,5 @@
+sta {z1}
+lda #0
+sta {z1}+1
+sta {z1}+2
+sta {z1}+3
diff --git a/src/main/fragment/vduz1=vduc1_plus_vduz2.asm b/src/main/fragment/vduz1=vduc1_plus_vduz2.asm
new file mode 100644
index 000000000..aee9842f5
--- /dev/null
+++ b/src/main/fragment/vduz1=vduc1_plus_vduz2.asm
@@ -0,0 +1,13 @@
+lda {z2}
+clc
+adc #<{c1}
+sta {z1}
+lda {z2}+1
+adc #>{c1}
+sta {z1}+1
+lda {z2}+2
+adc #0
+sta {z1}+2
+lda {z2}+3
+adc #0
+sta {z1}+3
\ No newline at end of file
diff --git a/src/main/fragment/vduz1=vduz1_plus_vduz2.asm b/src/main/fragment/vduz1=vduz1_plus_vduz2.asm
index 3574d1e24..973a718d1 100644
--- a/src/main/fragment/vduz1=vduz1_plus_vduz2.asm
+++ b/src/main/fragment/vduz1=vduz1_plus_vduz2.asm
@@ -10,5 +10,4 @@ adc {z2}+2
 sta {z1}+2
 lda {z1}+3
 adc {z2}+3
-sta {z1}+3
-
+sta {z1}+3
\ No newline at end of file
diff --git a/src/main/fragment/vduz1=vduz2_plus_vwuc1.asm b/src/main/fragment/vduz1=vduz2_plus_vwuc1.asm
index ff2fb6d2d..aee9842f5 100644
--- a/src/main/fragment/vduz1=vduz2_plus_vwuc1.asm
+++ b/src/main/fragment/vduz1=vduz2_plus_vwuc1.asm
@@ -10,5 +10,4 @@ adc #0
 sta {z1}+2
 lda {z2}+3
 adc #0
-sta {z1}+3
-
+sta {z1}+3
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
index aac9a3cb5..d10a28ec4 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
@@ -98,7 +98,9 @@ public interface ProgramExpressionBinary extends ProgramExpression {
             tmpVar.setType(toType);
             StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS);
             assignment.setrValue1(tmpVar.getRef());
+            stmtIt.previous();
             stmtIt.add(newAssignment);
+            stmtIt.next();
          }
       }
 
@@ -112,7 +114,9 @@ public interface ProgramExpressionBinary extends ProgramExpression {
             tmpVar.setType(toType);
             StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS);
             assignment.setrValue2(tmpVar.getRef());
+            stmtIt.previous();
             stmtIt.add(newAssignment);
+            stmtIt.next();
          }
       }
    }

From 21b3114b58c63d5d55615082445d65b7234206fc Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 7 May 2019 23:39:57 +0200
Subject: [PATCH 16/93] Working on fixing test errors - 202/350 working.

---
 src/test/ref/const-int-cast-problem.asm   | 19 +++++++++++++++++++
 src/test/ref/helloworld0.asm              | 16 ++++++++++++++++
 src/test/ref/tod018-problem.asm           | 12 ++++++++++++
 src/test/ref/typeid-plus-byte-problem.asm | 12 ++++++++++++
 src/test/ref/typemismatch.asm             |  7 +++++++
 5 files changed, 66 insertions(+)
 create mode 100644 src/test/ref/const-int-cast-problem.asm
 create mode 100644 src/test/ref/helloworld0.asm
 create mode 100644 src/test/ref/tod018-problem.asm
 create mode 100644 src/test/ref/typeid-plus-byte-problem.asm
 create mode 100644 src/test/ref/typemismatch.asm

diff --git a/src/test/ref/const-int-cast-problem.asm b/src/test/ref/const-int-cast-problem.asm
new file mode 100644
index 000000000..10377d0e9
--- /dev/null
+++ b/src/test/ref/const-int-cast-problem.asm
@@ -0,0 +1,19 @@
+// Test a problem with converting casted constant numbers to fixed type constant integers
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .label SCREEN = $400
+main: {
+    ldx #$79
+  b1:
+    txa
+    lsr
+    lsr
+    lsr
+    lsr
+    sta SCREEN,x
+    inx
+    cpx #$7b
+    bne b1
+    rts
+}
diff --git a/src/test/ref/helloworld0.asm b/src/test/ref/helloworld0.asm
new file mode 100644
index 000000000..4d3606742
--- /dev/null
+++ b/src/test/ref/helloworld0.asm
@@ -0,0 +1,16 @@
+// Tests minimal hello world
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .label SCREEN = $400
+main: {
+    ldx #0
+  b1:
+    lda msg,x
+    sta SCREEN,x
+    inx
+    cpx #$c
+    bne b1
+    rts
+}
+  msg: .text "hello world!@"
diff --git a/src/test/ref/tod018-problem.asm b/src/test/ref/tod018-problem.asm
new file mode 100644
index 000000000..abe4cf7a9
--- /dev/null
+++ b/src/test/ref/tod018-problem.asm
@@ -0,0 +1,12 @@
+// Tests a problem with tod018 not calculating types correctly
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label D018 = $d018
+    .label screen = $400
+    .const d018val = >screen&$3fff
+    lda #d018val
+    sta D018
+    rts
+}
diff --git a/src/test/ref/typeid-plus-byte-problem.asm b/src/test/ref/typeid-plus-byte-problem.asm
new file mode 100644
index 000000000..d92b22c23
--- /dev/null
+++ b/src/test/ref/typeid-plus-byte-problem.asm
@@ -0,0 +1,12 @@
+// Test that byte+byte creates a byte - even when there is a value overflow
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .label SCREEN = $400
+main: {
+    .const ubc2 = $fa
+    .const ubc1 = $c+$d+$e
+    lda #ubc1+ubc2
+    sta SCREEN
+    rts
+}
diff --git a/src/test/ref/typemismatch.asm b/src/test/ref/typemismatch.asm
new file mode 100644
index 000000000..29ae868a1
--- /dev/null
+++ b/src/test/ref/typemismatch.asm
@@ -0,0 +1,7 @@
+// Type mismatch - should fail gracefully
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    rts
+}

From 64a8389e6ea860db3079de2fdca9b5c9b9630eca Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Wed, 8 May 2019 00:11:33 +0200
Subject: [PATCH 17/93] Working on fixing test errors - 228/350 working.

---
 .../dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
index fd47ffd3c..0b1199cd6 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
@@ -29,7 +29,7 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization {
             // Special handling of assigning a pointer from an unsigned word
             if((programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) && (leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) {
                getLog().append("Adding pointer type conversion cast (" + leftType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
-               binary.addLeftCast(leftType, stmtIt, currentBlock.getScope(), getScope());
+               binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
             }
 
             if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) {

From ea990b5e87b2d4cabd8ff01d06191cc367dbacac Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Wed, 8 May 2019 23:24:48 +0200
Subject: [PATCH 18/93] Working on fixing test errors - fixed
 pointer-dereference-indexed - 228/350 working.

---
 .../iterator/ProgramExpressionBinary.java     | 56 +++++++++++++++++++
 .../iterator/ProgramExpressionIterator.java   | 17 +++---
 .../passes/PassNAddNumberTypeConversions.java |  8 +--
 3 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
index d10a28ec4..ff1a8b9e0 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
@@ -269,4 +269,60 @@ public interface ProgramExpressionBinary extends ProgramExpression {
          getConstantBinary().setRight(new ConstantCastValue(toType, getConstantBinary().getRight()));
       }
    }
+
+   /** Binary expression that is an indexed dereference of a pointer eg. ptr[i] or *(ptr+i). */
+   class ProgramExpressionBinaryPointerDereferenceIndexed implements ProgramExpressionBinary {
+      /** A program value containing a {@link ConstantBinary}. */
+      private ProgramValue programValue;
+
+      public ProgramExpressionBinaryPointerDereferenceIndexed(ProgramValue programValue) {
+         this.programValue = programValue;
+      }
+
+      public PointerDereferenceIndexed getPointerDereferenceIndexed() {
+         return (PointerDereferenceIndexed) programValue.get();
+      }
+
+      @Override
+      public RValue getLeft() {
+         return getPointerDereferenceIndexed().getPointer();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return Operators.PLUS;
+      }
+
+      @Override
+      public RValue getRight() {
+         return getPointerDereferenceIndexed().getIndex();
+      }
+
+      @Override
+      public void set(Value value) {
+         programValue.set(value);
+      }
+
+      @Override
+      public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         if(getPointerDereferenceIndexed().getPointer() instanceof ConstantValue) {
+            getPointerDereferenceIndexed().setPointer(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getPointer()));
+         }  else {
+            // Try to use CastValue - may later have to be supported!
+            getPointerDereferenceIndexed().setPointer(new CastValue(toType, getPointerDereferenceIndexed().getPointer()));
+         }
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         if(getPointerDereferenceIndexed().getIndex() instanceof ConstantValue) {
+            getPointerDereferenceIndexed().setIndex(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getIndex()));
+         }  else {
+            // Try to use CastValue - may later have to be supported!
+            getPointerDereferenceIndexed().setIndex(new CastValue(toType, getPointerDereferenceIndexed().getIndex()));
+         }
+      }
+   }
+
+
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
index e525c101f..c109a3001 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
@@ -7,6 +7,7 @@ import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementConditionalJump;
 import dk.camelot64.kickc.model.values.ConstantBinary;
 import dk.camelot64.kickc.model.values.ConstantUnary;
+import dk.camelot64.kickc.model.values.PointerDereferenceIndexed;
 
 import java.util.ListIterator;
 
@@ -25,13 +26,16 @@ public class ProgramExpressionIterator {
     */
    public static void execute(Program program, ProgramExpressionHandler handler) {
       // Iterate all symbols
-      ProgramValueIterator.execute(program.getScope(), (programValue, currentStmt, stmtIt, currentBlock) -> {
+      ProgramValueHandler programValueHandler = (programValue, currentStmt, stmtIt, currentBlock) -> {
          if(programValue.get() instanceof ConstantBinary) {
             handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), null, null, null);
          } else if(programValue.get() instanceof ConstantUnary) {
             handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null);
+         } else if(programValue.get() instanceof PointerDereferenceIndexed) {
+            handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null);
          }
-      });
+      };
+      ProgramValueIterator.execute(program.getScope(), programValueHandler);
 
       // Iterate all blocks/statements
       for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
@@ -53,14 +57,7 @@ public class ProgramExpressionIterator {
                }
             }
             // Iterate all statement values
-            ProgramValueIterator.execute(stmt, (programValue, currentStmt, stmtIt1, currentBlock) -> {
-               if(programValue.get() instanceof ConstantBinary) {
-                  handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), stmt, stmtIt, block);
-               } else if(programValue.get() instanceof ConstantUnary) {
-                  handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), stmt, stmtIt, block);
-               }
-
-            }, stmtIt, block);
+            ProgramValueIterator.execute(stmt, programValueHandler, stmtIt, block);
          }
       }
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
index 16688948f..6854e09b0 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -30,13 +30,13 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
                // Convert both left and right to the found type
                SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
                if(!leftType.equals(conversionType) && !(leftType instanceof SymbolTypePointer)) {
-                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
-                  binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
+                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + (currentStmt==null?"":currentStmt.toString(getProgram(), false)));
+                  binary.addLeftCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
                }
                SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
                if(!rightType.equals(conversionType) && !(rightType instanceof SymbolTypePointer)) {
-                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
-                  binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
+                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
+                  binary.addRightCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
                }
             }
          }

From f6f25e728b8bf535aca33eb040dc4851717a8e6e Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 9 May 2019 07:43:47 +0200
Subject: [PATCH 19/93] Working on special word+byte downgrade. - down to
 190/351.

---
 .../java/dk/camelot64/kickc/Compiler.java     |  1 +
 .../passes/PassNAddTypeConversionsNew.java    |  8 ++
 .../passes/PassNDowngradeBytePlusWord.java    | 91 +++++++++++++++++++
 3 files changed, 100 insertions(+)
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 74445a9ff..362b19c25 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -233,6 +233,7 @@ public class Compiler {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
       optimizations.add(new PassNAddTypeConversionsNew(program));
       optimizations.add(new PassNAddNumberTypeConversions(program));
+      optimizations.add(new PassNDowngradeBytePlusWord(program));
       optimizations.add(new PassNTypeInference(program));
       optimizations.add(new PassNTypeIdSimplification(program));
       optimizations.add(new Pass2CullEmptyBlocks(program));
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
index 0b1199cd6..4f4e3d1b6 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
@@ -35,6 +35,14 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization {
             if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) {
                SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
                if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) {
+                  // If byte-like + word-like - skip!!
+                  if(leftType.equals(SymbolType.WORD) && rightType.equals(SymbolType.BYTE)) {
+                     return;
+                  }
+                  if(rightType.equals(SymbolType.WORD) && leftType.equals(SymbolType.BYTE)) {
+                     return;
+                  }
+
                   // Convert both left and right to the found type
                   if(!leftType.equals(conversionType)) {
                      getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java
new file mode 100644
index 000000000..34182438b
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java
@@ -0,0 +1,91 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.types.SymbolTypePointer;
+import dk.camelot64.kickc.model.values.*;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Downgrade any number expression cast that are part of a WORD+NUMBER expression to BYTE if the number is small enough to fit in the byte.
+ */
+public class PassNDowngradeBytePlusWord extends Pass2SsaOptimization {
+
+   public PassNDowngradeBytePlusWord(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
+      ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(binaryExpression instanceof ProgramExpressionBinary) {
+            ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression;
+            RValue left = binary.getLeft();
+            RValue right = binary.getRight();
+            if(isConstantWord(left) && isWordLike(right) && isByteLike((ConstantValue) left)) {
+               getLog().append("Downgrading number conversion cast to (byte) " + binary.getLeft().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
+               binary.addLeftCast(SymbolType.BYTE, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
+               modified.set(true);
+            } else if(isConstantWord(right) && isWordLike(left) && isByteLike((ConstantValue) right)) {
+               getLog().append("Downgrading number conversion cast to (byte) " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
+               binary.addRightCast(SymbolType.BYTE, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
+               modified.set(true);
+            }
+
+         }
+      });
+      return modified.get();
+   }
+
+
+   /**
+    * Determines if a constant value is a byte-like value (can be represented inside a BYTE)
+    *
+    * @param constantValue The value to examine
+    * @return true if the value is a byte-like value
+    */
+   public boolean isByteLike(ConstantValue constantValue) {
+      ConstantLiteral constantLiteral = (constantValue).calculateLiteral(getScope());
+      if(constantLiteral instanceof ConstantInteger) {
+         ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
+         Long value = constantInteger.getValue();
+         if(SymbolType.BYTE.contains(value)) {
+            return true;
+         }
+      }
+      return false;
+   }
+
+   /**
+    * Determines if a value is a word-like value (WORD or Pointer)
+    *
+    * @param rValue The value to examine
+    * @return true if the value is a word-like value
+    */
+   public boolean isWordLike(RValue rValue) {
+      SymbolType symbolType = SymbolTypeInference.inferType(getProgram().getScope(), rValue);
+      return symbolType.equals(SymbolType.WORD) || symbolType instanceof SymbolTypePointer;
+   }
+
+
+   /**
+    * Determines if the passed value is a constant cast to WORD
+    *
+    * @param rValue The value to examine
+    * @return true if the value is a constant cast to word
+    */
+   public boolean isConstantWord(RValue rValue) {
+      if(rValue instanceof ConstantInteger && ((ConstantInteger) rValue).getType().equals(SymbolType.WORD)) {
+         return true;
+      }
+      if((rValue instanceof ConstantCastValue) && ((ConstantCastValue) rValue).getToType().equals(SymbolType.WORD))
+         return true;
+      return false;
+   }
+
+}

From 51c10d29c38742152e99901a5e3cdfc0a3e4f729 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Fri, 10 May 2019 11:20:37 +0200
Subject: [PATCH 20/93] Working on fixing type conversion casting. Still a work
 in progress!

---
 .../model/types/SymbolTypeConversion.java     | 12 +++++++---
 .../passes/Pass2ConstantSimplification.java   |  8 +++----
 .../passes/PassNAddNumberTypeConversions.java | 24 +++++++++++--------
 .../passes/PassNAddTypeConversionsNew.java    |  2 ++
 4 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index 15c35ad73..9e136c58b 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -27,6 +27,7 @@ public class SymbolTypeConversion {
     * @return The type resulting from a binary operator performed on the two parameters
     */
    public static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) {
+      // If any of the two types are unresolved - return an unresolved result
       if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) {
          return SymbolType.NUMBER;
       }
@@ -57,7 +58,7 @@ public class SymbolTypeConversion {
    }
 
    /**
-    * Find the integer type that results from a binary operator according to the special number type conversion https://gitlab.com/camelot/kickc/issues/181
+    * Find the integer type that a number operand in a binary operator should be converted/cast to according to number type conversion https://gitlab.com/camelot/kickc/issues/181
     *
     * @param left The left value
     * @param right The right value
@@ -65,7 +66,7 @@ public class SymbolTypeConversion {
     * @param currentStmt The current statement (used only for exception context)
     * @return a non-null fixed integer type if a number type conversion is relevant.
     */
-   public static SymbolType convertedNumberType(RValue left, RValue right, ProgramScope symbols, Statement currentStmt) {
+   public static SymbolType getNumberCastType(RValue left, RValue right, ProgramScope symbols, Statement currentStmt) {
 
       SymbolType leftType = SymbolTypeInference.inferType(symbols, left);
       SymbolType rightType = SymbolTypeInference.inferType(symbols, right);
@@ -80,6 +81,10 @@ public class SymbolTypeConversion {
             return null;
          }
 
+         // Treat pointers like WORD
+         if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD;
+         if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD;
+
          RValue numberVal;
          SymbolTypeIntegerFixed fixedType;
          if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) {
@@ -125,7 +130,8 @@ public class SymbolTypeConversion {
                      } else {
                         smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
                      }
-                     return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType;
+                     return smallestUnsignedType;
+                     //return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType;
                   }
                } else {
                   throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java
index 8b748d28e..cb4490626 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java
@@ -29,13 +29,13 @@ public class Pass2ConstantSimplification extends Pass2SsaOptimization {
                // Found a candidate!!
                ConstantInteger intOperand = (ConstantInteger) unary.getOperand();
                getLog().append("Simplifying constant integer increment "+unary);
-               programValue.set(new ConstantInteger(intOperand.getValue()+1));
+               programValue.set(new ConstantInteger(intOperand.getValue()+1, intOperand.getType()));
                optimized[0] = true;
             } else if(Operators.DECREMENT.equals(unary.getOperator()) && unary.getOperand() instanceof ConstantInteger) {
                // Found a candidate!!
                ConstantInteger intOperand = (ConstantInteger) unary.getOperand();
                getLog().append("Simplifying constant integer decrement "+unary);
-               programValue.set(new ConstantInteger(intOperand.getValue()+1));
+               programValue.set(new ConstantInteger(intOperand.getValue()-1, intOperand.getType()));
                optimized[0] = true;
             }
          } else if(programValue.get() instanceof ConstantBinary) {
@@ -43,10 +43,10 @@ public class Pass2ConstantSimplification extends Pass2SsaOptimization {
             if(Operators.MULTIPLY.equals(binary.getOperator())) {
                if(binary.getLeft() instanceof ConstantInteger && ((ConstantInteger) binary.getLeft()).getValue() == 0) {
                   getLog().append("Simplifying constant multiply by zero " + binary);
-                  programValue.set(new ConstantInteger(0L));
+                  programValue.set(new ConstantInteger(0L, binary.getType(getScope())));
                } else if(binary.getRight() instanceof ConstantInteger && ((ConstantInteger) binary.getRight()).getValue() == 0) {
                   getLog().append("Simplifying constant multiply by zero " + binary);
-                  programValue.set(new ConstantInteger(0L));
+                  programValue.set(new ConstantInteger(0L, binary.getType(getScope())));
                }
             } else if(Operators.PLUS.equals(binary.getOperator())) {
                if(binary.getLeft() instanceof ConstantInteger && ((ConstantInteger) binary.getLeft()).getValue() == 0) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
index 6854e09b0..7a69f1fd4 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -6,9 +6,10 @@ import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeConversion;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
 import dk.camelot64.kickc.model.values.RValue;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * Add casts to {@link SymbolType#NUMBER} expressions that meet a typed value in a binary expression (including assignment)
  */
@@ -20,28 +21,31 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
 
    @Override
    public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
       ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
          if(binaryExpression instanceof ProgramExpressionBinary) {
             ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression;
             RValue left = binary.getLeft();
             RValue right = binary.getRight();
-            SymbolType conversionType = SymbolTypeConversion.convertedNumberType(left, right, getScope(), currentStmt);
-            if(conversionType != null) {
+            SymbolType castType = SymbolTypeConversion.getNumberCastType(left, right, getScope(), currentStmt);
+            if(castType != null) {
                // Convert both left and right to the found type
                SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
-               if(!leftType.equals(conversionType) && !(leftType instanceof SymbolTypePointer)) {
-                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + (currentStmt==null?"":currentStmt.toString(getProgram(), false)));
-                  binary.addLeftCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+               if(SymbolType.NUMBER.equals(leftType)) {
+                  getLog().append("Adding number conversion cast (" + castType + ") " + binary.getLeft().toString() + " in " + (currentStmt==null?"":currentStmt.toString(getProgram(), false)));
+                  binary.addLeftCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+                  modified.set(true);
                }
                SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
-               if(!rightType.equals(conversionType) && !(rightType instanceof SymbolTypePointer)) {
-                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
-                  binary.addRightCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+               if(rightType.equals(SymbolType.NUMBER)) {
+                  getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
+                  binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+                  modified.set(true);
                }
             }
          }
       });
-      return false;
+      return modified.get();
    }
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
index 4f4e3d1b6..ee10bd5c5 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
@@ -32,6 +32,7 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization {
                binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
             }
 
+            /*
             if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) {
                SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
                if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) {
@@ -54,6 +55,7 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization {
                   }
                }
             }
+            */
          }
       });
       return false;

From 3c8845d6a6a751e314f52d5c60ca6e9db9dec536 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Sat, 11 May 2019 19:55:03 +0200
Subject: [PATCH 21/93] Added alias elimination to constant optimization phase.
 255/351.

---
 src/main/java/dk/camelot64/kickc/Compiler.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 362b19c25..9492c763b 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -299,6 +299,7 @@ public class Compiler {
    private void pass2InlineConstants() {
       // Constant inlining optimizations - as the last step to ensure that constant identification has been completed
       List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>();
+      constantOptimizations.add(new Pass2AliasElimination(program));
       constantOptimizations.add(new Pass2ConstantInlining(program));
       constantOptimizations.add(new Pass2ConstantStringConsolidation(program));
       constantOptimizations.add(new Pass2IdenticalPhiElimination(program));

From bd6ece561b3bf66a266380db6874f03bc7be2d09 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Sat, 11 May 2019 20:14:14 +0200
Subject: [PATCH 22/93] Fixed multiply to shift. 260/351.

---
 .../kickc/passes/Pass2MultiplyToShiftRewriting.java  | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java b/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java
index 123efd721..cad43daf9 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java
@@ -6,14 +6,7 @@ import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.operators.Operators;
 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.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 kickass.pass.expressions.expr.Constant;
 
 import java.util.ListIterator;
 
@@ -34,7 +27,8 @@ public class Pass2MultiplyToShiftRewriting extends Pass2SsaOptimization {
             if(statement instanceof StatementAssignment) {
                StatementAssignment assignment = (StatementAssignment) statement;
                if(Operators.MULTIPLY.equals(assignment.getOperator()) || Operators.DIVIDE.equals(assignment.getOperator())) {
-                  ConstantLiteral constantLiteral = getConstantLiteral(assignment);
+                  if(assignment.getrValue1() instanceof ConstantValue) continue;
+                  ConstantLiteral constantLiteral = getConstantLiteral2(assignment);
                   if(constantLiteral instanceof ConstantInteger) {
                      Long constantInt = ((ConstantInteger)constantLiteral).getInteger();
                      double power2 = Math.log(constantInt) / Math.log(2);
@@ -72,7 +66,7 @@ public class Pass2MultiplyToShiftRewriting extends Pass2SsaOptimization {
     * @param assignment The Assignment
     * @return The constant literal value for RValue2 (or null)
     */
-   private ConstantLiteral getConstantLiteral(StatementAssignment assignment) {
+   private ConstantLiteral getConstantLiteral2(StatementAssignment assignment) {
       if(assignment.getrValue2() instanceof ConstantValue) {
          ConstantValue constantValue = (ConstantValue) assignment.getrValue2();
          try {

From e56e66acd8d7b96b73e1f072d53fe473d63b6891 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Sat, 11 May 2019 23:16:03 +0200
Subject: [PATCH 23/93] Working on multiply/divide.

---
 .../dk/camelot64/kickc/model/operators/OperatorDivide.java | 3 +--
 .../camelot64/kickc/model/operators/OperatorMultiply.java  | 7 +++++++
 .../kickc/passes/Pass0GenerateStatementSequence.java       | 2 +-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
index 3ce383230..f36dfdaca 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
@@ -29,11 +29,10 @@ public class OperatorDivide extends OperatorBinary {
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
       if(left instanceof SymbolTypePointer) {
-         if(SymbolType.isByte(right) || SymbolType.isWord(right)) {
+         if(right.equals(SymbolType.BYTE) || right.equals(SymbolType.WORD)|| right.equals(SymbolType.NUMBER)) {
             return left;
          } else {
             throw new NoMatchingType("Cannot divide pointer by "+right.toString());
-
          }
       }
       // Handle numeric types through proper promotion
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
index 76bb36ec6..a4a98d455 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
@@ -22,6 +22,13 @@ public class OperatorMultiply extends OperatorBinary {
 
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+      if(left instanceof SymbolTypePointer) {
+         if(right.equals(SymbolType.BYTE) || right.equals(SymbolType.WORD)|| right.equals(SymbolType.NUMBER)) {
+            return left;
+         } else {
+            throw new NoMatchingType("Cannot multiply pointer by "+right.toString());
+         }
+      }
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
          return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index 65afaf38f..34533b203 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -501,7 +501,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
       } else {
          if(type instanceof SymbolTypeIntegerFixed) {
             // Add an zero value initializer
-            ConstantInteger zero = new ConstantInteger(0L);
+            ConstantInteger zero = new ConstantInteger(0L, type);
             Statement stmt = new StatementAssignment(lValue.getRef(), zero, new StatementSource(ctx), ensureUnusedComments(comments));
             sequence.addStatement(stmt);
          } else if(type instanceof SymbolTypeArray) {

From 6e566852bafe362e65782b00ace46e978476da49 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 12 May 2019 12:27:48 +0200
Subject: [PATCH 24/93] Fixed assignment type conversions and unnecesary
 byte/word casts. 269/351

---
 .../java/dk/camelot64/kickc/Compiler.java     |  4 +-
 .../model/types/SymbolTypeConversion.java     | 46 +++++++++----
 .../kickc/model/types/SymbolTypeMatch.java    | 31 ---------
 .../kickc/passes/Pass2AssertTypeMatch.java    |  4 +-
 .../Pass2ConstantCastSimplification.java      | 20 +++++-
 .../passes/Pass2ConstantIdentification.java   |  4 +-
 .../PassNAddTypeConversionAssignment.java     | 57 ++++++++++++++++
 .../passes/PassNAddTypeConversionsNew.java    | 65 -------------------
 .../passes/PassNDowngradeBytePlusWord.java    |  1 -
 9 files changed, 115 insertions(+), 117 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 9492c763b..2e73baad4 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -165,7 +165,7 @@ public class Compiler {
       new Pass1FixLValuesLoHi(program).execute();
       new Pass1AssertNoLValueIntermediate(program).execute();
       new Pass1PointerSizeofFix(program).execute();
-      new PassNAddTypeConversionsNew(program).execute();
+      new PassNAddTypeConversionAssignment(program).execute();
       new Pass1EarlyConstantIdentification(program).execute();
       new PassNStatementIndices(program).step();
       new PassNCallGraphAnalysis(program).step();
@@ -231,7 +231,7 @@ public class Compiler {
 
    private void pass2Optimize() {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
-      optimizations.add(new PassNAddTypeConversionsNew(program));
+      optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new PassNAddNumberTypeConversions(program));
       optimizations.add(new PassNDowngradeBytePlusWord(program));
       optimizations.add(new PassNTypeInference(program));
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index 9e136c58b..f1663a6b8 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -85,6 +85,7 @@ public class SymbolTypeConversion {
          if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD;
          if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD;
 
+         // Identify which of the two operands is a number and which is a fixed type
          RValue numberVal;
          SymbolTypeIntegerFixed fixedType;
          if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) {
@@ -95,19 +96,12 @@ public class SymbolTypeConversion {
             // Right is the number type - left is the fixed type
             numberVal = right;
             fixedType = (SymbolTypeIntegerFixed) leftType;
-         } else if(SymbolType.NUMBER.equals(leftType) && rightType instanceof SymbolTypePointer) {
-            // Left is the number type - right is a pointer (effectively unsigned word)
-            numberVal = left;
-            fixedType = SymbolType.WORD;
-         } else if(SymbolType.NUMBER.equals(rightType) && leftType instanceof SymbolTypePointer) {
-            // Right is the number type - left is a pointer (effectively unsigned word)
-            numberVal = right;
-            fixedType = SymbolType.WORD;
          } else {
             // Binary operator combining number and non-integer
             return null;
          }
 
+         // Find the cast type if possible
          if(numberVal instanceof ConstantValue) {
             ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols);
             if(constantLiteral instanceof ConstantInteger) {
@@ -115,14 +109,14 @@ public class SymbolTypeConversion {
                if(SymbolType.NUMBER.equals(constantInteger.getType())) {
                   Long value = constantInteger.getValue();
                   if(fixedType.isSigned()) {
-                     // b) If one operand is a signed type and the other a number they are both converted to the smallest signed type that can hold the values.
+                     // b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
                      SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value);
                      if(smallestSignedType == null) {
                         throw new CompileError("Number constant has value that cannot be represented by a signed type " + value, currentStmt);
                      }
-                     return smallestSignedType.getBits() > fixedType.getBits() ? smallestSignedType : fixedType;
+                     return smallestSignedType;
                   } else {
-                     // c) If one operand is an unsigned type and the other a number they are both converted to the smallest unsigned type that can hold the values.
+                     // b) If one operand is a signed type and the other a number the number is converted to the smallest unsigned type that can hold its values.
                      //    If the number value is negative it is converted to unsigned using two's complement.
                      SymbolTypeIntegerFixed smallestUnsignedType;
                      if(value < 0) {
@@ -131,7 +125,6 @@ public class SymbolTypeConversion {
                         smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
                      }
                      return smallestUnsignedType;
-                     //return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType;
                   }
                } else {
                   throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
@@ -145,4 +138,33 @@ public class SymbolTypeConversion {
       // No number conversion
       return null;
    }
+
+   /**
+    * Determines if the types of an assignment match up properly
+    * @param lValueType The type of the LValue
+    * @param rValueType The type of the RValue
+    * @return true if the types match up
+    */
+   public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) {
+      if(lValueType.equals(rValueType))
+         return true;
+      if(lValueType.equals(SymbolType.WORD) && rValueType.equals(SymbolType.BYTE))
+         return true;
+      if(lValueType.equals(SymbolType.SWORD) && rValueType.equals(SymbolType.SBYTE))
+         return true;
+      if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
+         // L-value is still a number - constants are probably not done being identified & typed
+         return true;
+      }
+      if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
+         // String value can be assigned into a pointer
+         return true;
+      }
+      if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && assignmentTypeMatch(((SymbolTypePointer) lValueType).getElementType(), ((SymbolTypePointer) rValueType).getElementType())) {
+         // Pointer types assigned from each other
+         // TODO: Maybe handle sizes
+         return true;
+      }
+      return false;
+   }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java
deleted file mode 100644
index b058abbb2..000000000
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMatch.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package dk.camelot64.kickc.model.types;
-
-/** Container for function checking if types of an assignment match up */
-public class SymbolTypeMatch {
-
-   /**
-    * Determines if the types of an assignment match up properly
-    * @param lValueType The type of the LValue
-    * @param rValueType The type of the RValue
-    * @return true if the types match up
-    */
-   public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) {
-      if(lValueType.equals(rValueType)) {
-         return true;
-      }
-      if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
-         // L-value is still a number - constants are probably not done being identified & typed
-         return true;
-      }
-      if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
-         // String value can be assigned into a pointer
-         return true;
-      }
-      if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && assignmentTypeMatch(((SymbolTypePointer) lValueType).getElementType(), ((SymbolTypePointer) rValueType).getElementType())) {
-         // Pointer types assigned from each other
-         // TODO: Maybe handle sizes
-         return true;
-      }
-      return false;
-   }
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
index 82c5fce43..5e9e3157d 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
@@ -7,8 +7,8 @@ import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementConditionalJump;
 import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypeMatch;
 import dk.camelot64.kickc.model.values.LValue;
 import dk.camelot64.kickc.model.values.RValue;
 
@@ -51,7 +51,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion {
       LValue lValue = statement.getlValue();
       SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
       SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement);
-      if(SymbolTypeMatch.assignmentTypeMatch(lValueType, rValueType)) return;
+      if(SymbolTypeConversion.assignmentTypeMatch(lValueType, rValueType)) return;
       // Types do not match
       getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false));
       throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource());
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
index 893003447..b8daf00a8 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
@@ -28,10 +28,10 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
          if(programExpression.getOperator() instanceof OperatorCast) {
             OperatorCast operatorCast = (OperatorCast) programExpression.getOperator();
             ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression;
+            SymbolType castType = operatorCast.getToType();
             if(unary.getOperand() instanceof ConstantInteger) {
                ConstantInteger constantInteger = (ConstantInteger) unary.getOperand();
                if(SymbolType.NUMBER.equals(constantInteger.getType())) {
-                  SymbolType castType = operatorCast.getToType();
                   if(castType instanceof SymbolTypeIntegerFixed ) {
                      ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
                      programExpression.set(newConstInt);
@@ -43,6 +43,14 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
                      getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
                      optimized.set(true);
                   }
+               } else if(castType instanceof SymbolTypeIntegerFixed) {
+                  if(((SymbolTypeIntegerFixed) castType).contains(constantInteger.getValue())) {
+                     // Cast type contains the value - cast not needed
+                     ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
+                     programExpression.set(newConstInt);
+                     getLog().append("Simplifying constant integer cast " + newConstInt.toString());
+                     optimized.set(true);
+                  }
                }
             }
          }
@@ -52,8 +60,8 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
             ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get();
             if(constantCastValue.getValue() instanceof ConstantInteger) {
                ConstantInteger constantInteger = (ConstantInteger) constantCastValue.getValue();
+               SymbolType castType = constantCastValue.getToType();
                if(SymbolType.NUMBER.equals(constantInteger.getType())) {
-                  SymbolType castType = constantCastValue.getToType();
                   if(castType instanceof SymbolTypeIntegerFixed ) {
                      ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
                      programValue.set(newConstInt);
@@ -65,6 +73,14 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
                      getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
                      optimized.set(true);
                   }
+               } else if(castType instanceof SymbolTypeIntegerFixed) {
+                  if(((SymbolTypeIntegerFixed) castType).contains(constantInteger.getValue())) {
+                     // Cast type contains the value - cast not needed
+                     ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
+                     programValue.set(newConstInt);
+                     getLog().append("Simplifying constant integer cast " + newConstInt.toString());
+                     optimized.set(true);
+                  }
                }
             }
          }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
index d4df53443..be3634d84 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
@@ -15,8 +15,8 @@ import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.symbols.Scope;
 import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypeMatch;
 import dk.camelot64.kickc.model.values.*;
 
 import java.util.LinkedHashMap;
@@ -79,7 +79,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
             continue;
          }
 
-         if(!SymbolTypeMatch.assignmentTypeMatch(variableType, valueType)) {
+         if(!SymbolTypeConversion.assignmentTypeMatch(variableType, valueType)) {
                throw new CompileError(
                      "Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) +
                            "\n value: (" + valueType.toString() + ") " + constVal.calculateLiteral(getScope()) +
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
new file mode 100644
index 000000000..e2f2049c0
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
@@ -0,0 +1,57 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.types.*;
+import dk.camelot64.kickc.model.values.RValue;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Add a cast a variable is assigned something of a convertible type.
+ * Also allows pointers to be assigned integer values.
+ */
+public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
+
+   public PassNAddTypeConversionAssignment(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
+      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(programExpression instanceof ProgramExpressionBinary) {
+            ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression;
+            RValue left = binary.getLeft();
+            RValue right = binary.getRight();
+            SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
+            SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
+
+            if(!SymbolTypeConversion.assignmentTypeMatch(leftType, rightType)) {
+               // Assigning a pointer from an unsigned word
+               if(programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) {
+                  if((leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) {
+                     getLog().append("Adding pointer type conversion cast (" + leftType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
+                     binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
+                     modified.set(true);
+                  }
+               }
+               if(leftType instanceof SymbolTypeIntegerFixed && SymbolType.isInteger(rightType)) {
+                  SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
+                  // Add cast to the right Type if needed
+                  if(leftType.equals(conversionType) && !rightType.equals(conversionType)) {
+                     getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
+                     binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
+                     modified.set(true);
+                  }
+               }
+            }
+         }
+      });
+      return modified.get();
+   }
+
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
deleted file mode 100644
index ee10bd5c5..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
-import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
-import dk.camelot64.kickc.model.types.*;
-import dk.camelot64.kickc.model.values.RValue;
-
-/**
- * Add casts in binary expressions where left/right types are not equal according to the C99 type conversion rules
- * 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70.
- */
-public class PassNAddTypeConversionsNew extends Pass2SsaOptimization {
-
-   public PassNAddTypeConversionsNew(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
-         if(programExpression instanceof ProgramExpressionBinary) {
-            ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression;
-            RValue left = binary.getLeft();
-            RValue right = binary.getRight();
-            SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
-            SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
-
-            // Special handling of assigning a pointer from an unsigned word
-            if((programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryAssignmentLValue) && (leftType instanceof SymbolTypePointer) && SymbolType.isInteger(rightType)) {
-               getLog().append("Adding pointer type conversion cast (" + leftType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
-               binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
-            }
-
-            /*
-            if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) {
-               SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
-               if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) {
-                  // If byte-like + word-like - skip!!
-                  if(leftType.equals(SymbolType.WORD) && rightType.equals(SymbolType.BYTE)) {
-                     return;
-                  }
-                  if(rightType.equals(SymbolType.WORD) && leftType.equals(SymbolType.BYTE)) {
-                     return;
-                  }
-
-                  // Convert both left and right to the found type
-                  if(!leftType.equals(conversionType)) {
-                     getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + currentStmt.toString(getProgram(), false));
-                     binary.addLeftCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
-                  }
-                  if(!rightType.equals(conversionType)) {
-                     getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + currentStmt.toString(getProgram(), false));
-                     binary.addRightCast(conversionType, stmtIt, currentBlock.getScope(), getScope());
-                  }
-               }
-            }
-            */
-         }
-      });
-      return false;
-   }
-
-
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java
index 34182438b..b3f819d53 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java
@@ -42,7 +42,6 @@ public class PassNDowngradeBytePlusWord extends Pass2SsaOptimization {
       return modified.get();
    }
 
-
    /**
     * Determines if a constant value is a byte-like value (can be represented inside a BYTE)
     *

From e09d81cd132b50c0ed75ef55d3818082cc76fb76 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 12 May 2019 12:59:47 +0200
Subject: [PATCH 25/93] Improved no-cast detection. 271/351

---
 .../camelot64/kickc/fragment/AsmFormat.java   | 46 +++++++++++--------
 .../Pass2ConstantCastSimplification.java      |  4 +-
 .../dk/camelot64/kickc/test/TestPrograms.java |  2 +-
 3 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
index 895e806a8..26db72078 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
@@ -114,12 +114,14 @@ public class AsmFormat {
             // No cast needed
             return getAsmConstant(program, operand, outerPrecedence, codeScope);
          }
-         if(SymbolType.NUMBER.equals(operandType)) {
-            List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand);
-            if(operandInferedTypes.contains(SymbolType.BYTE) || operandInferedTypes.contains(SymbolType.SBYTE)) {
-               // No cast needed
-               return getAsmConstant(program, operand, outerPrecedence, codeScope);
-            }
+         ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope());
+         if(constantLiteral instanceof ConstantInteger && Operators.CAST_BYTE.equals(operator) && SymbolType.BYTE.contains(((ConstantInteger) constantLiteral).getValue())) {
+            // No cast needed
+            return getAsmConstant(program, operand, outerPrecedence, codeScope);
+         }
+         if(constantLiteral instanceof ConstantInteger && Operators.CAST_SBYTE.equals(operator) && SymbolType.SBYTE.contains(((ConstantInteger) constantLiteral).getValue())) {
+            // No cast needed
+            return getAsmConstant(program, operand, outerPrecedence, codeScope);
          }
          // Cast is needed
          return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
@@ -129,12 +131,18 @@ public class AsmFormat {
             // No cast needed
             return getAsmConstant(program, operand, outerPrecedence, codeScope);
          }
-         if(SymbolType.NUMBER.equals(operandType)) {
-            List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand);
-            if(operandInferedTypes.contains(SymbolType.WORD) || operandInferedTypes.contains(SymbolType.SWORD)) {
-               // No cast needed
-               return getAsmConstant(program, operand, outerPrecedence, codeScope);
-            }
+         ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope());
+         if(constantLiteral instanceof ConstantInteger  && Operators.CAST_WORD.equals(operator)&& SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) {
+            // No cast needed
+            return getAsmConstant(program, operand, outerPrecedence, codeScope);
+         }
+         if(constantLiteral instanceof ConstantInteger  && Operators.CAST_SWORD.equals(operator)&& SymbolType.SWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
+            // No cast needed
+            return getAsmConstant(program, operand, outerPrecedence, codeScope);
+         }
+         if(constantLiteral instanceof ConstantInteger  && (operator instanceof OperatorCastPtr) && SymbolType.WORD.contains(((ConstantInteger) constantLiteral).getValue())) {
+            // No cast needed
+            return getAsmConstant(program, operand, outerPrecedence, codeScope);
          }
          // Cast is needed
          return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffff), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
@@ -144,12 +152,14 @@ public class AsmFormat {
             // No cast needed
             return getAsmConstant(program, operand, outerPrecedence, codeScope);
          }
-         if(SymbolType.NUMBER.equals(operandType)) {
-            List<SymbolTypeIntegerFixed> operandInferedTypes = SymbolTypeNumberInference.inferTypes(program.getScope(), operand);
-            if(operandInferedTypes.contains(SymbolType.DWORD) || operandInferedTypes.contains(SymbolType.SDWORD)) {
-               // No cast needed
-               return getAsmConstant(program, operand, outerPrecedence, codeScope);
-            }
+         ConstantLiteral constantLiteral = operand.calculateLiteral(program.getScope());
+         if(constantLiteral instanceof ConstantInteger  && Operators.CAST_DWORD.equals(operator)&& SymbolType.DWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
+            // No cast needed
+            return getAsmConstant(program, operand, outerPrecedence, codeScope);
+         }
+         if(constantLiteral instanceof ConstantInteger  && Operators.CAST_SDWORD.equals(operator)&& SymbolType.SDWORD.contains(((ConstantInteger) constantLiteral).getValue())) {
+            // No cast needed
+            return getAsmConstant(program, operand, outerPrecedence, codeScope);
          }
          // Cast is needed
          return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
index b8daf00a8..0d516f99e 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
@@ -8,9 +8,7 @@ import dk.camelot64.kickc.model.operators.OperatorCast;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.values.ConstantCastValue;
-import dk.camelot64.kickc.model.values.ConstantInteger;
-import dk.camelot64.kickc.model.values.ConstantPointer;
+import dk.camelot64.kickc.model.values.*;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 6a0063197..100a0e868 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -49,7 +49,7 @@ public class TestPrograms {
 
    @Test
    public void testNumberType() throws IOException, URISyntaxException {
-      compileAndCompare("number-type", log());
+      compileAndCompare("number-type");
    }
 
    @Test

From 8db7736830746b2f5999ecfc9cea4169fa3b67ac Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 12 May 2019 13:51:36 +0200
Subject: [PATCH 26/93] Improved no-cast detection. 273/351

---
 .../camelot64/kickc/model/types/SymbolTypeConversion.java | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index f1663a6b8..88dd99c38 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -150,8 +150,16 @@ public class SymbolTypeConversion {
          return true;
       if(lValueType.equals(SymbolType.WORD) && rValueType.equals(SymbolType.BYTE))
          return true;
+      if(lValueType.equals(SymbolType.DWORD) && rValueType.equals(SymbolType.BYTE))
+         return true;
+      if(lValueType.equals(SymbolType.DWORD) && rValueType.equals(SymbolType.WORD))
+         return true;
       if(lValueType.equals(SymbolType.SWORD) && rValueType.equals(SymbolType.SBYTE))
          return true;
+      if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SBYTE))
+         return true;
+      if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SWORD))
+         return true;
       if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
          // L-value is still a number - constants are probably not done being identified & typed
          return true;

From ef05cc8c3bd1ecbe52a13ab33f8356534024d7df Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 12 May 2019 13:56:04 +0200
Subject: [PATCH 27/93] Eliminating SymbolTypeMulti - 273/351

---
 .../kickc/model/types/SymbolType.java         | 48 +++----------------
 .../kickc/model/types/SymbolTypeMulti.java    |  1 -
 2 files changed, 6 insertions(+), 43 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
index 2d6c20a6b..71e41be30 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
@@ -113,13 +113,7 @@ public interface SymbolType {
     * @return true if the type is BYTE compatible
     */
    static boolean isByte(SymbolType type) {
-      if(BYTE.equals(type)) {
-         return true;
-      } else if(type instanceof SymbolTypeMulti) {
-         return ((SymbolTypeMulti) type).isByte();
-      } else {
-         return false;
-      }
+      return BYTE.equals(type);
    }
 
    /**
@@ -129,13 +123,7 @@ public interface SymbolType {
     * @return true if the type is SBYTE compatible
     */
    static boolean isSByte(SymbolType type) {
-      if(SBYTE.equals(type)) {
-         return true;
-      } else if(type instanceof SymbolTypeMulti) {
-         return ((SymbolTypeMulti) type).isSByte();
-      } else {
-         return false;
-      }
+      return SBYTE.equals(type);
    }
 
    /**
@@ -145,13 +133,7 @@ public interface SymbolType {
     * @return true if the type is WORD compatible
     */
    static boolean isWord(SymbolType type) {
-      if(WORD.equals(type)) {
-         return true;
-      } else if(type instanceof SymbolTypeMulti) {
-         return ((SymbolTypeMulti) type).isWord();
-      } else {
-         return false;
-      }
+      return WORD.equals(type);
    }
 
    /**
@@ -161,13 +143,7 @@ public interface SymbolType {
     * @return true if the type is SWORD compatible
     */
    static boolean isSWord(SymbolType type) {
-      if(SWORD.equals(type)) {
-         return true;
-      } else if(type instanceof SymbolTypeMulti) {
-         return ((SymbolTypeMulti) type).isSWord();
-      } else {
-         return false;
-      }
+      return SWORD.equals(type);
    }
 
    /**
@@ -177,13 +153,7 @@ public interface SymbolType {
     * @return true if the type is DWORD compatible
     */
    static boolean isDWord(SymbolType type) {
-      if(DWORD.equals(type)) {
-         return true;
-      } else if(type instanceof SymbolTypeMulti) {
-         return ((SymbolTypeMulti) type).isDWord();
-      } else {
-         return false;
-      }
+      return DWORD.equals(type);
    }
 
    /**
@@ -193,13 +163,7 @@ public interface SymbolType {
     * @return true if the type is SDWORD compatible
     */
    static boolean isSDWord(SymbolType type) {
-      if(SDWORD.equals(type)) {
-         return true;
-      } else if(type instanceof SymbolTypeMulti) {
-         return ((SymbolTypeMulti) type).isSWord();
-      } else {
-         return false;
-      }
+      return SDWORD.equals(type);
    }
 
    /**
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
index f3438573e..9c0b8924e 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
@@ -1,6 +1,5 @@
 package dk.camelot64.kickc.model.types;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 

From 7767c1216b8910003b3d8baac2eb3fc05a51db01 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 12 May 2019 14:32:16 +0200
Subject: [PATCH 28/93] Added missing fragment - 274/351

---
 src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm |  6 +++++
 .../fragment/AsmFragmentInstanceSpec.java     | 26 +++++++++----------
 .../types/SymbolTypeNumberInference.java      | 25 +++++++++++-------
 3 files changed, 35 insertions(+), 22 deletions(-)
 create mode 100644 src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm

diff --git a/src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm b/src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm
new file mode 100644
index 000000000..92a07250f
--- /dev/null
+++ b/src/main/fragment/vbsaa_lt_vbsc1_then_la1.asm
@@ -0,0 +1,6 @@
+sec
+sbc #{c1}
+bvc !+
+eor #$80
+!:
+bmi {la1}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
index 539207338..09d9be44f 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
@@ -3,11 +3,9 @@ package dk.camelot64.kickc.fragment;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypeMulti;
-import dk.camelot64.kickc.model.values.ConstantValue;
-import dk.camelot64.kickc.model.values.ScopeRef;
-import dk.camelot64.kickc.model.values.Value;
+import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
+import dk.camelot64.kickc.model.types.SymbolTypeNumberInference;
+import dk.camelot64.kickc.model.values.*;
 
 import java.util.*;
 
@@ -38,6 +36,7 @@ public class AsmFragmentInstanceSpec {
 
    /**
     * Creates an asm fragment instance specification.
+    *
     * @param program The symbol table
     * @param signature The fragment signature.
     * @param bindings Binding of named values in the fragment to values (constants, variables, ...)
@@ -70,7 +69,7 @@ public class AsmFragmentInstanceSpec {
    private ConstantValue variationConstant;
 
    /** When iterating variations this is iterates the potential types for the constant value. */
-   private Iterator<SymbolType> variationIterator;
+   private Iterator<SymbolTypeIntegerFixed> variationIterator;
 
    /** The name of the current variation in the bindings. */
    private String variationCurrentName;
@@ -82,10 +81,11 @@ public class AsmFragmentInstanceSpec {
     * Does any more variations of the ASM fragment instance specification exist?
     * Variations are used for finding the right fragment to use for constant numbers.
     * For instance the number 1000 can be represented as several different types (unsigned/signed word/dword).
+    *
     * @return true if more variations exits
     */
    public boolean hasNextVariation() {
-      if(variationIterator==null) {
+      if(variationIterator == null) {
          // Look for variations
          // TODO Currently only one iterable constant value is handled - add support for multiple iterable constant values!
          for(String name : bindings.keySet()) {
@@ -93,9 +93,9 @@ public class AsmFragmentInstanceSpec {
                // Found a constant value that may be multi-typed
                Value value = bindings.get(name);
                if(value instanceof ConstantValue) {
-                  SymbolType symbolType = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value);
-                  if(symbolType instanceof SymbolTypeMulti) {
-                     Collection<SymbolType> types = ((SymbolTypeMulti) symbolType).getTypes();
+                  ConstantLiteral constantLiteral = ((ConstantValue) value).calculateLiteral(program.getScope());
+                  if(constantLiteral instanceof ConstantInteger) {
+                     List<SymbolTypeIntegerFixed> types = SymbolTypeNumberInference.inferTypes(((ConstantInteger) constantLiteral).getValue());
                      if(types.size() > 1) {
                         // Found constant value with multiple types
                         variationConstant = (ConstantValue) value;
@@ -111,7 +111,7 @@ public class AsmFragmentInstanceSpec {
          }
          // If no variations exist add empty iterator
          if(variationIterator == null) {
-            List<SymbolType> empty = new ArrayList<>();
+            List<SymbolTypeIntegerFixed> empty = new ArrayList<>();
             variationIterator = empty.iterator();
          }
       }
@@ -126,7 +126,7 @@ public class AsmFragmentInstanceSpec {
       if(hasNextVariation()) {
          SymbolType nextVariationValue = variationIterator.next();
          // Find the next name
-         String variationConstName = "c"+variationCurrentName.substring(variationCurrentName.length() - 1);
+         String variationConstName = "c" + variationCurrentName.substring(variationCurrentName.length() - 1);
          String variationNextName = AsmFragmentInstanceSpecFactory.getTypePrefix(nextVariationValue) + variationConstName;
          // Update bindings
          Value constValue = bindings.get(variationCurrentName);
@@ -136,7 +136,7 @@ public class AsmFragmentInstanceSpec {
          this.signature = signature.replace(variationCurrentName, variationNextName);
          variationCurrentName = variationNextName;
          variationCurrentValue = nextVariationValue;
-      }  else {
+      } else {
          this.signature = "no-more-variations";
          this.bindings = new LinkedHashMap<>();
       }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
index acef7130b..983e6a21f 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
@@ -97,18 +97,25 @@ public class SymbolTypeNumberInference {
     */
    public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantLiteral literal) {
       if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) {
-         ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>();
-         ConstantInteger constantInteger = (ConstantInteger) literal;
-         Long number = constantInteger.getValue();
-         for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) {
-            if(typeInteger.contains(number)) {
-               potentialTypes.add(typeInteger);
-            }
-         }
-         return potentialTypes;
+         return inferTypes(((ConstantInteger) literal).getValue());
       } else {
          throw new InternalError("Literal must number type.");
       }
    }
 
+   /**
+    * Find any fixed integer types that can contain the passed integer value
+    * @param value the value to examine
+    * @return All fixed size integer types capable of representing the passed value
+    */
+   public static List<SymbolTypeIntegerFixed> inferTypes(Long value) {
+      ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>();
+      for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) {
+         if(typeInteger.contains(value)) {
+            potentialTypes.add(typeInteger);
+         }
+      }
+      return potentialTypes;
+   }
+
 }

From 07b67efb7ce4c7bd5ed24b14f7bc6c3ed8f72a8d Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 12 May 2019 14:42:41 +0200
Subject: [PATCH 29/93] Eliminating SymbolTypeMulti - 274/351

---
 .../camelot64/kickc/fragment/AsmFormat.java   | 20 +++----
 .../kickc/fragment/AsmFragmentInstance.java   |  2 +-
 .../AsmFragmentInstanceSpecFactory.java       | 24 ++++----
 .../kickc/model/operators/OperatorDWord.java  |  6 +-
 .../model/operators/OperatorGetHigh.java      |  8 +--
 .../kickc/model/operators/OperatorGetLow.java |  8 +--
 .../kickc/model/operators/OperatorPlus.java   |  6 +-
 .../model/operators/OperatorSetHigh.java      | 12 ++--
 .../kickc/model/operators/OperatorSetLow.java |  8 +--
 .../kickc/model/operators/OperatorSizeOf.java | 15 ++---
 .../kickc/model/operators/OperatorTypeId.java | 36 +----------
 .../kickc/model/operators/OperatorWord.java   |  3 +-
 .../kickc/model/types/SymbolType.java         | 60 -------------------
 .../model/types/SymbolTypeInference.java      |  4 +-
 .../passes/Pass2FixInlineConstructors.java    |  4 +-
 .../kickc/passes/Pass2NopCastElimination.java | 10 ++--
 .../kickc/passes/Pass4CodeGeneration.java     | 18 +++---
 .../kickc/passes/Pass4RegistersFinalize.java  | 12 ++--
 18 files changed, 79 insertions(+), 177 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
index 26db72078..331c51337 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
@@ -10,8 +10,6 @@ import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.*;
 
-import java.util.List;
-
 /** Formatting of numbers, constants, names and more for KickAssembler */
 public class AsmFormat {
 
@@ -165,22 +163,22 @@ public class AsmFormat {
          return getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) 0xffffffffL), Operators.BOOL_AND, operand), outerPrecedence, codeScope);
       } else if(Operators.LOWBYTE.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
-         if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
+         if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
             return getAsmConstant(program, operand, outerPrecedence, codeScope);
-         } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
+         } else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
             return "<" + getAsmConstant(program, operand, outerPrecedence, codeScope);
-         } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
+         } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
             return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_AND, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope);
          } else {
             throw new CompileError("Unhandled type " + operand);
          }
       } else if(Operators.HIBYTE.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
-         if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
+         if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
             return getAsmConstant(program, new ConstantInteger(0l), outerPrecedence, codeScope);
-         } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
+         } else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
             return ">" + getAsmConstant(program, operand, outerPrecedence, codeScope);
-         } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
+         } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
             return getAsmConstant(program, new ConstantBinary(operand, Operators.SHIFT_RIGHT, new ConstantInteger((long) 16)), outerPrecedence, codeScope);
          } else {
             throw new CompileError("Unhandled type " + operand);
@@ -191,11 +189,11 @@ public class AsmFormat {
          return getAsmConstant(program, new ConstantBinary(operand, Operators.MINUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope);
       } else if(Operators.BOOL_NOT.equals(operator)) {
          SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
-         if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
+         if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
             return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xff)), outerPrecedence, codeScope);
-         } else if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
+         } else if(SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType) || operandType instanceof SymbolTypePointer || SymbolType.STRING.equals(operandType)) {
             return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffff)), outerPrecedence, codeScope);
-         } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
+         } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
             return getAsmConstant(program, new ConstantBinary(operand, Operators.BOOL_XOR, new ConstantInteger((long) 0xffffffff)), outerPrecedence, codeScope);
          } else {
             throw new CompileError("Unhandled type " + operand);
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
index 9a34ffe2a..53793f4c9 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
@@ -301,7 +301,7 @@ public class AsmFragmentInstance {
       public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) {
          Number number = NumberParser.parseLiteral(ctx.NUMBER().getText());
          ConstantInteger intVal = new ConstantInteger(number.longValue());
-         boolean isZp = SymbolType.isByte(intVal.getType()) || SymbolType.isSByte(intVal.getType());
+         boolean isZp = SymbolType.BYTE.equals(intVal.getType()) || SymbolType.SBYTE.equals(intVal.getType());
          String param = AsmFormat.getAsmNumber(number);
          return new AsmParameter(param, isZp);
       }
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
index 396ec781e..de00e8edf 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
@@ -288,17 +288,17 @@ public class AsmFragmentInstanceSpecFactory {
     * @return The type name
     */
    static String getTypePrefix(SymbolType type) {
-      if(SymbolType.isByte(type)) {
+      if(SymbolType.BYTE.equals(type)) {
          return "vbu";
-      } else if(SymbolType.isSByte(type)) {
+      } else if(SymbolType.SBYTE.equals(type)) {
          return "vbs";
-      } else if(SymbolType.isWord(type)) {
+      } else if(SymbolType.WORD.equals(type)) {
          return "vwu";
-      } else if(SymbolType.isSWord(type)) {
+      } else if(SymbolType.SWORD.equals(type)) {
          return "vws";
-      } else if(SymbolType.isDWord(type)) {
+      } else if(SymbolType.DWORD.equals(type)) {
          return "vdu";
-      } else if(SymbolType.isSDWord(type)) {
+      } else if(SymbolType.SDWORD.equals(type)) {
          return "vds";
       } else if(SymbolType.STRING.equals(type)) {
          return "pbu";
@@ -306,17 +306,17 @@ public class AsmFragmentInstanceSpecFactory {
          return "vbo";
       } else if(type instanceof SymbolTypePointer) {
          SymbolType elementType = ((SymbolTypePointer) type).getElementType();
-         if(SymbolType.isByte(elementType)) {
+         if(SymbolType.BYTE.equals(elementType)) {
             return "pbu";
-         } else if(SymbolType.isSByte(elementType)) {
+         } else if(SymbolType.SBYTE.equals(elementType)) {
             return "pbs";
-         } else if(SymbolType.isWord(elementType)) {
+         } else if(SymbolType.WORD.equals(elementType)) {
             return "pwu";
-         } else if(SymbolType.isSWord(elementType)) {
+         } else if(SymbolType.SWORD.equals(elementType)) {
             return "pws";
-         } else if(SymbolType.isDWord(elementType)) {
+         } else if(SymbolType.DWORD.equals(elementType)) {
             return "pdu";
-         } else if(SymbolType.isSDWord(elementType)) {
+         } else if(SymbolType.SDWORD.equals(elementType)) {
             return "pds";
          } else if(SymbolType.BOOLEAN.equals(elementType)) {
             return "pbo";
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java
index c713d3255..b0e06378c 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java
@@ -32,13 +32,13 @@ public class OperatorDWord extends OperatorBinary {
       if(right instanceof SymbolTypePointer) {
          right = SymbolType.WORD;
       }
-      if(SymbolType.isByte(left)) {
+      if(SymbolType.BYTE.equals(left)) {
          left = SymbolType.WORD;
       }
-      if(SymbolType.isByte(right)) {
+      if(SymbolType.BYTE.equals(right)) {
          right = SymbolType.WORD;
       }
-      if(SymbolType.isWord(left) && SymbolType.isWord(right)) {
+      if(SymbolType.WORD.equals(left) && SymbolType.WORD.equals(right)) {
          return SymbolType.DWORD;
       }
       throw new NoMatchingType("DWord constructor cannot use " + left + " " + getOperator() + " " + right);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
index 81aad2e0e..d28f2f49f 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
@@ -22,9 +22,9 @@ public class OperatorGetHigh extends OperatorUnary {
    public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
       if(operand instanceof ConstantInteger) {
          ConstantInteger operandInt = (ConstantInteger) operand;
-         if(SymbolType.isWord(operandInt.getType()) || SymbolType.isSWord(operandInt.getType())) {
+         if(SymbolType.WORD.equals(operandInt.getType()) || SymbolType.SWORD.equals(operandInt.getType())) {
             return new ConstantInteger(operandInt.getInteger()>>8);
-         } else if(SymbolType.isDWord(operandInt.getType()) || SymbolType.isSDWord(operandInt.getType())) {
+         } else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) {
             return new ConstantInteger(operandInt.getInteger()>>16);
          }
       } else if(operand instanceof ConstantPointer) {
@@ -37,9 +37,9 @@ public class OperatorGetHigh extends OperatorUnary {
 
    @Override
    public SymbolType inferType(SymbolTypeSimple operandType) {
-      if(operandType instanceof SymbolTypePointer || SymbolType.isWord(operandType) || SymbolType.isSWord(operandType)) {
+      if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) {
          return SymbolType.BYTE;
-      } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
+      } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
          return SymbolType.WORD;
       } else if(SymbolType.STRING.equals(operandType)) {
          return SymbolType.BYTE;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
index 81fc490c0..c05e748d4 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
@@ -22,9 +22,9 @@ public class OperatorGetLow extends OperatorUnary {
    public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
       if(operand instanceof ConstantInteger) {
          ConstantInteger operandInt = (ConstantInteger) operand;
-         if(SymbolType.isWord(operandInt.getType()) || SymbolType.isSWord(operandInt.getType())) {
+         if(SymbolType.WORD.equals(operandInt.getType()) || SymbolType.SWORD.equals(operandInt.getType())) {
             return new ConstantInteger(operandInt.getInteger()&0xff);
-         } else if(SymbolType.isDWord(operandInt.getType()) || SymbolType.isSDWord(operandInt.getType())) {
+         } else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) {
             return new ConstantInteger(operandInt.getInteger()&0xffff);
          }
       } else if(operand instanceof ConstantPointer) {
@@ -37,9 +37,9 @@ public class OperatorGetLow extends OperatorUnary {
 
    @Override
    public SymbolType inferType(SymbolTypeSimple operandType) {
-      if(operandType instanceof SymbolTypePointer || SymbolType.isWord(operandType) || SymbolType.isSWord(operandType)) {
+      if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) {
          return SymbolType.BYTE;
-      } else if(SymbolType.isDWord(operandType) || SymbolType.isSDWord(operandType)) {
+      } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
          return SymbolType.WORD;
       } else if(SymbolType.STRING.equals(operandType)) {
          return SymbolType.BYTE;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
index 00844a779..0cb8ec7b8 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
@@ -23,7 +23,7 @@ public class OperatorPlus extends OperatorBinary {
          return new ConstantString(((ConstantString) left).getString() + ((ConstantString) right).getString());
       } else if(left instanceof ConstantString && right instanceof ConstantChar) {
          return new ConstantString(((ConstantString) left).getString() + ((ConstantChar) right).getChar());
-      } else if(left instanceof ConstantString && right instanceof ConstantInteger && SymbolType.isByte(((ConstantInteger) right).getType())) {
+      } else if(left instanceof ConstantString && right instanceof ConstantInteger && SymbolType.BYTE.equals(((ConstantInteger) right).getType())) {
          Character character = (char) ((ConstantInteger) right).getInteger().byteValue();
          return new ConstantString(((ConstantString) left).getString() + character);
       } else if(left instanceof ConstantPointer && right instanceof ConstantInteger) {
@@ -62,9 +62,9 @@ public class OperatorPlus extends OperatorBinary {
    private boolean isStringLike(SymbolTypeSimple type) {
       if(SymbolType.STRING.equals(type)) {
          return true;
-      } else if(SymbolType.isByte(type)) {
+      } else if(SymbolType.BYTE.equals(type)) {
          return true;
-      } else if(type instanceof SymbolTypeArray && SymbolType.isByte(((SymbolTypeArray) type).getElementType())) {
+      } else if(type instanceof SymbolTypeArray && SymbolType.BYTE.equals(((SymbolTypeArray) type).getElementType())) {
          return true;
       }
       return false;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java
index e5218c3bd..19662e139 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java
@@ -22,17 +22,17 @@ public class OperatorSetHigh extends OperatorBinary {
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
       if(left instanceof SymbolTypePointer) {
          return left;
-      } else if(SymbolType.isByte(left)) {
+      } else if(SymbolType.BYTE.equals(left)) {
          return SymbolType.WORD;
-      } else if(SymbolType.isSByte(left)) {
+      } else if(SymbolType.SBYTE.equals(left)) {
          return SymbolType.WORD;
-      } else if(SymbolType.isWord(left)) {
+      } else if(SymbolType.WORD.equals(left)) {
          return SymbolType.WORD;
-      } else if(SymbolType.isSWord(left)) {
+      } else if(SymbolType.SWORD.equals(left)) {
          return SymbolType.SWORD;
-      } else if(SymbolType.isDWord(left)) {
+      } else if(SymbolType.DWORD.equals(left)) {
          return SymbolType.DWORD;
-      } else if(SymbolType.isSDWord(left)) {
+      } else if(SymbolType.SDWORD.equals(left)) {
          return SymbolType.SDWORD;
       }
       throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java
index 12e3d486f..bd4cd763a 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java
@@ -23,13 +23,13 @@ public class OperatorSetLow extends OperatorBinary {
       if(left instanceof SymbolTypePointer) {
          return left;
       }
-      if(SymbolType.isWord(left)) {
+      if(SymbolType.WORD.equals(left)) {
          return SymbolType.WORD;
-      } else if(SymbolType.isSWord(left)) {
+      } else if(SymbolType.SWORD.equals(left)) {
          return SymbolType.SWORD;
-      } else if(SymbolType.isDWord(left)) {
+      } else if(SymbolType.DWORD.equals(left)) {
          return SymbolType.DWORD;
-      } else if(SymbolType.isSDWord(left)) {
+      } else if(SymbolType.SDWORD.equals(left)) {
          return SymbolType.SDWORD;
       }
       throw new RuntimeException("Type inference case not handled " + left + " " + getOperator() + " " + right);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
index 02d3e51e8..6300140e1 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.symbols.ConstantVar;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeMulti;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
 import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
@@ -20,7 +19,7 @@ public class OperatorSizeOf extends OperatorUnary {
    @Override
    public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
       SymbolType type = operand.getType(scope);
-      return new ConstantInteger((long)type.getSizeBytes());
+      return new ConstantInteger((long) type.getSizeBytes());
    }
 
    @Override
@@ -30,6 +29,7 @@ public class OperatorSizeOf extends OperatorUnary {
 
    /**
     * Get the constant variable containing the size of a specific type
+    *
     * @param programScope The program scope (used for finding/adding the constant).
     * @param type The type to get the variable for
     * @return The constant variable
@@ -37,7 +37,7 @@ public class OperatorSizeOf extends OperatorUnary {
    public static ConstantRef getSizeOfConstantVar(ProgramScope programScope, SymbolType type) {
       String typeConstName = getSizeofConstantName(type);
       ConstantVar typeSizeConstant = programScope.getConstant(typeConstName);
-      if(typeSizeConstant ==null) {
+      if(typeSizeConstant == null) {
          // Constant not found - create it
          long typeSize = type.getSizeBytes();
          typeSizeConstant = new ConstantVar(typeConstName, programScope, SymbolType.BYTE, new ConstantInteger(typeSize));
@@ -48,18 +48,15 @@ public class OperatorSizeOf extends OperatorUnary {
 
    /**
     * Get the name of the constant variable containing the size of a specific type
+    *
     * @param type The type to get the variable for
     * @return The name of the constant
     */
    public static String getSizeofConstantName(SymbolType type) {
-      if(type instanceof SymbolTypeMulti) {
-         // Grab the first sub-type. It will be the smallest
-         SymbolType subType = OperatorTypeId.getSubTypeToUse((SymbolTypeMulti) type);
-         return getSizeofConstantName(subType);
-      } else if(type instanceof SymbolTypePointer) {
+      if(type instanceof SymbolTypePointer) {
          return "SIZEOF_POINTER";
       } else {
-         return "SIZEOF_"+type.getTypeName().toUpperCase().replace(" ", "_");
+         return "SIZEOF_" + type.getTypeName().toUpperCase().replace(" ", "_");
       }
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java
index df22fc60d..c5dca47db 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java
@@ -36,7 +36,7 @@ public class OperatorTypeId extends OperatorUnary {
     * @return The constant variable
     */
    public static ConstantRef getTypeIdConstantVar(ProgramScope programScope, SymbolType type) {
-      String typeConstName = "TYPEID_"+getTypeIdConstantName(type);
+      String typeConstName = "TYPEID_" + getTypeIdConstantName(type);
       ConstantVar typeIdConstant = programScope.getConstant(typeConstName);
       if(typeIdConstant == null) {
          // Constant not found - create it
@@ -54,15 +54,7 @@ public class OperatorTypeId extends OperatorUnary {
     * @return The name of the constant
     */
    private static String getTypeIdConstantName(SymbolType type) {
-      if(type instanceof SymbolTypeMulti) {
-         // Grab the first sub-type. It will be the smallest
-         SymbolType subType = getSubTypeToUse((SymbolTypeMulti) type);
-         if(subType==null) {
-            return "VOID";
-         } else {
-            return getTypeIdConstantName(subType);
-         }
-      } else if(type instanceof SymbolTypeProcedure) {
+      if(type instanceof SymbolTypeProcedure) {
          return "PROCEDURE";
       } else if(type instanceof SymbolTypePointer) {
          return "POINTER_" + getTypeIdConstantName(((SymbolTypePointer) type).getElementType());
@@ -113,33 +105,9 @@ public class OperatorTypeId extends OperatorUnary {
          return 0x0f;
       } else if(type instanceof SymbolTypePointer) {
          return 0x10 + getTypeId(((SymbolTypePointer) type).getElementType());
-      } else if(type instanceof SymbolTypeMulti) {
-         // Return the smallest type ID
-         SymbolType useType = getSubTypeToUse((SymbolTypeMulti) type);
-         if(useType==null) return 0;
-         return getTypeId(useType);
       } else {
          return 0;
       }
    }
 
-   /**
-    * Find the sub-type to use for typeid()
-    * @param type The multi type
-    * @return The sub-type to use
-    */
-   public static SymbolType getSubTypeToUse(SymbolTypeMulti type) {
-      SymbolType useType = null;
-      Integer useID = null;
-      for(SymbolType subType : type.getTypes()) {
-         int subId = getTypeId(subType);
-         if(useType==null || subId < useID) {
-            useType = subType;
-            useID = subId;
-         }
-      }
-      return useType;
-   }
-
-
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java
index 1ddc3a770..c84710823 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.NoMatchingType;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
 import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -25,7 +24,7 @@ public class OperatorWord extends OperatorBinary {
 
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
-      if(SymbolType.isByte(left) && SymbolType.isByte(right)) {
+      if(SymbolType.BYTE.equals(left) && SymbolType.BYTE.equals(right)) {
          return SymbolType.WORD;
       }
       throw new NoMatchingType("Word constructor cannot use " + left + " " + getOperator() + " " + right);
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
index 71e41be30..34747ed97 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
@@ -106,66 +106,6 @@ public interface SymbolType {
     */
    int getSizeBytes();
 
-   /**
-    * Is the type {@link #BYTE} or compatible {@link SymbolTypeMulti}
-    *
-    * @param type The type to examine
-    * @return true if the type is BYTE compatible
-    */
-   static boolean isByte(SymbolType type) {
-      return BYTE.equals(type);
-   }
-
-   /**
-    * Is the type {@link #SBYTE} or compatible {@link SymbolTypeMulti}
-    *
-    * @param type The type to examine
-    * @return true if the type is SBYTE compatible
-    */
-   static boolean isSByte(SymbolType type) {
-      return SBYTE.equals(type);
-   }
-
-   /**
-    * Is the type {@link #WORD} or compatible {@link SymbolTypeMulti}
-    *
-    * @param type The type to examine
-    * @return true if the type is WORD compatible
-    */
-   static boolean isWord(SymbolType type) {
-      return WORD.equals(type);
-   }
-
-   /**
-    * Is the type {@link #SWORD} or compatible {@link SymbolTypeMulti}
-    *
-    * @param type The type to examine
-    * @return true if the type is SWORD compatible
-    */
-   static boolean isSWord(SymbolType type) {
-      return SWORD.equals(type);
-   }
-
-   /**
-    * Is the type {@link #DWORD} or compatible {@link SymbolTypeMulti}
-    *
-    * @param type The type to examine
-    * @return true if the type is DWORD compatible
-    */
-   static boolean isDWord(SymbolType type) {
-      return DWORD.equals(type);
-   }
-
-   /**
-    * Is the type {@link #SDWORD} or compatible {@link SymbolTypeMulti}
-    *
-    * @param type The type to examine
-    * @return true if the type is SDWORD compatible
-    */
-   static boolean isSDWord(SymbolType type) {
-      return SDWORD.equals(type);
-   }
-
    /**
     * Is the type an integer type (including {@link #NUMBER})
     *
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index 31bf4b7a9..100244aca 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -148,13 +148,13 @@ public class SymbolTypeInference {
          }
       }
       if(elmType != null) {
-         if((list.getList().size() == 2 && SymbolType.isByte(elmType) || SymbolType.isSByte(elmType))) {
+         if((list.getList().size() == 2 && SymbolType.BYTE.equals(elmType) || SymbolType.SBYTE.equals(elmType))) {
             // Potentially a word constructor - return a composite type
             ArrayList<SymbolType> types = new ArrayList<>();
             types.add(new SymbolTypeArray(elmType));
             types.add(SymbolType.WORD);
             return new SymbolTypeMulti(types);
-         } else if((list.getList().size() == 2 && SymbolType.isWord(elmType))) {
+         } else if((list.getList().size() == 2 && SymbolType.WORD.equals(elmType))) {
             // Potentially a dword constructor - return a composite type
             ArrayList<SymbolType> types = new ArrayList<>();
             types.add(new SymbolTypeArray(elmType));
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
index 49b6afce4..e13b30941 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
@@ -49,7 +49,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
 
       @Override
       protected boolean isSubType(SymbolType elmType) {
-         return SymbolType.isByte(elmType);
+         return SymbolType.BYTE.equals(elmType);
       }
    }
 
@@ -62,7 +62,7 @@ public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
 
       @Override
       protected boolean isSubType(SymbolType elmType) {
-         return SymbolType.isWord(elmType);
+         return SymbolType.WORD.equals(elmType);
       }
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java
index a298ad251..b66de4df4 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java
@@ -40,19 +40,19 @@ public class Pass2NopCastElimination extends Pass2SsaOptimization {
                   SymbolType rValType = SymbolTypeInference.inferType(getScope(), assignment.getrValue2());
                   boolean isNopCast = false;
                   SymbolType toType = null;
-                  if(SymbolType.isByte(rValType) && Operators.CAST_SBYTE.equals(assignment.getOperator())) {
+                  if(SymbolType.BYTE.equals(rValType) && Operators.CAST_SBYTE.equals(assignment.getOperator())) {
                      isNopCast = true;
                      toType = SymbolType.SBYTE;
-                  } else if(SymbolType.isSByte(rValType) && Operators.CAST_BYTE.equals(assignment.getOperator())) {
+                  } else if(SymbolType.SBYTE.equals(rValType) && Operators.CAST_BYTE.equals(assignment.getOperator())) {
                      isNopCast = true;
                      toType = SymbolType.BYTE;
-                  } else if(SymbolType.isWord(rValType) && Operators.CAST_SWORD.equals(assignment.getOperator())) {
+                  } else if(SymbolType.WORD.equals(rValType) && Operators.CAST_SWORD.equals(assignment.getOperator())) {
                      isNopCast = true;
                      toType = SymbolType.SWORD;
-                  } else if(SymbolType.isSWord(rValType) && Operators.CAST_WORD.equals(assignment.getOperator())) {
+                  } else if(SymbolType.SWORD.equals(rValType) && Operators.CAST_WORD.equals(assignment.getOperator())) {
                      isNopCast = true;
                      toType = SymbolType.WORD;
-                  } else if(SymbolType.isWord(rValType) && assignment.getOperator() instanceof OperatorCastPtr) {
+                  } else if(SymbolType.WORD.equals(rValType) && assignment.getOperator() instanceof OperatorCastPtr) {
                      isNopCast = true;
                      OperatorCastPtr castOperator = (OperatorCastPtr) (assignment.getOperator());
                      toType = new SymbolTypePointer(castOperator.getElementType());
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
index 630581697..e758eb361 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
@@ -387,13 +387,13 @@ public class Pass4CodeGeneration {
                   String asmElement = AsmFormat.getAsmConstant(program, element, 99, scopeRef);
                   asmElements.add(asmElement);
                }
-               if(SymbolType.isByte(elementType) || SymbolType.isSByte(elementType)) {
+               if(SymbolType.BYTE.equals(elementType) || SymbolType.SBYTE.equals(elementType)) {
                   asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.BYTE, asmElements);
                   added.add(asmName);
-               } else if(SymbolType.isWord(elementType) || SymbolType.isSWord(elementType)) {
+               } else if(SymbolType.WORD.equals(elementType) || SymbolType.SWORD.equals(elementType)) {
                   asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmElements);
                   added.add(asmName);
-               } else if(SymbolType.isDWord(elementType) || SymbolType.isSDWord(elementType)) {
+               } else if(SymbolType.DWORD.equals(elementType) || SymbolType.SDWORD.equals(elementType)) {
                   asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.DWORD, asmElements);
                   added.add(asmName);
                } else if(elementType instanceof SymbolTypePointer) {
@@ -410,27 +410,27 @@ public class Pass4CodeGeneration {
                   throw new Pass2SsaAssertion.AssertionFailed("Error! Array size is not constant integer " + constantVar.toString(program));
                }
                int size = ((ConstantInteger) arraySizeConst).getInteger().intValue();
-               if(SymbolType.isByte(constantArrayFilled.getElementType())) {
+               if(SymbolType.BYTE.equals(constantArrayFilled.getElementType())) {
                   String asmSize = AsmFormat.getAsmConstant(program, arraySize, 99, scopeRef);
                   asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.BYTE, asmSize, size, "0");
                   added.add(asmName);
-               } else if(SymbolType.isSByte(constantArrayFilled.getElementType())) {
+               } else if(SymbolType.SBYTE.equals(constantArrayFilled.getElementType())) {
                   String asmSize = AsmFormat.getAsmConstant(program, arraySize, 99, scopeRef);
                   asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.BYTE, asmSize, size, "0");
                   added.add(asmName);
-               } else if(SymbolType.isWord(constantArrayFilled.getElementType())) {
+               } else if(SymbolType.WORD.equals(constantArrayFilled.getElementType())) {
                   String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef);
                   asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0");
                   added.add(asmName);
-               } else if(SymbolType.isSWord(constantArrayFilled.getElementType())) {
+               } else if(SymbolType.SWORD.equals(constantArrayFilled.getElementType())) {
                   String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef);
                   asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0");
                   added.add(asmName);
-               } else if(SymbolType.isDWord(constantArrayFilled.getElementType())) {
+               } else if(SymbolType.DWORD.equals(constantArrayFilled.getElementType())) {
                   String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(4L), Operators.MULTIPLY, arraySize), 99, scopeRef);
                   asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.DWORD, asmSize, size, "0");
                   added.add(asmName);
-               } else if(SymbolType.isSDWord(constantArrayFilled.getElementType())) {
+               } else if(SymbolType.SDWORD.equals(constantArrayFilled.getElementType())) {
                   String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(4L), Operators.MULTIPLY, arraySize), 99, scopeRef);
                   asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.DWORD, asmSize, size, "0");
                   added.add(asmName);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java
index 157b04ca7..e36e1348a 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java
@@ -195,23 +195,23 @@ public class Pass4RegistersFinalize extends Pass2Base {
     */
    private Registers.Register allocateNewRegisterZp(Variable variable) {
       SymbolType varType = variable.getType();
-      if(SymbolType.isByte(varType)) {
+      if(SymbolType.BYTE.equals(varType)) {
          return new Registers.RegisterZpByte(allocateZp((1)));
-      } else if(SymbolType.isSByte(varType)) {
+      } else if(SymbolType.SBYTE.equals(varType)) {
          return new Registers.RegisterZpByte(allocateZp(1));
-      } else if(SymbolType.isWord(varType)) {
+      } else if(SymbolType.WORD.equals(varType)) {
          Registers.RegisterZpWord registerZpWord =
                new Registers.RegisterZpWord(allocateZp(2));
          return registerZpWord;
-      } else if(SymbolType.isSWord(varType)) {
+      } else if(SymbolType.SWORD.equals(varType)) {
          Registers.RegisterZpWord registerZpWord =
                new Registers.RegisterZpWord(allocateZp(2));
          return registerZpWord;
-      } else if(SymbolType.isDWord(varType)) {
+      } else if(SymbolType.DWORD.equals(varType)) {
          Registers.RegisterZpDWord registerZpDWord =
                new Registers.RegisterZpDWord(allocateZp(4));
          return registerZpDWord;
-      } else if(SymbolType.isSDWord(varType)) {
+      } else if(SymbolType.SDWORD.equals(varType)) {
          Registers.RegisterZpDWord registerZpDWord =
                new Registers.RegisterZpDWord(allocateZp(4));
          return registerZpDWord;

From fe60b31f73113438f9aa780c44f82ff8d5719660 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 12 May 2019 21:18:55 +0200
Subject: [PATCH 30/93] New literal word constructor handling - 277/354

---
 .../java/dk/camelot64/kickc/Compiler.java     |  1 +
 .../iterator/ProgramExpressionIterator.java   |  6 +-
 .../iterator/ProgramExpressionUnary.java      | 37 ++++++++-
 .../kickc/model/types/SymbolTypeArray.java    |  6 +-
 .../model/types/SymbolTypeInference.java      | 81 ++-----------------
 .../kickc/model/values/ValueList.java         |  4 +
 .../Pass2ConstantCastSimplification.java      | 31 -------
 .../passes/Pass2FixInlineConstructorsNew.java | 69 ++++++++++++++++
 .../PassNAddTypeConversionAssignment.java     | 19 +++++
 .../dk/camelot64/kickc/test/TestPrograms.java | 15 ++++
 src/test/kc/inline-word-0.kc                  |  7 ++
 src/test/kc/inline-word-1.kc                  |  7 ++
 src/test/kc/inline-word-2.kc                  |  7 ++
 13 files changed, 174 insertions(+), 116 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
 create mode 100644 src/test/kc/inline-word-0.kc
 create mode 100644 src/test/kc/inline-word-1.kc
 create mode 100644 src/test/kc/inline-word-2.kc

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 2e73baad4..4d524e483 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -254,6 +254,7 @@ public class Compiler {
       optimizations.add(new Pass2ConstantIfs(program));
       optimizations.add(new Pass2ConstantStringConsolidation(program));
       optimizations.add(new Pass2FixInlineConstructors(program));
+      optimizations.add(new Pass2FixInlineConstructorsNew(program));
       optimizations.add(new Pass2TypeInference(program));
       optimizations.add(new PassNEliminateUnusedVars(program, true));
       optimizations.add(new Pass2EliminateRedundantCasts(program));
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
index c109a3001..6a6d9c3dc 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
@@ -5,9 +5,7 @@ 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.StatementConditionalJump;
-import dk.camelot64.kickc.model.values.ConstantBinary;
-import dk.camelot64.kickc.model.values.ConstantUnary;
-import dk.camelot64.kickc.model.values.PointerDereferenceIndexed;
+import dk.camelot64.kickc.model.values.*;
 
 import java.util.ListIterator;
 
@@ -33,6 +31,8 @@ public class ProgramExpressionIterator {
             handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null);
          } else if(programValue.get() instanceof PointerDereferenceIndexed) {
             handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null);
+         } else if(programValue.get() instanceof ConstantCastValue) {
+            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), null, null, null);
          }
       };
       ProgramValueIterator.execute(program.getScope(), programValueHandler);
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
index a2795032d..fdcdeb4a0 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
@@ -1,7 +1,9 @@
 package dk.camelot64.kickc.model.iterator;
 
 import dk.camelot64.kickc.model.operators.OperatorUnary;
+import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.values.ConstantCastValue;
 import dk.camelot64.kickc.model.values.ConstantUnary;
 import dk.camelot64.kickc.model.values.RValue;
 import dk.camelot64.kickc.model.values.Value;
@@ -52,7 +54,7 @@ public interface ProgramExpressionUnary extends ProgramExpression {
 
    /** Unary expression as part of a constant expression. */
    class ProgramExpressionUnaryConstant implements ProgramExpressionUnary {
-      
+
       /** A ProgramValue containing a {@link ConstantUnary}. */
       private ProgramValue programValue;
 
@@ -81,4 +83,37 @@ public interface ProgramExpressionUnary extends ProgramExpression {
 
    }
 
+   /** Unary cast expression {@link ConstantCastValue} as part of a constant expression. */
+   class ProgramExpressionUnaryCast implements ProgramExpressionUnary {
+
+      /** A ProgramValue containing a {@link ConstantCastValue}. */
+      private ProgramValue programValue;
+
+      ProgramExpressionUnaryCast(ProgramValue programValue) {
+         this.programValue = programValue;
+      }
+
+      public ConstantCastValue getConstantUnary() {
+         return (ConstantCastValue) programValue.get();
+      }
+
+      @Override
+      public OperatorUnary getOperator() {
+         return Operators.getCastUnary(getConstantUnary().getToType());
+      }
+
+      @Override
+      public RValue getOperand() {
+         return getConstantUnary().getValue();
+      }
+
+      @Override
+      public void set(Value value) {
+         programValue.set(value);
+      }
+
+   }
+
+
+
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeArray.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeArray.java
index 738b40754..7aaa8fce2 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeArray.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeArray.java
@@ -31,11 +31,7 @@ public class SymbolTypeArray extends SymbolTypePointer {
    @Override
    public String getTypeName() {
       SymbolType elementType = getElementType();
-      if(elementType instanceof SymbolTypeMulti) {
-         return "(" + elementType.getTypeName() + ")" + "[" + (size == null ? "" : size.toString()) + "]";
-      } else {
-         return elementType.getTypeName() + "[" + (size == null ? "" : size.toString()) + "]";
-      }
+      return elementType.getTypeName() + "[" + (size == null ? "" : size.toString()) + "]";
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index 100244aca..d512f96e7 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -9,10 +9,6 @@ import dk.camelot64.kickc.model.statements.*;
 import dk.camelot64.kickc.model.symbols.*;
 import dk.camelot64.kickc.model.values.*;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
 /**
  * Type inference of expressions (rValues & unary/binary operators)
  */
@@ -126,7 +122,7 @@ public class SymbolTypeInference {
       } else if(rValue instanceof ProcedureRef) {
          Procedure procedure = symbols.getProcedure((ProcedureRef) rValue);
          return procedure.getType();
-      }  else if(rValue instanceof AssignmentRValue) {
+      } else if(rValue instanceof AssignmentRValue) {
          return inferTypeRValue(symbols, ((AssignmentRValue) rValue).getAssignment());
       }
       if(type == null) {
@@ -148,21 +144,8 @@ public class SymbolTypeInference {
          }
       }
       if(elmType != null) {
-         if((list.getList().size() == 2 && SymbolType.BYTE.equals(elmType) || SymbolType.SBYTE.equals(elmType))) {
-            // Potentially a word constructor - return a composite type
-            ArrayList<SymbolType> types = new ArrayList<>();
-            types.add(new SymbolTypeArray(elmType));
-            types.add(SymbolType.WORD);
-            return new SymbolTypeMulti(types);
-         } else if((list.getList().size() == 2 && SymbolType.WORD.equals(elmType))) {
-            // Potentially a dword constructor - return a composite type
-            ArrayList<SymbolType> types = new ArrayList<>();
-            types.add(new SymbolTypeArray(elmType));
-            types.add(SymbolType.DWORD);
-            return new SymbolTypeMulti(types);
-         } else {
-            return new SymbolTypeArray(elmType);
-         }
+         long size = list.getList().size();
+         return new SymbolTypeArray(elmType, new ConstantInteger(size, size<256?SymbolType.BYTE:SymbolType.WORD));
       } else {
          throw new RuntimeException("Cannot infer list element type " + list.toString());
       }
@@ -223,13 +206,8 @@ public class SymbolTypeInference {
             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;
-            }
+            } else if(!type.equals(valueType))
+               throw new CompileError("Types not compatible " + type + " and " + valueType);
          }
          if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
             program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program));
@@ -295,53 +273,4 @@ public class SymbolTypeInference {
       }
    }
 
-   /**
-    * Find the symbol type that is the intersection between the two passed types.
-    * Handles SymbolTypeMulti by intersecting the sub type lists.
-    *
-    * @param type1 The first type
-    * @param type2 The second type
-    * @return The intersection between the two types (handling multi-types)
-    */
-   public static SymbolType intersectTypes(SymbolType type1, SymbolType type2) {
-      List<SymbolType> newSubTypes = new ArrayList<>();
-      if(type1 instanceof SymbolTypeMulti) {
-         Collection<SymbolType> subTypes1 = ((SymbolTypeMulti) type1).getTypes();
-         if(type2 instanceof SymbolTypeMulti) {
-            Collection<SymbolType> subTypes2 = ((SymbolTypeMulti) type2).getTypes();
-            for(SymbolType subType1 : subTypes1) {
-               if(subTypes2.contains(subType1)) {
-                  newSubTypes.add(subType1);
-               }
-            }
-         } else {
-            // Element type is not multi - check if the list type contains it
-            if(subTypes1.contains(type2)) {
-               newSubTypes.add(type2);
-            }
-         }
-      } else {
-         // List-type not multi - check if the element type contains it
-         if(type2 instanceof SymbolTypeMulti) {
-            Collection<SymbolType> subTypes2 = ((SymbolTypeMulti) type2).getTypes();
-            if(subTypes2.contains(type1)) {
-               newSubTypes.add(type1);
-            }
-         } else {
-            // Element type is not multi - check if the list type is the same
-            if(type1.equals(type2)) {
-               newSubTypes.add(type1);
-            }
-         }
-      }
-      if(newSubTypes.size() == 0) {
-         return null;
-      } else if(newSubTypes.size() == 1) {
-         // A single type matching - use it
-         return newSubTypes.get(0);
-      } else {
-         // Multiple matches was found - use them
-         return new SymbolTypeMulti(newSubTypes);
-      }
-   }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ValueList.java b/src/main/java/dk/camelot64/kickc/model/values/ValueList.java
index fd704486a..a81adb58a 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ValueList.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ValueList.java
@@ -38,4 +38,8 @@ public class ValueList implements RValue {
       return out.toString();
    }
 
+   @Override
+   public String toString() {
+      return toString(null);
+   }
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
index 0d516f99e..467e386ca 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
@@ -53,37 +53,6 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
             }
          }
       });
-      ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
-         if(programValue.get() instanceof ConstantCastValue) {
-            ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get();
-            if(constantCastValue.getValue() instanceof ConstantInteger) {
-               ConstantInteger constantInteger = (ConstantInteger) constantCastValue.getValue();
-               SymbolType castType = constantCastValue.getToType();
-               if(SymbolType.NUMBER.equals(constantInteger.getType())) {
-                  if(castType instanceof SymbolTypeIntegerFixed ) {
-                     ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
-                     programValue.set(newConstInt);
-                     getLog().append("Simplifying constant integer cast " + newConstInt.toString());
-                     optimized.set(true);
-                  }  else if(castType instanceof SymbolTypePointer) {
-                     ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType());
-                     programValue.set(newConstPointer);
-                     getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
-                     optimized.set(true);
-                  }
-               } else if(castType instanceof SymbolTypeIntegerFixed) {
-                  if(((SymbolTypeIntegerFixed) castType).contains(constantInteger.getValue())) {
-                     // Cast type contains the value - cast not needed
-                     ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
-                     programValue.set(newConstInt);
-                     getLog().append("Simplifying constant integer cast " + newConstInt.toString());
-                     optimized.set(true);
-                  }
-               }
-            }
-         }
-
-      });
       return optimized.get();
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
new file mode 100644
index 000000000..edd754321
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
@@ -0,0 +1,69 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.Comment;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
+import dk.camelot64.kickc.model.operators.OperatorBinary;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.symbols.Scope;
+import dk.camelot64.kickc.model.symbols.VariableIntermediate;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.values.CastValue;
+import dk.camelot64.kickc.model.values.RValue;
+import dk.camelot64.kickc.model.values.ValueList;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Identifies word constructors <code> (word) { b1, b2 }</code> and replaces
+ * them with a binary operator <code>word w = b1 w= b2 ;</code>
+ */
+public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization {
+
+   public Pass2FixInlineConstructorsNew(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean optimized = new AtomicBoolean(false);
+      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(programExpression instanceof ProgramExpressionUnary) {
+            if(programExpression.getOperator().equals(Operators.CAST_WORD)) {
+               if(((ProgramExpressionUnary) programExpression).getOperand() instanceof ValueList) {
+                  ValueList list = (ValueList) ((ProgramExpressionUnary) programExpression).getOperand();
+                  List<RValue> listValues = list.getList();
+                  if(listValues.size()==2) {
+
+                     OperatorBinary constructOperator = Operators.WORD;
+                     SymbolType constructType = SymbolType.WORD;
+
+                     // Convert list to a word constructor in a new tmp variable
+                     Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope());
+                     VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
+                     tmpVar.setTypeInferred(constructType);
+                     // Move backward - to insert before the current statement
+                     stmtIt.previous();
+                     // Add assignment of the new tmpVar
+                     StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), new CastValue(SymbolType.BYTE, listValues.get(0)), constructOperator, new CastValue(SymbolType.BYTE, listValues.get(1)), currentStmt.getSource(), Comment.NO_COMMENTS);
+                     stmtIt.add(assignment);
+                     // Move back before the current statement
+                     stmtIt.next();
+                     // Replace current value with the reference
+                     programExpression.set(tmpVar.getRef());
+                     Pass2FixInlineConstructorsNew.this.getLog().append("Fixing inline constructor with " + assignment.toString());
+                     optimized.set(true);
+                  }
+               }
+            }
+         }
+      });
+      return optimized.get();
+
+   }
+
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
index e2f2049c0..908cb0587 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
@@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.types.*;
+import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.RValue;
 
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -37,6 +38,15 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
                      binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
                      modified.set(true);
                   }
+
+                  // Detect word literal constructor
+                  if(leftType.equals(SymbolType.WORD) && isLiteralWordCandidate(rightType)) {
+                     SymbolType conversionType = SymbolType.WORD;
+                     getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
+                     binary.addRightCast(SymbolType.WORD, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
+                     modified.set(true);
+                  }
+
                }
                if(leftType instanceof SymbolTypeIntegerFixed && SymbolType.isInteger(rightType)) {
                   SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
@@ -53,5 +63,14 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
       return modified.get();
    }
 
+   public static boolean isLiteralWordCandidate(SymbolType rightType) {
+      if(rightType instanceof SymbolTypeArray) {
+         SymbolTypeArray rightArray = (SymbolTypeArray) rightType;
+         if(new ConstantInteger(2L, SymbolType.BYTE).equals(rightArray.getSize()))
+            if(SymbolType.BYTE.equals(rightArray.getElementType()) || SymbolType.NUMBER.equals(rightArray.getElementType()))
+               return true;
+      }
+      return false;
+   }
 
 }
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 100a0e868..3bb2350d3 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -1359,6 +1359,21 @@ public class TestPrograms {
       compileAndCompare("inline-assignment");
    }
 
+   @Test
+   public void testInlineWord0() throws IOException, URISyntaxException {
+      compileAndCompare("inline-word-0");
+   }
+
+   @Test
+   public void testInlineWord1() throws IOException, URISyntaxException {
+      compileAndCompare("inline-word-1");
+   }
+
+   @Test
+   public void testInlineWord2() throws IOException, URISyntaxException {
+      compileAndCompare("inline-word-2");
+   }
+
    @Test
    public void testInlineWord() throws IOException, URISyntaxException {
       compileAndCompare("inline-word");
diff --git a/src/test/kc/inline-word-0.kc b/src/test/kc/inline-word-0.kc
new file mode 100644
index 000000000..e4ef83c7c
--- /dev/null
+++ b/src/test/kc/inline-word-0.kc
@@ -0,0 +1,7 @@
+// Tests minimal inline word
+
+void main() {
+    word w = { 0x02ub, 0x01ub };
+    word* screen = 0x0400;
+    screen[0] = w;
+}
\ No newline at end of file
diff --git a/src/test/kc/inline-word-1.kc b/src/test/kc/inline-word-1.kc
new file mode 100644
index 000000000..9154746f8
--- /dev/null
+++ b/src/test/kc/inline-word-1.kc
@@ -0,0 +1,7 @@
+// Tests minimal inline word
+
+void main() {
+    word w = { 0x01, 0x02 };
+    word* screen = 0x0400;
+    screen[0] = w;
+}
\ No newline at end of file
diff --git a/src/test/kc/inline-word-2.kc b/src/test/kc/inline-word-2.kc
new file mode 100644
index 000000000..9cff6751a
--- /dev/null
+++ b/src/test/kc/inline-word-2.kc
@@ -0,0 +1,7 @@
+// Tests minimal inline word
+
+void main() {
+    word w = { 0x01, 0x02ub };
+    word* screen = 0x0400;
+    screen[0] = w;
+}
\ No newline at end of file

From 3d56f3705a8fd725943667f3c760905725f2fe85 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Mon, 13 May 2019 09:17:30 +0200
Subject: [PATCH 31/93] Array initializer with number handling - 278/358

---
 .../java/dk/camelot64/kickc/Compiler.java     |  4 +-
 .../iterator/ProgramExpressionBinary.java     |  8 ++-
 .../model/types/SymbolTypeInference.java      |  8 ++-
 .../Pass2ConstantRValueConsolidation.java     |  2 +-
 .../passes/Pass2FixInlineConstructorsNew.java | 71 +++++++++++++------
 .../PassNAddArrayNumberTypeConversions.java   | 63 ++++++++++++++++
 .../PassNAddTypeConversionAssignment.java     | 19 ++++-
 .../dk/camelot64/kickc/test/TestPrograms.java | 22 +++++-
 src/test/kc/inline-pointer-0.kc               |  6 ++
 src/test/kc/inline-pointer-1.kc               | 11 +++
 src/test/kc/inline-pointer-2.kc               |  6 ++
 src/test/kc/mixed-array-0.kc                  |  9 +++
 src/test/kc/true-inline-words.kc              |  2 +-
 13 files changed, 200 insertions(+), 31 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNAddArrayNumberTypeConversions.java
 create mode 100644 src/test/kc/inline-pointer-0.kc
 create mode 100644 src/test/kc/inline-pointer-1.kc
 create mode 100644 src/test/kc/inline-pointer-2.kc
 create mode 100644 src/test/kc/mixed-array-0.kc

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 4d524e483..6440f0256 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -233,6 +233,7 @@ public class Compiler {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
       optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new PassNAddNumberTypeConversions(program));
+      optimizations.add(new PassNAddArrayNumberTypeConversions(program));
       optimizations.add(new PassNDowngradeBytePlusWord(program));
       optimizations.add(new PassNTypeInference(program));
       optimizations.add(new PassNTypeIdSimplification(program));
@@ -253,8 +254,9 @@ public class Compiler {
       //optimizations.add(new Pass2ConstantAdditionElimination(program));
       optimizations.add(new Pass2ConstantIfs(program));
       optimizations.add(new Pass2ConstantStringConsolidation(program));
-      optimizations.add(new Pass2FixInlineConstructors(program));
+      //optimizations.add(new Pass2FixInlineConstructors(program));
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
+      optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new Pass2TypeInference(program));
       optimizations.add(new PassNEliminateUnusedVars(program, true));
       optimizations.add(new Pass2EliminateRedundantCasts(program));
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
index ff1a8b9e0..f23553a71 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
@@ -169,7 +169,13 @@ public interface ProgramExpressionBinary extends ProgramExpression {
          if(assignment.getrValue1() == null && assignment.getOperator() == null) {
             assignment.setOperator(Operators.getCastUnary(toType));
          } else {
-            throw new InternalError("Not implemented!");
+            Scope blockScope = symbols.getScope(currentScope);
+            VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
+            SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
+            tmpVar.setType(rightType);
+            StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
+            assignment.setlValue(tmpVar.getRef());
+            stmtIt.add(newAssignment);
          }
       }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index d512f96e7..8944b1cfa 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -139,7 +139,13 @@ public class SymbolTypeInference {
             elmType = type;
          } else {
             if(!elmType.equals(type)) {
-               throw new RuntimeException("Array element has type mismatch " + elm.toString() + " not matching type " + elmType.getTypeName());
+               if(SymbolType.NUMBER.equals(elmType) && SymbolType.isInteger(type)) {
+                  elmType = SymbolType.NUMBER;
+               } else if(SymbolType.isInteger(elmType) && SymbolType.NUMBER.equals(type)) {
+                  elmType = SymbolType.NUMBER;
+               } else {
+                  throw new CompileError("Array element has type mismatch "+elm.toString() + " not matching type " + elmType.getTypeName());
+               }
             }
          }
       }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
index eed062e60..edf2a49c3 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantRValueConsolidation.java
@@ -98,7 +98,7 @@ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
                   } else {
                      if(!listType.equals(elmType)) {
                         // No overlap between list type and element type
-                        throw new RuntimeException("Array type " + listType + " does not match element type" + elmType + ". Array: " + valueList.toString(getProgram()));
+                        throw new RuntimeException("Array type " + listType + " does not match element type " + elmType + ". Array: " + valueList.toString(getProgram()));
                      }
                   }
                   elements.add(constantValue);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
index edd754321..e8c83cf29 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
@@ -1,11 +1,15 @@
 package dk.camelot64.kickc.passes;
 
 import dk.camelot64.kickc.model.Comment;
+import dk.camelot64.kickc.model.ControlFlowBlock;
 import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpression;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
 import dk.camelot64.kickc.model.operators.OperatorBinary;
+import dk.camelot64.kickc.model.operators.OperatorCastPtr;
 import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.symbols.Scope;
 import dk.camelot64.kickc.model.symbols.VariableIntermediate;
@@ -15,6 +19,7 @@ import dk.camelot64.kickc.model.values.RValue;
 import dk.camelot64.kickc.model.values.ValueList;
 
 import java.util.List;
+import java.util.ListIterator;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -32,29 +37,19 @@ public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization {
       AtomicBoolean optimized = new AtomicBoolean(false);
       ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
          if(programExpression instanceof ProgramExpressionUnary) {
-            if(programExpression.getOperator().equals(Operators.CAST_WORD)) {
-               if(((ProgramExpressionUnary) programExpression).getOperand() instanceof ValueList) {
-                  ValueList list = (ValueList) ((ProgramExpressionUnary) programExpression).getOperand();
-                  List<RValue> listValues = list.getList();
-                  if(listValues.size()==2) {
-
-                     OperatorBinary constructOperator = Operators.WORD;
-                     SymbolType constructType = SymbolType.WORD;
-
-                     // Convert list to a word constructor in a new tmp variable
-                     Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope());
-                     VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
-                     tmpVar.setTypeInferred(constructType);
-                     // Move backward - to insert before the current statement
-                     stmtIt.previous();
-                     // Add assignment of the new tmpVar
-                     StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), new CastValue(SymbolType.BYTE, listValues.get(0)), constructOperator, new CastValue(SymbolType.BYTE, listValues.get(1)), currentStmt.getSource(), Comment.NO_COMMENTS);
-                     stmtIt.add(assignment);
-                     // Move back before the current statement
-                     stmtIt.next();
-                     // Replace current value with the reference
-                     programExpression.set(tmpVar.getRef());
-                     Pass2FixInlineConstructorsNew.this.getLog().append("Fixing inline constructor with " + assignment.toString());
+            if(((ProgramExpressionUnary) programExpression).getOperand() instanceof ValueList) {
+               ValueList list = (ValueList) ((ProgramExpressionUnary) programExpression).getOperand();
+               List<RValue> listValues = list.getList();
+               if(listValues.size() == 2) {
+                  if(programExpression.getOperator().equals(Operators.CAST_WORD)) {
+                     addLiteralWordConstructor(Operators.WORD, SymbolType.WORD, SymbolType.BYTE, programExpression, listValues, currentStmt, stmtIt, currentBlock);
+                     optimized.set(true);
+                  } else if(programExpression.getOperator() instanceof OperatorCastPtr) {
+                     SymbolType castType = ((OperatorCastPtr) programExpression.getOperator()).getToType();
+                     addLiteralWordConstructor(Operators.WORD, castType, SymbolType.BYTE, programExpression, listValues, currentStmt, stmtIt, currentBlock);
+                     optimized.set(true);
+                  } else if(programExpression.getOperator().equals(Operators.CAST_DWORD)) {
+                     addLiteralWordConstructor(Operators.DWORD, SymbolType.DWORD, SymbolType.WORD, programExpression, listValues, currentStmt, stmtIt, currentBlock);
                      optimized.set(true);
                   }
                }
@@ -65,5 +60,35 @@ public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization {
 
    }
 
+   /**
+    * Add a literal word/dword constructor.
+    * Converts a cast value-list with 2 items to a word/dword constructor.
+    * (word) { 1, 2 }  ->  1 =w 2
+    * @param constructOperator The operator to add
+    * @param constructType The type being constructed
+    * @param subType The sub-type
+    * @param programExpression The program expression containing the cast value list
+    * @param listValues
+    * @param currentStmt
+    * @param stmtIt
+    * @param currentBlock
+    */
+   public void addLiteralWordConstructor(OperatorBinary constructOperator, SymbolType constructType, SymbolType subType, ProgramExpression programExpression, List<RValue> listValues, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
+      // Convert list to a word constructor in a new tmp variable
+      Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope());
+      VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
+      tmpVar.setTypeInferred(constructType);
+      // Move backward - to insert before the current statement
+      stmtIt.previous();
+      // Add assignment of the new tmpVar
+      StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), new CastValue(subType, listValues.get(0)), constructOperator, new CastValue(subType, listValues.get(1)), currentStmt.getSource(), Comment.NO_COMMENTS);
+      stmtIt.add(assignment);
+      // Move back before the current statement
+      stmtIt.next();
+      // Replace current value with the reference
+      programExpression.set(tmpVar.getRef());
+      Pass2FixInlineConstructorsNew.this.getLog().append("Fixing inline constructor with " + assignment.toString());
+   }
+
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddArrayNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddArrayNumberTypeConversions.java
new file mode 100644
index 000000000..fb3599b09
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddArrayNumberTypeConversions.java
@@ -0,0 +1,63 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeArray;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
+import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.values.*;
+
+import java.util.ListIterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Add casts to {@link SymbolType#NUMBER} expressions that are inside array initializers based on the type of the array
+ */
+public class PassNAddArrayNumberTypeConversions extends Pass2SsaOptimization {
+
+   public PassNAddArrayNumberTypeConversions(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
+      ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(binaryExpression instanceof ProgramExpressionBinary) {
+            ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression;
+            RValue left = binary.getLeft();
+            RValue right = binary.getRight();
+            SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
+            if(leftType instanceof SymbolTypeArray && right instanceof ValueList) {
+               SymbolType declaredElmType = ((SymbolTypeArray) leftType).getElementType();
+               ListIterator<RValue> elmIterator = ((ValueList) right).getList().listIterator();
+               while(elmIterator.hasNext()) {
+                  RValue elm = elmIterator.next();
+                  SymbolType elmType = SymbolTypeInference.inferType(getProgram().getScope(), elm);
+                  if(SymbolType.NUMBER.equals(elmType)) {
+                     // Add a cast - if the value fits.
+                     if(!SymbolTypeConversion.assignmentTypeMatch(declaredElmType, elmType)) {
+                        throw new CompileError("Array type " + declaredElmType + " does not match element type " + elmType , currentStmt);
+                     }
+                     // TODO: Test if the value matches the declared type!
+                     if(elm instanceof ConstantValue) {
+                        elmIterator.set(new ConstantCastValue(declaredElmType, (ConstantValue) elm));
+                     }  else {
+                        elmIterator.set(new CastValue(declaredElmType, elm));
+                     }
+                     modified.set(true);
+                  }
+               }
+               if(modified.get()) {
+                  getLog().append("Adding number conversion cast (" + declaredElmType+ ") to elements in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
+               }
+            }
+         }
+      });
+      return modified.get();
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
index 908cb0587..3fde76260 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
@@ -43,7 +43,22 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
                   if(leftType.equals(SymbolType.WORD) && isLiteralWordCandidate(rightType)) {
                      SymbolType conversionType = SymbolType.WORD;
                      getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
-                     binary.addRightCast(SymbolType.WORD, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
+                     binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
+                     modified.set(true);
+                  }
+                  // Detect word literal constructor
+                  if(leftType instanceof SymbolTypePointer && isLiteralWordCandidate(rightType)) {
+                     SymbolType conversionType = SymbolType.WORD;
+                     getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
+                     binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
+                     modified.set(true);
+                  }
+
+                  // Detect dword literal constructor
+                  if(leftType.equals(SymbolType.DWORD) && isLiteralWordCandidate(rightType)) {
+                     SymbolType conversionType = SymbolType.DWORD;
+                     getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
+                     binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
                      modified.set(true);
                   }
 
@@ -67,7 +82,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
       if(rightType instanceof SymbolTypeArray) {
          SymbolTypeArray rightArray = (SymbolTypeArray) rightType;
          if(new ConstantInteger(2L, SymbolType.BYTE).equals(rightArray.getSize()))
-            if(SymbolType.BYTE.equals(rightArray.getElementType()) || SymbolType.NUMBER.equals(rightArray.getElementType()))
+            if(SymbolType.isInteger(rightArray.getElementType()))
                return true;
       }
       return false;
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 3bb2350d3..ca909666e 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,9 +32,29 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testMixedArray0() throws IOException, URISyntaxException {
+      compileAndCompare("mixed-array-0");
+   }
+
+   @Test
+   public void testInlinePointer2() throws IOException, URISyntaxException {
+      compileAndCompare("inline-pointer-2");
+   }
+
+   @Test
+   public void testInlinePointer1() throws IOException, URISyntaxException {
+      compileAndCompare("inline-pointer-1");
+   }
+
+   @Test
+   public void testInlinePointer0() throws IOException, URISyntaxException {
+      compileAndCompare("inline-pointer-0");
+   }
+
    @Test
    public void testToD018Problem() throws IOException, URISyntaxException {
-      compileAndCompare("tod018-problem", log());
+      compileAndCompare("tod018-problem");
    }
 
    @Test
diff --git a/src/test/kc/inline-pointer-0.kc b/src/test/kc/inline-pointer-0.kc
new file mode 100644
index 000000000..6f60ecd49
--- /dev/null
+++ b/src/test/kc/inline-pointer-0.kc
@@ -0,0 +1,6 @@
+// Tests creating a literal pointer from two bytes
+
+void main() {
+    byte* screen = (byte*) { 4, 0 };
+    *screen = 'a';
+}
\ No newline at end of file
diff --git a/src/test/kc/inline-pointer-1.kc b/src/test/kc/inline-pointer-1.kc
new file mode 100644
index 000000000..bb1523bbc
--- /dev/null
+++ b/src/test/kc/inline-pointer-1.kc
@@ -0,0 +1,11 @@
+// Tests creating a literal pointer from two bytes
+
+void main() {
+    puta(4, 0x00);
+    puta(5, 0x18);
+}
+
+void puta(byte ph, byte pl) {
+    byte* screen = (byte*) { ph, pl };
+    *screen = 'a';
+}
\ No newline at end of file
diff --git a/src/test/kc/inline-pointer-2.kc b/src/test/kc/inline-pointer-2.kc
new file mode 100644
index 000000000..7bfdfdfe6
--- /dev/null
+++ b/src/test/kc/inline-pointer-2.kc
@@ -0,0 +1,6 @@
+// Tests creating a literal pointer from two bytes
+
+void main() {
+    byte* screen = (byte*){ 4, 0 } + (word){ 0, 40 };
+    *screen = 'a';
+}
\ No newline at end of file
diff --git a/src/test/kc/mixed-array-0.kc b/src/test/kc/mixed-array-0.kc
new file mode 100644
index 000000000..7065854c7
--- /dev/null
+++ b/src/test/kc/mixed-array-0.kc
@@ -0,0 +1,9 @@
+// Test an array with mixed byte/number types
+
+void main() {
+    byte[] msg = { 1ub, 2, 3 };
+    byte* SCREEN = 0x400;
+    SCREEN[0] = msg[0];
+    SCREEN[1] = msg[1];
+    SCREEN[2] = msg[2];
+}
\ No newline at end of file
diff --git a/src/test/kc/true-inline-words.kc b/src/test/kc/true-inline-words.kc
index b9d96a0b6..cc701f1e0 100644
--- a/src/test/kc/true-inline-words.kc
+++ b/src/test/kc/true-inline-words.kc
@@ -3,7 +3,7 @@ void main() {
     byte[] bs = { 'c', 'm' };           // constant byte array
     byte b = 4;                         // constant byte
     word w = { b, 0 };                  // constant inline word
-    word w2 = { 1, 1 } + w + { 0, 0 };  // constant inline words inside expression
+    word w2 = (word){ 1, 1 } + w + (word){ 0, 0 };  // constant inline words inside expression
     byte* sc = w2;                      // implicit cast to (byte*)
     *sc = bs[1];                        // In the end $501 is set to 'c'
 

From 6e0b665423f1106220dcbb0bed8f909414411e82 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Mon, 13 May 2019 09:24:23 +0200
Subject: [PATCH 32/93] Added an array initializer with negative values.

---
 src/test/java/dk/camelot64/kickc/test/TestPrograms.java | 5 +++++
 src/test/kc/mixed-array-1.kc                            | 9 +++++++++
 2 files changed, 14 insertions(+)
 create mode 100644 src/test/kc/mixed-array-1.kc

diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index ca909666e..83498d3aa 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,6 +32,11 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testMixedArray1() throws IOException, URISyntaxException {
+      compileAndCompare("mixed-array-1", log());
+   }
+
    @Test
    public void testMixedArray0() throws IOException, URISyntaxException {
       compileAndCompare("mixed-array-0");
diff --git a/src/test/kc/mixed-array-1.kc b/src/test/kc/mixed-array-1.kc
new file mode 100644
index 000000000..b3c7880b6
--- /dev/null
+++ b/src/test/kc/mixed-array-1.kc
@@ -0,0 +1,9 @@
+// Test an array with mixed byte/number types
+
+void main() {
+    signed byte[] msg = { -1, 0, 1 };
+    signed byte* SCREEN = 0x400;
+    SCREEN[0] = msg[0];
+    SCREEN[1] = msg[1];
+    SCREEN[2] = msg[2];
+}
\ No newline at end of file

From 6cfa5c750cd7e27972052fdfda3533d8b53b6ca4 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 14 May 2019 00:16:17 +0200
Subject: [PATCH 33/93] Implemented cast constant identification. 282/359

---
 .../java/dk/camelot64/kickc/Compiler.java     |  2 ++
 .../kickc/passes/Pass2ConstantValues.java     | 36 +++++++++++++++++++
 2 files changed, 38 insertions(+)
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2ConstantValues.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 6440f0256..a2fac8fe0 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -249,6 +249,7 @@ public class Compiler {
       optimizations.add(new Pass2ConditionalAndOrRewriting(program));
       optimizations.add(new Pass2ConstantRValueConsolidation(program));
       optimizations.add(new Pass2ConstantIdentification(program));
+      optimizations.add(new Pass2ConstantValues(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
       //optimizations.add(new Pass2ConstantAdditionElimination(program));
@@ -308,6 +309,7 @@ public class Compiler {
       constantOptimizations.add(new Pass2IdenticalPhiElimination(program));
       constantOptimizations.add(new Pass2ConstantRValueConsolidation(program));
       constantOptimizations.add(new Pass2ConstantIdentification(program));
+      constantOptimizations.add(new Pass2ConstantValues(program));
       constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
       constantOptimizations.add(new Pass2ConstantSimplification(program));
       constantOptimizations.add(new Pass2ConstantCastSimplification(program));
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantValues.java
new file mode 100644
index 000000000..e81c7b10b
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantValues.java
@@ -0,0 +1,36 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
+import dk.camelot64.kickc.model.values.*;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Compiler Pass identifying constants values
+ */
+public class Pass2ConstantValues extends Pass2SsaOptimization {
+
+   public Pass2ConstantValues(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
+
+      ProgramValueIterator.execute(getProgram().getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
+         Value value = programValue.get();
+         if((value instanceof RValue) && !(value instanceof ConstantValue)) {
+            ConstantValue constant = Pass2ConstantIdentification.getConstant((RValue) value);
+            if(constant!=null) {
+               programValue.set(constant);
+               getLog().append("Constant value identified " + value+ " in "+ (currentStmt==null?"":currentStmt.toString(getProgram(), false)));
+               modified.set(true);
+            }
+         }
+      });
+      return modified.get();
+   }
+
+}

From 17a0db4472644bd6ce68556283dec94b3a53f73b Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Thu, 16 May 2019 08:51:14 +0200
Subject: [PATCH 34/93] Minor fixes

---
 src/main/fragment/vwuz1=vbuaa_rol_1.asm                  | 5 +++++
 src/main/java/dk/camelot64/kickc/NumberParser.java       | 2 +-
 .../camelot64/kickc/model/types/SymbolTypeInference.java | 6 +++++-
 src/test/java/dk/camelot64/kickc/test/TestPrograms.java  | 5 +++++
 src/test/kc/sandbox.kc                                   | 4 ++--
 src/test/kc/type-inference.kc                            | 9 +++++++++
 6 files changed, 27 insertions(+), 4 deletions(-)
 create mode 100644 src/main/fragment/vwuz1=vbuaa_rol_1.asm
 create mode 100644 src/test/kc/type-inference.kc

diff --git a/src/main/fragment/vwuz1=vbuaa_rol_1.asm b/src/main/fragment/vwuz1=vbuaa_rol_1.asm
new file mode 100644
index 000000000..9c3c7c279
--- /dev/null
+++ b/src/main/fragment/vwuz1=vbuaa_rol_1.asm
@@ -0,0 +1,5 @@
+asl
+sta {z1}
+lda #0
+rol
+sta {z1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/NumberParser.java b/src/main/java/dk/camelot64/kickc/NumberParser.java
index 4f222860d..e72a28df8 100644
--- a/src/main/java/dk/camelot64/kickc/NumberParser.java
+++ b/src/main/java/dk/camelot64/kickc/NumberParser.java
@@ -13,7 +13,7 @@ public class NumberParser {
          throw new NumberFormatException("Not Implemented: non-integer parsing. " + literal);
       }
 
-      SymbolType type = null;
+      SymbolType type = SymbolType.NUMBER;
       if(literal.endsWith("ub") || literal.endsWith("uc")) {
          type = SymbolType.BYTE;
          literal = literal.substring(0, literal.length()-2);
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index 8944b1cfa..e0517349f 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -213,7 +213,11 @@ public class SymbolTypeInference {
             if(type == null) {
                type = valueType;
             } else if(!type.equals(valueType))
-               throw new CompileError("Types not compatible " + type + " and " + valueType);
+               if(valueType instanceof SymbolTypeInteger && type instanceof SymbolTypeInteger) {
+                  type = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) valueType, (SymbolTypeInteger) type);
+               } else  {
+                  throw new CompileError("Phi value has type mismatch "+phiRValue.toString() + " not matching type " + type.getTypeName());
+               }
          }
          if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
             program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program));
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 83498d3aa..4235009d8 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,6 +32,11 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testTypeInference() throws IOException, URISyntaxException {
+      compileAndCompare("type-inference", log().verboseSSAOptimize());
+   }
+
    @Test
    public void testMixedArray1() throws IOException, URISyntaxException {
       compileAndCompare("mixed-array-1", log());
diff --git a/src/test/kc/sandbox.kc b/src/test/kc/sandbox.kc
index 403776835..9cf4f4229 100644
--- a/src/test/kc/sandbox.kc
+++ b/src/test/kc/sandbox.kc
@@ -47,9 +47,9 @@ byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) {
 				for (digit = 0; digit < b; ++digit) dst[bLen++] = buf6[digit];
 				if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' '; 
             } else if (b == 'x' || b == 'X'){ // hex
-				b = (w >> 4) & 0xF;
+				b = ((byte)w >> 4) & 0xF;
 				dst[bLen++] = (b < 10 ? '0' : 0x57) + b; // "('a' - 10)" is the normal way -- not supported  -- https://gitlab.com/camelot/kickc/issues/184 [FIXED]
-				b = w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
+				b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
 			}
             bFormat = 0;
 			continue;
diff --git a/src/test/kc/type-inference.kc b/src/test/kc/type-inference.kc
new file mode 100644
index 000000000..968ecdf1d
--- /dev/null
+++ b/src/test/kc/type-inference.kc
@@ -0,0 +1,9 @@
+// Test inference of integer types in expressions
+
+void main() {
+    const word* screen = 0x0400;
+    for( byte b: 0..20) {
+        screen[b] = -0x30+b;
+    }
+}
+

From 71cedd4d292a89db36026aaa17da7f86008f6e9e Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Fri, 17 May 2019 01:07:47 +0200
Subject: [PATCH 35/93] Working on fixing casts.

---
 src/main/fragment/_deref_pduc1=vduz1.asm      |  8 +++
 src/main/fragment/pbuz1=_ptr_vwuz2.asm        |  4 ++
 ...vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm |  7 ++
 ...vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm |  7 ++
 src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm |  3 +
 src/main/fragment/vwsz1=_sword_vbuaa.asm      |  3 +
 .../java/dk/camelot64/kickc/Compiler.java     |  6 +-
 .../AsmFragmentInstanceSpecFactory.java       | 14 ++--
 .../iterator/ProgramExpressionBinary.java     | 52 +++++++++++++++
 .../iterator/ProgramExpressionIterator.java   |  9 +++
 .../iterator/ProgramExpressionUnary.java      | 39 +++++++++--
 .../kickc/model/operators/OperatorSizeOf.java |  2 +-
 .../model/types/SymbolTypeConversion.java     | 19 ++++++
 .../kickc/passes/Pass3AddAssignmentCasts.java | 41 ++++++++++++
 ...tion.java => PassNCastSimplification.java} | 29 +++++---
 .../dk/camelot64/kickc/test/TestPrograms.java | 66 +++++++++++--------
 src/test/kc/fragment-variations.kc            | 16 +++++
 src/test/kc/sizeof-expr.kc                    |  4 +-
 18 files changed, 277 insertions(+), 52 deletions(-)
 create mode 100644 src/main/fragment/_deref_pduc1=vduz1.asm
 create mode 100644 src/main/fragment/pbuz1=_ptr_vwuz2.asm
 create mode 100644 src/main/fragment/pwsc1_derefidx_vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm
 create mode 100644 src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm
 create mode 100644 src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm
 create mode 100644 src/main/fragment/vwsz1=_sword_vbuaa.asm
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java
 rename src/main/java/dk/camelot64/kickc/passes/{Pass2ConstantCastSimplification.java => PassNCastSimplification.java} (71%)
 create mode 100644 src/test/kc/fragment-variations.kc

diff --git a/src/main/fragment/_deref_pduc1=vduz1.asm b/src/main/fragment/_deref_pduc1=vduz1.asm
new file mode 100644
index 000000000..7b88fe56a
--- /dev/null
+++ b/src/main/fragment/_deref_pduc1=vduz1.asm
@@ -0,0 +1,8 @@
+lda {z1}
+sta {c1}
+lda {z1}+1
+sta {c1}+1
+lda {z1}+2
+sta {c1}+2
+lda {z1}+3
+sta {c1}+3
diff --git a/src/main/fragment/pbuz1=_ptr_vwuz2.asm b/src/main/fragment/pbuz1=_ptr_vwuz2.asm
new file mode 100644
index 000000000..5b8ff5c26
--- /dev/null
+++ b/src/main/fragment/pbuz1=_ptr_vwuz2.asm
@@ -0,0 +1,4 @@
+lda {z2}
+sta {z1}
+lda {z2}+1
+sta {z1}+1
diff --git a/src/main/fragment/pwsc1_derefidx_vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm b/src/main/fragment/pwsc1_derefidx_vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm
new file mode 100644
index 000000000..574b6dc27
--- /dev/null
+++ b/src/main/fragment/pwsc1_derefidx_vbuxx=pwsc1_derefidx_vbuxx_minus_vwsz1.asm
@@ -0,0 +1,7 @@
+lda {c1},x
+sec
+sbc {z1}
+sta {c1},x
+lda {c1}+1,x
+sbc {z1}+1
+sta {c1}+1,x
\ No newline at end of file
diff --git a/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm b/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm
new file mode 100644
index 000000000..856be16de
--- /dev/null
+++ b/src/main/fragment/pwsc1_derefidx_vbuyy=pwsc1_derefidx_vbuyy_minus_vwsz1.asm
@@ -0,0 +1,7 @@
+lda {c1},y
+sec
+sbc {z1}
+sta {c1},y
+lda {c1}+1,y
+sbc {z1}+1
+sta {c1}+1,y
\ No newline at end of file
diff --git a/src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm b/src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm
new file mode 100644
index 000000000..9c8b937fb
--- /dev/null
+++ b/src/main/fragment/vbsaa=_neg__sbyte_vbuaa.asm
@@ -0,0 +1,3 @@
+eor #$ff
+clc
+adc #$01
\ No newline at end of file
diff --git a/src/main/fragment/vwsz1=_sword_vbuaa.asm b/src/main/fragment/vwsz1=_sword_vbuaa.asm
new file mode 100644
index 000000000..e87d75da4
--- /dev/null
+++ b/src/main/fragment/vwsz1=_sword_vbuaa.asm
@@ -0,0 +1,3 @@
+sta {z1}
+lda #0
+sta {z1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index a2fac8fe0..19d962e42 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -270,7 +270,7 @@ public class Compiler {
       optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new Pass2InlineDerefIdx(program));
       optimizations.add(new Pass2DeInlineWordDerefIdx(program));
-      optimizations.add(new Pass2ConstantCastSimplification(program));
+      optimizations.add(new PassNCastSimplification(program));
       pass2Execute(optimizations);
    }
 
@@ -312,7 +312,7 @@ public class Compiler {
       constantOptimizations.add(new Pass2ConstantValues(program));
       constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
       constantOptimizations.add(new Pass2ConstantSimplification(program));
-      constantOptimizations.add(new Pass2ConstantCastSimplification(program));
+      constantOptimizations.add(new PassNCastSimplification(program));
       constantOptimizations.add(new Pass2ConstantIfs(program));
       pass2Execute(constantOptimizations);
 
@@ -373,6 +373,8 @@ public class Compiler {
       new Pass3AssertConstants(program).check();
       new Pass3AssertArrayLengths(program).check();
       new Pass3AssertNoMulDivMod(program).check();
+      new Pass3AddAssignmentCasts(program).execute();
+      new PassNCastSimplification(program).execute();
       new PassNBlockSequencePlanner(program).step();
       // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes
       new Pass3PhiLifting(program).perform();
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
index de00e8edf..bf197e32e 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
@@ -5,6 +5,8 @@ import dk.camelot64.kickc.model.ControlFlowGraph;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.Registers;
 import dk.camelot64.kickc.model.operators.Operator;
+import dk.camelot64.kickc.model.operators.OperatorUnary;
+import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementConditionalJump;
@@ -228,13 +230,15 @@ public class AsmFragmentInstanceSpecFactory {
       if(value instanceof CastValue) {
          CastValue castVal = (CastValue) value;
          SymbolType toType = castVal.getToType();
-         value = castVal.getValue();
-         return bind(value, toType);
+         OperatorUnary castUnary = Operators.getCastUnary(toType);
+         return getOperatorFragmentName(castUnary) + bind(castVal.getValue());
       } else if(value instanceof ConstantCastValue) {
          ConstantCastValue castVal = (ConstantCastValue) value;
-         SymbolType toType = castVal.getToType();
-         value = castVal.getValue();
-         return bind(value, toType);
+         if(castType==null) {
+            return bind(castVal.getValue(), castVal.getToType());
+         } else {
+            return bind(castVal.getValue(), castType);
+         }
       } else if(value instanceof PointerDereference) {
          PointerDereference deref = (PointerDereference) value;
          SymbolType ptrType = null;
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
index f23553a71..e0b959796 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
@@ -7,6 +7,7 @@ import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementConditionalJump;
+import dk.camelot64.kickc.model.statements.StatementPhiBlock;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.symbols.Scope;
 import dk.camelot64.kickc.model.symbols.VariableIntermediate;
@@ -331,4 +332,55 @@ public interface ProgramExpressionBinary extends ProgramExpression {
    }
 
 
+   /** Assignment of a phi value to a phi variable. */
+   class ProgramExpressionBinaryPhiValueAssignemnt implements ProgramExpressionBinary {
+
+      private final StatementPhiBlock.PhiVariable phiVariable;
+      private final StatementPhiBlock.PhiRValue value;
+
+      public ProgramExpressionBinaryPhiValueAssignemnt(StatementPhiBlock.PhiVariable phiVariable, StatementPhiBlock.PhiRValue value) {
+         this.phiVariable = phiVariable;
+         this.value = value;
+      }
+
+      @Override
+      public RValue getLeft() {
+         return phiVariable.getVariable();
+      }
+
+      @Override
+      public OperatorBinary getOperator() {
+         return Operators.ASSIGNMENT;
+      }
+
+      @Override
+      public RValue getRight() {
+         return value.getrValue();
+      }
+
+      @Override
+      public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         throw new InternalError("Not supported!");
+      }
+
+      @Override
+      public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
+         if(getRight() instanceof ConstantValue) {
+            value.setrValue(new ConstantCastValue(toType, (ConstantValue) getRight()));
+         }  else {
+            // Try to use CastValue - may later have to be supported!
+            value.setrValue(new CastValue(toType, getRight()));
+         }
+      }
+
+      @Override
+      public void set(Value value) {
+         throw new InternalError("Not supported!");
+      }
+   }
+
+
+
+
+
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
index 6a6d9c3dc..1995dbf5e 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
@@ -5,6 +5,7 @@ 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.StatementConditionalJump;
+import dk.camelot64.kickc.model.statements.StatementPhiBlock;
 import dk.camelot64.kickc.model.values.*;
 
 import java.util.ListIterator;
@@ -32,6 +33,8 @@ public class ProgramExpressionIterator {
          } else if(programValue.get() instanceof PointerDereferenceIndexed) {
             handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null);
          } else if(programValue.get() instanceof ConstantCastValue) {
+            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstantCast(programValue), null, null, null);
+         } else if(programValue.get() instanceof CastValue) {
             handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), null, null, null);
          }
       };
@@ -55,6 +58,12 @@ public class ProgramExpressionIterator {
                if(condJump.getrValue1() != null && condJump.getOperator() != null && condJump.getrValue2() != null) {
                   handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConditionalJump(condJump), stmt, stmtIt, block);
                }
+            } else if(stmt instanceof StatementPhiBlock) {
+               for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) stmt).getPhiVariables()) {
+                  for(StatementPhiBlock.PhiRValue value : phiVariable.getValues()) {
+                     handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPhiValueAssignemnt(phiVariable, value), stmt, stmtIt, block);
+                  }
+               }
             }
             // Iterate all statement values
             ProgramValueIterator.execute(stmt, programValueHandler, stmtIt, block);
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
index fdcdeb4a0..5b0fe07d9 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionUnary.java
@@ -3,10 +3,7 @@ package dk.camelot64.kickc.model.iterator;
 import dk.camelot64.kickc.model.operators.OperatorUnary;
 import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
-import dk.camelot64.kickc.model.values.ConstantCastValue;
-import dk.camelot64.kickc.model.values.ConstantUnary;
-import dk.camelot64.kickc.model.values.RValue;
-import dk.camelot64.kickc.model.values.Value;
+import dk.camelot64.kickc.model.values.*;
 
 /**
  * A binary expression in the program being iterated by {@link ProgramExpressionIterator}
@@ -84,12 +81,12 @@ public interface ProgramExpressionUnary extends ProgramExpression {
    }
 
    /** Unary cast expression {@link ConstantCastValue} as part of a constant expression. */
-   class ProgramExpressionUnaryCast implements ProgramExpressionUnary {
+   class ProgramExpressionUnaryConstantCast implements ProgramExpressionUnary {
 
       /** A ProgramValue containing a {@link ConstantCastValue}. */
       private ProgramValue programValue;
 
-      ProgramExpressionUnaryCast(ProgramValue programValue) {
+      ProgramExpressionUnaryConstantCast(ProgramValue programValue) {
          this.programValue = programValue;
       }
 
@@ -114,6 +111,36 @@ public interface ProgramExpressionUnary extends ProgramExpression {
 
    }
 
+   /** Unary cast expression {@link CastValue} as part of a constant expression. */
+   class ProgramExpressionUnaryCast implements ProgramExpressionUnary {
+
+      /** A ProgramValue containing a {@link CastValue}. */
+      private ProgramValue programValue;
+
+      ProgramExpressionUnaryCast(ProgramValue programValue) {
+         this.programValue = programValue;
+      }
+
+      public CastValue getConstantUnary() {
+         return (CastValue) programValue.get();
+      }
+
+      @Override
+      public OperatorUnary getOperator() {
+         return Operators.getCastUnary(getConstantUnary().getToType());
+      }
+
+      @Override
+      public RValue getOperand() {
+         return getConstantUnary().getValue();
+      }
+
+      @Override
+      public void set(Value value) {
+         programValue.set(value);
+      }
+
+   }
 
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
index 6300140e1..11fa1b0a1 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
@@ -40,7 +40,7 @@ public class OperatorSizeOf extends OperatorUnary {
       if(typeSizeConstant == null) {
          // Constant not found - create it
          long typeSize = type.getSizeBytes();
-         typeSizeConstant = new ConstantVar(typeConstName, programScope, SymbolType.BYTE, new ConstantInteger(typeSize));
+         typeSizeConstant = new ConstantVar(typeConstName, programScope, SymbolType.BYTE, new ConstantInteger(typeSize&0xff, SymbolType.BYTE));
          programScope.add(typeSizeConstant);
       }
       return typeSizeConstant.getRef();
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index 88dd99c38..6326a145b 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -175,4 +175,23 @@ public class SymbolTypeConversion {
       }
       return false;
    }
+
+   /**
+    * Determines if the left side of an assignment needs a cast to be assigned to the right side
+    * @param lValueType The type of the LValue
+    * @param rValueType The type of the RValue
+    * @return true if the left side needs a cast
+    */
+   public static boolean assignmentCastNeeded(SymbolType lValueType, SymbolType rValueType) {
+      if(lValueType.equals(rValueType))
+         return false;
+      else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer)
+         return false;
+      else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType))
+         return false;
+      else
+      return true;
+
+   }
+
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java
new file mode 100644
index 000000000..aee315662
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java
@@ -0,0 +1,41 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
+import dk.camelot64.kickc.model.types.SymbolTypeInference;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Add casts to assignments where the lvalue and rvalue have different matching types.
+ */
+public class Pass3AddAssignmentCasts extends Pass2SsaOptimization {
+
+   public Pass3AddAssignmentCasts(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
+      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(programExpression instanceof ProgramExpressionBinary) {
+            if(Operators.ASSIGNMENT.equals(programExpression.getOperator())) {
+               ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression;
+               SymbolType leftType = SymbolTypeInference.inferType(getScope(), binary.getLeft());
+               SymbolType rightType = SymbolTypeInference.inferType(getScope(), binary.getRight());
+               if(SymbolTypeConversion.assignmentTypeMatch(leftType, rightType) && SymbolTypeConversion.assignmentCastNeeded(leftType, rightType)) {
+                  binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
+                  getLog().append("Adding assignment cast to " + currentStmt.toString(getProgram(), false));
+                  modified.set(true);
+               }
+            }
+         }
+      });
+      return modified.get();
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java
similarity index 71%
rename from src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
rename to src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java
index 467e386ca..5661a8624 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantCastSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java
@@ -3,19 +3,21 @@ package dk.camelot64.kickc.passes;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
-import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
 import dk.camelot64.kickc.model.operators.OperatorCast;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.values.*;
+import dk.camelot64.kickc.model.types.*;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.ConstantPointer;
+import dk.camelot64.kickc.model.values.RValue;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
-/** Simplifies casts of (number) constants to a type. */
-public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
+/** Simplifies casts
+ * - Inlines casts of (number) constants
+ * - Removes unnecessary casts
+ * */
+public class PassNCastSimplification extends Pass2SsaOptimization {
 
-   public Pass2ConstantCastSimplification(Program program) {
+   public PassNCastSimplification(Program program) {
       super(program);
    }
 
@@ -27,8 +29,15 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
             OperatorCast operatorCast = (OperatorCast) programExpression.getOperator();
             ProgramExpressionUnary unary = (ProgramExpressionUnary) programExpression;
             SymbolType castType = operatorCast.getToType();
-            if(unary.getOperand() instanceof ConstantInteger) {
-               ConstantInteger constantInteger = (ConstantInteger) unary.getOperand();
+            SymbolType operandType = SymbolTypeInference.inferType(getScope(), ((ProgramExpressionUnary) programExpression).getOperand());
+            RValue unaryOperand = unary.getOperand();
+            if(!SymbolTypeConversion.assignmentCastNeeded(castType, operandType)) {
+               // Cast Not needed
+               programExpression.set(unaryOperand);
+               getLog().append("Simplifying constant integer cast " + unaryOperand.toString(getProgram()));
+               optimized.set(true);
+            } else if(unaryOperand instanceof ConstantInteger) {
+               ConstantInteger constantInteger = (ConstantInteger) unaryOperand;
                if(SymbolType.NUMBER.equals(constantInteger.getType())) {
                   if(castType instanceof SymbolTypeIntegerFixed ) {
                      ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 4235009d8..4c242b507 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,14 +32,52 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   /*
+    * Avaiting String concatenation
+
+   @Test
+   public void testLiterals() throws IOException, URISyntaxException {
+      compileAndCompare("literals");
+   }
+
+
+    @Test
+    public void testConstantStringConcat() throws IOException, URISyntaxException {
+      compileAndCompare("constant-string-concat");
+    }
+
+   @Test
+   public void testConcatChar() throws IOException, URISyntaxException {
+      compileAndCompare("concat-char");
+   }
+
+   @Test
+   public void testC64DtvGfxModes() throws IOException, URISyntaxException {
+      compileAndCompare("c64dtv-gfxmodes", 10);
+   }
+
+   @Test
+   public void testC64DtvGfxExplorer() throws IOException, URISyntaxException {
+      compileAndCompare("c64dtv-gfxexplorer", 10);
+   }
+
+    */
+
+
+
+   @Test
+   public void testFragmentVariations() throws IOException, URISyntaxException {
+      compileAndCompare("fragment-variations");
+   }
+
    @Test
    public void testTypeInference() throws IOException, URISyntaxException {
-      compileAndCompare("type-inference", log().verboseSSAOptimize());
+      compileAndCompare("type-inference");
    }
 
    @Test
    public void testMixedArray1() throws IOException, URISyntaxException {
-      compileAndCompare("mixed-array-1", log());
+      compileAndCompare("mixed-array-1");
    }
 
    @Test
@@ -1059,11 +1097,6 @@ public class TestPrograms {
       compileAndCompare("assignment-chained");
    }
 
-   @Test
-   public void testConcatChar() throws IOException, URISyntaxException {
-      compileAndCompare("concat-char");
-   }
-
    @Test
    public void testConstMultDiv() throws IOException, URISyntaxException {
       compileAndCompare("const-mult-div");
@@ -1184,11 +1217,6 @@ public class TestPrograms {
       compileAndCompare("c64dtv-8bppcharstretch");
    }
 
-   @Test
-   public void testC64DtvGfxExplorer() throws IOException, URISyntaxException {
-      compileAndCompare("c64dtv-gfxexplorer", 10);
-   }
-
    @Test
    public void testInlineString2() throws IOException, URISyntaxException {
       compileAndCompare("inline-string-2");
@@ -1209,11 +1237,6 @@ public class TestPrograms {
       compileAndCompare("keyboard-glitch");
    }
 
-   @Test
-   public void testC64DtvGfxModes() throws IOException, URISyntaxException {
-      compileAndCompare("c64dtv-gfxmodes", 10);
-   }
-
    @Test
    public void testNoromCharset() throws IOException, URISyntaxException {
       compileAndCompare("norom-charset");
@@ -1359,11 +1382,6 @@ public class TestPrograms {
       compileAndCompare("arrays-init");
    }
 
-   @Test
-   public void testConstantStringConcat() throws IOException, URISyntaxException {
-      compileAndCompare("constant-string-concat");
-   }
-
    @Test
    public void testTrueInlineWords() throws IOException, URISyntaxException {
       compileAndCompare("true-inline-words");
@@ -1579,10 +1597,6 @@ public class TestPrograms {
       compileAndCompare("halfscii");
    }
 
-   @Test
-   public void testLiterals() throws IOException, URISyntaxException {
-      compileAndCompare("literals");
-   }
 
    @Test
    public void testScroll() throws IOException, URISyntaxException {
diff --git a/src/test/kc/fragment-variations.kc b/src/test/kc/fragment-variations.kc
new file mode 100644
index 000000000..ded7edfd4
--- /dev/null
+++ b/src/test/kc/fragment-variations.kc
@@ -0,0 +1,16 @@
+// Tests that ASM fragment variations works
+// ASM fragment variations "cast" constants to different types
+
+void main() {
+    dword* screen = 0x400;
+    word w = 10;
+    screen[0] = mul16u(w, w);
+    w = 1000;
+    screen[1] = mul16u(w, w);
+}
+
+dword mul16u(word b, word a) {
+    dword mb = b;
+    return mb+a;
+}
+
diff --git a/src/test/kc/sizeof-expr.kc b/src/test/kc/sizeof-expr.kc
index d48116db5..adc8538ac 100644
--- a/src/test/kc/sizeof-expr.kc
+++ b/src/test/kc/sizeof-expr.kc
@@ -19,7 +19,7 @@ void main() {
     byte[] bc = { 1, 2, 3, 4 };
     // Strings
     byte[] sa = "camelot";
-    byte[] sb = "cml"+" "+"rules";
+    //byte[] sb = { 'a', 'b', 'c', 0};
 
     SCREEN[idx++] = '0'+sizeof(0);
     SCREEN[idx++] = '0'+sizeof(idx);
@@ -37,6 +37,6 @@ void main() {
     SCREEN[idx++] = '0'+sizeof(bb);
     SCREEN[idx++] = '0'+sizeof(bc);
     SCREEN[idx++] = '0'+sizeof(sa);
-    SCREEN[idx++] = '0'+sizeof(sb);
+    //SCREEN[idx++] = '0'+sizeof(sb);
 
 }
\ No newline at end of file

From 0876603ca750eedf122d5d6c4145b1c9c8d34a86 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Fri, 17 May 2019 08:55:04 +0200
Subject: [PATCH 36/93] Working on casts

---
 src/main/java/dk/camelot64/kickc/Compiler.java               | 4 ++--
 .../camelot64/kickc/model/operators/OperatorShiftLeft.java   | 4 ----
 .../camelot64/kickc/model/operators/OperatorShiftRight.java  | 4 ----
 .../kickc/passes/Pass2MultiplyToShiftRewriting.java          | 5 +++--
 src/test/java/dk/camelot64/kickc/test/TestPrograms.java      | 2 +-
 5 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 19d962e42..577463f7f 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -261,12 +261,11 @@ public class Compiler {
       optimizations.add(new Pass2TypeInference(program));
       optimizations.add(new PassNEliminateUnusedVars(program, true));
       optimizations.add(new Pass2EliminateRedundantCasts(program));
-      optimizations.add(new Pass2NopCastElimination(program));
+      //optimizations.add(new Pass2NopCastElimination(program));
       optimizations.add(new Pass2EliminateUnusedBlocks(program));
       optimizations.add(new Pass2RangeResolving(program));
       optimizations.add(new Pass2ComparisonOptimization(program));
       optimizations.add(new Pass2ConstantCallPointerIdentification(program));
-      optimizations.add(new Pass2MultiplyToShiftRewriting(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new Pass2InlineDerefIdx(program));
       optimizations.add(new Pass2DeInlineWordDerefIdx(program));
@@ -303,6 +302,7 @@ public class Compiler {
    private void pass2InlineConstants() {
       // Constant inlining optimizations - as the last step to ensure that constant identification has been completed
       List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>();
+      constantOptimizations.add(new Pass2MultiplyToShiftRewriting(program));
       constantOptimizations.add(new Pass2AliasElimination(program));
       constantOptimizations.add(new Pass2ConstantInlining(program));
       constantOptimizations.add(new Pass2ConstantStringConsolidation(program));
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
index c6c7f3f72..3350f82f7 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
@@ -26,11 +26,7 @@ public class OperatorShiftLeft extends OperatorBinary {
 
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
-      if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
-         return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right);
-      } else {
          return left;
-      }
    }
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
index dc9c66a69..2f8a9dca0 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
@@ -25,11 +25,7 @@ public class OperatorShiftRight extends OperatorBinary {
 
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
-      if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
-         return SymbolTypeConversion.convertedMathType( (SymbolTypeInteger) left, (SymbolTypeInteger)right);
-      } else {
          return left;
-      }
    }
 
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java b/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java
index cad43daf9..5664593e6 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2MultiplyToShiftRewriting.java
@@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.values.*;
 
 import java.util.ListIterator;
@@ -44,12 +45,12 @@ public class Pass2MultiplyToShiftRewriting extends Pass2SsaOptimization {
                         if(Operators.MULTIPLY.equals(assignment.getOperator())) {
                            getLog().append("Rewriting multiplication to use shift "+statement.toString(getProgram(), false));
                            assignment.setOperator(Operators.SHIFT_LEFT);
-                           assignment.setrValue2(new ConstantInteger((long)power2));
+                           assignment.setrValue2(new ConstantInteger((long)power2, SymbolType.BYTE));
                            optimized = true;
                         }  else if(Operators.DIVIDE.equals(assignment.getOperator())) {
                            getLog().append("Rewriting division to use shift "+statement.toString(getProgram(), false));
                            assignment.setOperator(Operators.SHIFT_RIGHT);
-                           assignment.setrValue2(new ConstantInteger((long)power2));
+                           assignment.setrValue2(new ConstantInteger((long)power2, SymbolType.BYTE));
                            optimized = true;
                         }
                      }
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 4c242b507..66978362f 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -333,7 +333,7 @@ public class TestPrograms {
 
    @Test
    public void testPointerCast2() throws IOException, URISyntaxException {
-      compileAndCompare("pointer-cast-2");
+      compileAndCompare("pointer-cast-2", log());
    }
 
    @Test

From c200eaa53518ecbbb0557252eaba2d85cc8d8da4 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Sat, 18 May 2019 00:37:09 +0200
Subject: [PATCH 37/93] Working on casts

---
 .../java/dk/camelot64/kickc/Compiler.java     |  1 +
 .../AsmFragmentInstanceSpecFactory.java       | 14 +++++--
 .../model/types/SymbolTypeConversion.java     |  4 +-
 .../kickc/passes/Pass2InlineCast.java         | 39 +++++++++++++++++++
 .../dk/camelot64/kickc/test/TestPrograms.java |  4 +-
 src/test/kc/number-type.kc                    | 26 ++++++-------
 6 files changed, 68 insertions(+), 20 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 577463f7f..eb8f14abf 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -268,6 +268,7 @@ public class Compiler {
       optimizations.add(new Pass2ConstantCallPointerIdentification(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new Pass2InlineDerefIdx(program));
+      optimizations.add(new Pass2InlineCast(program));
       optimizations.add(new Pass2DeInlineWordDerefIdx(program));
       optimizations.add(new PassNCastSimplification(program));
       pass2Execute(optimizations);
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
index bf197e32e..caf298e42 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
@@ -228,13 +228,21 @@ public class AsmFragmentInstanceSpecFactory {
    public String bind(Value value, SymbolType castType) {
 
       if(value instanceof CastValue) {
-         CastValue castVal = (CastValue) value;
-         SymbolType toType = castVal.getToType();
+         CastValue cast = (CastValue) value;
+         SymbolType toType = cast.getToType();
          OperatorUnary castUnary = Operators.getCastUnary(toType);
-         return getOperatorFragmentName(castUnary) + bind(castVal.getValue());
+         RValue castValue = cast.getValue();
+         SymbolType castValueType = SymbolTypeInference.inferType(this.program.getScope(), castValue);
+         if(castValueType.getSizeBytes()==toType.getSizeBytes()) {
+            return bind(castValue, toType);
+         } else {
+            return getOperatorFragmentName(castUnary) + bind(castValue);
+         }
       } else if(value instanceof ConstantCastValue) {
          ConstantCastValue castVal = (ConstantCastValue) value;
          if(castType==null) {
+            // TODO: If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff )
+
             return bind(castVal.getValue(), castVal.getToType());
          } else {
             return bind(castVal.getValue(), castType);
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index 6326a145b..b82e23e76 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -185,9 +185,9 @@ public class SymbolTypeConversion {
    public static boolean assignmentCastNeeded(SymbolType lValueType, SymbolType rValueType) {
       if(lValueType.equals(rValueType))
          return false;
-      else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer)
+      else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(((SymbolTypePointer) rValueType).getElementType()))
          return false;
-      else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType))
+      else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE))
          return false;
       else
       return true;
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java
new file mode 100644
index 000000000..2ba632bed
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineCast.java
@@ -0,0 +1,39 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.ControlFlowBlock;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.operators.OperatorCast;
+import dk.camelot64.kickc.model.statements.Statement;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.values.CastValue;
+
+/** Identify unary casts */
+public class Pass2InlineCast extends Pass2SsaOptimization {
+
+   public Pass2InlineCast(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      boolean optimized = false;
+      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
+         for(Statement statement : block.getStatements()) {
+            if(statement instanceof StatementAssignment) {
+               StatementAssignment assignment = (StatementAssignment) statement;
+               if(assignment.getrValue1()==null && assignment.getOperator() instanceof OperatorCast) {
+                  SymbolType toType = ((OperatorCast) assignment.getOperator()).getToType();
+                  assignment.setrValue2(new CastValue(toType, assignment.getrValue2()));
+                  assignment.setOperator(null);
+                  getLog().append("Inlining cast "+assignment.toString(getProgram(), false));
+                  optimized = true;
+               }
+            }
+         }
+      }
+      return optimized;
+   }
+
+
+}
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 66978362f..ec6380462 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -117,7 +117,7 @@ public class TestPrograms {
 
    @Test
    public void testNumberType() throws IOException, URISyntaxException {
-      compileAndCompare("number-type");
+      compileAndCompare("number-type", log());
    }
 
    @Test
@@ -333,7 +333,7 @@ public class TestPrograms {
 
    @Test
    public void testPointerCast2() throws IOException, URISyntaxException {
-      compileAndCompare("pointer-cast-2", log());
+      compileAndCompare("pointer-cast-2");
    }
 
    @Test
diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc
index 74f270661..2ce2a2ca2 100644
--- a/src/test/kc/number-type.kc
+++ b/src/test/kc/number-type.kc
@@ -3,25 +3,25 @@
 
 void main() {
     testBytes();
-    testSBytes();
+    //testSBytes();
 }
 
 void testBytes() {
     // Constant values resolvable to bytes
     const byte* SCREEN = 0x0400;
     byte idx = 0;
-    SCREEN[idx++] = 12;
-    SCREEN[idx++] = 6+6;
-    SCREEN[idx++] = 18-6;
-    SCREEN[idx++] = 1812-1800;
-    SCREEN[idx++] = 1+2+3+6;
-    SCREEN[idx++] = 2*6;
-    SCREEN[idx++] = 3<<2;
-    SCREEN[idx++] = 24>>1;
-    SCREEN[idx++] = 15&28;
-    SCREEN[idx++] = 4|8;
-    SCREEN[idx++] = 5^9;
-    SCREEN[idx++] = (2+2)*(15/5);
+    //SCREEN[idx++] = 12;
+    //SCREEN[idx++] = 6+6;
+    //SCREEN[idx++] = 18-6;
+    //SCREEN[idx++] = 1812-1800;
+    //SCREEN[idx++] = 1+2+3+6;
+    //SCREEN[idx++] = 2*6;
+    //SCREEN[idx++] = 3<<2;
+    //SCREEN[idx++] = 24>>1;
+    //SCREEN[idx++] = 15&28;
+    //SCREEN[idx++] = 4|8;
+    //SCREEN[idx++] = 5^9;
+    //SCREEN[idx++] = (2+2)*(15/5);
     SCREEN[idx++] = (byte)(4096+12);
 }
 

From 9f27006540778c8ff4bf619b69482622bd9cc426 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 08:14:34 +0200
Subject: [PATCH 38/93] Working on casts

---
 .../AsmFragmentInstanceSpecFactory.java       | 34 +++++++++++++------
 .../dk/camelot64/kickc/test/TestPrograms.java |  4 +--
 .../kc/examples/sinplotter/sine-plotter.kc    |  2 +-
 src/test/kc/number-type.kc                    | 26 +++++++-------
 4 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
index caf298e42..5030079a3 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
@@ -14,10 +14,7 @@ import dk.camelot64.kickc.model.symbols.ConstantVar;
 import dk.camelot64.kickc.model.symbols.Label;
 import dk.camelot64.kickc.model.symbols.Symbol;
 import dk.camelot64.kickc.model.symbols.Variable;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
+import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.*;
 
 import java.util.LinkedHashMap;
@@ -89,6 +86,7 @@ public class AsmFragmentInstanceSpecFactory {
 
    /**
     * Get the created ASM fragment instance specification
+    *
     * @return The ASM fragment instance specification
     */
    public AsmFragmentInstanceSpec getAsmFragmentInstanceSpec() {
@@ -233,19 +231,35 @@ public class AsmFragmentInstanceSpecFactory {
          OperatorUnary castUnary = Operators.getCastUnary(toType);
          RValue castValue = cast.getValue();
          SymbolType castValueType = SymbolTypeInference.inferType(this.program.getScope(), castValue);
-         if(castValueType.getSizeBytes()==toType.getSizeBytes()) {
+         if(castValueType.getSizeBytes() == toType.getSizeBytes()) {
             return bind(castValue, toType);
          } else {
             return getOperatorFragmentName(castUnary) + bind(castValue);
          }
       } else if(value instanceof ConstantCastValue) {
          ConstantCastValue castVal = (ConstantCastValue) value;
-         if(castType==null) {
-            // TODO: If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff )
+         ConstantValue val = castVal.getValue();
+         if(castType == null) {
+            SymbolType toType = castVal.getToType();
+            // If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff )
+            ConstantLiteral constantLiteral = val.calculateLiteral(program.getScope());
+            if(constantLiteral instanceof ConstantInteger) {
+               if(toType instanceof SymbolTypeIntegerFixed) {
+                  if(!((SymbolTypeIntegerFixed) toType).contains(((ConstantInteger) constantLiteral).getValue())) {
+                     if(toType.getSizeBytes() == 1) {
+                        val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val);
+                     } else if(toType.getSizeBytes() == 2) {
+                        val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val);
+                     } else {
+                        throw new InternalError("Not implemented!");
+                     }
+                  }
+               }
+            }
 
-            return bind(castVal.getValue(), castVal.getToType());
+            return bind(val, toType);
          } else {
-            return bind(castVal.getValue(), castType);
+            return bind(val, castType);
          }
       } else if(value instanceof PointerDereference) {
          PointerDereference deref = (PointerDereference) value;
@@ -357,7 +371,7 @@ public class AsmFragmentInstanceSpecFactory {
                   Registers.RegisterType.ZP_BYTE.equals(register.getType()) ||
                   Registers.RegisterType.ZP_WORD.equals(register.getType()) ||
                   Registers.RegisterType.ZP_DWORD.equals(register.getType())
-            ) {
+      ) {
          // Examine if the ZP register is already bound
          Registers.RegisterZp registerZp = (Registers.RegisterZp) register;
          String zpNameIdx = null;
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index ec6380462..d7455e9d6 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,8 +63,6 @@ public class TestPrograms {
 
     */
 
-
-
    @Test
    public void testFragmentVariations() throws IOException, URISyntaxException {
       compileAndCompare("fragment-variations");
@@ -117,7 +115,7 @@ public class TestPrograms {
 
    @Test
    public void testNumberType() throws IOException, URISyntaxException {
-      compileAndCompare("number-type", log());
+      compileAndCompare("number-type");
    }
 
    @Test
diff --git a/src/test/kc/examples/sinplotter/sine-plotter.kc b/src/test/kc/examples/sinplotter/sine-plotter.kc
index a46eb11c2..300f5591c 100644
--- a/src/test/kc/examples/sinplotter/sine-plotter.kc
+++ b/src/test/kc/examples/sinplotter/sine-plotter.kc
@@ -12,7 +12,7 @@ const word SIN_SIZE = 512;
 
 signed word[512] align($100) sin;
 
-signed word* sin2 = $1400;
+signed word* sin2 = $1500;
 
 kickasm(pc sin2) {{
     .for(var i=0; i<512; i++) {
diff --git a/src/test/kc/number-type.kc b/src/test/kc/number-type.kc
index 2ce2a2ca2..74f270661 100644
--- a/src/test/kc/number-type.kc
+++ b/src/test/kc/number-type.kc
@@ -3,25 +3,25 @@
 
 void main() {
     testBytes();
-    //testSBytes();
+    testSBytes();
 }
 
 void testBytes() {
     // Constant values resolvable to bytes
     const byte* SCREEN = 0x0400;
     byte idx = 0;
-    //SCREEN[idx++] = 12;
-    //SCREEN[idx++] = 6+6;
-    //SCREEN[idx++] = 18-6;
-    //SCREEN[idx++] = 1812-1800;
-    //SCREEN[idx++] = 1+2+3+6;
-    //SCREEN[idx++] = 2*6;
-    //SCREEN[idx++] = 3<<2;
-    //SCREEN[idx++] = 24>>1;
-    //SCREEN[idx++] = 15&28;
-    //SCREEN[idx++] = 4|8;
-    //SCREEN[idx++] = 5^9;
-    //SCREEN[idx++] = (2+2)*(15/5);
+    SCREEN[idx++] = 12;
+    SCREEN[idx++] = 6+6;
+    SCREEN[idx++] = 18-6;
+    SCREEN[idx++] = 1812-1800;
+    SCREEN[idx++] = 1+2+3+6;
+    SCREEN[idx++] = 2*6;
+    SCREEN[idx++] = 3<<2;
+    SCREEN[idx++] = 24>>1;
+    SCREEN[idx++] = 15&28;
+    SCREEN[idx++] = 4|8;
+    SCREEN[idx++] = 5^9;
+    SCREEN[idx++] = (2+2)*(15/5);
     SCREEN[idx++] = (byte)(4096+12);
 }
 

From 855434afa91f35ef0c75d72cbeb7e7c207398933 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 08:51:22 +0200
Subject: [PATCH 39/93] Added missing fragment and ternary type inference test

---
 src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm          | 11 +++++++++++
 .../java/dk/camelot64/kickc/test/TestPrograms.java    |  5 +++++
 src/test/kc/ternary-inference.kc                      | 10 ++++++++++
 3 files changed, 26 insertions(+)
 create mode 100644 src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm
 create mode 100644 src/test/kc/ternary-inference.kc

diff --git a/src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm b/src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm
new file mode 100644
index 000000000..1d0b489df
--- /dev/null
+++ b/src/main/fragment/vwsz1=vbsaa_plus_vwsc1.asm
@@ -0,0 +1,11 @@
+tax
+clc
+adc #<{c1}
+sta {z1}
+txa
+ora #$7f
+bmi !+
+lda #0
+!:
+adc #>{c1}
+sta {z1}+1
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index d7455e9d6..e7a351b6a 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,11 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testTernaryInference() throws IOException, URISyntaxException {
+      compileAndCompare("ternary-inference");
+   }
+
    @Test
    public void testFragmentVariations() throws IOException, URISyntaxException {
       compileAndCompare("fragment-variations");
diff --git a/src/test/kc/ternary-inference.kc b/src/test/kc/ternary-inference.kc
new file mode 100644
index 000000000..47e22265d
--- /dev/null
+++ b/src/test/kc/ternary-inference.kc
@@ -0,0 +1,10 @@
+// Type inference into the ternary operator
+
+void main() {
+
+    const byte* screen = 0x400;
+    for(byte i: 0..10) {
+        screen[i] = (i<5?0x57:'0')+i;
+    }
+
+}
\ No newline at end of file

From 13cc9e453cdaed1a265015d6be5412e8e1ed3cf6 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 12:23:13 +0200
Subject: [PATCH 40/93] Fixed a few tests. +0 in derefidx and rangenext() on
 signed words.

---
 .../fragment/pptz1_derefidx_vbuc1=pbuz2.asm   |  6 ++++++
 .../fragment/pptz1_derefidx_vbuc1=pwuz2.asm   |  6 ++++++
 .../fragment/pptz1_derefidx_vbuyy=pbuz2.asm   |  5 +++++
 .../fragment/pptz1_derefidx_vbuyy=pwuz2.asm   |  5 +++++
 .../camelot64/kickc/fragment/AsmFormat.java   |  6 +++++-
 .../model/types/SymbolTypeInference.java      |  2 +-
 .../Pass0GenerateStatementSequence.java       | 19 ++++++++++++++-----
 .../Pass2ConstantAdditionElimination.java     |  7 +++++++
 .../dk/camelot64/kickc/test/TestPrograms.java |  2 +-
 9 files changed, 50 insertions(+), 8 deletions(-)
 create mode 100644 src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm
 create mode 100644 src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm
 create mode 100644 src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm
 create mode 100644 src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm

diff --git a/src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm b/src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm
new file mode 100644
index 000000000..d59fe6a79
--- /dev/null
+++ b/src/main/fragment/pptz1_derefidx_vbuc1=pbuz2.asm
@@ -0,0 +1,6 @@
+ldy #{c1}
+lda {z2}
+sta ({z1}),y
+iny
+lda {z2}+1
+sta ({z1}),y
diff --git a/src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm b/src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm
new file mode 100644
index 000000000..d59fe6a79
--- /dev/null
+++ b/src/main/fragment/pptz1_derefidx_vbuc1=pwuz2.asm
@@ -0,0 +1,6 @@
+ldy #{c1}
+lda {z2}
+sta ({z1}),y
+iny
+lda {z2}+1
+sta ({z1}),y
diff --git a/src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm b/src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm
new file mode 100644
index 000000000..54ae1d53c
--- /dev/null
+++ b/src/main/fragment/pptz1_derefidx_vbuyy=pbuz2.asm
@@ -0,0 +1,5 @@
+lda {z2}
+sta ({z1}),y
+iny
+lda {z2}+1
+sta ({z1}),y
\ No newline at end of file
diff --git a/src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm b/src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm
new file mode 100644
index 000000000..54ae1d53c
--- /dev/null
+++ b/src/main/fragment/pptz1_derefidx_vbuyy=pwuz2.asm
@@ -0,0 +1,5 @@
+lda {z2}
+sta ({z1}),y
+iny
+lda {z2}+1
+sta ({z1}),y
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
index 331c51337..3e0c94f69 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
@@ -230,7 +230,11 @@ public class AsmFormat {
          if(number.longValue() >= 0L && number.longValue() <= 255L) {
             return SHORT_ASM_NUMBERS[number.intValue()];
          } else {
-            return String.format("$%x", number.longValue());
+            if(number.longValue()<0) {
+               return String.format("-$%x", -number.longValue());
+            } else {
+               return String.format("$%x", number.longValue());
+            }
          }
       }
       throw new RuntimeException("Unsupported number type " + number);
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index e0517349f..75ef3d7e5 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -118,7 +118,7 @@ public class SymbolTypeInference {
       } else if(rValue instanceof RangeComparison) {
          return ((RangeComparison) rValue).getType();
       } else if(rValue instanceof RangeNext) {
-         return SymbolType.BYTE;
+         return inferType(symbols, ((RangeNext) rValue).getRangeFirst());
       } else if(rValue instanceof ProcedureRef) {
          Procedure procedure = symbols.getProcedure((ProcedureRef) rValue);
          return procedure.getType();
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index 34533b203..3426efd3c 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -907,6 +907,10 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
       // Assign loop variable with first value
       RValue rangeLastValue = (RValue) visit(rangeLastCtx);
       RValue rangeFirstValue = (RValue) visit(rangeFirstCtx);
+      if(varType!=null) {
+         if(rangeFirstValue instanceof ConstantInteger) ((ConstantInteger) rangeFirstValue).setType(varType);
+         if(rangeLastValue instanceof ConstantInteger) ((ConstantInteger) rangeLastValue).setType(varType);
+      }
       Statement stmtInit = new StatementAssignment(lValue.getRef(), rangeFirstValue, new StatementSource(ctx), Comment.NO_COMMENTS);
       sequence.addStatement(stmtInit);
       // Add label
@@ -1348,11 +1352,16 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
       RValue child = (RValue) this.visit(ctx.expr());
       String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText();
       Operator operator = Operators.getUnary(op);
-      VariableIntermediate tmpVar = getCurrentScope().addVariableIntermediate();
-      VariableRef tmpVarRef = tmpVar.getRef();
-      Statement stmt = new StatementAssignment(tmpVarRef, operator, child, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
-      sequence.addStatement(stmt);
-      return tmpVarRef;
+      // Special handling of negative literal number
+      if(child instanceof ConstantInteger && operator.equals(Operators.NEG)) {
+         return new ConstantInteger(-((ConstantInteger) child).getInteger(), ((ConstantInteger) child).getType());
+      }  else {
+         VariableIntermediate tmpVar = getCurrentScope().addVariableIntermediate();
+         VariableRef tmpVarRef = tmpVar.getRef();
+         Statement stmt = new StatementAssignment(tmpVarRef, operator, child, new StatementSource(ctx), ensureUnusedComments(getCommentsSymbol(ctx)));
+         sequence.addStatement(stmt);
+         return tmpVarRef;
+      }
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java
index 0c5f23010..15dc207c3 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java
@@ -93,6 +93,13 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
             return true;
          }
       }
+      if(pointerDereferenceIndexed.getIndex() instanceof ConstantInteger ) {
+         if(((ConstantInteger)pointerDereferenceIndexed.getIndex()).getValue()==0L) {
+            value.set(new PointerDereferenceSimple(pointerDereferenceIndexed.getPointer()));
+            getLog().append("Simplified zero-index dereference" + value.get().toString());
+            return true;
+         }
+      }
       return false;
    }
 
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index e7a351b6a..d14adcd43 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -65,7 +65,7 @@ public class TestPrograms {
 
    @Test
    public void testTernaryInference() throws IOException, URISyntaxException {
-      compileAndCompare("ternary-inference");
+      compileAndCompare("ternary-inference", log());
    }
 
    @Test

From 06aed186e2d053c8aa4e092b56e3fc2ebf5f17a5 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 12:43:13 +0200
Subject: [PATCH 41/93] Fixed type inference for rangenext

---
 .../camelot64/kickc/model/types/SymbolTypeInference.java   | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index 75ef3d7e5..4a244cbdb 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -118,7 +118,12 @@ public class SymbolTypeInference {
       } else if(rValue instanceof RangeComparison) {
          return ((RangeComparison) rValue).getType();
       } else if(rValue instanceof RangeNext) {
-         return inferType(symbols, ((RangeNext) rValue).getRangeFirst());
+         SymbolType rangedType = inferType(symbols, ((RangeNext) rValue).getRangeFirst());
+         if(SymbolType.SBYTE.equals(rangedType) || SymbolType.SWORD.equals(rangedType) || SymbolType.SDWORD.equals(rangedType)) {
+            return SymbolType.SBYTE;
+         } else {
+            return SymbolType.BYTE;
+         }
       } else if(rValue instanceof ProcedureRef) {
          Procedure procedure = symbols.getProcedure((ProcedureRef) rValue);
          return procedure.getType();

From fe41c2ba4290007cb662fa13eda837d1bec5df2f Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 13:58:26 +0200
Subject: [PATCH 42/93] Fixed array indexing using word-size indices

---
 .../java/dk/camelot64/kickc/Compiler.java     |  9 +++--
 .../kickc/model/VariableReferenceInfos.java   | 36 +++++++++++--------
 .../dk/camelot64/kickc/test/TestPrograms.java | 25 ++++++++++---
 src/test/kc/derefidx-word-0.kc                | 10 ++++++
 src/test/kc/derefidx-word-1.kc                |  7 ++++
 src/test/kc/derefidx-word-2.kc                |  9 +++++
 6 files changed, 75 insertions(+), 21 deletions(-)
 create mode 100644 src/test/kc/derefidx-word-0.kc
 create mode 100644 src/test/kc/derefidx-word-1.kc
 create mode 100644 src/test/kc/derefidx-word-2.kc

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index eb8f14abf..3aa809b1b 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -267,10 +267,10 @@ public class Compiler {
       optimizations.add(new Pass2ComparisonOptimization(program));
       optimizations.add(new Pass2ConstantCallPointerIdentification(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
-      optimizations.add(new Pass2InlineDerefIdx(program));
       optimizations.add(new Pass2InlineCast(program));
-      optimizations.add(new Pass2DeInlineWordDerefIdx(program));
       optimizations.add(new PassNCastSimplification(program));
+      optimizations.add(new Pass2InlineDerefIdx(program));
+      optimizations.add(new Pass2DeInlineWordDerefIdx(program));
       pass2Execute(optimizations);
    }
 
@@ -303,6 +303,8 @@ public class Compiler {
    private void pass2InlineConstants() {
       // Constant inlining optimizations - as the last step to ensure that constant identification has been completed
       List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>();
+      constantOptimizations.add(new PassNStatementIndices(program));
+      constantOptimizations.add(new PassNVariableReferenceInfos(program));
       constantOptimizations.add(new Pass2MultiplyToShiftRewriting(program));
       constantOptimizations.add(new Pass2AliasElimination(program));
       constantOptimizations.add(new Pass2ConstantInlining(program));
@@ -315,6 +317,9 @@ public class Compiler {
       constantOptimizations.add(new Pass2ConstantSimplification(program));
       constantOptimizations.add(new PassNCastSimplification(program));
       constantOptimizations.add(new Pass2ConstantIfs(program));
+      constantOptimizations.add(new Pass2InlineDerefIdx(program));
+      constantOptimizations.add(new PassNEliminateUnusedVars(program, true));
+
       pass2Execute(constantOptimizations);
 
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java
index fec6f0316..a799b28bd 100644
--- a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java
+++ b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java
@@ -224,9 +224,11 @@ public class VariableReferenceInfos {
    public Collection<Integer> getConstRefStatements(ConstantRef constRef) {
       Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
       LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
-      refs.stream()
-            .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
-            .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
+      if(refs!=null) {
+         refs.stream()
+               .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
+               .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
+      }
       return stmts;
    }
 
@@ -239,9 +241,11 @@ public class VariableReferenceInfos {
    public Collection<Integer> getVarRefStatements(VariableRef varRef) {
       Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
       LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
-      refs.stream()
-            .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
-            .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
+      if(refs!=null) {
+         refs.stream()
+               .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
+               .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
+      }
       return stmts;
    }
 
@@ -254,10 +258,12 @@ public class VariableReferenceInfos {
    public Collection<Integer> getVarUseStatements(VariableRef varRef) {
       Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(varRef);
       LinkedHashSet<Integer> stmts = new LinkedHashSet<>();
-      refs.stream()
-            .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
-            .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType())
-            .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
+      if(refs!=null) {
+         refs.stream()
+               .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInStatement)
+               .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE == referenceToSymbolVar.getReferenceType())
+               .forEach(referenceToSymbolVar -> stmts.add(((ReferenceInStatement) referenceToSymbolVar).getStatementIdx()));
+      }
       return stmts;
    }
 
@@ -271,10 +277,12 @@ public class VariableReferenceInfos {
    public Collection<SymbolVariableRef> getSymbolRefConsts(ConstantRef constRef) {
       Collection<ReferenceToSymbolVar> refs = symbolVarReferences.get(constRef);
       LinkedHashSet<SymbolVariableRef> constRefs = new LinkedHashSet<>();
-      refs.stream()
-            .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
-            .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol)
-            .forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol()));
+      if(refs!=null) {
+         refs.stream()
+               .filter(referenceToSymbolVar -> ReferenceToSymbolVar.ReferenceType.USE.equals(referenceToSymbolVar.getReferenceType()))
+               .filter(referenceToSymbolVar -> referenceToSymbolVar instanceof ReferenceInSymbol)
+               .forEach(referenceToSymbolVar -> constRefs.add(((ReferenceInSymbol) referenceToSymbolVar).getReferencingSymbol()));
+      }
       return constRefs;
    }
 
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index d14adcd43..9f56c9b5e 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,26 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testDoubleIndexingArrays() throws IOException, URISyntaxException {
+      compileAndCompare("double-indexing-arrays");
+   }
+
+   @Test
+   public void testDerefidxWord2() throws IOException, URISyntaxException {
+      compileAndCompare("derefidx-word-2");
+   }
+
+   @Test
+   public void testDerefidxWord1() throws IOException, URISyntaxException {
+      compileAndCompare("derefidx-word-1");
+   }
+
+   @Test
+   public void testDerefidxWord0() throws IOException, URISyntaxException {
+      compileAndCompare("derefidx-word-0");
+   }
+
    @Test
    public void testTernaryInference() throws IOException, URISyntaxException {
       compileAndCompare("ternary-inference", log());
@@ -574,11 +594,6 @@ public class TestPrograms {
       compileAndCompare("irq-idx-problem");
    }
 
-   @Test
-   public void testDoubleIndexingArrays() throws IOException, URISyntaxException {
-      compileAndCompare("double-indexing-arrays");
-   }
-
    @Test
    public void testInlineKickAsmClobber() throws IOException, URISyntaxException {
       compileAndCompare("inline-kasm-clobber");
diff --git a/src/test/kc/derefidx-word-0.kc b/src/test/kc/derefidx-word-0.kc
new file mode 100644
index 000000000..7b5117853
--- /dev/null
+++ b/src/test/kc/derefidx-word-0.kc
@@ -0,0 +1,10 @@
+// Tests that array-indexing by a word variable is turned into pointer addition
+
+void main() {
+    const byte* screen = 0x0400;
+    for( word i=0;i<1000;i+=40) {
+        screen[i] = 'a';
+    }
+
+}
+
diff --git a/src/test/kc/derefidx-word-1.kc b/src/test/kc/derefidx-word-1.kc
new file mode 100644
index 000000000..5124674fa
--- /dev/null
+++ b/src/test/kc/derefidx-word-1.kc
@@ -0,0 +1,7 @@
+// Tests that array-indexing by a constant word is turned into a constant pointer
+
+void main() {
+    const byte* screen = 0x0400;
+    screen[40*10] = 'a';
+}
+
diff --git a/src/test/kc/derefidx-word-2.kc b/src/test/kc/derefidx-word-2.kc
new file mode 100644
index 000000000..af8417918
--- /dev/null
+++ b/src/test/kc/derefidx-word-2.kc
@@ -0,0 +1,9 @@
+// Tests that array-indexing by a word variable that is a sum of a constant word and a byte is turned back into derefidx
+
+void main() {
+    const byte* screen = 0x0400;
+    for( byte i : 0..39) {
+        screen[40*10+i] = 'a';
+    }
+}
+

From 9cec38d0754a38044605a314b94d96230321c845 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 21:37:34 +0200
Subject: [PATCH 43/93] Fixed negative numbers, zero-addition, zero inlining.

---
 .../java/dk/camelot64/kickc/Compiler.java     |   7 +
 .../camelot64/kickc/fragment/AsmFormat.java   |   2 +-
 .../kickc/fragment/AsmFragmentInstance.java   |   3 +-
 .../AsmFragmentInstanceSpecFactory.java       |  43 ++++--
 .../model/operators/OperatorBitwiseAnd.java   |   5 +-
 .../model/operators/OperatorGetHigh.java      |   6 +
 .../kickc/model/operators/OperatorGetLow.java |   8 +-
 .../model/types/SymbolTypeConversion.java     |  15 +-
 .../kickc/passes/Pass2InlineDerefIdx.java     |   6 +
 .../passes/Pass4RegisterUpliftRemains.java    |   7 +-
 .../passes/PassNSimplifyConstantZero.java     |  44 ++++++
 .../PassNSimplifyExpressionWithZero.java      |  58 ++++++++
 .../dk/camelot64/kickc/test/TestPrograms.java |   7 +-
 .../kc/examples/sinplotter/sine-plotter.kc    |   2 +-
 src/test/kc/gfxbank.kc                        |   8 +
 src/test/ref/bresenhamarr.asm                 |   3 +-
 src/test/ref/c64dtv-8bppcharstretch.asm       |   7 +-
 src/test/ref/c64dtv-8bppchunkystretch.asm     |  10 +-
 src/test/ref/c64dtv-blittermin.asm            |   7 +-
 src/test/ref/cast-not-needed-2.asm            |   6 +-
 src/test/ref/cast-not-needed-3.asm            |   6 +-
 src/test/ref/cast-precedence-problem.asm      |   2 +-
 src/test/ref/complex/tetris/test-sprites.asm  |   2 +-
 src/test/ref/complex/tetris/tetris.asm        |  46 +++---
 src/test/ref/consolidate-constant-problem.asm |   4 +-
 src/test/ref/const-signed-promotion.asm       |   1 -
 src/test/ref/constantmin.asm                  |   3 +-
 src/test/ref/constants.asm                    |   2 +-
 src/test/ref/derefidx-word-0.asm              |  39 +++++
 src/test/ref/derefidx-word-1.asm              |  10 ++
 src/test/ref/derefidx-word-2.asm              |  15 ++
 src/test/ref/examples/3d/3d.asm               |  51 +++----
 src/test/ref/examples/3d/perspective.asm      |   6 +-
 .../examples/bresenham/bitmap-bresenham.asm   |  11 +-
 .../ref/examples/chargen/chargen-analysis.asm |   5 +-
 .../examples/fastmultiply/fastmultiply8.asm   |   7 +-
 src/test/ref/examples/fire/fire.asm           |   2 +-
 .../multiplexer/simple-multiplexer.asm        |   8 +-
 .../ref/examples/plasma/plasma-unroll.asm     |   2 +-
 src/test/ref/examples/plasma/plasma.asm       |   2 +-
 src/test/ref/examples/rotate/rotate.asm       |  80 +++++-----
 .../ref/examples/scrolllogo/scrolllogo.asm    | 133 +++++++++--------
 .../ref/examples/sinplotter/sine-plotter.asm  | 137 ++++++++++--------
 .../ref/examples/sinsprites/sinus-sprites.asm |   6 +-
 src/test/ref/forrangedwords.asm               |   2 +-
 src/test/ref/fragment-variations.asm          |  74 ++++++++++
 src/test/ref/gfxbank.asm                      |  16 ++
 src/test/ref/halfscii.asm                     |  28 ++--
 src/test/ref/inline-function-if.asm           |   4 +-
 src/test/ref/inline-kasm-resource.asm         |   2 +-
 src/test/ref/inline-pointer-0.asm             |  10 ++
 src/test/ref/inline-pointer-1.asm             |  24 +++
 src/test/ref/inline-pointer-2.asm             |   9 ++
 src/test/ref/inline-string-3.asm              |   9 +-
 src/test/ref/inline-word-0.asm                |  13 ++
 src/test/ref/inline-word-1.asm                |  13 ++
 src/test/ref/inline-word-2.asm                |  13 ++
 src/test/ref/inline-word.asm                  |   3 +-
 src/test/ref/int-literals.asm                 |  16 +-
 src/test/ref/line-anim.asm                    |  84 ++++++-----
 src/test/ref/linegen.asm                      |  16 +-
 src/test/ref/liverange-call-problem.asm       |   4 +-
 src/test/ref/min-fmul-16.asm                  |   2 +-
 src/test/ref/mixed-array-0.asm                |  15 ++
 src/test/ref/mixed-array-1.asm                |  15 ++
 .../simple-multiplexer-irq.asm                |   8 +-
 src/test/ref/number-conversion.asm            |   8 +-
 src/test/ref/operator-lohi-problem.asm        |   6 +-
 src/test/ref/ptr-complex.asm                  |   3 +-
 src/test/ref/roll-sprite-msb.asm              |   6 +-
 src/test/ref/scan-desire-problem.asm          |   5 +-
 src/test/ref/semi-struct-2.asm                |   5 +-
 src/test/ref/signed-indexed-subtract.asm      |  53 ++++---
 src/test/ref/signed-words.asm                 |  36 +++--
 src/test/ref/sinus-basic.asm                  |   4 +-
 src/test/ref/sinusgen16.asm                   |  65 +++++----
 src/test/ref/sinusgen16b.asm                  | 124 +++++++++-------
 src/test/ref/sinusgen8.asm                    |  25 ++--
 src/test/ref/sinusgen8b.asm                   |  83 ++++++-----
 src/test/ref/sinusgenscale8.asm               |  28 ++--
 src/test/ref/sizeof-expr.asm                  |  10 +-
 src/test/ref/test-comparisons-sword.asm       |   6 +-
 src/test/ref/test-division.asm                |  65 ++++-----
 src/test/ref/test-multiply-16bit.asm          |  99 +++++++++----
 src/test/ref/test-multiply-8bit.asm           |  65 ++++++---
 src/test/ref/test-scroll-up.asm               |   4 +-
 src/test/ref/test-signed-word-minus-byte.asm  |  28 +++-
 src/test/ref/test-word-size-arrays.asm        |   2 +-
 src/test/ref/true-inline-words.asm            |   6 +-
 src/test/ref/type-inference.asm               |  23 +++
 src/test/ref/type-mix.asm                     |  15 +-
 src/test/ref/typeid-plus-bytes.asm            | 113 +++++++++++++--
 src/test/ref/uninitialized.asm                |   7 +-
 src/test/ref/valuelist-error.asm              |  10 ++
 94 files changed, 1441 insertions(+), 677 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNSimplifyConstantZero.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNSimplifyExpressionWithZero.java
 create mode 100644 src/test/kc/gfxbank.kc
 create mode 100644 src/test/ref/derefidx-word-0.asm
 create mode 100644 src/test/ref/derefidx-word-1.asm
 create mode 100644 src/test/ref/derefidx-word-2.asm
 create mode 100644 src/test/ref/fragment-variations.asm
 create mode 100644 src/test/ref/gfxbank.asm
 create mode 100644 src/test/ref/inline-pointer-0.asm
 create mode 100644 src/test/ref/inline-pointer-1.asm
 create mode 100644 src/test/ref/inline-pointer-2.asm
 create mode 100644 src/test/ref/inline-word-0.asm
 create mode 100644 src/test/ref/inline-word-1.asm
 create mode 100644 src/test/ref/inline-word-2.asm
 create mode 100644 src/test/ref/mixed-array-0.asm
 create mode 100644 src/test/ref/mixed-array-1.asm
 create mode 100644 src/test/ref/type-inference.asm
 create mode 100644 src/test/ref/valuelist-error.asm

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 3aa809b1b..b5dd695b3 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -269,8 +269,12 @@ public class Compiler {
       optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new Pass2InlineCast(program));
       optimizations.add(new PassNCastSimplification(program));
+      optimizations.add(new PassNStatementIndices(program));
+      optimizations.add(new PassNVariableReferenceInfos(program));
       optimizations.add(new Pass2InlineDerefIdx(program));
       optimizations.add(new Pass2DeInlineWordDerefIdx(program));
+      optimizations.add(new PassNSimplifyConstantZero(program));
+      optimizations.add(new PassNSimplifyExpressionWithZero(program));
       pass2Execute(optimizations);
    }
 
@@ -319,6 +323,9 @@ public class Compiler {
       constantOptimizations.add(new Pass2ConstantIfs(program));
       constantOptimizations.add(new Pass2InlineDerefIdx(program));
       constantOptimizations.add(new PassNEliminateUnusedVars(program, true));
+      constantOptimizations.add(new PassNSimplifyConstantZero(program));
+      constantOptimizations.add(new PassNSimplifyExpressionWithZero(program));
+
 
       pass2Execute(constantOptimizations);
 
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
index 3e0c94f69..edd3e0899 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
@@ -231,7 +231,7 @@ public class AsmFormat {
             return SHORT_ASM_NUMBERS[number.intValue()];
          } else {
             if(number.longValue()<0) {
-               return String.format("-$%x", -number.longValue());
+               return "-"+getAsmNumber(-number.longValue());
             } else {
                return String.format("$%x", number.longValue());
             }
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
index 53793f4c9..21f9e65f3 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
@@ -300,8 +300,7 @@ public class AsmFragmentInstance {
       @Override
       public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) {
          Number number = NumberParser.parseLiteral(ctx.NUMBER().getText());
-         ConstantInteger intVal = new ConstantInteger(number.longValue());
-         boolean isZp = SymbolType.BYTE.equals(intVal.getType()) || SymbolType.SBYTE.equals(intVal.getType());
+         boolean isZp = SymbolType.BYTE.contains(number.longValue()) || SymbolType.SBYTE.contains(number.longValue());
          String param = AsmFormat.getAsmNumber(number);
          return new AsmParameter(param, isZp);
       }
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
index 5030079a3..f3e3624c4 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
@@ -1,9 +1,6 @@
 package dk.camelot64.kickc.fragment;
 
-import dk.camelot64.kickc.model.ControlFlowBlock;
-import dk.camelot64.kickc.model.ControlFlowGraph;
-import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.Registers;
+import dk.camelot64.kickc.model.*;
 import dk.camelot64.kickc.model.operators.Operator;
 import dk.camelot64.kickc.model.operators.OperatorUnary;
 import dk.camelot64.kickc.model.operators.Operators;
@@ -17,6 +14,7 @@ import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.*;
 
+import java.lang.InternalError;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
@@ -242,17 +240,32 @@ public class AsmFragmentInstanceSpecFactory {
          if(castType == null) {
             SymbolType toType = castVal.getToType();
             // If value literal not matching cast type then add expression code to transform it into the value space ( eg. value & 0xff )
-            ConstantLiteral constantLiteral = val.calculateLiteral(program.getScope());
-            if(constantLiteral instanceof ConstantInteger) {
-               if(toType instanceof SymbolTypeIntegerFixed) {
-                  if(!((SymbolTypeIntegerFixed) toType).contains(((ConstantInteger) constantLiteral).getValue())) {
-                     if(toType.getSizeBytes() == 1) {
-                        val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val);
-                     } else if(toType.getSizeBytes() == 2) {
-                        val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val);
-                     } else {
-                        throw new InternalError("Not implemented!");
-                     }
+
+            if(toType instanceof SymbolTypeIntegerFixed) {
+               SymbolTypeIntegerFixed integerFixed = (SymbolTypeIntegerFixed) toType;
+               ConstantLiteral constantLiteral;
+               Long integerValue;
+               try {
+                  constantLiteral = val.calculateLiteral(program.getScope());
+                  if(constantLiteral instanceof ConstantInteger) {
+                     integerValue = ((ConstantInteger) constantLiteral).getValue();
+                  } else if(constantLiteral instanceof ConstantPointer) {
+                     integerValue = ((ConstantPointer) constantLiteral).getValue();
+                  } else {
+                     throw new InternalError("Not implemented "+constantLiteral);
+                  }
+               } catch (ConstantNotLiteral e) {
+                  // Assume it is a word
+                  integerValue = 0xffffL;
+               }
+
+               if(!integerFixed.contains(integerValue)) {
+                  if(toType.getSizeBytes() == 1) {
+                     val = new ConstantBinary(new ConstantInteger(0xffL, SymbolType.BYTE), Operators.BOOL_AND, val);
+                  } else if(toType.getSizeBytes() == 2) {
+                     val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val);
+                  } else {
+                     throw new InternalError("Not implemented "+toType);
                   }
                }
             }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
index e7906ff6f..931576215 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
@@ -31,7 +31,10 @@ public class OperatorBitwiseAnd extends OperatorBinary {
       }
       // Handle numeric types
       if(SymbolType.isInteger(type1) && SymbolType.isInteger(type2)) {
-         return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) type1, (SymbolTypeInteger) type2);
+         if(type1.getSizeBytes()<type2.getSizeBytes())
+            return type1;
+         else
+            return type2;
       }
 
       throw new CompileError("Type inference case not handled " + type1 + " " + getOperator() + " " + type2);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
index d28f2f49f..79902c0c2 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
@@ -26,6 +26,10 @@ public class OperatorGetHigh extends OperatorUnary {
             return new ConstantInteger(operandInt.getInteger()>>8);
          } else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) {
             return new ConstantInteger(operandInt.getInteger()>>16);
+         } else if(SymbolType.BYTE.equals(operandInt.getType()) || SymbolType.SBYTE.equals(operandInt.getType())) {
+            return new ConstantInteger(0L, SymbolType.BYTE);
+         } else if(SymbolType.NUMBER.equals(operandInt.getType())) {
+            throw new ConstantNotLiteral("Operand not resolved "+operand);
          }
       } else if(operand instanceof ConstantPointer) {
          return new ConstantInteger(((ConstantPointer) operand).getLocation()>>8);
@@ -41,6 +45,8 @@ public class OperatorGetHigh extends OperatorUnary {
          return SymbolType.BYTE;
       } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
          return SymbolType.WORD;
+      } else if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
+         return SymbolType.BYTE;
       } else if(SymbolType.STRING.equals(operandType)) {
          return SymbolType.BYTE;
       } else if(SymbolType.NUMBER.equals(operandType)) {
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
index c05e748d4..7542903f6 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
@@ -26,13 +26,17 @@ public class OperatorGetLow extends OperatorUnary {
             return new ConstantInteger(operandInt.getInteger()&0xff);
          } else if(SymbolType.DWORD.equals(operandInt.getType()) || SymbolType.SDWORD.equals(operandInt.getType())) {
             return new ConstantInteger(operandInt.getInteger()&0xffff);
+         } else if(SymbolType.BYTE.equals(operandInt.getType()) || SymbolType.SBYTE.equals(operandInt.getType())) {
+            return operandInt;
+         } else if(SymbolType.NUMBER.equals(operandInt.getType())) {
+            throw new ConstantNotLiteral("Operand not resolved "+operand);
          }
       } else if(operand instanceof ConstantPointer) {
          return new ConstantInteger(((ConstantPointer) operand).getLocation()&0xff);
       } else if(operand instanceof ConstantString) {
          throw new ConstantNotLiteral("address of string is not literal");
       }
-      throw new CompileError("Calculation not implemented " + getOperator() + " " + operand );
+      throw new ConstantNotLiteral("Calculation not implemented " + getOperator() + " " + operand );
    }
 
    @Override
@@ -41,6 +45,8 @@ public class OperatorGetLow extends OperatorUnary {
          return SymbolType.BYTE;
       } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
          return SymbolType.WORD;
+      } else if(SymbolType.BYTE.equals(operandType) || SymbolType.SBYTE.equals(operandType)) {
+         return SymbolType.BYTE;
       } else if(SymbolType.STRING.equals(operandType)) {
          return SymbolType.BYTE;
       } else if(SymbolType.NUMBER.equals(operandType)) {
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index b82e23e76..df8ec8b90 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -1,6 +1,7 @@
 package dk.camelot64.kickc.model.types;
 
 import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.ConstantNotLiteral;
 import dk.camelot64.kickc.model.InternalError;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
@@ -103,7 +104,13 @@ public class SymbolTypeConversion {
 
          // Find the cast type if possible
          if(numberVal instanceof ConstantValue) {
-            ConstantLiteral constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols);
+            ConstantLiteral constantLiteral;
+            try {
+               constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols);
+            } catch( ConstantNotLiteral e) {
+               // Postpone til later!
+               return null;
+            }
             if(constantLiteral instanceof ConstantInteger) {
                ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
                if(SymbolType.NUMBER.equals(constantInteger.getType())) {
@@ -161,7 +168,11 @@ public class SymbolTypeConversion {
       if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SWORD))
          return true;
       if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
-         // L-value is still a number - constants are probably not done being identified & typed
+         // R-value is still a number - constants are probably not done being identified & typed
+         return true;
+      }
+      if(SymbolType.NUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
+         // R-value is still a number - constants are probably not done being identified & typed
          return true;
       }
       if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java
index 795d55117..3a8146be7 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2InlineDerefIdx.java
@@ -12,6 +12,7 @@ import dk.camelot64.kickc.model.types.SymbolTypeInference;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
 import dk.camelot64.kickc.model.values.*;
 
+import java.util.Collection;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /** Identify derefs of pointers that are defined as pointer + value - and inline them as derefidx instead */
@@ -71,6 +72,11 @@ public class Pass2InlineDerefIdx extends Pass2SsaOptimization {
 
 
    public RValue attemptInlineDeref(StatementAssignment derefAssignment) {
+      VariableRef derefVar = (VariableRef) derefAssignment.getlValue();
+      Collection<Integer> varUseStatements = getProgram().getVariableReferenceInfos().getVarUseStatements(derefVar);
+      if(varUseStatements.size()>2) {
+         return null;
+      }
       if(Operators.PLUS.equals(derefAssignment.getOperator())) {
          SymbolType derefLeftType = SymbolTypeInference.inferType(getScope(), derefAssignment.getrValue1());
          if(derefLeftType instanceof SymbolTypePointer) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java
index 6e023bbb0..7e4f48ee0 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegisterUpliftRemains.java
@@ -18,12 +18,7 @@ public class Pass4RegisterUpliftRemains extends Pass2Base {
       LiveRangeEquivalenceClassSet equivalenceClassSet = getProgram().getLiveRangeEquivalenceClassSet();
       List<LiveRangeEquivalenceClass> equivalenceClasses = new ArrayList<>(equivalenceClassSet.getEquivalenceClasses());
       final VariableRegisterWeights registerWeights = getProgram().getVariableRegisterWeights();
-      Collections.sort(equivalenceClasses, new Comparator<LiveRangeEquivalenceClass>() {
-         @Override
-         public int compare(LiveRangeEquivalenceClass o1, LiveRangeEquivalenceClass o2) {
-            return Double.compare(registerWeights.getTotalWeight(o2), registerWeights.getTotalWeight(o1));
-         }
-      });
+      Collections.sort(equivalenceClasses, (o1, o2) -> Double.compare(registerWeights.getTotalWeight(o2), registerWeights.getTotalWeight(o1)));
 
       Set<String> unknownFragments = new LinkedHashSet<>();
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyConstantZero.java b/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyConstantZero.java
new file mode 100644
index 000000000..6b01d695d
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyConstantZero.java
@@ -0,0 +1,44 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.ConstantNotLiteral;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
+import dk.camelot64.kickc.model.values.*;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Simplify any constant expression evaluating to zero
+ */
+public class PassNSimplifyConstantZero extends Pass2SsaOptimization {
+
+   public PassNSimplifyConstantZero(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
+
+      ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
+         Value value = programValue.get();
+         if(value instanceof ConstantValue && !(value instanceof ConstantInteger) &&!(value instanceof ConstantRef)) {
+            ConstantLiteral literal;
+            try {
+               literal = ((ConstantValue) value).calculateLiteral(getProgram().getScope());
+            } catch( ConstantNotLiteral e) {
+               return;
+            }
+            if(literal instanceof ConstantInteger) {
+               if(((ConstantInteger) literal).getInteger()==0L) {
+                  getLog().append("Simplifying constant evaluating to zero "+value.toString(getProgram()) + " in "+(currentStmt==null?"":currentStmt.toString(getProgram(), false)));
+                  programValue.set(new ConstantInteger(0L, ((ConstantInteger) literal).getType()));
+                  modified.set(true);
+               }
+            }
+         }
+      });
+      return modified.get();
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyExpressionWithZero.java b/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyExpressionWithZero.java
new file mode 100644
index 000000000..c59ea0bd1
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNSimplifyExpressionWithZero.java
@@ -0,0 +1,58 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
+import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
+import dk.camelot64.kickc.model.operators.Operator;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.PointerDereferenceSimple;
+import dk.camelot64.kickc.model.values.RValue;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Simplify any binary expression containing a zero value (if possible
+ */
+public class PassNSimplifyExpressionWithZero extends Pass2SsaOptimization {
+
+   public PassNSimplifyExpressionWithZero(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
+
+      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
+         if(programExpression instanceof ProgramExpressionBinary) {
+            ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression;
+            RValue left = binary.getLeft();
+            RValue right = binary.getRight();
+            Operator operator = programExpression.getOperator();
+            if(Operators.PLUS.equals(operator) || Operators.MINUS.equals(operator) || Operators.BOOL_OR.equals(operator) || Operators.BOOL_XOR.equals(operator)) {
+               if(left instanceof ConstantInteger && ((ConstantInteger) left).getInteger() == 0) {
+                  getLog().append("Simplifying expression containing zero " + binary.getRight().toString()+ " in "+ (currentStmt==null?"":currentStmt.toString(getProgram(), false)));
+                  if(programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed) {
+                     programExpression.set(new PointerDereferenceSimple(binary.getRight()));
+                  }  else {
+                     programExpression.set(binary.getRight());
+                  }
+                  modified.set(true);
+               } else if(right instanceof ConstantInteger && ((ConstantInteger) right).getInteger() == 0) {
+                  getLog().append("Simplifying expression containing zero " + binary.getLeft().toString()+ " in "+ (currentStmt==null?"":currentStmt.toString(getProgram(), false)));
+                  if(programExpression instanceof ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed) {
+                     programExpression.set(new PointerDereferenceSimple(binary.getLeft()));
+                  }  else {
+                     programExpression.set(binary.getLeft());
+                  }
+                  modified.set(true);
+               }
+            }
+         }
+      });
+
+      return modified.get();
+   }
+
+}
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 9f56c9b5e..7a4ea6db5 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,11 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testGfxBankOptimization() throws IOException, URISyntaxException {
+      compileAndCompare("gfxbank");
+   }
+
    @Test
    public void testDoubleIndexingArrays() throws IOException, URISyntaxException {
       compileAndCompare("double-indexing-arrays");
@@ -1743,7 +1748,7 @@ public class TestPrograms {
 
    @Test
    public void testForClassicMin() throws IOException, URISyntaxException {
-      compileAndCompare("forclassicmin", log());
+      compileAndCompare("forclassicmin");
    }
 
    @Test
diff --git a/src/test/kc/examples/sinplotter/sine-plotter.kc b/src/test/kc/examples/sinplotter/sine-plotter.kc
index 300f5591c..a46eb11c2 100644
--- a/src/test/kc/examples/sinplotter/sine-plotter.kc
+++ b/src/test/kc/examples/sinplotter/sine-plotter.kc
@@ -12,7 +12,7 @@ const word SIN_SIZE = 512;
 
 signed word[512] align($100) sin;
 
-signed word* sin2 = $1500;
+signed word* sin2 = $1400;
 
 kickasm(pc sin2) {{
     .for(var i=0; i<512; i++) {
diff --git a/src/test/kc/gfxbank.kc b/src/test/kc/gfxbank.kc
new file mode 100644
index 000000000..990aaa585
--- /dev/null
+++ b/src/test/kc/gfxbank.kc
@@ -0,0 +1,8 @@
+// Test minimization of constants
+
+import "c64"
+
+void main() {
+    const byte* PLAYFIELD_CHARSET = $2800;
+	vicSelectGfxBank(PLAYFIELD_CHARSET);
+}
diff --git a/src/test/ref/bresenhamarr.asm b/src/test/ref/bresenhamarr.asm
index 7c3c586de..6f5b47054 100644
--- a/src/test/ref/bresenhamarr.asm
+++ b/src/test/ref/bresenhamarr.asm
@@ -19,9 +19,8 @@ main: {
     ldx #yd/2
     lda #x0
     sta x
-    lda #x0+y0*$28
+    lda #<0
     sta idx
-    lda #0
     sta idx+1
   b1:
     lda idx
diff --git a/src/test/ref/c64dtv-8bppcharstretch.asm b/src/test/ref/c64dtv-8bppcharstretch.asm
index 0e1316723..4cb9bf646 100644
--- a/src/test/ref/c64dtv-8bppcharstretch.asm
+++ b/src/test/ref/c64dtv-8bppcharstretch.asm
@@ -77,7 +77,7 @@ main: {
     lda #VIC_MCM|VIC_CSEL
     sta VIC_CONTROL2
     // Plane A: SCREEN
-    lda #<SCREEN
+    lda #0
     sta DTV_PLANEA_START_LO
     lda #>SCREEN
     sta DTV_PLANEA_START_MI
@@ -89,7 +89,6 @@ main: {
     sta DTV_PLANEA_MODULO_LO
     sta DTV_PLANEA_MODULO_HI
     // Plane B: CHARSET8
-    lda #<CHARSET8
     sta DTV_PLANEB_START_LO
     lda #>CHARSET8
     sta DTV_PLANEB_START_MI
@@ -233,9 +232,9 @@ gfx_init_plane_charset8: {
     lda #0
     sta ch
     sta col
-    lda #<$4000+(CHARSET8&$3fff)
+    lda #<$4000
     sta gfxa
-    lda #>$4000+(CHARSET8&$3fff)
+    lda #>$4000
     sta gfxa+1
     lda #<CHARGEN+1
     sta chargen
diff --git a/src/test/ref/c64dtv-8bppchunkystretch.asm b/src/test/ref/c64dtv-8bppchunkystretch.asm
index 47a9811aa..350dbd2a5 100644
--- a/src/test/ref/c64dtv-8bppchunkystretch.asm
+++ b/src/test/ref/c64dtv-8bppchunkystretch.asm
@@ -65,7 +65,7 @@ main: {
     lda #VIC_MCM|VIC_CSEL
     sta VIC_CONTROL2
     // Plane B: CHUNKY
-    lda #<CHUNKY
+    lda #0
     sta DTV_PLANEB_START_LO
     lda #>CHUNKY
     sta DTV_PLANEB_START_MI
@@ -84,9 +84,9 @@ main: {
     sta CIA2_PORT_A
     // Set VIC Bank
     // VIC memory
-    lda #(CHUNKY&$3fff)/$40|(0)/4
+    lda #0
     sta VIC_MEMORY
-    ldx #0
+    tax
   // DTV Palette - Grey Tones
   b1:
     txa
@@ -195,7 +195,7 @@ gfx_init_chunky: {
     .label gfxb = 5
     .label x = 3
     .label y = 2
-    lda #$ff&CHUNKY/$4000
+    lda #CHUNKY/$4000
     jsr dtvSetCpuBankSegment1
     ldx #($ff&CHUNKY/$4000)+1
     lda #0
@@ -205,7 +205,7 @@ gfx_init_chunky: {
     lda #>$4000
     sta gfxb+1
   b1:
-    lda #0
+    lda #<0
     sta x
     sta x+1
   b2:
diff --git a/src/test/ref/c64dtv-blittermin.asm b/src/test/ref/c64dtv-blittermin.asm
index b74c1966c..b7e126dea 100644
--- a/src/test/ref/c64dtv-blittermin.asm
+++ b/src/test/ref/c64dtv-blittermin.asm
@@ -85,9 +85,9 @@ main: {
     sta DTV_BLITTER_SRCA_HI
     sta DTV_BLITTER_SRCA_MOD_LO
     sta DTV_BLITTER_SRCA_MOD_HI
-    lda #<$100
+    lda #<$80
     sta DTV_BLITTER_SRCA_LIN_LO
-    lda #>$100
+    lda #0
     sta DTV_BLITTER_SRCA_LIN_HI
     lda #$10
     sta DTV_BLITTER_SRCA_STEP
@@ -100,14 +100,12 @@ main: {
     sta DTV_BLITTER_SRCB_HI
     sta DTV_BLITTER_SRCB_MOD_LO
     sta DTV_BLITTER_SRCB_MOD_HI
-    lda #<$100
     sta DTV_BLITTER_SRCB_LIN_LO
     lda #>$100
     sta DTV_BLITTER_SRCB_LIN_HI
     lda #0
     sta DTV_BLITTER_SRCB_STEP
     // Step 0.0
-    lda #<SCREEN
     sta DTV_BLITTER_DEST_LO
     lda #>SCREEN
     sta DTV_BLITTER_DEST_MI
@@ -115,7 +113,6 @@ main: {
     sta DTV_BLITTER_DEST_HI
     sta DTV_BLITTER_DEST_MOD_LO
     sta DTV_BLITTER_DEST_MOD_HI
-    lda #<$100
     sta DTV_BLITTER_DEST_LIN_LO
     lda #>$100
     sta DTV_BLITTER_DEST_LIN_HI
diff --git a/src/test/ref/cast-not-needed-2.asm b/src/test/ref/cast-not-needed-2.asm
index c91a7229a..f6c04cf1c 100644
--- a/src/test/ref/cast-not-needed-2.asm
+++ b/src/test/ref/cast-not-needed-2.asm
@@ -2,14 +2,12 @@
 .pc = $801 "Basic"
 :BasicUpstart(main)
 .pc = $80d "Program"
-  .const SIZEOF_POINTER = 2
 main: {
-    .const getScreen1_id = 0
     .label getScreen1_return = 2
     .label spritePtr1_return = 2
-    lda screens+getScreen1_id*SIZEOF_POINTER
+    lda screens
     sta getScreen1_return
-    lda screens+getScreen1_id*SIZEOF_POINTER+1
+    lda screens+1
     sta getScreen1_return+1
     clc
     lda spritePtr1_return
diff --git a/src/test/ref/cast-not-needed-3.asm b/src/test/ref/cast-not-needed-3.asm
index 4a3ee07b6..c57565015 100644
--- a/src/test/ref/cast-not-needed-3.asm
+++ b/src/test/ref/cast-not-needed-3.asm
@@ -2,15 +2,13 @@
 .pc = $801 "Basic"
 :BasicUpstart(main)
 .pc = $80d "Program"
-  .const SIZEOF_POINTER = 2
 main: {
     .label DSP = $400
-    .const getScreen1_id = 0
     .label getScreen1_return = 2
     .label spritePtr1__0 = 2
-    lda screens+getScreen1_id*SIZEOF_POINTER
+    lda screens
     sta getScreen1_return
-    lda screens+getScreen1_id*SIZEOF_POINTER+1
+    lda screens+1
     sta getScreen1_return+1
     clc
     lda spritePtr1__0
diff --git a/src/test/ref/cast-precedence-problem.asm b/src/test/ref/cast-precedence-problem.asm
index d0d46735c..18f118178 100644
--- a/src/test/ref/cast-precedence-problem.asm
+++ b/src/test/ref/cast-precedence-problem.asm
@@ -7,8 +7,8 @@ main: {
     .const min = $a
     .const max = $c8
     .label BGCOL = $d021
-    .const sumb = min+max
     .const sumw = min+max
+    .const sumb = min+max
     .const midb = (sumb>>1)+1
     .const midw = (sumw>>1)+1
     lda #midw
diff --git a/src/test/ref/complex/tetris/test-sprites.asm b/src/test/ref/complex/tetris/test-sprites.asm
index a35164dc2..61571e8bb 100644
--- a/src/test/ref/complex/tetris/test-sprites.asm
+++ b/src/test/ref/complex/tetris/test-sprites.asm
@@ -84,7 +84,7 @@ bbegin:
   rts
 main: {
     .const toSpritePtr2_return = SIN_SPRITE/$40
-    .const vicSelectGfxBank1_toDd001_return = 3^(>PLAYFIELD_SCREEN_1)/$40
+    .const vicSelectGfxBank1_toDd001_return = 3
     .const toD0181_return = (>(PLAYFIELD_SCREEN_1&$3fff)*4)|(>PLAYFIELD_CHARSET)/4&$f
     .label xpos = 2
     .label ypos = 3
diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm
index 889a3b29e..5787e8dbe 100644
--- a/src/test/ref/complex/tetris/tetris.asm
+++ b/src/test/ref/complex/tetris/tetris.asm
@@ -205,18 +205,20 @@ main: {
     ldx play_spawn_current.piece_idx
     lda #$20
     jsr render_next
-    ldy play_spawn_current._7
-    lda PIECES,y
+    lda current_piece_gfx
     sta current_piece
-    lda PIECES+1,y
+    lda current_piece_gfx+1
     sta current_piece+1
     lda #0
     sta level_bcd
     sta level
     sta score_bcd
     sta score_bcd+1
+    lda #<0>>$10
     sta score_bcd+2
+    lda #>0>>$10
     sta score_bcd+3
+    lda #<0
     sta lines_bcd
     sta lines_bcd+1
     sta current_movedown_counter
@@ -308,16 +310,16 @@ render_score: {
     jsr render_bcd
     ldx score_bytes+1
     ldy #0
-    lda #score_offset+2
+    lda #<score_offset+2
     sta render_bcd.offset
-    tya
+    lda #>score_offset+2
     sta render_bcd.offset+1
     jsr render_bcd
     ldx score_bytes
     ldy #0
-    lda #score_offset+4
+    lda #<score_offset+4
     sta render_bcd.offset
-    tya
+    lda #>score_offset+4
     sta render_bcd.offset+1
     jsr render_bcd
     lda lines_bcd+1
@@ -331,9 +333,9 @@ render_score: {
     lda lines_bcd
     tax
     ldy #0
-    lda #lines_offset+1
+    lda #<lines_offset+1
     sta render_bcd.offset
-    tya
+    lda #>lines_offset+1
     sta render_bcd.offset+1
     jsr render_bcd
     ldx level_bcd
@@ -390,8 +392,8 @@ render_bcd: {
 // Render the next tetromino in the "next" area
 render_next: {
     .const next_area_offset = $28*$c+$18+4
-    .label next_piece_char = $a
     .label next_piece_gfx = 5
+    .label next_piece_char = $a
     .label screen_next_area = 7
     .label l = 9
     cmp #0
@@ -409,13 +411,14 @@ render_next: {
   b1:
     txa
     asl
+    // Render the next piece
     tay
-    lda PIECES_NEXT_CHARS,x
-    sta next_piece_char
     lda PIECES,y
     sta next_piece_gfx
     lda PIECES+1,y
     sta next_piece_gfx+1
+    lda PIECES_NEXT_CHARS,x
+    sta next_piece_char
     lda #0
     sta l
   b3:
@@ -816,10 +819,9 @@ play_move_down: {
     tax
     jsr play_update_score
     jsr play_spawn_current
-    ldy play_spawn_current._7
-    lda PIECES,y
+    lda current_piece_gfx
     sta current_piece
-    lda PIECES+1,y
+    lda current_piece_gfx+1
     sta current_piece+1
     lda #0
     sta current_orientation
@@ -838,20 +840,18 @@ play_move_down: {
 // Spawn a new piece
 // Moves the next piece into the current and spawns a new next piece
 play_spawn_current: {
-    .label _7 = 4
     .label piece_idx = $21
     // Move next piece into current
     ldx next_piece_idx
     txa
     asl
-    sta _7
-    lda PIECES_CHARS,x
-    sta current_piece_char
-    ldy _7
+    tay
     lda PIECES,y
     sta current_piece_gfx
     lda PIECES+1,y
     sta current_piece_gfx+1
+    lda PIECES_CHARS,x
+    sta current_piece_char
     lda PIECES_START_X,x
     sta current_xpos
     lda PIECES_START_Y,x
@@ -860,9 +860,9 @@ play_spawn_current: {
     sta play_collision.xpos
     lda current_ypos
     sta play_collision.ypos
-    lda PIECES,y
+    lda current_piece_gfx
     sta current_piece_104
-    lda PIECES+1,y
+    lda current_piece_gfx+1
     sta current_piece_104+1
     ldx #0
     jsr play_collision
@@ -1378,7 +1378,7 @@ sprites_init: {
 }
 // Initialize rendering
 render_init: {
-    .const vicSelectGfxBank1_toDd001_return = 3^(>PLAYFIELD_CHARSET)/$40
+    .const vicSelectGfxBank1_toDd001_return = 3
     .label li_1 = 5
     .label li_2 = 7
     lda #3
diff --git a/src/test/ref/consolidate-constant-problem.asm b/src/test/ref/consolidate-constant-problem.asm
index f8146c526..be6c8721f 100644
--- a/src/test/ref/consolidate-constant-problem.asm
+++ b/src/test/ref/consolidate-constant-problem.asm
@@ -6,7 +6,7 @@ main: {
     lda #0
     sta screen+$27
     sta screen+$26
-    sta $28*1+screen+$27
-    sta screen+$26+$28*1
+    sta screen+$28*1+$27
+    sta screen+$28*1+$26
     rts
 }
diff --git a/src/test/ref/const-signed-promotion.asm b/src/test/ref/const-signed-promotion.asm
index 90042051c..fbe66dba9 100644
--- a/src/test/ref/const-signed-promotion.asm
+++ b/src/test/ref/const-signed-promotion.asm
@@ -2,7 +2,6 @@
 .pc = $801 "Basic"
 :BasicUpstart(main)
 .pc = $80d "Program"
-  .const SIZEOF_SIGNED_WORD = 2
 main: {
     .label screen = $400
     ldx #0
diff --git a/src/test/ref/constantmin.asm b/src/test/ref/constantmin.asm
index 4832ff399..5fc98d7cf 100644
--- a/src/test/ref/constantmin.asm
+++ b/src/test/ref/constantmin.asm
@@ -5,12 +5,11 @@
   .const STAR = $51
   .label VIC = $d000
   .const RED = 2
-  .label BGCOL = VIC+$10*2+1
 main: {
     lda #STAR
     sta SCREEN
     lda #RED
-    sta BGCOL
+    sta VIC+$10*2+1
     ldx #$28
   b1:
     lda #STAR+1
diff --git a/src/test/ref/constants.asm b/src/test/ref/constants.asm
index e49be31e1..7d603723c 100644
--- a/src/test/ref/constants.asm
+++ b/src/test/ref/constants.asm
@@ -18,8 +18,8 @@ main: {
 test_sbytes: {
     .const bb = 0
     .const bc = bb+2
-    .const bd = bc-4
     .const bf = $ff&-$7f-$7f
+    .const bd = bc-4
     .const be = -bd
     lda #0
     sta assert_sbyte.c
diff --git a/src/test/ref/derefidx-word-0.asm b/src/test/ref/derefidx-word-0.asm
new file mode 100644
index 000000000..a893d8fe3
--- /dev/null
+++ b/src/test/ref/derefidx-word-0.asm
@@ -0,0 +1,39 @@
+// Tests that array-indexing by a word variable is turned into pointer addition
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    .label i = 2
+    .label _1 = 4
+    lda #<0
+    sta i
+    sta i+1
+  b1:
+    lda i
+    clc
+    adc #<screen
+    sta _1
+    lda i+1
+    adc #>screen
+    sta _1+1
+    lda #'a'
+    ldy #0
+    sta (_1),y
+    lda #$28
+    clc
+    adc i
+    sta i
+    bcc !+
+    inc i+1
+  !:
+    lda i+1
+    cmp #>$3e8
+    bcc b1
+    bne !+
+    lda i
+    cmp #<$3e8
+    bcc b1
+  !:
+    rts
+}
diff --git a/src/test/ref/derefidx-word-1.asm b/src/test/ref/derefidx-word-1.asm
new file mode 100644
index 000000000..631845860
--- /dev/null
+++ b/src/test/ref/derefidx-word-1.asm
@@ -0,0 +1,10 @@
+// Tests that array-indexing by a constant word is turned into a constant pointer
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    lda #'a'
+    sta screen+$28*$a
+    rts
+}
diff --git a/src/test/ref/derefidx-word-2.asm b/src/test/ref/derefidx-word-2.asm
new file mode 100644
index 000000000..44af2978a
--- /dev/null
+++ b/src/test/ref/derefidx-word-2.asm
@@ -0,0 +1,15 @@
+// Tests that array-indexing by a word variable that is a sum of a constant word and a byte is turned back into derefidx
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    ldx #0
+  b1:
+    lda #'a'
+    sta screen+$28*$a,x
+    inx
+    cpx #$28
+    bne b1
+    rts
+}
diff --git a/src/test/ref/examples/3d/3d.asm b/src/test/ref/examples/3d/3d.asm
index 0dcdcb236..c555981f4 100644
--- a/src/test/ref/examples/3d/3d.asm
+++ b/src/test/ref/examples/3d/3d.asm
@@ -129,13 +129,13 @@ anim: {
     tya
     asl
     tax
-    lda #$80
+    lda xp
     clc
-    adc xp
+    adc #$80
     sta SPRITES_XPOS,x
-    lda #$80
+    lda yp
     clc
-    adc yp
+    adc #$80
     sta SPRITES_YPOS,x
     inc i
     lda #8
@@ -149,10 +149,9 @@ anim: {
     // Increment angles        
     inc sx
     inc sx
-    lda sy
-    sec
-    sbc #3
-    sta sy
+    lax sy
+    axs #3
+    stx sy
     jmp b2
 }
 debug_print: {
@@ -336,8 +335,7 @@ print_sbyte_at: {
     .label at = 6
     cpx #0
     bmi b1
-    lda #' '
-    sta print_char_at.ch
+    ldy #' '
     jsr print_char_at
   b2:
     inc print_byte_at.at
@@ -347,8 +345,7 @@ print_sbyte_at: {
     jsr print_byte_at
     rts
   b1:
-    lda #'-'
-    sta print_char_at.ch
+    ldy #'-'
     jsr print_char_at
     txa
     eor #$ff
@@ -358,17 +355,16 @@ print_sbyte_at: {
     jmp b2
 }
 // Print a single char
-// print_char_at(byte zeropage(8) ch, byte* zeropage(6) at)
+// print_char_at(byte register(Y) ch, byte* zeropage(6) at)
 print_char_at: {
     .label at = 6
-    .label ch = 8
-    lda ch
+    tya
     ldy #0
     sta (at),y
     rts
 }
 // Print a byte as HEX at a specific position
-// print_byte_at(byte* zeropage(6) at)
+// print_byte_at(byte register(X) b, byte* zeropage(6) at)
 print_byte_at: {
     .label at = 6
     txa
@@ -378,7 +374,7 @@ print_byte_at: {
     lsr
     tay
     lda print_hextab,y
-    sta print_char_at.ch
+    tay
     jsr print_char_at
     lda #$f
     axs #0
@@ -386,8 +382,7 @@ print_byte_at: {
     bne !+
     inc print_char_at.at+1
   !:
-    lda print_hextab,x
-    sta print_char_at.ch
+    ldy print_hextab,x
     jsr print_char_at
     rts
 }
@@ -395,10 +390,10 @@ print_byte_at: {
 // The rotation matrix is prepared by calling prepare_matrix() 
 // The passed points must be in the interval [-$3f;$3f].
 // Implemented in assembler to utilize seriously fast multiplication 
-// rotate_matrix(signed byte register(X) x, signed byte zeropage(5) y, signed byte zeropage(8) z)
+// rotate_matrix(signed byte register(X) x, signed byte zeropage(5) y, signed byte zeropage($a) z)
 rotate_matrix: {
     .label y = 5
-    .label z = 8
+    .label z = $a
     txa
     sta xr
     lda y
@@ -543,7 +538,7 @@ calculate_matrix: {
     .label sy = 3
     .label t1 = 4
     .label t3 = 5
-    .label t4 = 8
+    .label t4 = $a
     .label t5 = $b
     .label t6 = $c
     .label t7 = $d
@@ -959,9 +954,9 @@ debug_print_init: {
     str11: .text "yp@"
 }
 // Print a string at a specific screen position
-// print_str_at(byte* zeropage(6) str, byte* zeropage(9) at)
+// print_str_at(byte* zeropage(6) str, byte* zeropage(8) at)
 print_str_at: {
-    .label at = 9
+    .label at = 8
     .label str = 6
   b1:
     ldy #0
@@ -1014,7 +1009,7 @@ sprites_init: {
     sta SPRITES_ENABLE
     ldx #0
   b1:
-    lda #$ff&SPRITE/$40
+    lda #SPRITE/$40
     sta sprites_ptr,x
     lda #GREEN
     sta SPRITES_COLS,x
@@ -1024,6 +1019,9 @@ sprites_init: {
     rts
 }
   print_hextab: .text "0123456789abcdef"
+  // Positions to rotate
+  xs: .byte -$34, -$34, -$34, 0, 0, $34, $34, $34
+  ys: .byte -$34, 0, $34, -$34, $34, -$34, 0, $34
   zs: .byte $34, $34, $34, $34, $34, $34, $34, $34
   // Rotated positions
   xrs: .fill 8, 0
@@ -1036,9 +1034,6 @@ sprites_init: {
   yps: .fill 8, 0
   // The rotation matrix
   rotation_matrix: .fill 9, 0
-  // Positions to rotate
-  xs: .byte -$34, -$34, -$34, 0, 0, $34, $34, $34
-  ys: .byte -$34, 0, $34, -$34, $34, -$34, 0, $34
 .pc = mulf_sqr1 "mulf_sqr1"
   .for(var i=0;i<$200;i++) {
     	.if(i<=159) { .byte round((i*i)/256) }
diff --git a/src/test/ref/examples/3d/perspective.asm b/src/test/ref/examples/3d/perspective.asm
index 7dea6c315..db564e9c2 100644
--- a/src/test/ref/examples/3d/perspective.asm
+++ b/src/test/ref/examples/3d/perspective.asm
@@ -32,8 +32,8 @@ main: {
     rts
 }
 do_perspective: {
-    .label y = -$47
     .label x = $39
+    .label y = -$47
     .label z = $36
     lda #<$400
     sta print_char_cursor
@@ -240,9 +240,9 @@ mulf_init: {
     .label val = 6
     .label sqr = 2
     .label add = 4
-    lda #1
+    lda #<1
     sta add
-    lda #0
+    lda #>1
     sta add+1
     tax
     sta sqr
diff --git a/src/test/ref/examples/bresenham/bitmap-bresenham.asm b/src/test/ref/examples/bresenham/bitmap-bresenham.asm
index a5ee012ff..9c513d6a8 100644
--- a/src/test/ref/examples/bresenham/bitmap-bresenham.asm
+++ b/src/test/ref/examples/bresenham/bitmap-bresenham.asm
@@ -187,6 +187,7 @@ bitmap_plot: {
     .label _0 = 9
     .label plotter_x = 9
     .label plotter_y = $b
+    .label plotter = 9
     lda bitmap_plot_xhi,x
     sta plotter_x+1
     lda bitmap_plot_xlo,x
@@ -204,8 +205,8 @@ bitmap_plot: {
     sta _0+1
     lda bitmap_plot_bit,x
     ldy #0
-    ora (_0),y
-    sta (_0),y
+    ora (plotter),y
+    sta (plotter),y
     rts
 }
 // bitmap_line_ydxi(byte zeropage(7) y, byte register(X) x, byte zeropage(6) y1, byte zeropage(3) yd, byte zeropage(4) xd)
@@ -335,11 +336,11 @@ init_screen: {
 bitmap_clear: {
     .label bitmap = 9
     .label y = 2
-    .label _3 = 9
+    .label _4 = 9
     lda bitmap_plot_xlo
-    sta _3
+    sta _4
     lda bitmap_plot_xhi
-    sta _3+1
+    sta _4+1
     lda #0
     sta y
   b1:
diff --git a/src/test/ref/examples/chargen/chargen-analysis.asm b/src/test/ref/examples/chargen/chargen-analysis.asm
index 3acea7f3d..9a4f94c32 100644
--- a/src/test/ref/examples/chargen/chargen-analysis.asm
+++ b/src/test/ref/examples/chargen/chargen-analysis.asm
@@ -312,10 +312,11 @@ mul8u: {
     .label mb = $b
     .label res = 9
     .label return = 9
-    lda #b
+    lda #<b
     sta mb
-    lda #0
+    lda #>b
     sta mb+1
+    lda #<0
     sta res
     sta res+1
   b1:
diff --git a/src/test/ref/examples/fastmultiply/fastmultiply8.asm b/src/test/ref/examples/fastmultiply/fastmultiply8.asm
index 1ca0be223..b01b2b3b8 100644
--- a/src/test/ref/examples/fastmultiply/fastmultiply8.asm
+++ b/src/test/ref/examples/fastmultiply/fastmultiply8.asm
@@ -145,10 +145,11 @@ print_char_at: {
     rts
 }
 // Print a byte as HEX at a specific position
-// print_byte_at(byte* zeropage(8) at)
+// print_byte_at(byte zeropage($a) b, byte* zeropage(8) at)
 print_byte_at: {
+    .label b = $a
     .label at = 8
-    lda print_sbyte_at.b
+    lda b
     lsr
     lsr
     lsr
@@ -158,7 +159,7 @@ print_byte_at: {
     sta print_char_at.ch
     jsr print_char_at
     lda #$f
-    and print_sbyte_at.b
+    and b
     tay
     inc print_char_at.at
     bne !+
diff --git a/src/test/ref/examples/fire/fire.asm b/src/test/ref/examples/fire/fire.asm
index d14cf06e3..e6481db83 100644
--- a/src/test/ref/examples/fire/fire.asm
+++ b/src/test/ref/examples/fire/fire.asm
@@ -307,7 +307,7 @@ sid_rnd_init: {
 fillscreen: {
     .label screen = 2
     .label i = 4
-    lda #0
+    lda #<0
     sta i
     sta i+1
   b1:
diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
index 449776ef4..0b59051e7 100644
--- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm
+++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
@@ -219,13 +219,13 @@ init: {
     lda #VIC_DEN|VIC_RSEL|3
     sta D011
     jsr plexInit
-    lda #$20
+    lda #<$20
     sta xp
-    lda #0
+    lda #>$20
     sta xp+1
-    tax
+    ldx #0
   b1:
-    lda #$ff&SPRITE/$40
+    lda #SPRITE/$40
     sta PLEX_PTR,x
     txa
     asl
diff --git a/src/test/ref/examples/plasma/plasma-unroll.asm b/src/test/ref/examples/plasma/plasma-unroll.asm
index 6ac675a5a..761f2a967 100644
--- a/src/test/ref/examples/plasma/plasma-unroll.asm
+++ b/src/test/ref/examples/plasma/plasma-unroll.asm
@@ -254,7 +254,7 @@ makecharset: {
     sta print_char_cursor
     lda #>print_line_cursor
     sta print_char_cursor+1
-    lda #0
+    lda #<0
     sta c
     sta c+1
   b1:
diff --git a/src/test/ref/examples/plasma/plasma.asm b/src/test/ref/examples/plasma/plasma.asm
index 5bdbc6470..f0b03b983 100644
--- a/src/test/ref/examples/plasma/plasma.asm
+++ b/src/test/ref/examples/plasma/plasma.asm
@@ -190,7 +190,7 @@ makecharset: {
     sta print_char_cursor
     lda #>print_line_cursor
     sta print_char_cursor+1
-    lda #0
+    lda #<0
     sta c
     sta c+1
   b1:
diff --git a/src/test/ref/examples/rotate/rotate.asm b/src/test/ref/examples/rotate/rotate.asm
index e96371907..89dbfc313 100644
--- a/src/test/ref/examples/rotate/rotate.asm
+++ b/src/test/ref/examples/rotate/rotate.asm
@@ -27,14 +27,16 @@ main: {
     rts
 }
 anim: {
-    .label _4 = 7
-    .label _6 = 9
+    .label _4 = 5
+    .label _6 = 5
     .label _9 = 5
     .label _10 = 5
     .label _11 = 5
     .label _12 = 5
-    .label x = $b
-    .label y = $c
+    .label cos_a = $b
+    .label sin_a = $c
+    .label x = $d
+    .label y = $e
     .label xr = 7
     .label yr = 9
     .label xpos = 5
@@ -48,6 +50,11 @@ anim: {
     cmp RASTER
     bne b2
     inc BORDERCOL
+    ldy angle
+    lda COS,y
+    sta cos_a
+    lda SIN,y
+    sta sin_a
     lda #0
     sta sprite_msb
     sta i
@@ -58,27 +65,25 @@ anim: {
     // signed fixed[7.0]
     lda ys,y
     sta y
-    ldy angle
-    lda COS,y
+    lda cos_a
     jsr mulf8u_prepare
     ldy x
     jsr mulf8s_prepared
-    lda mulf8s_prepared.return
-    sta _4
-    lda mulf8s_prepared.return+1
-    sta _4+1
-    asl xr
-    rol xr+1
+    lda _4
+    asl
+    sta xr
+    lda _4+1
+    rol
+    sta xr+1
     ldy y
     jsr mulf8s_prepared
-    lda mulf8s_prepared.return
-    sta _6
-    lda mulf8s_prepared.return+1
-    sta _6+1
-    asl yr
-    rol yr+1
-    ldy angle
-    lda SIN,y
+    lda _6
+    asl
+    sta yr
+    lda _6+1
+    rol
+    sta yr+1
+    lda sin_a
     jsr mulf8u_prepare
     ldy y
     jsr mulf8s_prepared
@@ -104,18 +109,16 @@ anim: {
     adc _12+1
     sta yr+1
     lda xr+1
+    tax
+    clc
+    adc #<$18+$95
     sta xpos
+    txa
     ora #$7f
     bmi !+
     lda #0
   !:
-    sta xpos+1
-    lda xpos
-    clc
-    adc #$18+$95
-    sta xpos
-    lda xpos+1
-    adc #0
+    adc #>$18+$95
     sta xpos+1
     lsr sprite_msb
     cmp #0
@@ -153,35 +156,44 @@ anim: {
 // mulf8s_prepared(signed byte register(Y) b)
 mulf8s_prepared: {
     .label memA = $fd
+    .label _8 = $f
+    .label _12 = $f
     .label m = 5
     .label return = 5
+    tya
     jsr mulf8u_prepared
     lda memA
     cmp #0
     bpl b1
     lda m+1
-    sty $ff
+    sta _8
+    tya
+    eor #$ff
     sec
-    sbc $ff
+    adc _8
     sta m+1
   b1:
     cpy #0
     bpl b2
     lda m+1
+    sta _12
+    lda memA
+    eor #$ff
     sec
-    sbc memA
+    adc _12
     sta m+1
   b2:
     rts
 }
 // Calculate fast multiply with a prepared unsigned byte to a word result
 // The prepared number is set by calling mulf8u_prepare(byte a)
+// mulf8u_prepared(byte register(A) b)
 mulf8u_prepared: {
     .label resL = $fe
     .label memB = $ff
     .label return = 5
-    sty memB
-    ldx memB
+    sta memB
+    tax
     sec
   sm1:
     lda mulf_sqr1_lo,x
@@ -218,7 +230,7 @@ init: {
     sta SPRITES_ENABLE
     ldx #0
   b1:
-    lda #$ff&SPRITE/$40
+    lda #SPRITE/$40
     sta sprites_ptr,x
     lda #GREEN
     sta SPRITES_COLS,x
@@ -246,7 +258,7 @@ mulf_init: {
     sta sqr1_lo
     lda #>mulf_sqr1_lo+1
     sta sqr1_lo+1
-    lda #0
+    lda #<0
     sta sqr
     sta sqr+1
     tax
diff --git a/src/test/ref/examples/scrolllogo/scrolllogo.asm b/src/test/ref/examples/scrolllogo/scrolllogo.asm
index 638b1528c..bd40df77b 100644
--- a/src/test/ref/examples/scrolllogo/scrolllogo.asm
+++ b/src/test/ref/examples/scrolllogo/scrolllogo.asm
@@ -68,7 +68,7 @@ loop: {
     .label _1 = 9
     .label _5 = 9
     .label xpos = 9
-    lda #0
+    lda #<0
     sta xsin_idx
     sta xsin_idx+1
   b1:
@@ -109,7 +109,7 @@ loop: {
     lda xsin_idx
     cmp #<XSIN_SIZE
     bne b4
-    lda #0
+    lda #<0
     sta xsin_idx
     sta xsin_idx+1
   b4:
@@ -120,8 +120,8 @@ loop: {
 render_logo: {
     .label _3 = $f
     .label xpos = 9
-    .label x_char = 4
     .label logo_idx = 4
+    .label logo_start = 4
     lda xpos
     and #7
     ora #VIC_MCM
@@ -142,20 +142,21 @@ render_logo: {
     ror _3+1
     ror _3
     lda _3
-    sta x_char
+    tax
     lda xpos+1
     bmi b1
+    stx logo_start
     ldy #0
-  b2:
-    cpy x_char
-    bne b3
+  b3:
+    cpy logo_start
+    bne b4
     lda #0
     sta logo_idx
-  b5:
-    cpy #$28
-    bne b6
-    rts
   b6:
+    cpy #$28
+    bne b7
+    rts
+  b7:
     lda logo_idx
     sta SCREEN,y
     lda #$28*1
@@ -180,8 +181,8 @@ render_logo: {
     sta SCREEN+$28*5,y
     iny
     inc logo_idx
-    jmp b5
-  b3:
+    jmp b6
+  b4:
     lda #0
     sta SCREEN,y
     sta SCREEN+$28*1,y
@@ -190,23 +191,23 @@ render_logo: {
     sta SCREEN+$28*4,y
     sta SCREEN+$28*5,y
     iny
-    jmp b2
+    jmp b3
   b1:
-    lda x_char
+    txa
     eor #$ff
     clc
     adc #1
     sta logo_idx
     ldy #0
-  b8:
+  b9:
     lda #$28
     cmp logo_idx
-    bne b9
-  b11:
-    cpy #$28
-    bne b12
-    rts
+    bne b10
   b12:
+    cpy #$28
+    bne b13
+    rts
+  b13:
     lda #0
     sta SCREEN,y
     sta SCREEN+$28*1,y
@@ -215,8 +216,8 @@ render_logo: {
     sta SCREEN+$28*4,y
     sta SCREEN+$28*5,y
     iny
-    jmp b11
-  b9:
+    jmp b12
+  b10:
     lda logo_idx
     sta SCREEN,y
     lda #$28*1
@@ -241,7 +242,7 @@ render_logo: {
     sta SCREEN+$28*5,y
     iny
     inc logo_idx
-    jmp b8
+    jmp b9
 }
 // Generate signed word sinus table - with values in the range min-max.
 // sintab - the table to generate into
@@ -254,22 +255,24 @@ sin16s_gen2: {
     .label _5 = $b
     .label _6 = $f
     .label _8 = $f
-    .label step = $1b
+    .label step = $19
     .label sintab = 2
     .label x = 5
     .label i = 9
     jsr div32u16u
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<xsin
     sta sintab
     lda #>xsin
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
+    lda #<0>>$10
     sta x+2
+    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -329,21 +332,25 @@ sin16s_gen2: {
 }
 // Multiply of two signed words to a signed double word
 // Fixes offsets introduced by using unsigned multiplication
-// mul16s(signed word zeropage($17) a)
+// mul16s(signed word zeropage($15) a)
 mul16s: {
     .label _9 = $f
     .label _16 = $f
     .label m = $b
     .label return = $b
-    .label a = $17
+    .label a = $15
     lda a
     sta mul16u.a
     lda a+1
     sta mul16u.a+1
     lda #<sin16s_gen2.ampl
-    sta mul16u.b
+    sta mul16u.mb
     lda #>sin16s_gen2.ampl
-    sta mul16u.b+1
+    sta mul16u.mb+1
+    lda #<sin16s_gen2.ampl>>$10
+    sta mul16u.mb+2
+    lda #>sin16s_gen2.ampl>>$10
+    sta mul16u.mb+3
     jsr mul16u
     lda a+1
     bpl b2
@@ -366,23 +373,19 @@ mul16s: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage($11) a, word zeropage($f) b)
+// mul16u(word zeropage($f) a, word zeropage($17) b)
 mul16u: {
-    .label mb = $13
-    .label a = $11
+    .label mb = $11
+    .label a = $f
     .label res = $b
     .label return = $b
-    .label b = $f
-    lda b
-    sta mb
-    lda b+1
-    sta mb+1
-    lda #0
-    sta mb+2
-    sta mb+3
+    .label b = $17
+    lda #<0
     sta res
     sta res+1
+    lda #<0>>$10
     sta res+2
+    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -424,17 +427,18 @@ mul16u: {
 // sin16s(dword zeropage($b) x)
 sin16s: {
     .label _4 = $b
+    .label _20 = $15
     .label x = $b
-    .label return = $17
-    .label x1 = $1f
-    .label x2 = $19
-    .label x3 = $19
+    .label return = $15
+    .label x1 = $1d
+    .label x2 = $15
+    .label x3 = $15
     .label x3_6 = $f
-    .label usinx = $17
-    .label x4 = $19
+    .label usinx = $1f
+    .label x4 = $15
     .label x5 = $f
     .label x5_128 = $f
-    .label sinx = $17
+    .label sinx = $15
     .label isUpper = 4
     lda x+3
     cmp #>PI_u4f28>>$10
@@ -580,9 +584,17 @@ sin16s: {
     lda usinx+1
     adc x5_128+1
     sta usinx+1
+    lda usinx
+    sta sinx
+    lda usinx+1
+    sta sinx+1
     lda isUpper
     cmp #0
     beq b3
+    lda usinx
+    sta _20
+    lda usinx+1
+    sta _20+1
     sec
     lda sinx
     eor #$ff
@@ -597,19 +609,26 @@ sin16s: {
 }
 // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result.
 // The select parameter indicates how many of the highest bits of the 32-bit result to skip
-// mulu16_sel(word zeropage($19) v1, word zeropage($f) v2, byte register(X) select)
+// mulu16_sel(word zeropage($15) v1, word zeropage($17) v2, byte register(X) select)
 mulu16_sel: {
     .label _0 = $b
     .label _1 = $b
-    .label v1 = $19
-    .label v2 = $f
+    .label v1 = $15
+    .label v2 = $17
     .label return = $f
-    .label return_1 = $19
-    .label return_10 = $19
+    .label return_1 = $15
+    .label return_10 = $15
     lda v1
     sta mul16u.a
     lda v1+1
     sta mul16u.a+1
+    lda mul16u.b
+    sta mul16u.mb
+    lda mul16u.b+1
+    sta mul16u.mb+1
+    lda #0
+    sta mul16u.mb+2
+    sta mul16u.mb+3
     jsr mul16u
     cpx #0
     beq !e+
@@ -630,14 +649,14 @@ mulu16_sel: {
 // Divide unsigned 32-bit dword dividend with a 16-bit word divisor
 // The 16-bit word remainder can be found in rem16u after the division
 div32u16u: {
-    .label quotient_hi = $11
+    .label quotient_hi = $15
     .label quotient_lo = $f
-    .label return = $1b
+    .label return = $19
     lda #<PI2_u4f28>>$10
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #0
+    lda #<0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
diff --git a/src/test/ref/examples/sinplotter/sine-plotter.asm b/src/test/ref/examples/sinplotter/sine-plotter.asm
index 76895de72..951d02189 100644
--- a/src/test/ref/examples/sinplotter/sine-plotter.asm
+++ b/src/test/ref/examples/sinplotter/sine-plotter.asm
@@ -36,7 +36,7 @@
   .label sin2 = $1400
   .label rem16u = 2
 main: {
-    .const vicSelectGfxBank1_toDd001_return = 3^(>SCREEN)/$40
+    .const vicSelectGfxBank1_toDd001_return = 3
     .const toD0181_return = (>(SCREEN&$3fff)*4)|(>BITMAP)/4&$f
     sei
     // Disable normal interrupt
@@ -73,7 +73,7 @@ render_sine: {
     .label sin2_val = 6
     .label xpos = 4
     .label sin_idx = 2
-    lda #0
+    lda #<0
     sta xpos
     sta xpos+1
     sta sin_idx
@@ -149,7 +149,7 @@ render_sine: {
     lda xpos
     cmp #<$140
     bne b2
-    lda #0
+    lda #<0
     sta xpos
     sta xpos+1
   b2:
@@ -174,33 +174,34 @@ render_sine: {
 // Plot a single dot in the bitmap
 // bitmap_plot(word zeropage(4) x, byte register(X) y)
 bitmap_plot: {
-    .label _1 = $10
+    .label _1 = $15
     .label plotter = 6
+    .label plotter_1 = $15
     .label x = 4
-    .label _3 = 6
+    .label _4 = 6
     lda bitmap_plot_yhi,x
-    sta _3+1
+    sta _4+1
     lda bitmap_plot_ylo,x
-    sta _3
+    sta _4
     lda x
     and #<$fff8
     sta _1
     lda x+1
     and #>$fff8
     sta _1+1
-    lda plotter
+    lda plotter_1
     clc
-    adc _1
-    sta plotter
-    lda plotter+1
-    adc _1+1
-    sta plotter+1
+    adc plotter
+    sta plotter_1
+    lda plotter_1+1
+    adc plotter+1
+    sta plotter_1+1
     lda x
     tay
     lda bitmap_plot_bit,y
     ldy #0
-    ora (plotter),y
-    sta (plotter),y
+    ora (plotter_1),y
+    sta (plotter_1),y
     rts
 }
 // wrap_y(signed word zeropage(6) y)
@@ -230,13 +231,13 @@ wrap_y: {
     sta y+1
     jmp b3
   b2:
-    sec
     lda y
-    sbc #$c8
+    sec
+    sbc #<$c8
     sta y
-    bcs !+
-    dec y+1
-  !:
+    lda y+1
+    sbc #>$c8
+    sta y+1
     jmp b1
 }
 // Generate signed word sinus table - with values in the range min-max.
@@ -250,22 +251,24 @@ sin16s_gen2: {
     .label _5 = $c
     .label _6 = 6
     .label _8 = 6
-    .label step = $1b
+    .label step = $19
     .label sintab = 2
     .label x = 8
     .label i = 4
     jsr div32u16u
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<sin
     sta sintab
     lda #>sin
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
+    lda #<0>>$10
     sta x+2
+    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -325,21 +328,25 @@ sin16s_gen2: {
 }
 // Multiply of two signed words to a signed double word
 // Fixes offsets introduced by using unsigned multiplication
-// mul16s(signed word zeropage($17) a)
+// mul16s(signed word zeropage($15) a)
 mul16s: {
     .label _9 = 6
     .label _16 = 6
     .label m = $c
     .label return = $c
-    .label a = $17
+    .label a = $15
     lda a
     sta mul16u.a
     lda a+1
     sta mul16u.a+1
     lda #<sin16s_gen2.ampl
-    sta mul16u.b
+    sta mul16u.mb
     lda #>sin16s_gen2.ampl
-    sta mul16u.b+1
+    sta mul16u.mb+1
+    lda #<sin16s_gen2.ampl>>$10
+    sta mul16u.mb+2
+    lda #>sin16s_gen2.ampl>>$10
+    sta mul16u.mb+3
     jsr mul16u
     lda a+1
     bpl b2
@@ -362,23 +369,19 @@ mul16s: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage($10) a, word zeropage(6) b)
+// mul16u(word zeropage(6) a, word zeropage($17) b)
 mul16u: {
-    .label mb = $12
-    .label a = $10
+    .label mb = $10
+    .label a = 6
     .label res = $c
     .label return = $c
-    .label b = 6
-    lda b
-    sta mb
-    lda b+1
-    sta mb+1
-    lda #0
-    sta mb+2
-    sta mb+3
+    .label b = $17
+    lda #<0
     sta res
     sta res+1
+    lda #<0>>$10
     sta res+2
+    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -420,18 +423,19 @@ mul16u: {
 // sin16s(dword zeropage($c) x)
 sin16s: {
     .label _4 = $c
+    .label _20 = $15
     .label x = $c
-    .label return = $17
-    .label x1 = $1f
-    .label x2 = $19
-    .label x3 = $19
+    .label return = $15
+    .label x1 = $1d
+    .label x2 = $15
+    .label x3 = $15
     .label x3_6 = 6
-    .label usinx = $17
-    .label x4 = $19
+    .label usinx = $1f
+    .label x4 = $15
     .label x5 = 6
     .label x5_128 = 6
-    .label sinx = $17
-    .label isUpper = $16
+    .label sinx = $15
+    .label isUpper = $14
     lda x+3
     cmp #>PI_u4f28>>$10
     bcc b4
@@ -576,9 +580,17 @@ sin16s: {
     lda usinx+1
     adc x5_128+1
     sta usinx+1
+    lda usinx
+    sta sinx
+    lda usinx+1
+    sta sinx+1
     lda isUpper
     cmp #0
     beq b3
+    lda usinx
+    sta _20
+    lda usinx+1
+    sta _20+1
     sec
     lda sinx
     eor #$ff
@@ -593,19 +605,26 @@ sin16s: {
 }
 // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result.
 // The select parameter indicates how many of the highest bits of the 32-bit result to skip
-// mulu16_sel(word zeropage($19) v1, word zeropage(6) v2, byte register(X) select)
+// mulu16_sel(word zeropage($15) v1, word zeropage($17) v2, byte register(X) select)
 mulu16_sel: {
     .label _0 = $c
     .label _1 = $c
-    .label v1 = $19
-    .label v2 = 6
+    .label v1 = $15
+    .label v2 = $17
     .label return = 6
-    .label return_1 = $19
-    .label return_10 = $19
+    .label return_1 = $15
+    .label return_10 = $15
     lda v1
     sta mul16u.a
     lda v1+1
     sta mul16u.a+1
+    lda mul16u.b
+    sta mul16u.mb
+    lda mul16u.b+1
+    sta mul16u.mb+1
+    lda #0
+    sta mul16u.mb+2
+    sta mul16u.mb+3
     jsr mul16u
     cpx #0
     beq !e+
@@ -626,14 +645,14 @@ mulu16_sel: {
 // Divide unsigned 32-bit dword dividend with a 16-bit word divisor
 // The 16-bit word remainder can be found in rem16u after the division
 div32u16u: {
-    .label quotient_hi = $10
+    .label quotient_hi = $15
     .label quotient_lo = 6
-    .label return = $1b
+    .label return = $19
     lda #<PI2_u4f28>>$10
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #0
+    lda #<0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
@@ -713,12 +732,12 @@ divr16u: {
 // Clear all graphics on the bitmap
 bitmap_clear: {
     .label bitmap = 2
-    .label y = $16
-    .label _3 = 2
+    .label y = $14
+    .label _4 = 2
     lda bitmap_plot_ylo
-    sta _3
+    sta _4
     lda bitmap_plot_yhi
-    sta _3+1
+    sta _4+1
     lda #0
     sta y
   b1:
@@ -742,7 +761,7 @@ bitmap_clear: {
 }
 // Initialize bitmap plotting tables
 bitmap_init: {
-    .label _3 = $16
+    .label _3 = $14
     .label yoffs = 2
     ldx #0
     lda #$80
diff --git a/src/test/ref/examples/sinsprites/sinus-sprites.asm b/src/test/ref/examples/sinsprites/sinus-sprites.asm
index 6d699fc87..81a9c2d21 100644
--- a/src/test/ref/examples/sinsprites/sinus-sprites.asm
+++ b/src/test/ref/examples/sinsprites/sinus-sprites.asm
@@ -228,9 +228,9 @@ gen_sintab: {
     lda #>f_amp
     sta setMEMtoFAC.mem+1
     jsr setMEMtoFAC
-    lda #2
+    lda #<2
     sta setFAC.w
-    lda #0
+    lda #>2
     sta setFAC.w+1
     jsr setFAC
     lda #<f_amp
@@ -596,7 +596,7 @@ place_sprites: {
     sta spr_x
     lda #0
     sta j
-    lda #$ff&sprites/$40
+    lda #sprites/$40
     sta spr_id
   b1:
     lda spr_id
diff --git a/src/test/ref/forrangedwords.asm b/src/test/ref/forrangedwords.asm
index 8716f7084..60b793ab1 100644
--- a/src/test/ref/forrangedwords.asm
+++ b/src/test/ref/forrangedwords.asm
@@ -5,7 +5,7 @@ main: {
     .label SCREEN = $400
     .label w = 2
     .label sw = 2
-    lda #0
+    lda #<0
     sta w
     sta w+1
   b1:
diff --git a/src/test/ref/fragment-variations.asm b/src/test/ref/fragment-variations.asm
new file mode 100644
index 000000000..451bee711
--- /dev/null
+++ b/src/test/ref/fragment-variations.asm
@@ -0,0 +1,74 @@
+// Tests that ASM fragment variations works
+// ASM fragment variations "cast" constants to different types
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .const SIZEOF_DWORD = 4
+main: {
+    .label screen = $400
+    .label _0 = 2
+    .label _1 = 2
+    lda #<$a
+    sta mul16u.a
+    lda #>$a
+    sta mul16u.a+1
+    lda #<$a
+    sta mul16u.mb
+    lda #>$a
+    sta mul16u.mb+1
+    lda #<$a>>$10
+    sta mul16u.mb+2
+    lda #>$a>>$10
+    sta mul16u.mb+3
+    jsr mul16u
+    lda _0
+    sta screen
+    lda _0+1
+    sta screen+1
+    lda _0+2
+    sta screen+2
+    lda _0+3
+    sta screen+3
+    lda #<$3e8
+    sta mul16u.a
+    lda #>$3e8
+    sta mul16u.a+1
+    lda #<$3e8
+    sta mul16u.mb
+    lda #>$3e8
+    sta mul16u.mb+1
+    lda #<$3e8>>$10
+    sta mul16u.mb+2
+    lda #>$3e8>>$10
+    sta mul16u.mb+3
+    jsr mul16u
+    lda _1
+    sta screen+1*SIZEOF_DWORD
+    lda _1+1
+    sta screen+1*SIZEOF_DWORD+1
+    lda _1+2
+    sta screen+1*SIZEOF_DWORD+2
+    lda _1+3
+    sta screen+1*SIZEOF_DWORD+3
+    rts
+}
+// mul16u(word zeropage(6) a)
+mul16u: {
+    .label return = 2
+    .label mb = 2
+    .label a = 6
+    lda return
+    clc
+    adc a
+    sta return
+    lda return+1
+    adc a+1
+    sta return+1
+    lda return+2
+    adc #0
+    sta return+2
+    lda return+3
+    adc #0
+    sta return+3
+    rts
+}
diff --git a/src/test/ref/gfxbank.asm b/src/test/ref/gfxbank.asm
new file mode 100644
index 000000000..54c84cffb
--- /dev/null
+++ b/src/test/ref/gfxbank.asm
@@ -0,0 +1,16 @@
+// Test minimization of constants
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  // CIA#2 Port A: Serial bus, RS-232, VIC memory bank
+  .label CIA2_PORT_A = $dd00
+  // CIA #2 Port A data direction register.
+  .label CIA2_PORT_A_DDR = $dd02
+main: {
+    .const vicSelectGfxBank1_toDd001_return = 3
+    lda #3
+    sta CIA2_PORT_A_DDR
+    lda #vicSelectGfxBank1_toDd001_return
+    sta CIA2_PORT_A
+    rts
+}
diff --git a/src/test/ref/halfscii.asm b/src/test/ref/halfscii.asm
index 179529db1..b452a7471 100644
--- a/src/test/ref/halfscii.asm
+++ b/src/test/ref/halfscii.asm
@@ -7,10 +7,11 @@
   .label D018 = $d018
   .label CHARSET4 = $2800
 main: {
-    .label _1 = 6
-    .label _11 = 6
-    .label _21 = 6
-    .label _30 = 6
+    .label _1 = 8
+    .label _11 = 8
+    .label _21 = 8
+    .label _30 = 8
+    .label chargen1 = 6
     .label charset4 = 4
     .label chargen = 2
     sei
@@ -25,13 +26,19 @@ main: {
     lda #>CHARGEN
     sta chargen+1
   b1:
+    lda chargen
+    clc
+    adc #1
+    sta chargen1
+    lda chargen+1
+    adc #0
+    sta chargen1+1
     lda #$60
     ldy #0
     and (chargen),y
     sta _1
     lda #$60
-    ldy #1
-    and (chargen),y
+    and (chargen1),y
     lsr
     lsr
     ora _1
@@ -54,8 +61,7 @@ main: {
     and (chargen),y
     sta _11
     lda #$18
-    ldy #1
-    and (chargen),y
+    and (chargen1),y
     lsr
     lsr
     ora _11
@@ -75,8 +81,7 @@ main: {
     asl
     sta _21
     lda #6
-    ldy #1
-    and (chargen),y
+    and (chargen1),y
     lsr
     ora _21
     tay
@@ -95,8 +100,7 @@ main: {
     asl
     sta _30
     lda #1
-    tay
-    and (chargen),y
+    and (chargen1),y
     ora _30
     tay
     lda bits_count,y
diff --git a/src/test/ref/inline-function-if.asm b/src/test/ref/inline-function-if.asm
index 8f77a44d9..d5729668a 100644
--- a/src/test/ref/inline-function-if.asm
+++ b/src/test/ref/inline-function-if.asm
@@ -6,8 +6,8 @@
 main: {
     .const toUpper1_ch = 'c'
     .const toUpper2_ch = 'm'
-    .const toUpper1_res = toUpper1_ch+$40
-    lda #toUpper1_res
+    .const toUpper1_return = toUpper1_ch+$40
+    lda #toUpper1_return
     sta screen
     lda #toUpper2_ch
     sta screen+1
diff --git a/src/test/ref/inline-kasm-resource.asm b/src/test/ref/inline-kasm-resource.asm
index f54a110c8..54b571824 100644
--- a/src/test/ref/inline-kasm-resource.asm
+++ b/src/test/ref/inline-kasm-resource.asm
@@ -8,7 +8,7 @@
   .label SPRITES_XPOS = $d000
   .label SPRITES_YPOS = $d001
 main: {
-    lda #$ff&SPRITE/$40
+    lda #SPRITE/$40
     sta SCREEN+$3f8
     lda #1
     sta SPRITES_ENABLE
diff --git a/src/test/ref/inline-pointer-0.asm b/src/test/ref/inline-pointer-0.asm
new file mode 100644
index 000000000..3e2b5610f
--- /dev/null
+++ b/src/test/ref/inline-pointer-0.asm
@@ -0,0 +1,10 @@
+// Tests creating a literal pointer from two bytes
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = 4*$100
+    lda #'a'
+    sta screen
+    rts
+}
diff --git a/src/test/ref/inline-pointer-1.asm b/src/test/ref/inline-pointer-1.asm
new file mode 100644
index 000000000..4da10ae54
--- /dev/null
+++ b/src/test/ref/inline-pointer-1.asm
@@ -0,0 +1,24 @@
+// Tests creating a literal pointer from two bytes
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    ldx #0
+    lda #4
+    jsr puta
+    ldx #$18
+    lda #5
+    jsr puta
+    rts
+}
+// puta(byte register(A) ph, byte register(X) pl)
+puta: {
+    .label screen = 2
+    .label _2 = 2
+    sta _2+1
+    stx _2
+    lda #'a'
+    ldy #0
+    sta (screen),y
+    rts
+}
diff --git a/src/test/ref/inline-pointer-2.asm b/src/test/ref/inline-pointer-2.asm
new file mode 100644
index 000000000..32a924a78
--- /dev/null
+++ b/src/test/ref/inline-pointer-2.asm
@@ -0,0 +1,9 @@
+// Tests creating a literal pointer from two bytes
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    lda #'a'
+    sta 4*$100+$28
+    rts
+}
diff --git a/src/test/ref/inline-string-3.asm b/src/test/ref/inline-string-3.asm
index aaf848ee9..1e2abba8f 100644
--- a/src/test/ref/inline-string-3.asm
+++ b/src/test/ref/inline-string-3.asm
@@ -7,17 +7,18 @@
 main: {
     .label PTR = $9ffe
     .label SCREEN = $400
-    .label _6 = 2
+    .label ptr = 2
+    .label _7 = 2
     lda #<STRING
     sta PTR
     lda #>STRING
     sta PTR+1
     lda PTR
-    sta _6
+    sta _7
     lda PTR+1
-    sta _6+1
+    sta _7+1
     ldy #0
-    lda (_6),y
+    lda (ptr),y
     sta SCREEN
     rts
     STRING: .text "camelot"
diff --git a/src/test/ref/inline-word-0.asm b/src/test/ref/inline-word-0.asm
new file mode 100644
index 000000000..d1161c334
--- /dev/null
+++ b/src/test/ref/inline-word-0.asm
@@ -0,0 +1,13 @@
+// Tests minimal inline word
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    .const w = 2*$100+1
+    lda #<w
+    sta screen
+    lda #>w
+    sta screen+1
+    rts
+}
diff --git a/src/test/ref/inline-word-1.asm b/src/test/ref/inline-word-1.asm
new file mode 100644
index 000000000..bb6135dcc
--- /dev/null
+++ b/src/test/ref/inline-word-1.asm
@@ -0,0 +1,13 @@
+// Tests minimal inline word
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    .const w = 1*$100+2
+    lda #<w
+    sta screen
+    lda #>w
+    sta screen+1
+    rts
+}
diff --git a/src/test/ref/inline-word-2.asm b/src/test/ref/inline-word-2.asm
new file mode 100644
index 000000000..bb6135dcc
--- /dev/null
+++ b/src/test/ref/inline-word-2.asm
@@ -0,0 +1,13 @@
+// Tests minimal inline word
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    .const w = 1*$100+2
+    lda #<w
+    sta screen
+    lda #>w
+    sta screen+1
+    rts
+}
diff --git a/src/test/ref/inline-word.asm b/src/test/ref/inline-word.asm
index 505c1ebc1..7b80c88b1 100644
--- a/src/test/ref/inline-word.asm
+++ b/src/test/ref/inline-word.asm
@@ -4,6 +4,7 @@
   .label SCREEN = $400
 main: {
     .label w = 3
+    .label sc = 3
     .label h = 2
     lda #0
     sta h
@@ -17,7 +18,7 @@ main: {
     stx w
     lda #'*'
     ldy #0
-    sta (w),y
+    sta (sc),y
     inx
     cpx #8
     bne b2
diff --git a/src/test/ref/int-literals.asm b/src/test/ref/int-literals.asm
index 8f7755754..dc02bae1d 100644
--- a/src/test/ref/int-literals.asm
+++ b/src/test/ref/int-literals.asm
@@ -10,11 +10,13 @@
   .const TYPEID_SIGNED_DWORD = 6
   .const RED = 2
   .const GREEN = 5
+  .label SCREEN = $400
+  .label COLS = $d800
 main: {
     .label s = 2
-    lda #<$400
+    lda #<SCREEN
     sta s
-    lda #>$400
+    lda #>SCREEN
     sta s+1
   b1:
     lda #' '
@@ -25,11 +27,11 @@ main: {
     inc s+1
   !:
     lda s+1
-    cmp #>$400+$3e8
+    cmp #>SCREEN+$3e8
     bcc b1
     bne !+
     lda s
-    cmp #<$400+$3e8
+    cmp #<SCREEN+$3e8
     bcc b1
   !:
     jsr testSimpleTypes
@@ -109,14 +111,14 @@ assertType: {
     cmp t2
     beq b1
     lda #RED
-    sta $d800,x
+    sta COLS,x
   b2:
     tya
-    sta $400,x
+    sta SCREEN,x
     inx
     rts
   b1:
     lda #GREEN
-    sta $d800,x
+    sta COLS,x
     jmp b2
 }
diff --git a/src/test/ref/line-anim.asm b/src/test/ref/line-anim.asm
index 7f9b1338f..bd6739ae0 100644
--- a/src/test/ref/line-anim.asm
+++ b/src/test/ref/line-anim.asm
@@ -80,35 +80,38 @@ bitmap_plot: {
     .label _1 = 7
     .label x = 3
     .label plotter = 5
-    .label _3 = 5
+    .label plotter_1 = 7
+    .label _4 = 5
     lda bitmap_plot_yhi,x
-    sta _3+1
+    sta _4+1
     lda bitmap_plot_ylo,x
-    sta _3
+    sta _4
     lda x
     and #<$fff8
     sta _1
     lda x+1
     and #>$fff8
     sta _1+1
-    lda plotter
+    lda plotter_1
     clc
-    adc _1
-    sta plotter
-    lda plotter+1
-    adc _1+1
-    sta plotter+1
+    adc plotter
+    sta plotter_1
+    lda plotter_1+1
+    adc plotter+1
+    sta plotter_1+1
     lda x
     tay
     lda bitmap_plot_bit,y
     ldy #0
-    ora (plotter),y
-    sta (plotter),y
+    ora (plotter_1),y
+    sta (plotter_1),y
     rts
 }
 // Initialize the points to be animated
 // point_init(byte zeropage(2) point_idx)
 point_init: {
+    .label _0 = 9
+    .label _1 = 3
     .label _3 = 7
     .label _4 = 3
     .label _9 = 3
@@ -120,20 +123,28 @@ point_init: {
     .label abs16s1_return = 3
     .label abs16s2__2 = 5
     .label abs16s2_return = 5
-    .label x_stepf = 5
+    .label x_stepf = 3
     .label x_diff = 9
     lda point_idx
     asl
-    tax
+    tay
+    lda x_end,y
+    sta _0
+    lda x_end+1,y
+    sta _0+1
     lda point_idx
     asl
     tay
+    lda x_start,y
+    sta _1
+    lda x_start+1,y
+    sta _1+1
+    lda x_diff
     sec
-    lda x_end,x
-    sbc x_start,y
+    sbc _1
     sta x_diff
-    lda x_end+1,x
-    sbc x_start+1,y
+    lda x_diff+1
+    sbc _1+1
     sta x_diff+1
     ldy point_idx
     lda y_end,y
@@ -229,8 +240,8 @@ point_init: {
     lda x_diff+1
     bmi b4
     // x add = 1.0
-    ldy point_idx
     lda #$10
+    ldy point_idx
     sta x_add,y
   b5:
     jsr divr16s
@@ -278,23 +289,18 @@ point_init: {
 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5
 // divr16s(signed word zeropage(9) divisor, signed word zeropage(7) rem)
 divr16s: {
-    .const dividend = 0
     .label _10 = 7
     .label _13 = 9
-    .label resultu = 5
-    .label return = 5
+    .label _18 = 3
+    .label remu = 7
+    .label divisoru = 9
+    .label resultu = 3
+    .label return = 3
     .label divisor = 9
     .label rem = 7
-    .label dividendu = 3
-    .label divisoru = 9
-    .label remu = 7
     lda rem+1
     bmi b1
-    lda #dividend
-    sta dividendu
-    lda #0
-    sta dividendu+1
-    tay
+    ldy #0
   b2:
     lda divisor+1
     bmi b3
@@ -337,10 +343,6 @@ divr16s: {
     eor #$ff
     adc #0
     sta _10+1
-    lda #-dividend
-    sta dividendu
-    lda #0
-    sta dividendu+1
     ldy #1
     jmp b2
 }
@@ -348,17 +350,19 @@ divr16s: {
 // Returns the quotient dividend/divisor.
 // The final remainder will be set into the global variable rem16u
 // Implemented using simple binary division
-// divr16u(word zeropage(3) dividend, word zeropage(9) divisor, word zeropage(7) rem)
+// divr16u(word zeropage(5) dividend, word zeropage(9) divisor, word zeropage(7) rem)
 divr16u: {
     .label rem = 7
-    .label dividend = 3
-    .label quotient = 5
-    .label return = 5
+    .label dividend = 5
+    .label quotient = 3
+    .label return = 3
     .label divisor = 9
     ldx #0
     txa
     sta quotient
     sta quotient+1
+    sta dividend
+    sta dividend+1
   b1:
     asl rem
     rol rem+1
@@ -434,11 +438,11 @@ screen_fill: {
 bitmap_clear: {
     .label bitmap = 3
     .label y = 2
-    .label _3 = 3
+    .label _4 = 3
     lda bitmap_plot_ylo
-    sta _3
+    sta _4
     lda bitmap_plot_yhi
-    sta _3+1
+    sta _4+1
     lda #0
     sta y
   b1:
diff --git a/src/test/ref/linegen.asm b/src/test/ref/linegen.asm
index 4cbd79681..825a7fc29 100644
--- a/src/test/ref/linegen.asm
+++ b/src/test/ref/linegen.asm
@@ -38,7 +38,7 @@ main: {
     sta lin16u_gen.lintab
     lda #>lintab3
     sta lin16u_gen.lintab+1
-    lda #0
+    lda #<0
     sta lin16u_gen.min
     sta lin16u_gen.min+1
     lda #<$6488
@@ -76,7 +76,7 @@ main: {
     lda #>str1
     sta print_str.str+1
     jsr print_str
-    lda #0
+    lda #<0
     sta print_word.w
     sta print_word.w+1
     jsr print_word
@@ -309,10 +309,11 @@ lin16u_gen: {
     lda ampl+1
     sbc min+1
     sta ampl+1
-    lda #$14-1
+    lda #<$14-1
     sta divr16u.divisor
-    lda #0
+    lda #>$14-1
     sta divr16u.divisor+1
+    lda #<0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
@@ -320,10 +321,11 @@ lin16u_gen: {
     sta stepi
     lda divr16u.return+1
     sta stepi+1
-    lda #$14-1
+    lda #<$14-1
     sta divr16u.divisor
-    lda #0
+    lda #>$14-1
     sta divr16u.divisor+1
+    lda #<0
     sta divr16u.dividend
     sta divr16u.dividend+1
     jsr divr16u
@@ -342,7 +344,7 @@ lin16u_gen: {
     sta val+2
     lda min+1
     sta val+3
-    lda #0
+    lda #<0
     sta i
     sta i+1
   b1:
diff --git a/src/test/ref/liverange-call-problem.asm b/src/test/ref/liverange-call-problem.asm
index ff5e1ea3d..933c49ae1 100644
--- a/src/test/ref/liverange-call-problem.asm
+++ b/src/test/ref/liverange-call-problem.asm
@@ -8,11 +8,11 @@
   .label w2 = 2
 main: {
     .label SCREEN = $400
-    lda #0
+    lda #<0
     sta w1
     sta w1+1
     jsr incw1
-    lda #0
+    lda #<0
     sta w2
     sta w2+1
     jsr incw2
diff --git a/src/test/ref/min-fmul-16.asm b/src/test/ref/min-fmul-16.asm
index dc431ade4..ef4553748 100644
--- a/src/test/ref/min-fmul-16.asm
+++ b/src/test/ref/min-fmul-16.asm
@@ -226,7 +226,7 @@ mulf_init: {
     sta sqr1_lo
     lda #>mulf_sqr1_lo+1
     sta sqr1_lo+1
-    lda #0
+    lda #<0
     sta sqr
     sta sqr+1
     tax
diff --git a/src/test/ref/mixed-array-0.asm b/src/test/ref/mixed-array-0.asm
new file mode 100644
index 000000000..3e2175924
--- /dev/null
+++ b/src/test/ref/mixed-array-0.asm
@@ -0,0 +1,15 @@
+// Test an array with mixed byte/number types
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label SCREEN = $400
+    lda msg
+    sta SCREEN
+    lda msg+1
+    sta SCREEN+1
+    lda msg+2
+    sta SCREEN+2
+    rts
+    msg: .byte 1, 2, 3
+}
diff --git a/src/test/ref/mixed-array-1.asm b/src/test/ref/mixed-array-1.asm
new file mode 100644
index 000000000..2d92feb78
--- /dev/null
+++ b/src/test/ref/mixed-array-1.asm
@@ -0,0 +1,15 @@
+// Test an array with mixed byte/number types
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label SCREEN = $400
+    lda msg
+    sta SCREEN
+    lda msg+1
+    sta SCREEN+1
+    lda msg+2
+    sta SCREEN+2
+    rts
+    msg: .byte -1, 0, 1
+}
diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
index b3658492e..f9d6d5695 100644
--- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
+++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
@@ -167,13 +167,13 @@ init: {
     lda #VIC_DEN|VIC_RSEL|3
     sta D011
     jsr plexInit
-    lda #$20
+    lda #<$20
     sta xp
-    lda #0
+    lda #>$20
     sta xp+1
-    tax
+    ldx #0
   b1:
-    lda #$ff&SPRITE/$40
+    lda #SPRITE/$40
     sta PLEX_PTR,x
     txa
     asl
diff --git a/src/test/ref/number-conversion.asm b/src/test/ref/number-conversion.asm
index 17df64b44..412553a64 100644
--- a/src/test/ref/number-conversion.asm
+++ b/src/test/ref/number-conversion.asm
@@ -11,6 +11,8 @@
   .const TYPEID_DWORD = 5
   .const RED = 2
   .const GREEN = 5
+  .label SCREEN = $400
+  .label COLS = $d800
 main: {
     ldx #0
     lda #TYPEID_SIGNED_BYTE
@@ -167,14 +169,14 @@ assertType: {
     cmp t2
     beq b1
     lda #RED
-    sta $d800,x
+    sta COLS,x
   b2:
     tya
-    sta $400,x
+    sta SCREEN,x
     inx
     rts
   b1:
     lda #GREEN
-    sta $d800,x
+    sta COLS,x
     jmp b2
 }
diff --git a/src/test/ref/operator-lohi-problem.asm b/src/test/ref/operator-lohi-problem.asm
index 83e1032ff..332ca079f 100644
--- a/src/test/ref/operator-lohi-problem.asm
+++ b/src/test/ref/operator-lohi-problem.asm
@@ -9,11 +9,9 @@
   .label SCREEN = $400
 main: {
     .const dw = $2000
-    .const w1 = dw&$ffff
-    .const w2 = <dw+1
-    lda #<w1
+    .const w2 = dw+1&$ffff
+    lda #0
     sta SCREEN
-    lda #>w1
     sta SCREEN+1
     lda #<w2
     sta SCREEN+3
diff --git a/src/test/ref/ptr-complex.asm b/src/test/ref/ptr-complex.asm
index 214144b95..e8ef78d97 100644
--- a/src/test/ref/ptr-complex.asm
+++ b/src/test/ref/ptr-complex.asm
@@ -7,7 +7,6 @@ main: {
     .label screen = $400
     // Increment on a const named pointer
     .label BGCOL = $d020
-    .label sc2 = screen+$51
     ldx #0
   // RValue pointer expression (variable)
   b1:
@@ -17,7 +16,7 @@ main: {
     cpx #$b
     bne b1
     lda screen+$79
-    sta sc2
+    sta screen+$51
     // LValue pointer expression (constant - directly)
     lda screen+$7a
     sta screen+$52
diff --git a/src/test/ref/roll-sprite-msb.asm b/src/test/ref/roll-sprite-msb.asm
index 80b22ddde..18ab37b56 100644
--- a/src/test/ref/roll-sprite-msb.asm
+++ b/src/test/ref/roll-sprite-msb.asm
@@ -7,11 +7,11 @@
   .label SPRITES_XMSB = $d010
 main: {
     .label xpos = 2
-    lda #$c8
+    lda #<$c8
     sta xpos
-    lda #0
+    lda #>$c8
     sta xpos+1
-    tax
+    ldx #0
   b1:
     stx position_sprite.spriteno
     jsr position_sprite
diff --git a/src/test/ref/scan-desire-problem.asm b/src/test/ref/scan-desire-problem.asm
index 248cffd38..377b83bf5 100644
--- a/src/test/ref/scan-desire-problem.asm
+++ b/src/test/ref/scan-desire-problem.asm
@@ -172,10 +172,11 @@ mul8u: {
     .label mb = 6
     .label res = 4
     .label return = 4
-    lda #b
+    lda #<b
     sta mb
-    lda #0
+    lda #>b
     sta mb+1
+    lda #<0
     sta res
     sta res+1
   b1:
diff --git a/src/test/ref/semi-struct-2.asm b/src/test/ref/semi-struct-2.asm
index 0429bcc2f..d54d7ac9c 100644
--- a/src/test/ref/semi-struct-2.asm
+++ b/src/test/ref/semi-struct-2.asm
@@ -730,10 +730,11 @@ mul8u: {
     .label mb = 2
     .label res = 8
     .label return = 8
-    lda #SIZEOF_ENTRY
+    lda #<SIZEOF_ENTRY
     sta mb
-    lda #0
+    lda #>SIZEOF_ENTRY
     sta mb+1
+    lda #<0
     sta res
     sta res+1
   b1:
diff --git a/src/test/ref/signed-indexed-subtract.asm b/src/test/ref/signed-indexed-subtract.asm
index e82d13764..7ca3ce033 100644
--- a/src/test/ref/signed-indexed-subtract.asm
+++ b/src/test/ref/signed-indexed-subtract.asm
@@ -2,22 +2,25 @@
 .pc = $801 "Basic"
 :BasicUpstart(main)
 .pc = $80d "Program"
-  .label print_line_cursor = 2
+  .label print_line_cursor = 3
   .label print_char_cursor = 7
 main: {
-    ldy #0
+    .label i = 2
+    lda #0
+    sta i
   b1:
-    tya
+    lda i
     ldx #$80
     jsr sub
-    tya
+    lda i
     ldx #$40
     jsr sub
-    tya
+    lda i
     ldx #$40
     jsr sub
-    iny
-    cpy #9
+    inc i
+    lda #9
+    cmp i
     bne b1
     jsr print_cls
     lda #<$400
@@ -71,9 +74,9 @@ print_ln: {
     rts
 }
 // Print a signed word as HEX
-// print_sword(signed word zeropage(4) w)
+// print_sword(signed word zeropage(5) w)
 print_sword: {
-    .label w = 4
+    .label w = 5
     lda w+1
     bpl b1
     lda #'-'
@@ -92,19 +95,21 @@ print_sword: {
     rts
 }
 // Print a word as HEX
+// print_word(word zeropage(5) w)
 print_word: {
-    lda print_sword.w+1
+    .label w = 5
+    lda w+1
     sta print_byte.b
     jsr print_byte
-    lda print_sword.w
+    lda w
     sta print_byte.b
     jsr print_byte
     rts
 }
 // Print a byte as HEX
-// print_byte(byte zeropage(6) b)
+// print_byte(byte zeropage(2) b)
 print_byte: {
-    .label b = 6
+    .label b = 2
     lda b
     lsr
     lsr
@@ -133,7 +138,7 @@ print_char: {
 }
 // Clear the screen. Also resets current line/char cursor.
 print_cls: {
-    .label sc = 2
+    .label sc = 3
     lda #<$400
     sta sc
     lda #>$400
@@ -156,16 +161,20 @@ print_cls: {
 }
 // sub(byte register(A) idx, byte register(X) s)
 sub: {
+    .label _1 = 3
     asl
+    tay
+    txa
+    sta _1
+    lda #0
+    sta _1+1
+    lda words,y
     sec
-    stx $ff
-    tax
-    lda words,x
-    sbc $ff
-    sta words,x
-    bcs !+
-    dec words+1,x
-  !:
+    sbc _1
+    sta words,y
+    lda words+1,y
+    sbc _1+1
+    sta words+1,y
     rts
 }
   print_hextab: .text "0123456789abcdef"
diff --git a/src/test/ref/signed-words.asm b/src/test/ref/signed-words.asm
index e85a5777d..9a92c64eb 100644
--- a/src/test/ref/signed-words.asm
+++ b/src/test/ref/signed-words.asm
@@ -25,21 +25,22 @@
   .label yvel_22 = 6
 main: {
     jsr init
-    lda #$64
+    lda #<$64
     sta yvel_init
-    lda #0
+    lda #>$64
     sta yvel_init+1
-    lda #$c8
+    lda #<$c8
     sta xvel
-    lda #0
+    lda #>$c8
     sta xvel+1
+    lda #<0
     sta ypos
     sta ypos+1
     sta xpos
     sta xpos+1
-    lda #$64
+    lda #<$64
     sta yvel_12
-    lda #0
+    lda #>$64
     sta yvel_12+1
   b1:
     lda #$ff
@@ -64,13 +65,20 @@ anim: {
     eor #$ff
     adc #0
     sta xvel+1
+    lda #$a
+    sta $fe
+    ora #$7f
+    bmi !+
+    lda #0
+  !:
+    sta $ff
     sec
     lda yvel_init
-    sbc #$a
+    sbc $fe
     sta yvel_init
-    bcs !+
-    dec yvel_init+1
-  !:
+    lda yvel_init+1
+    sbc $ff
+    sta yvel_init+1
     lda yvel_init
     cmp #<-$c8
     lda yvel_init+1
@@ -79,16 +87,16 @@ anim: {
     eor #$80
   !:
     bpl b3
-    lda #$c8
+    lda #<$c8
     sta yvel
-    lda #0
+    lda #>$c8
     sta yvel+1
   b3:
     lda yvel
     sta yvel_22
     lda yvel+1
     sta yvel_22+1
-    lda #0
+    lda #<0
     sta ypos
     sta ypos+1
     sta xpos
@@ -182,7 +190,7 @@ init: {
     sta SPRITES_YPOS
     lda #WHITE
     sta SPRITES_COLS
-    lda #$ff&SPRITE/$40
+    lda #SPRITE/$40
     sta SPRITES_PTR
     lda #<SCREEN
     sta sc
diff --git a/src/test/ref/sinus-basic.asm b/src/test/ref/sinus-basic.asm
index bf19ef5b9..9e8385227 100644
--- a/src/test/ref/sinus-basic.asm
+++ b/src/test/ref/sinus-basic.asm
@@ -46,9 +46,9 @@ main: {
     lda #>f_i
     sta setMEMtoFAC.mem+1
     jsr setMEMtoFAC
-    lda #$19
+    lda #<$19
     sta setFAC.w
-    lda #0
+    lda #>$19
     sta setFAC.w+1
     jsr setFAC
     jsr divMEMbyFAC
diff --git a/src/test/ref/sinusgen16.asm b/src/test/ref/sinusgen16.asm
index f9d538a19..380d92e7c 100644
--- a/src/test/ref/sinusgen16.asm
+++ b/src/test/ref/sinusgen16.asm
@@ -112,11 +112,13 @@ print_sword: {
     rts
 }
 // Print a word as HEX
+// print_word(word zeropage(6) w)
 print_word: {
-    lda print_sword.w+1
+    .label w = 6
+    lda w+1
     tax
     jsr print_byte
-    lda print_sword.w
+    lda w
     tax
     jsr print_byte
     rts
@@ -178,22 +180,24 @@ print_cls: {
 // sin16s_gen(signed word* zeropage(2) sintab)
 sin16s_gen: {
     .label _1 = 6
-    .label step = $1b
+    .label step = $19
     .label sintab = 2
     .label x = $a
     .label i = 4
     jsr div32u16u
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<main.sintab1
     sta sintab
     lda #>main.sintab1
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
+    lda #<0>>$10
     sta x+2
+    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -252,16 +256,17 @@ sin16s_gen: {
 // sin16s(dword zeropage($f) x)
 sin16s: {
     .label _4 = $f
+    .label _20 = 6
     .label x = $f
     .label return = 6
-    .label x1 = $1f
-    .label x2 = 8
-    .label x3 = 8
-    .label x3_6 = $13
-    .label usinx = 6
-    .label x4 = 8
-    .label x5 = $13
-    .label x5_128 = $13
+    .label x1 = $1d
+    .label x2 = 6
+    .label x3 = 6
+    .label x3_6 = 8
+    .label usinx = $1f
+    .label x4 = 6
+    .label x5 = 8
+    .label x5_128 = 8
     .label sinx = 6
     .label isUpper = $e
     lda x+3
@@ -408,9 +413,17 @@ sin16s: {
     lda usinx+1
     adc x5_128+1
     sta usinx+1
+    lda usinx
+    sta sinx
+    lda usinx+1
+    sta sinx+1
     lda isUpper
     cmp #0
     beq b3
+    lda usinx
+    sta _20
+    lda usinx+1
+    sta _20+1
     sec
     lda sinx
     eor #$ff
@@ -425,15 +438,15 @@ sin16s: {
 }
 // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result.
 // The select parameter indicates how many of the highest bits of the 32-bit result to skip
-// mulu16_sel(word zeropage(8) v1, word zeropage($13) v2, byte register(X) select)
+// mulu16_sel(word zeropage(6) v1, word zeropage(8) v2, byte register(X) select)
 mulu16_sel: {
     .label _0 = $f
     .label _1 = $f
-    .label v1 = 8
-    .label v2 = $13
-    .label return = $13
-    .label return_1 = 8
-    .label return_10 = 8
+    .label v1 = 6
+    .label v2 = 8
+    .label return = 8
+    .label return_1 = 6
+    .label return_10 = 6
     lda v1
     sta mul16u.a
     lda v1+1
@@ -456,12 +469,12 @@ mulu16_sel: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage($15) a, word zeropage($13) b)
+// mul16u(word zeropage($13) a, word zeropage(8) b)
 mul16u: {
-    .label mb = $17
-    .label a = $15
+    .label a = $13
+    .label mb = $15
     .label res = $f
-    .label b = $13
+    .label b = 8
     .label return = $f
     lda b
     sta mb
@@ -472,7 +485,9 @@ mul16u: {
     sta mb+3
     sta res
     sta res+1
+    lda #<0>>$10
     sta res+2
+    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -513,12 +528,12 @@ mul16u: {
 div32u16u: {
     .label quotient_hi = 8
     .label quotient_lo = 6
-    .label return = $1b
+    .label return = $19
     lda #<PI2_u4f28>>$10
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #0
+    lda #<0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
diff --git a/src/test/ref/sinusgen16b.asm b/src/test/ref/sinusgen16b.asm
index c99639748..b5f324cfa 100644
--- a/src/test/ref/sinusgen16b.asm
+++ b/src/test/ref/sinusgen16b.asm
@@ -129,11 +129,13 @@ print_sword: {
     rts
 }
 // Print a word as HEX
+// print_word(word zeropage(8) w)
 print_word: {
-    lda print_sword.w+1
+    .label w = 8
+    lda w+1
     sta print_byte.b
     jsr print_byte
-    lda print_sword.w
+    lda w
     sta print_byte.b
     jsr print_byte
     rts
@@ -196,23 +198,25 @@ print_cls: {
 // wavelength - the number of sinus points in a total sinus wavelength (the size of the table)
 // sin16s_genb(signed word* zeropage(2) sintab)
 sin16s_genb: {
-    .label _2 = 8
-    .label step = $1d
+    .label _2 = 6
+    .label step = $1b
     .label sintab = 2
     .label x = $d
     .label i = 4
     jsr div32u16u
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<main.sintab2
     sta sintab
     lda #>main.sintab2
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
+    lda #<0>>$10
     sta x+2
+    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -266,17 +270,18 @@ sin16s_genb: {
 // result: signed word sin(x) s[0.15] - using the full range  -$7fff - $7fff
 // sin16sb(word zeropage(6) x)
 sin16sb: {
+    .label _19 = 6
     .label x = 6
-    .label return = 8
+    .label return = 6
     .label x1 = 6
-    .label x2 = $b
-    .label x3 = $b
-    .label x3_6 = $11
-    .label usinx = 8
-    .label x4 = $b
-    .label x5 = $11
-    .label x5_128 = $11
-    .label sinx = 8
+    .label x2 = 8
+    .label x3 = 8
+    .label x3_6 = $b
+    .label usinx = $1f
+    .label x4 = 8
+    .label x5 = $b
+    .label x5_128 = $b
+    .label sinx = 6
     .label isUpper = $a
     lda x+1
     cmp #>PI_u4f12
@@ -388,9 +393,17 @@ sin16sb: {
     lda usinx+1
     adc x5_128+1
     sta usinx+1
+    lda usinx
+    sta sinx
+    lda usinx+1
+    sta sinx+1
     lda isUpper
     cmp #0
     beq b3
+    lda usinx
+    sta _19
+    lda usinx+1
+    sta _19+1
     sec
     lda sinx
     eor #$ff
@@ -405,19 +418,19 @@ sin16sb: {
 }
 // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result.
 // The select parameter indicates how many of the highest bits of the 32-bit result to skip
-// mulu16_sel(word zeropage($b) v1, word zeropage($11) v2, byte register(X) select)
+// mulu16_sel(word zeropage(8) v1, word zeropage($b) v2, byte register(X) select)
 mulu16_sel: {
-    .label _0 = $15
-    .label _1 = $15
-    .label v1 = $b
-    .label v2 = $11
-    .label return = $b
-    .label return_11 = $11
-    .label return_14 = $11
-    .label return_16 = $11
-    .label return_17 = $11
-    .label return_18 = $11
-    .label return_20 = $11
+    .label _0 = $13
+    .label _1 = $13
+    .label v1 = 8
+    .label v2 = $b
+    .label return = 8
+    .label return_11 = $b
+    .label return_14 = $b
+    .label return_16 = $b
+    .label return_17 = $b
+    .label return_18 = $b
+    .label return_20 = $b
     lda v1
     sta mul16u.a
     lda v1+1
@@ -440,13 +453,13 @@ mulu16_sel: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage($13) a, word zeropage($11) b)
+// mul16u(word zeropage($11) a, word zeropage($b) b)
 mul16u: {
-    .label mb = $19
-    .label a = $13
-    .label res = $15
-    .label b = $11
-    .label return = $15
+    .label a = $11
+    .label mb = $17
+    .label res = $13
+    .label b = $b
+    .label return = $13
     lda b
     sta mb
     lda b+1
@@ -456,7 +469,9 @@ mul16u: {
     sta mb+3
     sta res
     sta res+1
+    lda #<0>>$10
     sta res+2
+    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -497,12 +512,12 @@ mul16u: {
 div32u16u: {
     .label quotient_hi = 8
     .label quotient_lo = 6
-    .label return = $1d
+    .label return = $1b
     lda #<PI2_u4f28>>$10
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #0
+    lda #<0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
@@ -585,22 +600,24 @@ divr16u: {
 // sin16s_gen(signed word* zeropage(2) sintab)
 sin16s_gen: {
     .label _1 = 6
-    .label step = $1d
+    .label step = $1b
     .label sintab = 2
     .label x = $d
     .label i = 4
     jsr div32u16u
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<main.sintab1
     sta sintab
     lda #>main.sintab1
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
+    lda #<0>>$10
     sta x+2
+    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -656,19 +673,20 @@ sin16s_gen: {
 // Calculate signed word sinus sin(x)
 // x: unsigned dword input u[4.28] in the interval $00000000 - PI2_u4f28
 // result: signed word sin(x) s[0.15] - using the full range  -$7fff - $7fff
-// sin16s(dword zeropage($15) x)
+// sin16s(dword zeropage($13) x)
 sin16s: {
-    .label _4 = $15
-    .label x = $15
+    .label _4 = $13
+    .label _20 = 6
+    .label x = $13
     .label return = 6
-    .label x1 = 8
-    .label x2 = $b
-    .label x3 = $b
-    .label x3_6 = $11
-    .label usinx = 6
-    .label x4 = $b
-    .label x5 = $11
-    .label x5_128 = $11
+    .label x1 = 6
+    .label x2 = 8
+    .label x3 = 8
+    .label x3_6 = $b
+    .label usinx = $1f
+    .label x4 = 8
+    .label x5 = $b
+    .label x5_128 = $b
     .label sinx = 6
     .label isUpper = $a
     lda x+3
@@ -815,9 +833,17 @@ sin16s: {
     lda usinx+1
     adc x5_128+1
     sta usinx+1
+    lda usinx
+    sta sinx
+    lda usinx+1
+    sta sinx+1
     lda isUpper
     cmp #0
     beq b3
+    lda usinx
+    sta _20
+    lda usinx+1
+    sta _20+1
     sec
     lda sinx
     eor #$ff
diff --git a/src/test/ref/sinusgen8.asm b/src/test/ref/sinusgen8.asm
index 9c3cdd67e..0c037f3c0 100644
--- a/src/test/ref/sinusgen8.asm
+++ b/src/test/ref/sinusgen8.asm
@@ -11,6 +11,7 @@
   .label print_char_cursor = 5
 main: {
     .label wavelength = $c0
+    .label _2 = 4
     .label sb = 4
     jsr sin8s_gen
     jsr print_cls
@@ -20,9 +21,11 @@ main: {
     sta print_char_cursor+1
     ldx #0
   b1:
+    lda sintabref,x
+    sta _2
     lda sintab2,x
     sec
-    sbc sintabref,x
+    sbc sb
     sta sb
     bmi b2
     lda #<str1
@@ -104,8 +107,10 @@ print_char: {
     rts
 }
 // Print a byte as HEX
+// print_byte(byte zeropage(4) b)
 print_byte: {
-    lda print_sbyte.b
+    .label b = 4
+    lda b
     lsr
     lsr
     lsr
@@ -114,7 +119,7 @@ print_byte: {
     lda print_hextab,y
     jsr print_char
     lda #$f
-    and print_sbyte.b
+    and b
     tay
     lda print_hextab,y
     jsr print_char
@@ -153,14 +158,14 @@ sin8s_gen: {
     .label x = 2
     .label i = 7
     jsr div16u
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<main.sintab2
     sta sintab
     lda #>main.sintab2
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
   // u[4.12]
@@ -170,6 +175,7 @@ sin8s_gen: {
     lda x+1
     sta sin8s.x+1
     jsr sin8s
+    tya
     ldy #0
     sta (sintab),y
     inc sintab
@@ -297,16 +303,17 @@ sin8s: {
     bcc b3
     dex
   b3:
+    txa
+    tay
     lda isUpper
     cmp #0
-    beq b14
+    beq b4
     txa
     eor #$ff
     clc
     adc #1
-    rts
-  b14:
-    txa
+    tay
+  b4:
     rts
 }
 // Calculate val*val for two unsigned byte values - the result is 8 selected bits of the 16-bit result.
diff --git a/src/test/ref/sinusgen8b.asm b/src/test/ref/sinusgen8b.asm
index 7ab3110de..e9cafe49a 100644
--- a/src/test/ref/sinusgen8b.asm
+++ b/src/test/ref/sinusgen8b.asm
@@ -129,8 +129,10 @@ print_char: {
     rts
 }
 // Print a byte as HEX
+// print_byte(byte zeropage(4) b)
 print_byte: {
-    lda print_sbyte.b
+    .label b = 4
+    lda b
     lsr
     lsr
     lsr
@@ -139,7 +141,7 @@ print_byte: {
     lda print_hextab,y
     jsr print_char
     lda #$f
-    and print_sbyte.b
+    and b
     tay
     lda print_hextab,y
     jsr print_char
@@ -179,17 +181,19 @@ sin16s_gen: {
     .label x = 7
     .label i = 5
     jsr div32u16u
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<main.sintabw
     sta sintab
     lda #>main.sintabw
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
+    lda #<0>>$10
     sta x+2
+    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -248,16 +252,17 @@ sin16s_gen: {
 // sin16s(dword zeropage($b) x)
 sin16s: {
     .label _4 = $b
+    .label _20 = $f
     .label x = $b
     .label return = $f
-    .label x1 = $20
-    .label x2 = $11
-    .label x3 = $11
-    .label x3_6 = $13
-    .label usinx = $f
-    .label x4 = $11
-    .label x5 = $13
-    .label x5_128 = $13
+    .label x1 = $1a
+    .label x2 = $f
+    .label x3 = $f
+    .label x3_6 = $11
+    .label usinx = $20
+    .label x4 = $f
+    .label x5 = $11
+    .label x5_128 = $11
     .label sinx = $f
     .label isUpper = 4
     lda x+3
@@ -404,9 +409,17 @@ sin16s: {
     lda usinx+1
     adc x5_128+1
     sta usinx+1
+    lda usinx
+    sta sinx
+    lda usinx+1
+    sta sinx+1
     lda isUpper
     cmp #0
     beq b3
+    lda usinx
+    sta _20
+    lda usinx+1
+    sta _20+1
     sec
     lda sinx
     eor #$ff
@@ -421,15 +434,15 @@ sin16s: {
 }
 // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result.
 // The select parameter indicates how many of the highest bits of the 32-bit result to skip
-// mulu16_sel(word zeropage($11) v1, word zeropage($13) v2, byte register(X) select)
+// mulu16_sel(word zeropage($f) v1, word zeropage($11) v2, byte register(X) select)
 mulu16_sel: {
     .label _0 = $b
     .label _1 = $b
-    .label v1 = $11
-    .label v2 = $13
-    .label return = $13
-    .label return_1 = $11
-    .label return_10 = $11
+    .label v1 = $f
+    .label v2 = $11
+    .label return = $11
+    .label return_1 = $f
+    .label return_10 = $f
     lda v1
     sta mul16u.a
     lda v1+1
@@ -452,12 +465,12 @@ mulu16_sel: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage($15) a, word zeropage($13) b)
+// mul16u(word zeropage($13) a, word zeropage($11) b)
 mul16u: {
-    .label mb = $17
-    .label a = $15
+    .label a = $13
+    .label mb = $15
     .label res = $b
-    .label b = $13
+    .label b = $11
     .label return = $b
     lda b
     sta mb
@@ -468,7 +481,9 @@ mul16u: {
     sta mb+3
     sta res
     sta res+1
+    lda #<0>>$10
     sta res+2
+    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -514,7 +529,7 @@ div32u16u: {
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #0
+    lda #<0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
@@ -601,14 +616,14 @@ sin8s_gen: {
     .label x = 2
     .label i = $11
     jsr div16u
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<main.sintabb
     sta sintab
     lda #>main.sintabb
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
   // u[4.12]
@@ -618,6 +633,7 @@ sin8s_gen: {
     lda x+1
     sta sin8s.x+1
     jsr sin8s
+    tya
     ldy #0
     sta (sintab),y
     inc sintab
@@ -745,25 +761,26 @@ sin8s: {
     bcc b3
     dex
   b3:
+    txa
+    tay
     lda isUpper
     cmp #0
-    beq b14
+    beq b4
     txa
     eor #$ff
     clc
     adc #1
-    rts
-  b14:
-    txa
+    tay
+  b4:
     rts
 }
 // Calculate val*val for two unsigned byte values - the result is 8 selected bits of the 16-bit result.
 // The select parameter indicates how many of the highest bits of the 16-bit result to skip
-// mulu8_sel(byte register(X) v1, byte register(Y) v2, byte zeropage($1b) select)
+// mulu8_sel(byte register(X) v1, byte register(Y) v2, byte zeropage($19) select)
 mulu8_sel: {
     .label _0 = $13
     .label _1 = $13
-    .label select = $1b
+    .label select = $19
     tya
     jsr mul8u
     ldy select
@@ -780,7 +797,7 @@ mulu8_sel: {
 // Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word
 // mul8u(byte register(X) a, byte register(A) b)
 mul8u: {
-    .label mb = $15
+    .label mb = $1a
     .label res = $13
     .label return = $13
     sta mb
@@ -822,7 +839,7 @@ div16u: {
     sta divr16u.dividend
     lda #>PI2_u4f12
     sta divr16u.dividend+1
-    lda #0
+    lda #<0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
diff --git a/src/test/ref/sinusgenscale8.asm b/src/test/ref/sinusgenscale8.asm
index 7cbff336f..792e19135 100644
--- a/src/test/ref/sinusgenscale8.asm
+++ b/src/test/ref/sinusgenscale8.asm
@@ -86,14 +86,14 @@ sin8u_table: {
     lda #>$400
     sta print_line_cursor+1
     jsr print_ln
-    lda #0
+    lda #<0
     sta i
     sta i+1
     lda #<main.sintab
     sta sintab
     lda #>main.sintab
     sta sintab+1
-    lda #0
+    lda #<0
     sta x
     sta x+1
   // u[4.12]
@@ -103,8 +103,7 @@ sin8u_table: {
     lda x+1
     sta sin8s.x+1
     jsr sin8s
-    sta sinx
-    tay
+    sty sinx
     jsr mul8su
     lda sinx_sc+1
     tax
@@ -327,7 +326,10 @@ mul8su: {
     .label return = $f
     tya
     tax
-    lda #b
+    lda #<b
+    sta mul8u.mb
+    lda #>b
+    sta mul8u.mb+1
     jsr mul8u
     cpy #0
     bpl b1
@@ -344,9 +346,7 @@ mul8u: {
     .label mb = $b
     .label res = $f
     .label return = $f
-    sta mb
-    lda #0
-    sta mb+1
+    lda #<0
     sta res
     sta res+1
   b1:
@@ -473,16 +473,17 @@ sin8s: {
     bcc b3
     dex
   b3:
+    txa
+    tay
     lda isUpper
     cmp #0
-    beq b14
+    beq b4
     txa
     eor #$ff
     clc
     adc #1
-    rts
-  b14:
-    txa
+    tay
+  b4:
     rts
 }
 // Calculate val*val for two unsigned byte values - the result is 8 selected bits of the 16-bit result.
@@ -493,6 +494,9 @@ mulu8_sel: {
     .label _1 = $f
     .label select = $11
     tya
+    sta mul8u.mb
+    lda #0
+    sta mul8u.mb+1
     jsr mul8u
     ldy select
     beq !e+
diff --git a/src/test/ref/sizeof-expr.asm b/src/test/ref/sizeof-expr.asm
index 1749feae1..5720d470d 100644
--- a/src/test/ref/sizeof-expr.asm
+++ b/src/test/ref/sizeof-expr.asm
@@ -6,6 +6,7 @@
   .const SIZEOF_BYTE = 1
   .const SIZEOF_WORD = 2
   .const SIZEOF_POINTER = 2
+  .const SIZEOF_NUMBER = $ff
 main: {
     .const sz = $f
     .label b = 2
@@ -15,13 +16,16 @@ main: {
     sta b
     sta w
     sta w+1
-    lda #'0'+SIZEOF_BYTE
+    //byte[] sb = { 'a', 'b', 'c', 0};
+    lda #'0'+SIZEOF_NUMBER
     sta SCREEN
+    lda #'0'+SIZEOF_BYTE
     sta SCREEN+1
     sta SCREEN+2
     sta SCREEN+3
-    lda #'0'+SIZEOF_WORD
+    lda #'0'+SIZEOF_NUMBER
     sta SCREEN+5
+    lda #'0'+SIZEOF_WORD
     sta SCREEN+6
     lda #'0'+SIZEOF_POINTER
     sta SCREEN+8
@@ -36,7 +40,5 @@ main: {
     sta SCREEN+$e
     lda #'0'+8*SIZEOF_BYTE
     sta SCREEN+$f
-    lda #'0'+$c*SIZEOF_BYTE
-    sta SCREEN+$10
     rts
 }
diff --git a/src/test/ref/test-comparisons-sword.asm b/src/test/ref/test-comparisons-sword.asm
index 426dacc95..7040fecd8 100644
--- a/src/test/ref/test-comparisons-sword.asm
+++ b/src/test/ref/test-comparisons-sword.asm
@@ -323,11 +323,13 @@ print_sword: {
     rts
 }
 // Print a word as HEX
+// print_word(word zeropage($a) w)
 print_word: {
-    lda print_sword.w+1
+    .label w = $a
+    lda w+1
     sta print_byte.b
     jsr print_byte
-    lda print_sword.w
+    lda w
     sta print_byte.b
     jsr print_byte
     rts
diff --git a/src/test/ref/test-division.asm b/src/test/ref/test-division.asm
index 6f74de8b7..d7b963748 100644
--- a/src/test/ref/test-division.asm
+++ b/src/test/ref/test-division.asm
@@ -4,8 +4,8 @@
 .pc = $80d "Program"
   .label print_char_cursor = 8
   .label print_line_cursor = 3
-  .label rem16u = $a
-  .label rem16s = $a
+  .label rem16u = $e
+  .label rem16s = $e
 main: {
     jsr print_cls
     jsr test_8u
@@ -17,7 +17,7 @@ main: {
 test_16s: {
     .label dividend = 5
     .label divisor = $13
-    .label res = $e
+    .label res = $c
     .label i = 2
     lda #0
     sta i
@@ -198,7 +198,7 @@ print_str: {
 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5
 // div16s(signed word zeropage(5) dividend, signed word zeropage($13) divisor)
 div16s: {
-    .label return = $e
+    .label return = $c
     .label dividend = 5
     .label divisor = $13
     lda dividend
@@ -217,25 +217,21 @@ div16s: {
 // Implemented using simple binary division
 // Follows the C99 standard by truncating toward zero on negative results.
 // See http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.5.5
-// divr16s(signed word zeropage(8) dividend, signed word zeropage($c) divisor)
+// divr16s(signed word zeropage(8) dividend, signed word zeropage($a) divisor)
 divr16s: {
-    .const rem = 0
     .label _8 = 8
-    .label _13 = $c
-    .label resultu = $e
-    .label return = $e
-    .label dividend = 8
-    .label divisor = $c
+    .label _13 = $a
+    .label _16 = $e
+    .label _18 = $c
     .label dividendu = 8
-    .label divisoru = $c
-    .label remu = $a
+    .label divisoru = $a
+    .label resultu = $c
+    .label return = $c
+    .label dividend = 8
+    .label divisor = $a
     lda dividend+1
     bmi b1
-    lda #rem
-    sta remu
-    lda #0
-    sta remu+1
-    tay
+    ldy #0
   b2:
     lda divisor+1
     bmi b3
@@ -287,10 +283,6 @@ divr16s: {
     eor #$ff
     adc #0
     sta _8+1
-    lda #-rem
-    sta remu
-    lda #0
-    sta remu+1
     ldy #1
     jmp b2
 }
@@ -298,17 +290,19 @@ divr16s: {
 // Returns the quotient dividend/divisor.
 // The final remainder will be set into the global variable rem16u
 // Implemented using simple binary division
-// divr16u(word zeropage(8) dividend, word zeropage($c) divisor, word zeropage($a) rem)
+// divr16u(word zeropage(8) dividend, word zeropage($a) divisor, word zeropage($e) rem)
 divr16u: {
-    .label rem = $a
+    .label rem = $e
     .label dividend = 8
-    .label quotient = $e
-    .label return = $e
-    .label divisor = $c
+    .label quotient = $c
+    .label return = $c
+    .label divisor = $a
     ldx #0
     txa
     sta quotient
     sta quotient+1
+    sta rem
+    sta rem+1
   b1:
     asl rem
     rol rem+1
@@ -446,7 +440,7 @@ div8s: {
     tay
     lda neg
     cmp #0
-    beq b9
+    beq b5
     txa
     eor #$ff
     clc
@@ -457,7 +451,7 @@ div8s: {
     clc
     adc #1
     rts
-  b9:
+  b5:
     tya
     rts
   b3:
@@ -537,8 +531,8 @@ divr8u: {
 }
 test_16u: {
     .label dividend = 5
-    .label divisor = $c
-    .label res = $e
+    .label divisor = $a
+    .label res = $c
     .label i = 2
     lda #0
     sta i
@@ -606,18 +600,15 @@ test_16u: {
 // Returns the quotient dividend/divisor.
 // The remainder will be set into the global variable rem16u
 // Implemented using simple binary division
-// div16u(word zeropage(5) dividend, word zeropage($c) divisor)
+// div16u(word zeropage(5) dividend, word zeropage($a) divisor)
 div16u: {
-    .label return = $e
+    .label return = $c
     .label dividend = 5
-    .label divisor = $c
+    .label divisor = $a
     lda dividend
     sta divr16u.dividend
     lda dividend+1
     sta divr16u.dividend+1
-    lda #0
-    sta divr16u.rem
-    sta divr16u.rem+1
     jsr divr16u
     rts
 }
diff --git a/src/test/ref/test-multiply-16bit.asm b/src/test/ref/test-multiply-16bit.asm
index e5701b8c6..e9858cdce 100644
--- a/src/test/ref/test-multiply-16bit.asm
+++ b/src/test/ref/test-multiply-16bit.asm
@@ -340,7 +340,9 @@ print_sword: {
 // mulf16s(signed word zeropage(3) a, signed word zeropage(5) b)
 mulf16s: {
     .label _9 = 9
+    .label _10 = $15
     .label _13 = 9
+    .label _14 = $15
     .label _16 = 9
     .label _17 = 9
     .label m = $11
@@ -362,12 +364,16 @@ mulf16s: {
     sta _9
     lda m+3
     sta _9+1
+    lda b
+    sta _10
+    lda b+1
+    sta _10+1
     lda _16
     sec
-    sbc b
+    sbc _10
     sta _16
     lda _16+1
-    sbc b+1
+    sbc _10+1
     sta _16+1
     lda _16
     sta m+2
@@ -380,12 +386,16 @@ mulf16s: {
     sta _13
     lda m+3
     sta _13+1
+    lda a
+    sta _14
+    lda a+1
+    sta _14+1
     lda _17
     sec
-    sbc a
+    sbc _14
     sta _17
     lda _17+1
-    sbc a+1
+    sbc _14+1
     sta _17+1
     lda _17
     sta m+2
@@ -519,21 +529,30 @@ mulf16u: {
 // mul16s(signed word zeropage(3) a, signed word zeropage(5) b)
 mul16s: {
     .label _9 = 9
+    .label _10 = $15
     .label _13 = 9
+    .label _14 = $15
     .label _16 = 9
     .label _17 = 9
     .label m = $19
     .label return = $19
     .label a = 3
     .label b = 5
-    lda b
-    sta mul16u.b
-    lda b+1
-    sta mul16u.b+1
     lda a
     sta mul16u.a
     lda a+1
     sta mul16u.a+1
+    lda b
+    sta mul16u.b
+    lda b+1
+    sta mul16u.b+1
+    lda mul16u.b
+    sta mul16u.mb
+    lda mul16u.b+1
+    sta mul16u.mb+1
+    lda #0
+    sta mul16u.mb+2
+    sta mul16u.mb+3
     jsr mul16u
     lda a+1
     bpl b1
@@ -541,12 +560,16 @@ mul16s: {
     sta _9
     lda m+3
     sta _9+1
+    lda b
+    sta _10
+    lda b+1
+    sta _10+1
     lda _16
     sec
-    sbc b
+    sbc _10
     sta _16
     lda _16+1
-    sbc b+1
+    sbc _10+1
     sta _16+1
     lda _16
     sta m+2
@@ -559,12 +582,16 @@ mul16s: {
     sta _13
     lda m+3
     sta _13+1
+    lda a
+    sta _14
+    lda a+1
+    sta _14+1
     lda _17
     sec
-    sbc a
+    sbc _14
     sta _17
     lda _17+1
-    sbc a+1
+    sbc _14+1
     sta _17+1
     lda _17
     sta m+2
@@ -574,23 +601,20 @@ mul16s: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage(9) a, word zeropage($17) b)
+// mul16u(word zeropage(9) a, word zeropage($15) b)
 mul16u: {
     .label mb = $11
     .label a = 9
     .label res = $19
+    .label b = $15
     .label return = $19
-    .label b = $17
-    lda b
-    sta mb
-    lda b+1
-    sta mb+1
-    lda #0
-    sta mb+2
-    sta mb+3
+    .label b_1 = $17
+    lda #<0
     sta res
     sta res+1
+    lda #<0>>$10
     sta res+2
+    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -643,12 +667,14 @@ muls16s: {
     lda a
     beq b5
   !:
-    lda #0
+    lda #<0
     sta j
     sta j+1
     sta m
     sta m+1
+    lda #<0>>$10
     sta m+2
+    lda #>0>>$10
     sta m+3
   b3:
     lda b+1
@@ -682,19 +708,23 @@ muls16s: {
     bne b3
     rts
   b5:
-    lda #0
+    lda #<0
     sta return
     sta return+1
+    lda #<0>>$10
     sta return+2
+    lda #>0>>$10
     sta return+3
     rts
   b6:
-    lda #0
+    lda #<0
     sta i
     sta i+1
     sta m
     sta m+1
+    lda #<0>>$10
     sta m+2
+    lda #>0>>$10
     sta m+3
   b4:
     lda b+1
@@ -774,6 +804,13 @@ mul16u_compare: {
     sta mul16u.a
     lda a+1
     sta mul16u.a+1
+    lda mul16u.b_1
+    sta mul16u.mb
+    lda mul16u.b_1+1
+    sta mul16u.mb+1
+    lda #0
+    sta mul16u.mb+2
+    sta mul16u.mb+3
     jsr mul16u
     jsr mulf16u
     lda ms
@@ -822,7 +859,9 @@ mul16u_compare: {
   b5:
     iny
     cpy #$10
-    bne b2
+    beq !b2+
+    jmp b2
+  !b2:
     inc i
     lda #$10
     cmp i
@@ -926,12 +965,14 @@ muls16u: {
     lda a+1
     beq b3
   !:
-    lda #0
+    lda #<0
     sta i
     sta i+1
     sta m
     sta m+1
+    lda #<0>>$10
     sta m+2
+    lda #>0>>$10
     sta m+3
   b2:
     lda m
@@ -959,10 +1000,12 @@ muls16u: {
     bne b2
     rts
   b3:
-    lda #0
+    lda #<0
     sta return
     sta return+1
+    lda #<0>>$10
     sta return+2
+    lda #>0>>$10
     sta return+3
     rts
 }
@@ -985,7 +1028,7 @@ mulf_init: {
     sta sqr1_lo
     lda #>mulf_sqr1_lo+1
     sta sqr1_lo+1
-    lda #0
+    lda #<0
     sta sqr
     sta sqr+1
     tax
diff --git a/src/test/ref/test-multiply-8bit.asm b/src/test/ref/test-multiply-8bit.asm
index 92b5ae098..5cf013274 100644
--- a/src/test/ref/test-multiply-8bit.asm
+++ b/src/test/ref/test-multiply-8bit.asm
@@ -267,26 +267,36 @@ print_sbyte: {
 // Fixes offsets introduced by using unsigned multiplication
 // mul8s(signed byte zeropage(2) a, signed byte register(Y) b)
 mul8s: {
+    .label _9 = $10
+    .label _13 = $10
     .label m = $c
-    .label a = 2
     .label return = $c
-    tya
+    .label a = 2
     ldx a
+    tya
+    sta mul8u.mb
+    lda #0
+    sta mul8u.mb+1
     jsr mul8u
     lda a
     cmp #0
     bpl b1
     lda m+1
-    sty $ff
+    sta _9
+    tya
+    eor #$ff
     sec
-    sbc $ff
+    adc _9
     sta m+1
   b1:
     cpy #0
     bpl b2
     lda m+1
+    sta _13
+    lda a
+    eor #$ff
     sec
-    sbc a
+    adc _13
     sta m+1
   b2:
     rts
@@ -297,9 +307,7 @@ mul8u: {
     .label mb = 6
     .label res = $c
     .label return = $c
-    sta mb
-    lda #0
-    sta mb+1
+    lda #<0
     sta res
     sta res+1
   b1:
@@ -331,34 +339,42 @@ mul8u: {
 mulf8s: {
     .label return = $e
     jsr mulf8u_prepare
-    stx mulf8s_prepared.b
+    txa
+    tay
     jsr mulf8s_prepared
     rts
 }
 // Calculate fast multiply with a prepared unsigned byte to a word result
 // The prepared number is set by calling mulf8s_prepare(byte a)
-// mulf8s_prepared(signed byte zeropage(3) b)
+// mulf8s_prepared(signed byte register(Y) b)
 mulf8s_prepared: {
     .label memA = $fd
+    .label _8 = $10
+    .label _12 = $10
     .label m = $e
-    .label b = 3
     .label return = $e
-    ldx b
+    tya
+    tax
     jsr mulf8u_prepared
     lda memA
     cmp #0
     bpl b1
     lda m+1
+    sta _8
+    tya
+    eor #$ff
     sec
-    sbc b
+    adc _8
     sta m+1
   b1:
-    lda b
-    cmp #0
+    cpy #0
     bpl b2
     lda m+1
+    sta _12
+    lda memA
+    eor #$ff
     sec
-    sbc memA
+    adc _12
     sta m+1
   b2:
     rts
@@ -411,8 +427,8 @@ muls8s: {
     bmi b6
     cmp #1
     bmi b5
-    lda #0
-    tay
+    ldy #0
+    tya
     sta m
     sta m+1
   b3:
@@ -435,13 +451,13 @@ muls8s: {
     bne b3
     rts
   b5:
-    lda #0
+    lda #<0
     sta return
     sta return+1
     rts
   b6:
-    lda #0
-    tay
+    ldy #0
+    tya
     sta m
     sta m+1
   b4:
@@ -484,6 +500,9 @@ mul8u_compare: {
     jsr mulf8u
     ldx a
     lda b
+    sta mul8u.mb
+    lda #0
+    sta mul8u.mb+1
     jsr mul8u
     lda ms
     cmp mf
@@ -615,7 +634,7 @@ muls8u: {
     bne b2
     rts
   b3:
-    lda #0
+    lda #<0
     sta return
     sta return+1
     rts
@@ -777,7 +796,7 @@ mulf_init: {
     sta sqr1_lo
     lda #>mulf_sqr1_lo+1
     sta sqr1_lo+1
-    lda #0
+    lda #<0
     sta sqr
     sta sqr+1
     tax
diff --git a/src/test/ref/test-scroll-up.asm b/src/test/ref/test-scroll-up.asm
index 15c85f776..3f11d2fd0 100644
--- a/src/test/ref/test-scroll-up.asm
+++ b/src/test/ref/test-scroll-up.asm
@@ -17,7 +17,7 @@ scrollup3: {
     .label _4 = 7
     .label _5 = 9
     .label l2_4 = 4
-    lda #0
+    lda #<0
     sta l2
     sta l2+1
   b1:
@@ -111,7 +111,7 @@ scrollup1: {
     .label line = 2
     .label _6 = 7
     .label _7 = 4
-    lda #0
+    lda #<0
     sta line
     sta line+1
   b1:
diff --git a/src/test/ref/test-signed-word-minus-byte.asm b/src/test/ref/test-signed-word-minus-byte.asm
index 7323f8d14..44e686934 100644
--- a/src/test/ref/test-signed-word-minus-byte.asm
+++ b/src/test/ref/test-signed-word-minus-byte.asm
@@ -22,19 +22,33 @@ main: {
     lda #>$4d2
     sta w1+1
   b1:
+    lda #$5b
+    sta $fe
+    ora #$7f
+    bmi !+
+    lda #0
+  !:
+    sta $ff
     sec
     lda w1
-    sbc #$5b
+    sbc $fe
     sta w2
     lda w1+1
-    sbc #0
+    sbc $ff
     sta w2+1
+    lda #$29
+    sta $fe
+    ora #$7f
+    bmi !+
+    lda #0
+  !:
+    sta $ff
     sec
     lda w2
-    sbc #$29
+    sbc $fe
     sta w1
     lda w2+1
-    sbc #0
+    sbc $ff
     sta w1+1
     lda w1
     sta print_sword.w
@@ -102,11 +116,13 @@ print_sword: {
     rts
 }
 // Print a word as HEX
+// print_word(word zeropage(6) w)
 print_word: {
-    lda print_sword.w+1
+    .label w = 6
+    lda w+1
     sta print_byte.b
     jsr print_byte
-    lda print_sword.w
+    lda w
     sta print_byte.b
     jsr print_byte
     rts
diff --git a/src/test/ref/test-word-size-arrays.asm b/src/test/ref/test-word-size-arrays.asm
index 34f29fa59..7a768dfdd 100644
--- a/src/test/ref/test-word-size-arrays.asm
+++ b/src/test/ref/test-word-size-arrays.asm
@@ -10,7 +10,7 @@ main: {
     .label _8 = 6
     .label _9 = 4
     .label _10 = 4
-    lda #0
+    lda #<0
     sta line
     sta line+1
   b1:
diff --git a/src/test/ref/true-inline-words.asm b/src/test/ref/true-inline-words.asm
index 4dd088582..f8a2b1d7e 100644
--- a/src/test/ref/true-inline-words.asm
+++ b/src/test/ref/true-inline-words.asm
@@ -8,10 +8,12 @@ main: {
     .label pos = $501
     .label bgcol = $d021
     .const w = b*$100
-    .const w2 = 1*$100+1+w+0
+    .const w2 = 1*$100+1+w
+    // constant inline words inside expression
+    .label sc = w2
     // implicit cast to (byte*)
     lda bs+1
-    sta w2
+    sta sc
     lda #'m'
     cmp pos
     beq b1
diff --git a/src/test/ref/type-inference.asm b/src/test/ref/type-inference.asm
new file mode 100644
index 000000000..50476c017
--- /dev/null
+++ b/src/test/ref/type-inference.asm
@@ -0,0 +1,23 @@
+// Test inference of integer types in expressions
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    .label b = 2
+    lda #0
+    sta b
+  b1:
+    lax b
+    axs #-[-$30]
+    lda b
+    asl
+    tay
+    txa
+    sta screen,y
+    inc b
+    lda #$15
+    cmp b
+    bne b1
+    rts
+}
diff --git a/src/test/ref/type-mix.asm b/src/test/ref/type-mix.asm
index 8a32fe08f..f9d20ad6c 100644
--- a/src/test/ref/type-mix.asm
+++ b/src/test/ref/type-mix.asm
@@ -10,13 +10,20 @@ main: {
     sta w
     sta w+1
   b1:
+    lda #$c
+    sta $fe
+    ora #$7f
+    bmi !+
+    lda #0
+  !:
+    sta $ff
     sec
     lda w
-    sbc #$c
+    sbc $fe
     sta w
-    bcs !+
-    dec w+1
-  !:
+    lda w+1
+    sbc $ff
+    sta w+1
     lda w
     sta SCREEN,x
     inx
diff --git a/src/test/ref/typeid-plus-bytes.asm b/src/test/ref/typeid-plus-bytes.asm
index 3678d2e5c..5bd605bdd 100644
--- a/src/test/ref/typeid-plus-bytes.asm
+++ b/src/test/ref/typeid-plus-bytes.asm
@@ -5,36 +5,125 @@
   .const TYPEID_BYTE = 1
   .const TYPEID_SIGNED_BYTE = 2
   .label SCREEN = $400
+  .label SSCREEN = $400
 main: {
     jsr testUnsigned
+    jsr testUnsignedVals
     jsr testSigned
+    jsr testSignedVals
+    rts
+}
+testSignedVals: {
+    .const sbc1 = -$78
+    .label sbv1 = 5
+    lda #-$78
+    sta sbv1
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28
+    lda #sbc1
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1
+    lda sbv1
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1
+    lda #-$46+-$32
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1
+    lda #sbc1+-$78
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1
+    lda #-$78+sbc1
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1
+    lda #-$78
+    clc
+    adc sbv1
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1
+    lda #-$78
+    clc
+    adc sbv1
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1
+    lda #sbc1
+    clc
+    adc sbv1
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1
+    lda #sbc1
+    clc
+    adc sbv1
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1
+    lda sbv1
+    asl
+    sta SSCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1
     rts
 }
 testSigned: {
-    .label sbv1 = 3
-    lda #$13
+    .label sbv1 = 4
+    lda #-$78
     sta sbv1
+    lda #0
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28
     lda #TYPEID_SIGNED_BYTE
-    sta SCREEN+$28
-    sta SCREEN+$29
-    sta SCREEN+$2a
-    sta SCREEN+$2b
-    sta SCREEN+$2c
-    sta SCREEN+$2d
-    sta SCREEN+$2e
-    sta SCREEN+$2f
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1
+    lda #0
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1
+    lda #TYPEID_SIGNED_BYTE
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1+1+$28+1+1+1+1+1+1+1+1+1+1
+    rts
+}
+testUnsignedVals: {
+    .const ubc1 = $fa
+    .label ubv1 = 3
+    lda #$fa
+    sta ubv1
+    sta SCREEN+$b+$28
+    lda #ubc1
+    sta SCREEN+$b+$28+1
+    lda ubv1
+    sta SCREEN+$b+$28+1+1
+    lda #$78+$82
+    sta SCREEN+$b+$28+1+1+1
+    lda #ubc1+$fa
+    sta SCREEN+$b+$28+1+1+1+1
+    lda #$fa+ubc1
+    sta SCREEN+$b+$28+1+1+1+1+1
+    lax ubv1
+    axs #-[$fa]
+    stx SCREEN+$b+$28+1+1+1+1+1+1
+    lax ubv1
+    axs #-[$fa]
+    stx SCREEN+$b+$28+1+1+1+1+1+1+1
+    lda #ubc1
+    clc
+    adc ubv1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1
+    lda #ubc1
+    clc
+    adc ubv1
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1
+    lda ubv1
+    asl
+    sta SCREEN+$b+$28+1+1+1+1+1+1+1+1+1+1
     rts
 }
 testUnsigned: {
     .label ubv1 = 2
-    lda #$5b
+    lda #$fa
     sta ubv1
-    lda #TYPEID_BYTE
+    lda #0
     sta SCREEN
+    lda #TYPEID_BYTE
     sta SCREEN+1
     sta SCREEN+2
+    lda #0
     sta SCREEN+3
+    lda #TYPEID_BYTE
     sta SCREEN+4
     sta SCREEN+5
+    sta SCREEN+6
+    sta SCREEN+7
+    sta SCREEN+8
+    sta SCREEN+9
+    sta SCREEN+$a
     rts
 }
diff --git a/src/test/ref/uninitialized.asm b/src/test/ref/uninitialized.asm
index dd22c0239..24dc22e36 100644
--- a/src/test/ref/uninitialized.asm
+++ b/src/test/ref/uninitialized.asm
@@ -3,19 +3,14 @@
 :BasicUpstart(main)
 .pc = $80d "Program"
   .const b = 0
-  .const w = 0
-  .label ptr = 0
   .label SCREEN = $400
 main: {
     lda #b
     sta SCREEN
-    lda #<w
+    lda #0
     sta SCREEN+2
-    lda #>w
     sta SCREEN+3
-    lda #<ptr
     sta SCREEN+5
-    lda #>ptr
     sta SCREEN+5
     rts
 }
diff --git a/src/test/ref/valuelist-error.asm b/src/test/ref/valuelist-error.asm
new file mode 100644
index 000000000..eb9744a46
--- /dev/null
+++ b/src/test/ref/valuelist-error.asm
@@ -0,0 +1,10 @@
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    .const w = -1*$100+-1
+    lda #<w
+    sta screen
+    rts
+}

From eed40184501664cb80f5b147525cd42716504ba8 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 22:07:16 +0200
Subject: [PATCH 44/93] Added a blitter box

---
 .../dk/camelot64/kickc/test/TestPrograms.java |  5 ++
 src/test/kc/c64dtv-blitter-box.kc             | 57 +++++++++++++++++++
 src/test/kc/c64dtv-blittermin.kc              | 12 ++--
 3 files changed, 68 insertions(+), 6 deletions(-)
 create mode 100644 src/test/kc/c64dtv-blitter-box.kc

diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 7a4ea6db5..508e25cee 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -1230,6 +1230,11 @@ public class TestPrograms {
       compileAndCompare("c64dtv-blittermin");
    }
 
+   @Test
+   public void testC64DtvBlitterBox() throws IOException, URISyntaxException {
+      compileAndCompare("c64dtv-blitter-box");
+   }
+
    @Test
    public void testC64Dtv8bppChunkyStretch() throws IOException, URISyntaxException {
       compileAndCompare("c64dtv-8bppchunkystretch");
diff --git a/src/test/kc/c64dtv-blitter-box.kc b/src/test/kc/c64dtv-blitter-box.kc
new file mode 100644
index 000000000..df9ab614f
--- /dev/null
+++ b/src/test/kc/c64dtv-blitter-box.kc
@@ -0,0 +1,57 @@
+// Fill a box on the screen using the blitter
+
+import "c64dtv.kc"
+
+const byte* SCREEN = $400;
+const byte[] SRCA = "camelot rules!";
+const byte[] SRCB = { $80 };
+
+void main() {
+
+    *DTV_FEATURE = DTV_FEATURE_ENABLE;
+
+    // Instruct blitter not to continue previous blit
+    *DTV_BLITTER_CONTROL2 = DTV_BLIT_CLEAR_IRQ;
+
+    *DTV_BLITTER_SRCA_LO = <SRCA;
+    *DTV_BLITTER_SRCA_MI = >SRCA;
+    *DTV_BLITTER_SRCA_HI = 0;
+    *DTV_BLITTER_SRCA_MOD_LO = 0;
+    *DTV_BLITTER_SRCA_MOD_HI = 0;
+    *DTV_BLITTER_SRCA_LIN_LO = <$100uw;
+    *DTV_BLITTER_SRCA_LIN_HI = >$100uw;
+    *DTV_BLITTER_SRCA_STEP = 01; // Step 0.0
+
+    *DTV_BLITTER_SRCB_LO = <SRCB;
+    *DTV_BLITTER_SRCB_MI = >SRCB;
+    *DTV_BLITTER_SRCB_HI = 0;
+    *DTV_BLITTER_SRCB_MOD_LO = 0;
+    *DTV_BLITTER_SRCB_MOD_HI = 0;
+    *DTV_BLITTER_SRCB_LIN_LO = <$100uw;
+    *DTV_BLITTER_SRCB_LIN_HI = >$100uw;
+    *DTV_BLITTER_SRCB_STEP = $00; // Step 0.0
+
+    *DTV_BLITTER_DEST_LO = <SCREEN+40+5;
+    *DTV_BLITTER_DEST_MI = >SCREEN+40+5;
+    *DTV_BLITTER_DEST_HI = 0;
+    *DTV_BLITTER_DEST_MOD_LO = <21uw;
+    *DTV_BLITTER_DEST_MOD_HI = >21uw;
+    *DTV_BLITTER_DEST_LIN_LO = <19uw;
+    *DTV_BLITTER_DEST_LIN_HI = >19uw;
+    *DTV_BLITTER_DEST_STEP = $10; // Step 1.0
+
+    *DTV_BLITTER_LEN_LO = <20*10uw;
+    *DTV_BLITTER_LEN_HI = >20*10uw;
+
+    *DTV_BLITTER_ALU = DTV_BLIT_ADD;
+    *DTV_BLITTER_TRANSPARANCY = DTV_BLIT_TRANSPARANCY_NONE;
+
+    // Start blitter
+    *DTV_BLITTER_CONTROL = DTV_BLIT_FORCE_START | DTV_BLIT_SRCA_FWD | DTV_BLIT_SRCB_FWD| DTV_BLIT_DEST_FWD;
+    // Instruct blitter to continue at DEST and restart SRC A/B
+    *DTV_BLITTER_CONTROL2 = DTV_BLIT_DEST_CONT;
+
+     // wait til blitter is ready
+     do {} while((*DTV_BLITTER_CONTROL2 & DTV_BLIT_STATUS_BUSY)!=0);
+
+}
\ No newline at end of file
diff --git a/src/test/kc/c64dtv-blittermin.kc b/src/test/kc/c64dtv-blittermin.kc
index ee0002776..ffc43fa90 100644
--- a/src/test/kc/c64dtv-blittermin.kc
+++ b/src/test/kc/c64dtv-blittermin.kc
@@ -17,8 +17,8 @@ void main() {
     *DTV_BLITTER_SRCA_HI = 0;
     *DTV_BLITTER_SRCA_MOD_LO = 0;
     *DTV_BLITTER_SRCA_MOD_HI = 0;
-    *DTV_BLITTER_SRCA_LIN_LO = <$100;
-    *DTV_BLITTER_SRCA_LIN_HI = >$100;
+    *DTV_BLITTER_SRCA_LIN_LO = <$100uw;
+    *DTV_BLITTER_SRCA_LIN_HI = >$100uw;
     *DTV_BLITTER_SRCA_STEP = $10; // Step 1.0
 
     *DTV_BLITTER_SRCB_LO = <SRCB;
@@ -26,8 +26,8 @@ void main() {
     *DTV_BLITTER_SRCB_HI = 0;
     *DTV_BLITTER_SRCB_MOD_LO = 0;
     *DTV_BLITTER_SRCB_MOD_HI = 0;
-    *DTV_BLITTER_SRCB_LIN_LO = <$100;
-    *DTV_BLITTER_SRCB_LIN_HI = >$100;
+    *DTV_BLITTER_SRCB_LIN_LO = <$100uw;
+    *DTV_BLITTER_SRCB_LIN_HI = >$100uw;
     *DTV_BLITTER_SRCB_STEP = $00; // Step 0.0
 
     *DTV_BLITTER_DEST_LO = <SCREEN;
@@ -35,8 +35,8 @@ void main() {
     *DTV_BLITTER_DEST_HI = 0;
     *DTV_BLITTER_DEST_MOD_LO = 0;
     *DTV_BLITTER_DEST_MOD_HI = 0;
-    *DTV_BLITTER_DEST_LIN_LO = <$100;
-    *DTV_BLITTER_DEST_LIN_HI = >$100;
+    *DTV_BLITTER_DEST_LIN_LO = <$100uw;
+    *DTV_BLITTER_DEST_LIN_HI = >$100uw;
     *DTV_BLITTER_DEST_STEP = $10; // Step 1.0
 
     *DTV_BLITTER_LEN_LO = SRCA_LEN;

From abfa6f875f640f337abdcb51bbc8716c7b4ce348 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 22:40:46 +0200
Subject: [PATCH 45/93] Added a few tests

---
 .../dk/camelot64/kickc/test/TestPrograms.java |   5 +
 src/test/kc/number-inference-sum.kc           |  16 ++
 src/test/ref/c64dtv-blitter-box.asm           | 148 ++++++++++++++++++
 src/test/ref/number-inference-sum.asm         |  20 +++
 4 files changed, 189 insertions(+)
 create mode 100644 src/test/kc/number-inference-sum.kc
 create mode 100644 src/test/ref/c64dtv-blitter-box.asm
 create mode 100644 src/test/ref/number-inference-sum.asm

diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 508e25cee..112535fab 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,11 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testNumberInferenceSum() throws IOException, URISyntaxException {
+      compileAndCompare("number-inference-sum");
+   }
+
    @Test
    public void testGfxBankOptimization() throws IOException, URISyntaxException {
       compileAndCompare("gfxbank");
diff --git a/src/test/kc/number-inference-sum.kc b/src/test/kc/number-inference-sum.kc
new file mode 100644
index 000000000..b0aa72f6a
--- /dev/null
+++ b/src/test/kc/number-inference-sum.kc
@@ -0,0 +1,16 @@
+// Test inference of number types using a long sum
+// Currently fails - because the compiler does not handle byte+byte correctly (not truncating the result to 8 bits)
+
+void main() {
+    const word* screen = 0x0400;
+    const byte* bgcol = 0xd020;
+    const byte RED = 2;
+
+    byte b1 = 250;
+    byte b2 = b1+250;
+    word w = b2+1;
+    screen[0] = w;
+
+    if((w)>255) *bgcol = RED;
+
+}
\ No newline at end of file
diff --git a/src/test/ref/c64dtv-blitter-box.asm b/src/test/ref/c64dtv-blitter-box.asm
new file mode 100644
index 000000000..36d9a9a77
--- /dev/null
+++ b/src/test/ref/c64dtv-blitter-box.asm
@@ -0,0 +1,148 @@
+// Fill a box on the screen using the blitter
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  // Feature enables or disables the extra C64 DTV features
+  .label DTV_FEATURE = $d03f
+  .const DTV_FEATURE_ENABLE = 1
+  // Blitter Source A Start
+  .label DTV_BLITTER_SRCA_LO = $d320
+  .label DTV_BLITTER_SRCA_MI = $d321
+  .label DTV_BLITTER_SRCA_HI = $d322
+  // Blitter Source A Modulo
+  .label DTV_BLITTER_SRCA_MOD_LO = $d323
+  .label DTV_BLITTER_SRCA_MOD_HI = $d324
+  // Blitter Source A Line Length
+  .label DTV_BLITTER_SRCA_LIN_LO = $d325
+  .label DTV_BLITTER_SRCA_LIN_HI = $d326
+  // Blitter Source A Step ([7:4] integral part, [3:0] fractional part)
+  .label DTV_BLITTER_SRCA_STEP = $d327
+  // Blitter Source B Start
+  .label DTV_BLITTER_SRCB_LO = $d328
+  .label DTV_BLITTER_SRCB_MI = $d329
+  .label DTV_BLITTER_SRCB_HI = $d32a
+  // Blitter Source B Modulo
+  .label DTV_BLITTER_SRCB_MOD_LO = $d32b
+  .label DTV_BLITTER_SRCB_MOD_HI = $d32c
+  // Blitter Source B Line Length
+  .label DTV_BLITTER_SRCB_LIN_LO = $d32d
+  .label DTV_BLITTER_SRCB_LIN_HI = $d32e
+  // Blitter Source B Step ([7:4] integral part, [3:0] fractional part)
+  .label DTV_BLITTER_SRCB_STEP = $d32f
+  // Blitter Destination Start
+  .label DTV_BLITTER_DEST_LO = $d330
+  .label DTV_BLITTER_DEST_MI = $d331
+  .label DTV_BLITTER_DEST_HI = $d332
+  // Blitter Source B Modulo
+  .label DTV_BLITTER_DEST_MOD_LO = $d333
+  .label DTV_BLITTER_DEST_MOD_HI = $d334
+  // Blitter Source B Line Length
+  .label DTV_BLITTER_DEST_LIN_LO = $d335
+  .label DTV_BLITTER_DEST_LIN_HI = $d336
+  // Blitter Source B Step ([7:4] integral part, [3:0] fractional part)
+  .label DTV_BLITTER_DEST_STEP = $d337
+  // Blitter Blit Length
+  .label DTV_BLITTER_LEN_LO = $d338
+  .label DTV_BLITTER_LEN_HI = $d339
+  // Blitter Control
+  .label DTV_BLITTER_CONTROL = $d33a
+  // Bit[0] Force Start Strobe when set
+  .const DTV_BLIT_FORCE_START = 1
+  // Bit[1] Source A Direction Positive when set
+  .const DTV_BLIT_SRCA_FWD = 2
+  // Bit[2] Source B Direction Positive when set
+  .const DTV_BLIT_SRCB_FWD = 4
+  // Bit[3] Destination Direction Positive when set
+  .const DTV_BLIT_DEST_FWD = 8
+  // Blitter Transparency
+  .label DTV_BLITTER_TRANSPARANCY = $d33b
+  // No transparancy
+  // Bit[2]==Bit[1]==0: write in any case
+  .const DTV_BLIT_TRANSPARANCY_NONE = 0
+  // Controls the ALU operation
+  .label DTV_BLITTER_ALU = $d33e
+  .const DTV_BLIT_ADD = $30
+  // Blitter Control 2
+  .label DTV_BLITTER_CONTROL2 = $d33f
+  // Bit[0] Clear Blitter IRQ
+  .const DTV_BLIT_CLEAR_IRQ = 1
+  // Bit[3] Destination Continue
+  .const DTV_BLIT_DEST_CONT = 8
+  // Bit[0] Busy when set (When reading)
+  .const DTV_BLIT_STATUS_BUSY = 1
+  .label SCREEN = $400
+main: {
+    lda #DTV_FEATURE_ENABLE
+    sta DTV_FEATURE
+    // Instruct blitter not to continue previous blit
+    lda #DTV_BLIT_CLEAR_IRQ
+    sta DTV_BLITTER_CONTROL2
+    lda #<SRCA
+    sta DTV_BLITTER_SRCA_LO
+    lda #>SRCA
+    sta DTV_BLITTER_SRCA_MI
+    lda #0
+    sta DTV_BLITTER_SRCA_HI
+    sta DTV_BLITTER_SRCA_MOD_LO
+    sta DTV_BLITTER_SRCA_MOD_HI
+    sta DTV_BLITTER_SRCA_LIN_LO
+    lda #>$100
+    sta DTV_BLITTER_SRCA_LIN_HI
+    lda #1
+    sta DTV_BLITTER_SRCA_STEP
+    // Step 0.0
+    lda #<SRCB
+    sta DTV_BLITTER_SRCB_LO
+    lda #>SRCB
+    sta DTV_BLITTER_SRCB_MI
+    lda #0
+    sta DTV_BLITTER_SRCB_HI
+    sta DTV_BLITTER_SRCB_MOD_LO
+    sta DTV_BLITTER_SRCB_MOD_HI
+    sta DTV_BLITTER_SRCB_LIN_LO
+    lda #>$100
+    sta DTV_BLITTER_SRCB_LIN_HI
+    lda #0
+    sta DTV_BLITTER_SRCB_STEP
+    // Step 0.0
+    lda #<SCREEN+$28+5
+    sta DTV_BLITTER_DEST_LO
+    lda #>SCREEN+$28+5
+    sta DTV_BLITTER_DEST_MI
+    lda #0
+    sta DTV_BLITTER_DEST_HI
+    lda #<$15
+    sta DTV_BLITTER_DEST_MOD_LO
+    lda #0
+    sta DTV_BLITTER_DEST_MOD_HI
+    lda #<$13
+    sta DTV_BLITTER_DEST_LIN_LO
+    lda #0
+    sta DTV_BLITTER_DEST_LIN_HI
+    lda #$10
+    sta DTV_BLITTER_DEST_STEP
+    // Step 1.0
+    lda #<$14*$a
+    sta DTV_BLITTER_LEN_LO
+    lda #0
+    sta DTV_BLITTER_LEN_HI
+    lda #DTV_BLIT_ADD
+    sta DTV_BLITTER_ALU
+    lda #DTV_BLIT_TRANSPARANCY_NONE
+    sta DTV_BLITTER_TRANSPARANCY
+    // Start blitter
+    lda #DTV_BLIT_FORCE_START|DTV_BLIT_SRCA_FWD|DTV_BLIT_SRCB_FWD|DTV_BLIT_DEST_FWD
+    sta DTV_BLITTER_CONTROL
+    // Instruct blitter to continue at DEST and restart SRC A/B
+    lda #DTV_BLIT_DEST_CONT
+    sta DTV_BLITTER_CONTROL2
+  // wait til blitter is ready
+  b1:
+    lda #DTV_BLIT_STATUS_BUSY
+    and DTV_BLITTER_CONTROL2
+    cmp #0
+    bne b1
+    rts
+}
+  SRCA: .text "camelot rules!@"
+  SRCB: .byte $80
diff --git a/src/test/ref/number-inference-sum.asm b/src/test/ref/number-inference-sum.asm
new file mode 100644
index 000000000..9715ba4f5
--- /dev/null
+++ b/src/test/ref/number-inference-sum.asm
@@ -0,0 +1,20 @@
+// Test inference of number types using a long sum
+// Currently fails - because the compiler does not handle byte+byte correctly (not truncating the result to 8 bits)
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    .label bgcol = $d020
+    .const RED = 2
+    .const b1 = $fa
+    .const b2 = b1+$fa
+    .const w = b2+1
+    lda #<w
+    sta screen
+    lda #>w
+    sta screen+1
+    lda #RED
+    sta bgcol
+    rts
+}

From b5a9d4747233210c3c68eef3f7622d14ca3351d1 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 23:58:04 +0200
Subject: [PATCH 46/93] Improved code by avoiding unnecesary casts

---
 ...uxx.asm => pwuc1_derefidx_vbuaa=vbuxx.asm} |   0
 ...uaa.asm => pwuc1_derefidx_vbuxx=vbuaa.asm} |   0
 .../fragment/pwuc1_derefidx_vbuyy=vbuaa.asm   |   3 +
 src/main/fragment/vduz1=vwuz2.asm             |   7 +
 .../java/dk/camelot64/kickc/Compiler.java     |   4 -
 .../model/types/SymbolTypeConversion.java     |   3 +-
 .../passes/Pass2FixInlineConstructors.java    | 132 ------------------
 .../kickc/passes/Pass2NopCastElimination.java |  87 ------------
 .../kickc/passes/Pass3AddAssignmentCasts.java |  41 ------
 .../kickc/passes/Pass3PhiMemCoalesce.java     |  13 +-
 .../dk/camelot64/kickc/test/TestPrograms.java |   5 +
 src/test/kc/mul8u-min.kc                      |  14 ++
 src/test/ref/bresenhamarr.asm                 |   2 +-
 src/test/ref/c64dtv-8bppchunkystretch.asm     |   2 +-
 src/test/ref/c64dtv-blittermin.asm            |   3 +-
 src/test/ref/complex/tetris/tetris.asm        |   3 -
 src/test/ref/derefidx-word-0.asm              |   2 +-
 src/test/ref/examples/3d/perspective.asm      |   4 +-
 .../ref/examples/chargen/chargen-analysis.asm |   5 +-
 src/test/ref/examples/fire/fire.asm           |   2 +-
 .../multiplexer/simple-multiplexer.asm        |   6 +-
 .../ref/examples/plasma/plasma-unroll.asm     |   2 +-
 src/test/ref/examples/plasma/plasma.asm       |   2 +-
 src/test/ref/examples/rotate/rotate.asm       |   2 +-
 .../ref/examples/scrolllogo/scrolllogo.asm    |  52 ++++---
 .../ref/examples/sinplotter/sine-plotter.asm  |  62 ++++----
 .../ref/examples/sinsprites/sinus-sprites.asm |   4 +-
 src/test/ref/forrangedwords.asm               |   2 +-
 src/test/ref/fragment-variations.asm          |  10 +-
 src/test/ref/linegen.asm                      |  16 +--
 src/test/ref/liverange-call-problem.asm       |   4 +-
 src/test/ref/min-fmul-16.asm                  |   2 +-
 .../simple-multiplexer-irq.asm                |   6 +-
 src/test/ref/roll-sprite-msb.asm              |   6 +-
 src/test/ref/scan-desire-problem.asm          |   6 +-
 src/test/ref/semi-struct-2.asm                |   5 +-
 src/test/ref/signed-words.asm                 |  12 +-
 src/test/ref/sinus-basic.asm                  |   4 +-
 src/test/ref/sinusgen16.asm                   |  10 +-
 src/test/ref/sinusgen16b.asm                  |  16 +--
 src/test/ref/sinusgen8.asm                    |   4 +-
 src/test/ref/sinusgen8b.asm                   |  16 +--
 src/test/ref/sinusgenscale8.asm               |  10 +-
 src/test/ref/test-multiply-16bit.asm          |  32 ++---
 src/test/ref/test-multiply-8bit.asm           |   8 +-
 src/test/ref/test-scroll-up.asm               |   4 +-
 src/test/ref/test-word-size-arrays.asm        |   2 +-
 47 files changed, 185 insertions(+), 452 deletions(-)
 rename src/main/fragment/{pwuc1_derefidx_vbuaa=_word_vbuxx.asm => pwuc1_derefidx_vbuaa=vbuxx.asm} (100%)
 rename src/main/fragment/{pwuc1_derefidx_vbuxx=_word_vbuaa.asm => pwuc1_derefidx_vbuxx=vbuaa.asm} (100%)
 create mode 100644 src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm
 create mode 100644 src/main/fragment/vduz1=vwuz2.asm
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java
 create mode 100644 src/test/kc/mul8u-min.kc

diff --git a/src/main/fragment/pwuc1_derefidx_vbuaa=_word_vbuxx.asm b/src/main/fragment/pwuc1_derefidx_vbuaa=vbuxx.asm
similarity index 100%
rename from src/main/fragment/pwuc1_derefidx_vbuaa=_word_vbuxx.asm
rename to src/main/fragment/pwuc1_derefidx_vbuaa=vbuxx.asm
diff --git a/src/main/fragment/pwuc1_derefidx_vbuxx=_word_vbuaa.asm b/src/main/fragment/pwuc1_derefidx_vbuxx=vbuaa.asm
similarity index 100%
rename from src/main/fragment/pwuc1_derefidx_vbuxx=_word_vbuaa.asm
rename to src/main/fragment/pwuc1_derefidx_vbuxx=vbuaa.asm
diff --git a/src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm b/src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm
new file mode 100644
index 000000000..355a5914f
--- /dev/null
+++ b/src/main/fragment/pwuc1_derefidx_vbuyy=vbuaa.asm
@@ -0,0 +1,3 @@
+sta {c1},y
+lda #0
+sta {c1}+1,y
diff --git a/src/main/fragment/vduz1=vwuz2.asm b/src/main/fragment/vduz1=vwuz2.asm
new file mode 100644
index 000000000..7d25095ee
--- /dev/null
+++ b/src/main/fragment/vduz1=vwuz2.asm
@@ -0,0 +1,7 @@
+lda {z2}
+sta {z1}
+lda {z2}+1
+sta {z1}+1
+lda #0
+sta {z1}+2
+sta {z1}+3
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index b5dd695b3..4dc3c79f5 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -252,16 +252,13 @@ public class Compiler {
       optimizations.add(new Pass2ConstantValues(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
-      //optimizations.add(new Pass2ConstantAdditionElimination(program));
       optimizations.add(new Pass2ConstantIfs(program));
       optimizations.add(new Pass2ConstantStringConsolidation(program));
-      //optimizations.add(new Pass2FixInlineConstructors(program));
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
       optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new Pass2TypeInference(program));
       optimizations.add(new PassNEliminateUnusedVars(program, true));
       optimizations.add(new Pass2EliminateRedundantCasts(program));
-      //optimizations.add(new Pass2NopCastElimination(program));
       optimizations.add(new Pass2EliminateUnusedBlocks(program));
       optimizations.add(new Pass2RangeResolving(program));
       optimizations.add(new Pass2ComparisonOptimization(program));
@@ -386,7 +383,6 @@ public class Compiler {
       new Pass3AssertConstants(program).check();
       new Pass3AssertArrayLengths(program).check();
       new Pass3AssertNoMulDivMod(program).check();
-      new Pass3AddAssignmentCasts(program).execute();
       new PassNCastSimplification(program).execute();
       new PassNBlockSequencePlanner(program).step();
       // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index df8ec8b90..02b96b28c 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -202,7 +202,8 @@ public class SymbolTypeConversion {
          return false;
       else
       return true;
-
    }
 
+
+
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
deleted file mode 100644
index e13b30941..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructors.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.Comment;
-import dk.camelot64.kickc.model.ControlFlowBlock;
-import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.iterator.ProgramValue;
-import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
-import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
-import dk.camelot64.kickc.model.operators.Operator;
-import dk.camelot64.kickc.model.operators.Operators;
-import dk.camelot64.kickc.model.statements.Statement;
-import dk.camelot64.kickc.model.statements.StatementAssignment;
-import dk.camelot64.kickc.model.symbols.Scope;
-import dk.camelot64.kickc.model.symbols.VariableIntermediate;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeArray;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
-import dk.camelot64.kickc.model.values.Value;
-import dk.camelot64.kickc.model.values.ValueList;
-
-import java.util.ListIterator;
-
-/**
- * Identifies word constructors <code>{ b1, b2 }</code> and replaces
- * them with a binary operator <code>word w = b1 w= b2 ;</code>
- */
-public class Pass2FixInlineConstructors extends Pass2SsaOptimization {
-
-   public Pass2FixInlineConstructors(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      WordConstructor wordConstructor = new WordConstructor();
-      ProgramValueIterator.execute(getGraph(), wordConstructor);
-      DWordConstructor dwordConstructor = new DWordConstructor();
-      ProgramValueIterator.execute(getGraph(), dwordConstructor);
-      return wordConstructor.isOptimized() || dwordConstructor.isOptimized();
-   }
-
-   /** Replaces { b1, b2 } with a w= operator */
-   private class WordConstructor extends InlineConstructor {
-
-      public WordConstructor() {
-         super(SymbolType.WORD, Operators.WORD);
-      }
-
-      @Override
-      protected boolean isSubType(SymbolType elmType) {
-         return SymbolType.BYTE.equals(elmType);
-      }
-   }
-
-   /** Replaces { w1, w2 } with a dw= operator */
-   private class DWordConstructor extends InlineConstructor {
-
-      public DWordConstructor() {
-         super(SymbolType.DWORD, Operators.DWORD);
-      }
-
-      @Override
-      protected boolean isSubType(SymbolType elmType) {
-         return SymbolType.WORD.equals(elmType);
-      }
-   }
-
-
-   private abstract class InlineConstructor implements ProgramValueHandler {
-      private SymbolTypeIntegerFixed constructType;
-      private Operator constructOperator;
-      private boolean optimized;
-
-      public InlineConstructor(SymbolTypeIntegerFixed constructType, Operator constructOperator) {
-         this.constructType = constructType;
-         this.constructOperator = constructOperator;
-      }
-
-      protected abstract boolean isSubType(SymbolType elmType);
-
-      public boolean isOptimized() {
-         return optimized;
-      }
-
-      @Override
-      public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
-         Value rValue = programValue.get();
-         if(rValue instanceof ValueList) {
-            ValueList list = (ValueList) rValue;
-            if(list.getList().size() == 2) {
-               // We have a simple assignment of a length 2 value list to a variable
-               SymbolType elmType1 = SymbolTypeInference.inferType(Pass2FixInlineConstructors.this.getScope(), list.getList().get(0));
-               SymbolType elmType2 = SymbolTypeInference.inferType(Pass2FixInlineConstructors.this.getScope(), list.getList().get(1));
-               if(isSubType(elmType1) && isSubType(elmType2)) {
-                  // We have a 2-element list { byte, byte }
-
-                  // Check if we are assigning into a declared byte array
-                  if(currentStmt instanceof StatementAssignment) {
-                     StatementAssignment assignment = (StatementAssignment) currentStmt;
-                     if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2().equals(rValue)) {
-                        SymbolType lType = SymbolTypeInference.inferType(Pass2FixInlineConstructors.this.getScope(), assignment.getlValue());
-                        if(lType instanceof SymbolTypeArray && isSubType(((SymbolTypeArray) lType).getElementType())) {
-                           // We are assigning into a declared byte array - do not convert!
-                           return;
-                        }
-                     }
-                  }
-
-                  // Convert list to a word constructor in a new tmp variable
-                  Scope currentScope = Pass2FixInlineConstructors.this.getScope().getScope(currentBlock.getScope());
-                  VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
-                  tmpVar.setTypeInferred(constructType);
-                  // Move backward - to insert before the current statement
-                  stmtIt.previous();
-                  // Add assignment of the new tmpVar
-                  StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), list.getList().get(0), constructOperator, list.getList().get(1), currentStmt.getSource(), Comment.NO_COMMENTS);
-                  stmtIt.add(assignment);
-                  // Move back before the current statement
-                  stmtIt.next();
-                  // Replace current value with the reference
-                  programValue.set(tmpVar.getRef());
-                  Pass2FixInlineConstructors.this.getLog().append("Fixing inline constructor with " + assignment.toString());
-                  optimized = true;
-               }
-            }
-         }
-      }
-   }
-
-
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java
deleted file mode 100644
index b66de4df4..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2NopCastElimination.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.*;
-import dk.camelot64.kickc.model.operators.OperatorCastPtr;
-import dk.camelot64.kickc.model.operators.Operators;
-import dk.camelot64.kickc.model.values.*;
-import dk.camelot64.kickc.model.statements.Statement;
-import dk.camelot64.kickc.model.statements.StatementAssignment;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-
-import java.util.LinkedHashMap;
-import java.util.ListIterator;
-
-/**
- * Compiler Pass eliminating cast assignments that has no effect (byte to/from signed byte, word to/from signed word)
- */
-public class Pass2NopCastElimination extends Pass2SsaOptimization {
-
-   public Pass2NopCastElimination(Program program) {
-      super(program);
-   }
-
-   /**
-    * Eliminate cast assignments that has no effect (byte to/from signed byte, word to/from signed word)
-    */
-   @Override
-   public boolean step() {
-      LinkedHashMap<SymbolRef, RValue> castAliasses = new LinkedHashMap<>();
-
-      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
-         ListIterator<Statement> stmtIt = block.getStatements().listIterator();
-         while(stmtIt.hasNext()) {
-            Statement stmt = stmtIt.next();
-            if(stmt instanceof StatementAssignment) {
-               StatementAssignment assignment = (StatementAssignment) stmt;
-               if(assignment.getlValue() instanceof VariableRef && assignment.getrValue1()==null && assignment.getOperator()!=null ) {
-                  // It is a simple cast assignment - check if it is no-op
-                  SymbolType rValType = SymbolTypeInference.inferType(getScope(), assignment.getrValue2());
-                  boolean isNopCast = false;
-                  SymbolType toType = null;
-                  if(SymbolType.BYTE.equals(rValType) && Operators.CAST_SBYTE.equals(assignment.getOperator())) {
-                     isNopCast = true;
-                     toType = SymbolType.SBYTE;
-                  } else if(SymbolType.SBYTE.equals(rValType) && Operators.CAST_BYTE.equals(assignment.getOperator())) {
-                     isNopCast = true;
-                     toType = SymbolType.BYTE;
-                  } else if(SymbolType.WORD.equals(rValType) && Operators.CAST_SWORD.equals(assignment.getOperator())) {
-                     isNopCast = true;
-                     toType = SymbolType.SWORD;
-                  } else if(SymbolType.SWORD.equals(rValType) && Operators.CAST_WORD.equals(assignment.getOperator())) {
-                     isNopCast = true;
-                     toType = SymbolType.WORD;
-                  } else if(SymbolType.WORD.equals(rValType) && assignment.getOperator() instanceof OperatorCastPtr) {
-                     isNopCast = true;
-                     OperatorCastPtr castOperator = (OperatorCastPtr) (assignment.getOperator());
-                     toType = new SymbolTypePointer(castOperator.getElementType());
-                  } else if(rValType instanceof SymbolTypePointer  && Operators.CAST_WORD.equals(assignment.getOperator())) {
-                     isNopCast = true;
-                     toType = SymbolType.WORD;
-                  } else if(rValType instanceof SymbolTypePointer  && assignment.getOperator() instanceof OperatorCastPtr) {
-                     isNopCast = true;
-                     toType = new SymbolTypePointer(((OperatorCastPtr) assignment.getOperator()).getElementType());
-                  }
-                  if(isNopCast) {
-                     getLog().append("Eliminating Noop Cast "+assignment.toString(getProgram(), false));
-                     // Add the alias for replacement
-                     if(assignment.getrValue2() instanceof ConstantValue) {
-                        castAliasses.put((VariableRef) assignment.getlValue(), new ConstantCastValue(toType, (ConstantValue) assignment.getrValue2()));
-                     }  else {
-                        castAliasses.put((VariableRef) assignment.getlValue(), new CastValue(toType, assignment.getrValue2()));
-                     }
-                     // Remove the assignment
-                     stmtIt.remove();
-                  }
-               }
-            }
-         }
-      }
-      replaceVariables(castAliasses);
-      deleteSymbols(getScope(), castAliasses.keySet());
-      return (castAliasses.size() > 0);
-   }
-
-
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java
deleted file mode 100644
index aee315662..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/Pass3AddAssignmentCasts.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
-import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
-import dk.camelot64.kickc.model.operators.Operators;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeConversion;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Add casts to assignments where the lvalue and rvalue have different matching types.
- */
-public class Pass3AddAssignmentCasts extends Pass2SsaOptimization {
-
-   public Pass3AddAssignmentCasts(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      AtomicBoolean modified = new AtomicBoolean(false);
-      ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
-         if(programExpression instanceof ProgramExpressionBinary) {
-            if(Operators.ASSIGNMENT.equals(programExpression.getOperator())) {
-               ProgramExpressionBinary binary = (ProgramExpressionBinary) programExpression;
-               SymbolType leftType = SymbolTypeInference.inferType(getScope(), binary.getLeft());
-               SymbolType rightType = SymbolTypeInference.inferType(getScope(), binary.getRight());
-               if(SymbolTypeConversion.assignmentTypeMatch(leftType, rightType) && SymbolTypeConversion.assignmentCastNeeded(leftType, rightType)) {
-                  binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
-                  getLog().append("Adding assignment cast to " + currentStmt.toString(getProgram(), false));
-                  modified.set(true);
-               }
-            }
-         }
-      });
-      return modified.get();
-   }
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java
index 65b5fae89..7a4876a5e 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java
@@ -1,6 +1,8 @@
 package dk.camelot64.kickc.passes;
 
 import dk.camelot64.kickc.model.*;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
 import dk.camelot64.kickc.model.values.ConstantValue;
 import dk.camelot64.kickc.model.values.VariableRef;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
@@ -49,9 +51,12 @@ public class Pass3PhiMemCoalesce extends Pass2SsaOptimization {
     */
    public static class EquivalenceClassPhiInitializer extends ControlFlowGraphBaseVisitor<Void> {
 
+      private Program program;
+
       private LiveRangeEquivalenceClassSet phiEquivalenceClasses;
 
       public EquivalenceClassPhiInitializer(Program program) {
+         this.program = program;
          this.phiEquivalenceClasses = new LiveRangeEquivalenceClassSet(program);
       }
 
@@ -65,7 +70,13 @@ public class Pass3PhiMemCoalesce extends Pass2SsaOptimization {
                   VariableRef phiRVar = (VariableRef) phiRValue.getrValue();
                   LiveRangeEquivalenceClass rValEquivalenceClass = phiEquivalenceClasses.getOrCreateEquivalenceClass(phiRVar);
                   if(!rValEquivalenceClass.equals(equivalenceClass)) {
-                     phiEquivalenceClasses.consolidate(equivalenceClass, rValEquivalenceClass);
+                     SymbolType varType = program.getScope().getVariable(variable).getType();
+                     SymbolType rVarType = program.getScope().getVariable(phiRVar).getType();
+                     if(varType.getSizeBytes()==rVarType.getSizeBytes()) {
+                        phiEquivalenceClasses.consolidate(equivalenceClass, rValEquivalenceClass);
+                     } else {
+                        program.getLog().append("Not consolidating phi with different size "+variable.toString()+" "+phiRVar.toString());
+                     }
                   }
                }
             }
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 112535fab..e0d216b07 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,11 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testMul8uMin() throws IOException, URISyntaxException {
+      compileAndCompare("mul8u-min");
+   }
+
    @Test
    public void testNumberInferenceSum() throws IOException, URISyntaxException {
       compileAndCompare("number-inference-sum");
diff --git a/src/test/kc/mul8u-min.kc b/src/test/kc/mul8u-min.kc
new file mode 100644
index 000000000..83f0668cb
--- /dev/null
+++ b/src/test/kc/mul8u-min.kc
@@ -0,0 +1,14 @@
+// Minimal test of mul8u
+
+import "multiply"
+
+void main() {
+
+    const word* screen = 0x0400;
+    byte i = 0;
+
+    for(byte a: 0..5)
+        for (byte b: 0..5)
+            screen[i++] = mul8u(a,b);
+
+}
\ No newline at end of file
diff --git a/src/test/ref/bresenhamarr.asm b/src/test/ref/bresenhamarr.asm
index 6f5b47054..27134b6fd 100644
--- a/src/test/ref/bresenhamarr.asm
+++ b/src/test/ref/bresenhamarr.asm
@@ -19,7 +19,7 @@ main: {
     ldx #yd/2
     lda #x0
     sta x
-    lda #<0
+    lda #0
     sta idx
     sta idx+1
   b1:
diff --git a/src/test/ref/c64dtv-8bppchunkystretch.asm b/src/test/ref/c64dtv-8bppchunkystretch.asm
index 350dbd2a5..5d6615f06 100644
--- a/src/test/ref/c64dtv-8bppchunkystretch.asm
+++ b/src/test/ref/c64dtv-8bppchunkystretch.asm
@@ -205,7 +205,7 @@ gfx_init_chunky: {
     lda #>$4000
     sta gfxb+1
   b1:
-    lda #<0
+    lda #0
     sta x
     sta x+1
   b2:
diff --git a/src/test/ref/c64dtv-blittermin.asm b/src/test/ref/c64dtv-blittermin.asm
index b7e126dea..0628deace 100644
--- a/src/test/ref/c64dtv-blittermin.asm
+++ b/src/test/ref/c64dtv-blittermin.asm
@@ -85,9 +85,8 @@ main: {
     sta DTV_BLITTER_SRCA_HI
     sta DTV_BLITTER_SRCA_MOD_LO
     sta DTV_BLITTER_SRCA_MOD_HI
-    lda #<$80
     sta DTV_BLITTER_SRCA_LIN_LO
-    lda #0
+    lda #>$100
     sta DTV_BLITTER_SRCA_LIN_HI
     lda #$10
     sta DTV_BLITTER_SRCA_STEP
diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm
index 5787e8dbe..2ffbfb4d9 100644
--- a/src/test/ref/complex/tetris/tetris.asm
+++ b/src/test/ref/complex/tetris/tetris.asm
@@ -214,11 +214,8 @@ main: {
     sta level
     sta score_bcd
     sta score_bcd+1
-    lda #<0>>$10
     sta score_bcd+2
-    lda #>0>>$10
     sta score_bcd+3
-    lda #<0
     sta lines_bcd
     sta lines_bcd+1
     sta current_movedown_counter
diff --git a/src/test/ref/derefidx-word-0.asm b/src/test/ref/derefidx-word-0.asm
index a893d8fe3..95ea7045b 100644
--- a/src/test/ref/derefidx-word-0.asm
+++ b/src/test/ref/derefidx-word-0.asm
@@ -6,7 +6,7 @@ main: {
     .label screen = $400
     .label i = 2
     .label _1 = 4
-    lda #<0
+    lda #0
     sta i
     sta i+1
   b1:
diff --git a/src/test/ref/examples/3d/perspective.asm b/src/test/ref/examples/3d/perspective.asm
index db564e9c2..313e08cfb 100644
--- a/src/test/ref/examples/3d/perspective.asm
+++ b/src/test/ref/examples/3d/perspective.asm
@@ -240,9 +240,9 @@ mulf_init: {
     .label val = 6
     .label sqr = 2
     .label add = 4
-    lda #<1
+    lda #1
     sta add
-    lda #>1
+    lda #0
     sta add+1
     tax
     sta sqr
diff --git a/src/test/ref/examples/chargen/chargen-analysis.asm b/src/test/ref/examples/chargen/chargen-analysis.asm
index 9a4f94c32..3acea7f3d 100644
--- a/src/test/ref/examples/chargen/chargen-analysis.asm
+++ b/src/test/ref/examples/chargen/chargen-analysis.asm
@@ -312,11 +312,10 @@ mul8u: {
     .label mb = $b
     .label res = 9
     .label return = 9
-    lda #<b
+    lda #b
     sta mb
-    lda #>b
+    lda #0
     sta mb+1
-    lda #<0
     sta res
     sta res+1
   b1:
diff --git a/src/test/ref/examples/fire/fire.asm b/src/test/ref/examples/fire/fire.asm
index e6481db83..d14cf06e3 100644
--- a/src/test/ref/examples/fire/fire.asm
+++ b/src/test/ref/examples/fire/fire.asm
@@ -307,7 +307,7 @@ sid_rnd_init: {
 fillscreen: {
     .label screen = 2
     .label i = 4
-    lda #<0
+    lda #0
     sta i
     sta i+1
   b1:
diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
index 0b59051e7..c581edf00 100644
--- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm
+++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
@@ -219,11 +219,11 @@ init: {
     lda #VIC_DEN|VIC_RSEL|3
     sta D011
     jsr plexInit
-    lda #<$20
+    lda #$20
     sta xp
-    lda #>$20
+    lda #0
     sta xp+1
-    ldx #0
+    tax
   b1:
     lda #SPRITE/$40
     sta PLEX_PTR,x
diff --git a/src/test/ref/examples/plasma/plasma-unroll.asm b/src/test/ref/examples/plasma/plasma-unroll.asm
index 761f2a967..6ac675a5a 100644
--- a/src/test/ref/examples/plasma/plasma-unroll.asm
+++ b/src/test/ref/examples/plasma/plasma-unroll.asm
@@ -254,7 +254,7 @@ makecharset: {
     sta print_char_cursor
     lda #>print_line_cursor
     sta print_char_cursor+1
-    lda #<0
+    lda #0
     sta c
     sta c+1
   b1:
diff --git a/src/test/ref/examples/plasma/plasma.asm b/src/test/ref/examples/plasma/plasma.asm
index f0b03b983..5bdbc6470 100644
--- a/src/test/ref/examples/plasma/plasma.asm
+++ b/src/test/ref/examples/plasma/plasma.asm
@@ -190,7 +190,7 @@ makecharset: {
     sta print_char_cursor
     lda #>print_line_cursor
     sta print_char_cursor+1
-    lda #<0
+    lda #0
     sta c
     sta c+1
   b1:
diff --git a/src/test/ref/examples/rotate/rotate.asm b/src/test/ref/examples/rotate/rotate.asm
index 89dbfc313..21947b062 100644
--- a/src/test/ref/examples/rotate/rotate.asm
+++ b/src/test/ref/examples/rotate/rotate.asm
@@ -258,7 +258,7 @@ mulf_init: {
     sta sqr1_lo
     lda #>mulf_sqr1_lo+1
     sta sqr1_lo+1
-    lda #<0
+    lda #0
     sta sqr
     sta sqr+1
     tax
diff --git a/src/test/ref/examples/scrolllogo/scrolllogo.asm b/src/test/ref/examples/scrolllogo/scrolllogo.asm
index bd40df77b..46983d01e 100644
--- a/src/test/ref/examples/scrolllogo/scrolllogo.asm
+++ b/src/test/ref/examples/scrolllogo/scrolllogo.asm
@@ -68,7 +68,7 @@ loop: {
     .label _1 = 9
     .label _5 = 9
     .label xpos = 9
-    lda #<0
+    lda #0
     sta xsin_idx
     sta xsin_idx+1
   b1:
@@ -109,7 +109,7 @@ loop: {
     lda xsin_idx
     cmp #<XSIN_SIZE
     bne b4
-    lda #<0
+    lda #0
     sta xsin_idx
     sta xsin_idx+1
   b4:
@@ -260,19 +260,17 @@ sin16s_gen2: {
     .label x = 5
     .label i = 9
     jsr div32u16u
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<xsin
     sta sintab
     lda #>xsin
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
-    lda #<0>>$10
     sta x+2
-    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -332,13 +330,13 @@ sin16s_gen2: {
 }
 // Multiply of two signed words to a signed double word
 // Fixes offsets introduced by using unsigned multiplication
-// mul16s(signed word zeropage($15) a)
+// mul16s(signed word zeropage($f) a)
 mul16s: {
     .label _9 = $f
     .label _16 = $f
     .label m = $b
     .label return = $b
-    .label a = $15
+    .label a = $f
     lda a
     sta mul16u.a
     lda a+1
@@ -373,19 +371,17 @@ mul16s: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage($f) a, word zeropage($17) b)
+// mul16u(word zeropage($11) a, word zeropage($f) b)
 mul16u: {
-    .label mb = $11
-    .label a = $f
+    .label mb = $13
+    .label a = $11
     .label res = $b
     .label return = $b
-    .label b = $17
-    lda #<0
+    .label b = $f
+    lda #0
     sta res
     sta res+1
-    lda #<0>>$10
     sta res+2
-    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -427,18 +423,18 @@ mul16u: {
 // sin16s(dword zeropage($b) x)
 sin16s: {
     .label _4 = $b
-    .label _20 = $15
+    .label _20 = $f
     .label x = $b
-    .label return = $15
+    .label return = $f
     .label x1 = $1d
-    .label x2 = $15
-    .label x3 = $15
+    .label x2 = $17
+    .label x3 = $17
     .label x3_6 = $f
     .label usinx = $1f
-    .label x4 = $15
+    .label x4 = $17
     .label x5 = $f
     .label x5_128 = $f
-    .label sinx = $15
+    .label sinx = $f
     .label isUpper = 4
     lda x+3
     cmp #>PI_u4f28>>$10
@@ -609,15 +605,15 @@ sin16s: {
 }
 // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result.
 // The select parameter indicates how many of the highest bits of the 32-bit result to skip
-// mulu16_sel(word zeropage($15) v1, word zeropage($17) v2, byte register(X) select)
+// mulu16_sel(word zeropage($17) v1, word zeropage($f) v2, byte register(X) select)
 mulu16_sel: {
     .label _0 = $b
     .label _1 = $b
-    .label v1 = $15
-    .label v2 = $17
+    .label v1 = $17
+    .label v2 = $f
     .label return = $f
-    .label return_1 = $15
-    .label return_10 = $15
+    .label return_1 = $17
+    .label return_10 = $17
     lda v1
     sta mul16u.a
     lda v1+1
@@ -649,14 +645,14 @@ mulu16_sel: {
 // Divide unsigned 32-bit dword dividend with a 16-bit word divisor
 // The 16-bit word remainder can be found in rem16u after the division
 div32u16u: {
-    .label quotient_hi = $15
+    .label quotient_hi = $11
     .label quotient_lo = $f
     .label return = $19
     lda #<PI2_u4f28>>$10
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #<0
+    lda #0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
diff --git a/src/test/ref/examples/sinplotter/sine-plotter.asm b/src/test/ref/examples/sinplotter/sine-plotter.asm
index 951d02189..341d95d20 100644
--- a/src/test/ref/examples/sinplotter/sine-plotter.asm
+++ b/src/test/ref/examples/sinplotter/sine-plotter.asm
@@ -73,7 +73,7 @@ render_sine: {
     .label sin2_val = 6
     .label xpos = 4
     .label sin_idx = 2
-    lda #<0
+    lda #0
     sta xpos
     sta xpos+1
     sta sin_idx
@@ -149,7 +149,7 @@ render_sine: {
     lda xpos
     cmp #<$140
     bne b2
-    lda #<0
+    lda #0
     sta xpos
     sta xpos+1
   b2:
@@ -174,9 +174,9 @@ render_sine: {
 // Plot a single dot in the bitmap
 // bitmap_plot(word zeropage(4) x, byte register(X) y)
 bitmap_plot: {
-    .label _1 = $15
+    .label _1 = $10
     .label plotter = 6
-    .label plotter_1 = $15
+    .label plotter_1 = $10
     .label x = 4
     .label _4 = 6
     lda bitmap_plot_yhi,x
@@ -256,19 +256,17 @@ sin16s_gen2: {
     .label x = 8
     .label i = 4
     jsr div32u16u
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<sin
     sta sintab
     lda #>sin
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
-    lda #<0>>$10
     sta x+2
-    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -328,13 +326,13 @@ sin16s_gen2: {
 }
 // Multiply of two signed words to a signed double word
 // Fixes offsets introduced by using unsigned multiplication
-// mul16s(signed word zeropage($15) a)
+// mul16s(signed word zeropage(6) a)
 mul16s: {
     .label _9 = 6
     .label _16 = 6
     .label m = $c
     .label return = $c
-    .label a = $15
+    .label a = 6
     lda a
     sta mul16u.a
     lda a+1
@@ -369,19 +367,17 @@ mul16s: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage(6) a, word zeropage($17) b)
+// mul16u(word zeropage($10) a, word zeropage(6) b)
 mul16u: {
-    .label mb = $10
-    .label a = 6
+    .label mb = $12
+    .label a = $10
     .label res = $c
     .label return = $c
-    .label b = $17
-    lda #<0
+    .label b = 6
+    lda #0
     sta res
     sta res+1
-    lda #<0>>$10
     sta res+2
-    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -423,19 +419,19 @@ mul16u: {
 // sin16s(dword zeropage($c) x)
 sin16s: {
     .label _4 = $c
-    .label _20 = $15
+    .label _20 = 6
     .label x = $c
-    .label return = $15
+    .label return = 6
     .label x1 = $1d
-    .label x2 = $15
-    .label x3 = $15
+    .label x2 = $17
+    .label x3 = $17
     .label x3_6 = 6
     .label usinx = $1f
-    .label x4 = $15
+    .label x4 = $17
     .label x5 = 6
     .label x5_128 = 6
-    .label sinx = $15
-    .label isUpper = $14
+    .label sinx = 6
+    .label isUpper = $16
     lda x+3
     cmp #>PI_u4f28>>$10
     bcc b4
@@ -605,15 +601,15 @@ sin16s: {
 }
 // Calculate val*val for two unsigned word values - the result is 16 selected bits of the 32-bit result.
 // The select parameter indicates how many of the highest bits of the 32-bit result to skip
-// mulu16_sel(word zeropage($15) v1, word zeropage($17) v2, byte register(X) select)
+// mulu16_sel(word zeropage($17) v1, word zeropage(6) v2, byte register(X) select)
 mulu16_sel: {
     .label _0 = $c
     .label _1 = $c
-    .label v1 = $15
-    .label v2 = $17
+    .label v1 = $17
+    .label v2 = 6
     .label return = 6
-    .label return_1 = $15
-    .label return_10 = $15
+    .label return_1 = $17
+    .label return_10 = $17
     lda v1
     sta mul16u.a
     lda v1+1
@@ -645,14 +641,14 @@ mulu16_sel: {
 // Divide unsigned 32-bit dword dividend with a 16-bit word divisor
 // The 16-bit word remainder can be found in rem16u after the division
 div32u16u: {
-    .label quotient_hi = $15
+    .label quotient_hi = $10
     .label quotient_lo = 6
     .label return = $19
     lda #<PI2_u4f28>>$10
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #<0
+    lda #0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
@@ -732,7 +728,7 @@ divr16u: {
 // Clear all graphics on the bitmap
 bitmap_clear: {
     .label bitmap = 2
-    .label y = $14
+    .label y = $16
     .label _4 = 2
     lda bitmap_plot_ylo
     sta _4
@@ -761,7 +757,7 @@ bitmap_clear: {
 }
 // Initialize bitmap plotting tables
 bitmap_init: {
-    .label _3 = $14
+    .label _3 = $16
     .label yoffs = 2
     ldx #0
     lda #$80
diff --git a/src/test/ref/examples/sinsprites/sinus-sprites.asm b/src/test/ref/examples/sinsprites/sinus-sprites.asm
index 81a9c2d21..eddb6422e 100644
--- a/src/test/ref/examples/sinsprites/sinus-sprites.asm
+++ b/src/test/ref/examples/sinsprites/sinus-sprites.asm
@@ -228,9 +228,9 @@ gen_sintab: {
     lda #>f_amp
     sta setMEMtoFAC.mem+1
     jsr setMEMtoFAC
-    lda #<2
+    lda #2
     sta setFAC.w
-    lda #>2
+    lda #0
     sta setFAC.w+1
     jsr setFAC
     lda #<f_amp
diff --git a/src/test/ref/forrangedwords.asm b/src/test/ref/forrangedwords.asm
index 60b793ab1..8716f7084 100644
--- a/src/test/ref/forrangedwords.asm
+++ b/src/test/ref/forrangedwords.asm
@@ -5,7 +5,7 @@ main: {
     .label SCREEN = $400
     .label w = 2
     .label sw = 2
-    lda #<0
+    lda #0
     sta w
     sta w+1
   b1:
diff --git a/src/test/ref/fragment-variations.asm b/src/test/ref/fragment-variations.asm
index 451bee711..4fea75dc1 100644
--- a/src/test/ref/fragment-variations.asm
+++ b/src/test/ref/fragment-variations.asm
@@ -8,17 +8,15 @@ main: {
     .label screen = $400
     .label _0 = 2
     .label _1 = 2
-    lda #<$a
+    lda #$a
     sta mul16u.a
-    lda #>$a
+    lda #0
     sta mul16u.a+1
-    lda #<$a
+    lda #$a
     sta mul16u.mb
-    lda #>$a
+    lda #0
     sta mul16u.mb+1
-    lda #<$a>>$10
     sta mul16u.mb+2
-    lda #>$a>>$10
     sta mul16u.mb+3
     jsr mul16u
     lda _0
diff --git a/src/test/ref/linegen.asm b/src/test/ref/linegen.asm
index 825a7fc29..4cbd79681 100644
--- a/src/test/ref/linegen.asm
+++ b/src/test/ref/linegen.asm
@@ -38,7 +38,7 @@ main: {
     sta lin16u_gen.lintab
     lda #>lintab3
     sta lin16u_gen.lintab+1
-    lda #<0
+    lda #0
     sta lin16u_gen.min
     sta lin16u_gen.min+1
     lda #<$6488
@@ -76,7 +76,7 @@ main: {
     lda #>str1
     sta print_str.str+1
     jsr print_str
-    lda #<0
+    lda #0
     sta print_word.w
     sta print_word.w+1
     jsr print_word
@@ -309,11 +309,10 @@ lin16u_gen: {
     lda ampl+1
     sbc min+1
     sta ampl+1
-    lda #<$14-1
+    lda #$14-1
     sta divr16u.divisor
-    lda #>$14-1
+    lda #0
     sta divr16u.divisor+1
-    lda #<0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
@@ -321,11 +320,10 @@ lin16u_gen: {
     sta stepi
     lda divr16u.return+1
     sta stepi+1
-    lda #<$14-1
+    lda #$14-1
     sta divr16u.divisor
-    lda #>$14-1
+    lda #0
     sta divr16u.divisor+1
-    lda #<0
     sta divr16u.dividend
     sta divr16u.dividend+1
     jsr divr16u
@@ -344,7 +342,7 @@ lin16u_gen: {
     sta val+2
     lda min+1
     sta val+3
-    lda #<0
+    lda #0
     sta i
     sta i+1
   b1:
diff --git a/src/test/ref/liverange-call-problem.asm b/src/test/ref/liverange-call-problem.asm
index 933c49ae1..ff5e1ea3d 100644
--- a/src/test/ref/liverange-call-problem.asm
+++ b/src/test/ref/liverange-call-problem.asm
@@ -8,11 +8,11 @@
   .label w2 = 2
 main: {
     .label SCREEN = $400
-    lda #<0
+    lda #0
     sta w1
     sta w1+1
     jsr incw1
-    lda #<0
+    lda #0
     sta w2
     sta w2+1
     jsr incw2
diff --git a/src/test/ref/min-fmul-16.asm b/src/test/ref/min-fmul-16.asm
index ef4553748..dc431ade4 100644
--- a/src/test/ref/min-fmul-16.asm
+++ b/src/test/ref/min-fmul-16.asm
@@ -226,7 +226,7 @@ mulf_init: {
     sta sqr1_lo
     lda #>mulf_sqr1_lo+1
     sta sqr1_lo+1
-    lda #<0
+    lda #0
     sta sqr
     sta sqr+1
     tax
diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
index f9d6d5695..8b97b383b 100644
--- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
+++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
@@ -167,11 +167,11 @@ init: {
     lda #VIC_DEN|VIC_RSEL|3
     sta D011
     jsr plexInit
-    lda #<$20
+    lda #$20
     sta xp
-    lda #>$20
+    lda #0
     sta xp+1
-    ldx #0
+    tax
   b1:
     lda #SPRITE/$40
     sta PLEX_PTR,x
diff --git a/src/test/ref/roll-sprite-msb.asm b/src/test/ref/roll-sprite-msb.asm
index 18ab37b56..80b22ddde 100644
--- a/src/test/ref/roll-sprite-msb.asm
+++ b/src/test/ref/roll-sprite-msb.asm
@@ -7,11 +7,11 @@
   .label SPRITES_XMSB = $d010
 main: {
     .label xpos = 2
-    lda #<$c8
+    lda #$c8
     sta xpos
-    lda #>$c8
+    lda #0
     sta xpos+1
-    ldx #0
+    tax
   b1:
     stx position_sprite.spriteno
     jsr position_sprite
diff --git a/src/test/ref/scan-desire-problem.asm b/src/test/ref/scan-desire-problem.asm
index 377b83bf5..2cd3d41b5 100644
--- a/src/test/ref/scan-desire-problem.asm
+++ b/src/test/ref/scan-desire-problem.asm
@@ -76,6 +76,7 @@ draw_block: {
     asl
     sta x1
     lda #0
+    rol
     sta x1+1
     txa
     asl
@@ -172,11 +173,10 @@ mul8u: {
     .label mb = 6
     .label res = 4
     .label return = 4
-    lda #<b
+    lda #b
     sta mb
-    lda #>b
+    lda #0
     sta mb+1
-    lda #<0
     sta res
     sta res+1
   b1:
diff --git a/src/test/ref/semi-struct-2.asm b/src/test/ref/semi-struct-2.asm
index d54d7ac9c..0429bcc2f 100644
--- a/src/test/ref/semi-struct-2.asm
+++ b/src/test/ref/semi-struct-2.asm
@@ -730,11 +730,10 @@ mul8u: {
     .label mb = 2
     .label res = 8
     .label return = 8
-    lda #<SIZEOF_ENTRY
+    lda #SIZEOF_ENTRY
     sta mb
-    lda #>SIZEOF_ENTRY
+    lda #0
     sta mb+1
-    lda #<0
     sta res
     sta res+1
   b1:
diff --git a/src/test/ref/signed-words.asm b/src/test/ref/signed-words.asm
index 9a92c64eb..1f3826b81 100644
--- a/src/test/ref/signed-words.asm
+++ b/src/test/ref/signed-words.asm
@@ -25,22 +25,22 @@
   .label yvel_22 = 6
 main: {
     jsr init
-    lda #<$64
+    lda #$64
     sta yvel_init
-    lda #>$64
+    lda #0
     sta yvel_init+1
     lda #<$c8
     sta xvel
     lda #>$c8
     sta xvel+1
-    lda #<0
+    lda #0
     sta ypos
     sta ypos+1
     sta xpos
     sta xpos+1
-    lda #<$64
+    lda #$64
     sta yvel_12
-    lda #>$64
+    lda #0
     sta yvel_12+1
   b1:
     lda #$ff
@@ -96,7 +96,7 @@ anim: {
     sta yvel_22
     lda yvel+1
     sta yvel_22+1
-    lda #<0
+    lda #0
     sta ypos
     sta ypos+1
     sta xpos
diff --git a/src/test/ref/sinus-basic.asm b/src/test/ref/sinus-basic.asm
index 9e8385227..bf19ef5b9 100644
--- a/src/test/ref/sinus-basic.asm
+++ b/src/test/ref/sinus-basic.asm
@@ -46,9 +46,9 @@ main: {
     lda #>f_i
     sta setMEMtoFAC.mem+1
     jsr setMEMtoFAC
-    lda #<$19
+    lda #$19
     sta setFAC.w
-    lda #>$19
+    lda #0
     sta setFAC.w+1
     jsr setFAC
     jsr divMEMbyFAC
diff --git a/src/test/ref/sinusgen16.asm b/src/test/ref/sinusgen16.asm
index 380d92e7c..bdca50e5c 100644
--- a/src/test/ref/sinusgen16.asm
+++ b/src/test/ref/sinusgen16.asm
@@ -185,19 +185,17 @@ sin16s_gen: {
     .label x = $a
     .label i = 4
     jsr div32u16u
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<main.sintab1
     sta sintab
     lda #>main.sintab1
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
-    lda #<0>>$10
     sta x+2
-    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -485,9 +483,7 @@ mul16u: {
     sta mb+3
     sta res
     sta res+1
-    lda #<0>>$10
     sta res+2
-    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -533,7 +529,7 @@ div32u16u: {
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #<0
+    lda #0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
diff --git a/src/test/ref/sinusgen16b.asm b/src/test/ref/sinusgen16b.asm
index b5f324cfa..299b22494 100644
--- a/src/test/ref/sinusgen16b.asm
+++ b/src/test/ref/sinusgen16b.asm
@@ -204,19 +204,17 @@ sin16s_genb: {
     .label x = $d
     .label i = 4
     jsr div32u16u
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<main.sintab2
     sta sintab
     lda #>main.sintab2
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
-    lda #<0>>$10
     sta x+2
-    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -469,9 +467,7 @@ mul16u: {
     sta mb+3
     sta res
     sta res+1
-    lda #<0>>$10
     sta res+2
-    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -517,7 +513,7 @@ div32u16u: {
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #<0
+    lda #0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
@@ -605,19 +601,17 @@ sin16s_gen: {
     .label x = $d
     .label i = 4
     jsr div32u16u
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<main.sintab1
     sta sintab
     lda #>main.sintab1
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
-    lda #<0>>$10
     sta x+2
-    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
diff --git a/src/test/ref/sinusgen8.asm b/src/test/ref/sinusgen8.asm
index 0c037f3c0..5e117690a 100644
--- a/src/test/ref/sinusgen8.asm
+++ b/src/test/ref/sinusgen8.asm
@@ -158,14 +158,14 @@ sin8s_gen: {
     .label x = 2
     .label i = 7
     jsr div16u
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<main.sintab2
     sta sintab
     lda #>main.sintab2
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
   // u[4.12]
diff --git a/src/test/ref/sinusgen8b.asm b/src/test/ref/sinusgen8b.asm
index e9cafe49a..67172c57e 100644
--- a/src/test/ref/sinusgen8b.asm
+++ b/src/test/ref/sinusgen8b.asm
@@ -181,19 +181,17 @@ sin16s_gen: {
     .label x = 7
     .label i = 5
     jsr div32u16u
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<main.sintabw
     sta sintab
     lda #>main.sintabw
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
-    lda #<0>>$10
     sta x+2
-    lda #>0>>$10
     sta x+3
   // u[4.28]
   b1:
@@ -481,9 +479,7 @@ mul16u: {
     sta mb+3
     sta res
     sta res+1
-    lda #<0>>$10
     sta res+2
-    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -529,7 +525,7 @@ div32u16u: {
     sta divr16u.dividend
     lda #>PI2_u4f28>>$10
     sta divr16u.dividend+1
-    lda #<0
+    lda #0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
@@ -616,14 +612,14 @@ sin8s_gen: {
     .label x = 2
     .label i = $11
     jsr div16u
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<main.sintabb
     sta sintab
     lda #>main.sintabb
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
   // u[4.12]
@@ -839,7 +835,7 @@ div16u: {
     sta divr16u.dividend
     lda #>PI2_u4f12
     sta divr16u.dividend+1
-    lda #<0
+    lda #0
     sta divr16u.rem
     sta divr16u.rem+1
     jsr divr16u
diff --git a/src/test/ref/sinusgenscale8.asm b/src/test/ref/sinusgenscale8.asm
index 792e19135..ba40b7df7 100644
--- a/src/test/ref/sinusgenscale8.asm
+++ b/src/test/ref/sinusgenscale8.asm
@@ -86,14 +86,14 @@ sin8u_table: {
     lda #>$400
     sta print_line_cursor+1
     jsr print_ln
-    lda #<0
+    lda #0
     sta i
     sta i+1
     lda #<main.sintab
     sta sintab
     lda #>main.sintab
     sta sintab+1
-    lda #<0
+    lda #0
     sta x
     sta x+1
   // u[4.12]
@@ -326,9 +326,9 @@ mul8su: {
     .label return = $f
     tya
     tax
-    lda #<b
+    lda #b
     sta mul8u.mb
-    lda #>b
+    lda #0
     sta mul8u.mb+1
     jsr mul8u
     cpy #0
@@ -346,7 +346,7 @@ mul8u: {
     .label mb = $b
     .label res = $f
     .label return = $f
-    lda #<0
+    lda #0
     sta res
     sta res+1
   b1:
diff --git a/src/test/ref/test-multiply-16bit.asm b/src/test/ref/test-multiply-16bit.asm
index e9858cdce..4b1b9e166 100644
--- a/src/test/ref/test-multiply-16bit.asm
+++ b/src/test/ref/test-multiply-16bit.asm
@@ -601,20 +601,18 @@ mul16s: {
     rts
 }
 // Perform binary multiplication of two unsigned 16-bit words into a 32-bit unsigned double word
-// mul16u(word zeropage(9) a, word zeropage($15) b)
+// mul16u(word zeropage($1d) a, word zeropage(9) b)
 mul16u: {
     .label mb = $11
-    .label a = 9
+    .label a = $1d
     .label res = $19
-    .label b = $15
+    .label b = 9
     .label return = $19
     .label b_1 = $17
-    lda #<0
+    lda #0
     sta res
     sta res+1
-    lda #<0>>$10
     sta res+2
-    lda #>0>>$10
     sta res+3
   b1:
     lda a
@@ -667,14 +665,12 @@ muls16s: {
     lda a
     beq b5
   !:
-    lda #<0
+    lda #0
     sta j
     sta j+1
     sta m
     sta m+1
-    lda #<0>>$10
     sta m+2
-    lda #>0>>$10
     sta m+3
   b3:
     lda b+1
@@ -708,23 +704,19 @@ muls16s: {
     bne b3
     rts
   b5:
-    lda #<0
+    lda #0
     sta return
     sta return+1
-    lda #<0>>$10
     sta return+2
-    lda #>0>>$10
     sta return+3
     rts
   b6:
-    lda #<0
+    lda #0
     sta i
     sta i+1
     sta m
     sta m+1
-    lda #<0>>$10
     sta m+2
-    lda #>0>>$10
     sta m+3
   b4:
     lda b+1
@@ -965,14 +957,12 @@ muls16u: {
     lda a+1
     beq b3
   !:
-    lda #<0
+    lda #0
     sta i
     sta i+1
     sta m
     sta m+1
-    lda #<0>>$10
     sta m+2
-    lda #>0>>$10
     sta m+3
   b2:
     lda m
@@ -1000,12 +990,10 @@ muls16u: {
     bne b2
     rts
   b3:
-    lda #<0
+    lda #0
     sta return
     sta return+1
-    lda #<0>>$10
     sta return+2
-    lda #>0>>$10
     sta return+3
     rts
 }
@@ -1028,7 +1016,7 @@ mulf_init: {
     sta sqr1_lo
     lda #>mulf_sqr1_lo+1
     sta sqr1_lo+1
-    lda #<0
+    lda #0
     sta sqr
     sta sqr+1
     tax
diff --git a/src/test/ref/test-multiply-8bit.asm b/src/test/ref/test-multiply-8bit.asm
index 5cf013274..195dda466 100644
--- a/src/test/ref/test-multiply-8bit.asm
+++ b/src/test/ref/test-multiply-8bit.asm
@@ -307,7 +307,7 @@ mul8u: {
     .label mb = 6
     .label res = $c
     .label return = $c
-    lda #<0
+    lda #0
     sta res
     sta res+1
   b1:
@@ -451,7 +451,7 @@ muls8s: {
     bne b3
     rts
   b5:
-    lda #<0
+    lda #0
     sta return
     sta return+1
     rts
@@ -634,7 +634,7 @@ muls8u: {
     bne b2
     rts
   b3:
-    lda #<0
+    lda #0
     sta return
     sta return+1
     rts
@@ -796,7 +796,7 @@ mulf_init: {
     sta sqr1_lo
     lda #>mulf_sqr1_lo+1
     sta sqr1_lo+1
-    lda #<0
+    lda #0
     sta sqr
     sta sqr+1
     tax
diff --git a/src/test/ref/test-scroll-up.asm b/src/test/ref/test-scroll-up.asm
index 3f11d2fd0..15c85f776 100644
--- a/src/test/ref/test-scroll-up.asm
+++ b/src/test/ref/test-scroll-up.asm
@@ -17,7 +17,7 @@ scrollup3: {
     .label _4 = 7
     .label _5 = 9
     .label l2_4 = 4
-    lda #<0
+    lda #0
     sta l2
     sta l2+1
   b1:
@@ -111,7 +111,7 @@ scrollup1: {
     .label line = 2
     .label _6 = 7
     .label _7 = 4
-    lda #<0
+    lda #0
     sta line
     sta line+1
   b1:
diff --git a/src/test/ref/test-word-size-arrays.asm b/src/test/ref/test-word-size-arrays.asm
index 7a768dfdd..34f29fa59 100644
--- a/src/test/ref/test-word-size-arrays.asm
+++ b/src/test/ref/test-word-size-arrays.asm
@@ -10,7 +10,7 @@ main: {
     .label _8 = 6
     .label _9 = 4
     .label _10 = 4
-    lda #<0
+    lda #0
     sta line
     sta line+1
   b1:

From fa6e54fb876dcb68af5ec25826e178052641669e Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sat, 18 May 2019 23:58:24 +0200
Subject: [PATCH 47/93] Added test ref

---
 src/test/ref/mul8u-min.asm | 70 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 src/test/ref/mul8u-min.asm

diff --git a/src/test/ref/mul8u-min.asm b/src/test/ref/mul8u-min.asm
new file mode 100644
index 000000000..88d7cb90b
--- /dev/null
+++ b/src/test/ref/mul8u-min.asm
@@ -0,0 +1,70 @@
+// Minimal test of mul8u
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    .label _0 = 4
+    .label i = 3
+    .label a = 2
+    lda #0
+    sta i
+    sta a
+  b1:
+    ldy #0
+  b2:
+    ldx a
+    tya
+    jsr mul8u
+    lda i
+    asl
+    tax
+    lda _0
+    sta screen,x
+    lda _0+1
+    sta screen+1,x
+    inc i
+    iny
+    cpy #6
+    bne b2
+    inc a
+    lda #6
+    cmp a
+    bne b1
+    rts
+}
+// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word
+// mul8u(byte register(X) a, byte register(A) b)
+mul8u: {
+    .label mb = 6
+    .label res = 4
+    .label return = 4
+    sta mb
+    lda #0
+    sta mb+1
+    sta res
+    sta res+1
+  b1:
+    cpx #0
+    bne b2
+    rts
+  b2:
+    txa
+    and #1
+    cmp #0
+    beq b3
+    lda res
+    clc
+    adc mb
+    sta res
+    lda res+1
+    adc mb+1
+    sta res+1
+  b3:
+    txa
+    lsr
+    tax
+    asl mb
+    rol mb+1
+    jmp b1
+}

From f31dc244b52e991a55cbc535c069104e4a14bb46 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 19 May 2019 00:07:52 +0200
Subject: [PATCH 48/93] fixed tests

---
 src/test/java/dk/camelot64/kickc/test/TestPrograms.java | 5 -----
 src/test/kc/typemismatch.kc                             | 2 ++
 src/test/kc/valuelist-error.kc                          | 5 -----
 3 files changed, 2 insertions(+), 10 deletions(-)
 delete mode 100644 src/test/kc/valuelist-error.kc

diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index e0d216b07..bb0078a74 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -1831,11 +1831,6 @@ public class TestPrograms {
       assertError("invalid-consttype", "Constant variable has a non-matching type", false);
    }
 
-   @Test
-   public void testValueListError() throws IOException, URISyntaxException {
-      assertError("valuelist-error", "Value list not resolved to word constructor");
-   }
-
    @Test
    public void testArrayUninitialized() throws IOException, URISyntaxException {
       assertError("array-uninitialized", "Array has no declared size.");
diff --git a/src/test/kc/typemismatch.kc b/src/test/kc/typemismatch.kc
index d4d1f8b7c..d391e89a0 100644
--- a/src/test/kc/typemismatch.kc
+++ b/src/test/kc/typemismatch.kc
@@ -2,4 +2,6 @@
 void main() {
     word w = 5000;
     byte b = w;
+    const byte* screen = 0x0400;
+    screen[0] = b;
 }
\ No newline at end of file
diff --git a/src/test/kc/valuelist-error.kc b/src/test/kc/valuelist-error.kc
deleted file mode 100644
index 4463c8ebd..000000000
--- a/src/test/kc/valuelist-error.kc
+++ /dev/null
@@ -1,5 +0,0 @@
-void main() {
-    word w  = { -1, -1};
-    byte* screen = $400;
-    *screen = <w;
-}
\ No newline at end of file

From 624687153869af255c021b53ebfe6a1887086c8b Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 19 May 2019 01:16:12 +0200
Subject: [PATCH 49/93] Fixed tests

---
 .../java/dk/camelot64/kickc/Compiler.java     |   1 -
 .../kickc/model/types/SymbolTypeMulti.java    | 137 ------------------
 .../dk/camelot64/kickc/test/TestPrograms.java |  12 +-
 src/test/kc/sandbox.kc                        |   6 +-
 src/test/kc/ternary-inference.kc              |   4 +-
 src/test/ref/sandbox.asm                      |  60 ++++----
 src/test/ref/ternary-inference.asm            |  24 +++
 7 files changed, 62 insertions(+), 182 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
 create mode 100644 src/test/ref/ternary-inference.asm

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 4dc3c79f5..d7e23c9c2 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -323,7 +323,6 @@ public class Compiler {
       constantOptimizations.add(new PassNSimplifyConstantZero(program));
       constantOptimizations.add(new PassNSimplifyExpressionWithZero(program));
 
-
       pass2Execute(constantOptimizations);
 
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
deleted file mode 100644
index 9c0b8924e..000000000
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeMulti.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package dk.camelot64.kickc.model.types;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-/**
- * Symbol Type of an inline 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, dword/signed dword), while the value -252 only matches signed word or signed dword.
- */
-public class SymbolTypeMulti implements SymbolType {
-
-   /** All numeric types. */
-   public static final SymbolTypeMulti NUMERIC = new SymbolTypeMulti(Arrays.asList(BYTE, SBYTE, WORD, SWORD, DWORD, SDWORD));
-
-   /**
-    * All potential types for the inline constant.
-    */
-   private Collection<SymbolType> types;
-
-   public SymbolTypeMulti(Collection<SymbolType> types) {
-      this.types = types;
-   }
-
-   public Collection<SymbolType> getTypes() {
-      return types;
-   }
-
-   @Override
-   public int getSizeBytes() {
-      // Find the minimal sizeof - and return that
-      Integer size = null;
-      for(SymbolType type : types) {
-         if(size==null) {
-            size = type.getSizeBytes();
-         }  else if(size>type.getSizeBytes()) {
-            size = type.getSizeBytes();
-         }
-      }
-      if(size==null) {
-         return -1;
-      }
-      return size;
-   }
-
-   @Override
-   public String getTypeName() {
-      StringBuilder name = new StringBuilder();
-      boolean first = true;
-      for(SymbolType 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;
-      }
-      SymbolTypeMulti that = (SymbolTypeMulti) 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);
-   }
-
-   /**
-    * Is signed byte one of the potential types
-    *
-    * @return true if signed byte is a potential type
-    */
-   public boolean isSByte() {
-      return types.contains(SBYTE);
-   }
-
-   /**
-    * Is unsigned word one of the potential types
-    *
-    * @return true if unsigned word is a potential type
-    */
-   public boolean isWord() {
-      return types.contains(WORD);
-   }
-
-   /**
-    * Is signed word one of the potential types
-    *
-    * @return true if signed word is a potential type
-    */
-   public boolean isSWord() {
-      return types.contains(SWORD);
-   }
-
-   /**
-    * Is unsigned dword one of the potential types
-    *
-    * @return true if unsigned dword is a potential type
-    */
-   public boolean isDWord() {
-      return types.contains(DWORD);
-   }
-
-   /**
-    * Is signed dword one of the potential types
-    *
-    * @return true if signed dword is a potential type
-    */
-   public boolean isSDWord() {
-      return types.contains(SDWORD);
-   }
-
-
-}
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index bb0078a74..0fc59583b 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,12 @@ public class TestPrograms {
 
     */
 
+
+   @Test
+   public void testTernaryInference() throws IOException, URISyntaxException {
+      compileAndCompare("ternary-inference");
+   }
+
    @Test
    public void testMul8uMin() throws IOException, URISyntaxException {
       compileAndCompare("mul8u-min");
@@ -98,11 +104,6 @@ public class TestPrograms {
       compileAndCompare("derefidx-word-0");
    }
 
-   @Test
-   public void testTernaryInference() throws IOException, URISyntaxException {
-      compileAndCompare("ternary-inference", log());
-   }
-
    @Test
    public void testFragmentVariations() throws IOException, URISyntaxException {
       compileAndCompare("fragment-variations");
@@ -188,7 +189,6 @@ public class TestPrograms {
       compileAndCompare("sandbox");
    }
 
-
    //@Test
    //public void testPointerCast3() throws IOException, URISyntaxException {
    //   compileAndCompare("pointer-cast-3");
diff --git a/src/test/kc/sandbox.kc b/src/test/kc/sandbox.kc
index 9cf4f4229..3ff3ae112 100644
--- a/src/test/kc/sandbox.kc
+++ b/src/test/kc/sandbox.kc
@@ -48,8 +48,10 @@ byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) {
 				if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' '; 
             } else if (b == 'x' || b == 'X'){ // hex
 				b = ((byte)w >> 4) & 0xF;
-				dst[bLen++] = (b < 10 ? '0' : 0x57) + b; // "('a' - 10)" is the normal way -- not supported  -- https://gitlab.com/camelot/kickc/issues/184 [FIXED]
-				b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
+				dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b;
+				// "('a' - 10)" is the normal way -- not supported  -- https://gitlab.com/camelot/kickc/issues/184 [FIXED]
+				// (b < 10 ? '0' : 0x57) not supported
+				b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b;
 			}
             bFormat = 0;
 			continue;
diff --git a/src/test/kc/ternary-inference.kc b/src/test/kc/ternary-inference.kc
index 47e22265d..4f6e29973 100644
--- a/src/test/kc/ternary-inference.kc
+++ b/src/test/kc/ternary-inference.kc
@@ -1,10 +1,8 @@
 // Type inference into the ternary operator
 
 void main() {
-
     const byte* screen = 0x400;
     for(byte i: 0..10) {
-        screen[i] = (i<5?0x57:'0')+i;
+        screen[i] = (i<5?0x57ub:'0')+i;
     }
-
 }
\ No newline at end of file
diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm
index 83029cccc..559fa3c11 100644
--- a/src/test/ref/sandbox.asm
+++ b/src/test/ref/sandbox.asm
@@ -152,11 +152,10 @@ Print: {
 }
 // myprintf(byte* zeropage(8) str, word zeropage(2) w1, word zeropage(4) w2, word zeropage(6) w3)
 myprintf: {
-    .label _17 = $12
     .label str = 8
     .label bDigits = $11
     .label bLen = $10
-    .label digit = $a
+    .label b = $a
     .label bArg = $b
     .label return = $10
     .label w1 = 2
@@ -228,19 +227,13 @@ myprintf: {
     sta bFormat
     jmp b27
   b26:
-    lda w+1
-    sta _17+1
     lda w
-    sta _17
-    ldy #4
-  !:
-    lsr _17+1
-    ror _17
-    dey
-    bne !-
-    lda _17
-    and #$f
-    tax
+    lsr
+    lsr
+    lsr
+    lsr
+    ldx #$f
+    axs #0
     cpx #$a
     bcc b8
     lda #$57
@@ -255,8 +248,8 @@ myprintf: {
     sta strTemp,y
     iny
     lda w
-    and #$f
-    tax
+    ldx #$f
+    axs #0
     cpx #$a
     bcc b10
     lda #$57
@@ -277,35 +270,33 @@ myprintf: {
     lda w+1
     sta utoa.value+1
     jsr utoa
-    ldx #1
+    lda #1
+    sta b
   b12:
-    lda buf6,x
+    ldy b
+    lda buf6,y
     cmp #0
     bne b13
     lda bTrailing
     cmp #0
     beq b39
   b15:
-    lda #0
-    sta digit
+    ldx #0
   b19:
-    ldy digit
-    lda buf6,y
+    lda buf6,x
     ldy bLen
     sta strTemp,y
     inc bLen
-    inc digit
-    txa
-    cmp digit
-    beq !+
-    bcs b19
-  !:
+    inx
+    cpx b
+    bcc b19
     lda bTrailing
     cmp #0
     bne b40
     jmp b22
   b40:
-    cpx bDigits
+    lda b
+    cmp bDigits
     bcc b21
     jmp b22
   b21:
@@ -314,11 +305,13 @@ myprintf: {
     sta strTemp,y
     inc bLen
     dec bDigits
-    cpx bDigits
+    lda b
+    cmp bDigits
     bcc b21
     jmp b22
   b39:
-    cpx bDigits
+    lda b
+    cmp bDigits
     bcc b16
     jmp b15
   b16:
@@ -334,11 +327,12 @@ myprintf: {
     sta strTemp,y
     inc bLen
     dec bDigits
-    cpx bDigits
+    lda b
+    cmp bDigits
     bcc b16
     jmp b15
   b13:
-    inx
+    inc b
     jmp b12
   b6:
     lda w
diff --git a/src/test/ref/ternary-inference.asm b/src/test/ref/ternary-inference.asm
new file mode 100644
index 000000000..90df7b35e
--- /dev/null
+++ b/src/test/ref/ternary-inference.asm
@@ -0,0 +1,24 @@
+// Type inference into the ternary operator
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = $400
+    ldx #0
+  b1:
+    cpx #5
+    bcc b2
+    lda #'0'
+    jmp b3
+  b2:
+    lda #$57
+  b3:
+    stx $ff
+    clc
+    adc $ff
+    sta screen,x
+    inx
+    cpx #$b
+    bne b1
+    rts
+}

From 2ec68d6fd5d71af6c5b5be7fb21beb91f6ea901e Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Sun, 19 May 2019 09:31:12 +0200
Subject: [PATCH 50/93] added hex2dec test

---
 .../dk/camelot64/kickc/test/TestPrograms.java |   5 +
 src/test/kc/hex2dec.kc                        |  56 ++++
 src/test/ref/hex2dec.asm                      | 282 ++++++++++++++++++
 3 files changed, 343 insertions(+)
 create mode 100644 src/test/kc/hex2dec.kc
 create mode 100644 src/test/ref/hex2dec.asm

diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 0fc59583b..c4a10ab7a 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -64,6 +64,11 @@ public class TestPrograms {
     */
 
 
+   @Test
+   public void testHex2Dec() throws IOException, URISyntaxException {
+      compileAndCompare("hex2dec");
+   }
+
    @Test
    public void testTernaryInference() throws IOException, URISyntaxException {
       compileAndCompare("ternary-inference");
diff --git a/src/test/kc/hex2dec.kc b/src/test/kc/hex2dec.kc
new file mode 100644
index 000000000..d1d838356
--- /dev/null
+++ b/src/test/kc/hex2dec.kc
@@ -0,0 +1,56 @@
+// Testing hex to decimal conversion
+
+const unsigned char *control = 0xd011;
+const unsigned char *raster = 0xd012;
+const unsigned char *bordercol = 0xd020;
+
+void main() {
+    asm { sei }
+    cls();
+    while(true) {
+        do {
+            unsigned char rst = (*control&0x80)|(*raster>>1);
+        } while (rst!=0x30);
+        unsigned char *screen = 0x0400;
+        *bordercol = 1;
+        utoa(00000, screen); (*bordercol)++; screen += 40;
+        utoa(01234, screen); (*bordercol)++; screen += 40;
+        utoa(05678, screen); (*bordercol)++; screen += 40;
+        utoa(09999, screen); (*bordercol)++; screen += 40;
+        utoa(59999, screen);
+        *bordercol = 0;
+    }
+
+}
+
+void cls() {
+    unsigned char *screen = 0x0400;
+    for( unsigned char *sc: screen..screen+999) *sc=' ';
+}
+
+unsigned char[] DIGITS = "0123456789abcdef";
+const unsigned char RADIX_BINARY = 2;
+const unsigned char RADIX_OCTAL = 8;
+const unsigned char RADIX_DECIMAL = 10;
+const unsigned char RADIX_HEX = 16;
+
+
+
+// simple 'utoa' without using multiply or divide
+unsigned int append(unsigned char *dst, unsigned int value, unsigned int sub){
+    *dst = '0';
+    unsigned int sub3 = sub*2+sub;
+    while (value >= sub3){ *dst += 3; value -= sub3; }
+    while (value >= sub){ ++*dst; value -= sub; }
+    return value;
+}
+
+void utoa(unsigned int value, unsigned char *dst){
+    unsigned char bStarted = 0;
+    if (bStarted == 1 || value >= 10000){ value = append(dst++, value, 10000); bStarted = 1; }
+    if (bStarted == 1 || value >= 1000){ value = append(dst++, value, 1000); bStarted = 1; }
+    if (bStarted == 1 || value >= 100){ value = append(dst++, value, 100); bStarted = 1; }
+    if (bStarted == 1 || value >= 10){ value = append(dst++, value, 10); bStarted = 1; }
+    *dst++ = '0' + (unsigned char) value;
+    *dst = 0;
+}
diff --git a/src/test/ref/hex2dec.asm b/src/test/ref/hex2dec.asm
new file mode 100644
index 000000000..b080e5c44
--- /dev/null
+++ b/src/test/ref/hex2dec.asm
@@ -0,0 +1,282 @@
+// Testing hex to decimal conversion
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .label control = $d011
+  .label raster = $d012
+  .label bordercol = $d020
+main: {
+    .label _1 = 8
+    sei
+    jsr cls
+  b1:
+    lda #$80
+    and control
+    sta _1
+    lda raster
+    lsr
+    ora _1
+    cmp #$30
+    bne b1
+    lda #1
+    sta bordercol
+    lda #<$400
+    sta utoa.dst
+    lda #>$400
+    sta utoa.dst+1
+    lda #0
+    sta utoa.value
+    sta utoa.value+1
+    jsr utoa
+    inc bordercol
+    lda #<$400+$28
+    sta utoa.dst
+    lda #>$400+$28
+    sta utoa.dst+1
+    lda #<$4d2
+    sta utoa.value
+    lda #>$4d2
+    sta utoa.value+1
+    jsr utoa
+    inc bordercol
+    lda #<$400+$28+$28
+    sta utoa.dst
+    lda #>$400+$28+$28
+    sta utoa.dst+1
+    lda #<$162e
+    sta utoa.value
+    lda #>$162e
+    sta utoa.value+1
+    jsr utoa
+    inc bordercol
+    lda #<$400+$28+$28+$28
+    sta utoa.dst
+    lda #>$400+$28+$28+$28
+    sta utoa.dst+1
+    lda #<$270f
+    sta utoa.value
+    lda #>$270f
+    sta utoa.value+1
+    jsr utoa
+    inc bordercol
+    lda #<$400+$28+$28+$28+$28
+    sta utoa.dst
+    lda #>$400+$28+$28+$28+$28
+    sta utoa.dst+1
+    lda #<$ea5f
+    sta utoa.value
+    lda #>$ea5f
+    sta utoa.value+1
+    jsr utoa
+    lda #0
+    sta bordercol
+    jmp b1
+}
+// utoa(word zeropage(2) value, byte* zeropage(4) dst)
+utoa: {
+    .label value = 2
+    .label dst = 4
+    lda value+1
+    cmp #>$2710
+    bcc !+
+    beq !b5+
+    jmp b5
+  !b5:
+    lda value
+    cmp #<$2710
+    bcc !b5+
+    jmp b5
+  !b5:
+  !:
+    ldx #0
+  b1:
+    cpx #1
+    beq b6
+    lda value+1
+    cmp #>$3e8
+    bcc !+
+    bne b6
+    lda value
+    cmp #<$3e8
+    bcs b6
+  !:
+  b2:
+    cpx #1
+    beq b7
+    lda value+1
+    cmp #>$64
+    bcc !+
+    bne b7
+    lda value
+    cmp #<$64
+    bcs b7
+  !:
+  b3:
+    cpx #1
+    beq b8
+    lda value+1
+    cmp #>$a
+    bcc !+
+    bne b8
+    lda value
+    cmp #<$a
+    bcs b8
+  !:
+  b4:
+    lda value
+    clc
+    adc #'0'
+    ldy #0
+    sta (dst),y
+    inc dst
+    bne !+
+    inc dst+1
+  !:
+    lda #0
+    tay
+    sta (dst),y
+    rts
+  b8:
+    lda #$a
+    sta append.sub
+    lda #0
+    sta append.sub+1
+    jsr append
+    inc dst
+    bne !+
+    inc dst+1
+  !:
+    jmp b4
+  b7:
+    lda #$64
+    sta append.sub
+    lda #0
+    sta append.sub+1
+    jsr append
+    inc dst
+    bne !+
+    inc dst+1
+  !:
+    ldx #1
+    jmp b3
+  b6:
+    lda #<$3e8
+    sta append.sub
+    lda #>$3e8
+    sta append.sub+1
+    jsr append
+    inc dst
+    bne !+
+    inc dst+1
+  !:
+    ldx #1
+    jmp b2
+  b5:
+    lda #<$2710
+    sta append.sub
+    lda #>$2710
+    sta append.sub+1
+    jsr append
+    inc dst
+    bne !+
+    inc dst+1
+  !:
+    ldx #1
+    jmp b1
+}
+// simple 'utoa' without using multiply or divide
+// append(byte* zeropage(4) dst, word zeropage(2) value, word zeropage(6) sub)
+append: {
+    .label _0 = 9
+    .label sub3 = 9
+    .label value = 2
+    .label dst = 4
+    .label return = 2
+    .label sub = 6
+    lda #'0'
+    ldy #0
+    sta (dst),y
+    lda sub
+    asl
+    sta _0
+    lda sub+1
+    rol
+    sta _0+1
+    lda sub3
+    clc
+    adc sub
+    sta sub3
+    lda sub3+1
+    adc sub+1
+    sta sub3+1
+  b1:
+    lda sub3+1
+    cmp value+1
+    bne !+
+    lda sub3
+    cmp value
+  !:
+    bcc b2
+    beq b2
+  b3:
+    lda sub+1
+    cmp value+1
+    bne !+
+    lda sub
+    cmp value
+  !:
+    bcc b4
+    beq b4
+    rts
+  b4:
+    ldy #0
+    lda (dst),y
+    clc
+    adc #1
+    sta (dst),y
+    lda value
+    sec
+    sbc sub
+    sta value
+    lda value+1
+    sbc sub+1
+    sta value+1
+    jmp b3
+  b2:
+    lda #3
+    clc
+    ldy #0
+    adc (dst),y
+    sta (dst),y
+    lda value
+    sec
+    sbc sub3
+    sta value
+    lda value+1
+    sbc sub3+1
+    sta value+1
+    jmp b1
+}
+cls: {
+    .label screen = $400
+    .label sc = 2
+    lda #<screen
+    sta sc
+    lda #>screen
+    sta sc+1
+  b1:
+    lda #' '
+    ldy #0
+    sta (sc),y
+    inc sc
+    bne !+
+    inc sc+1
+  !:
+    lda sc+1
+    cmp #>screen+$3e7+1
+    bne b1
+    lda sc
+    cmp #<screen+$3e7+1
+    bne b1
+    rts
+}

From 9864995afb799046a72a13b4d28923b8a0b2615f Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Sun, 19 May 2019 21:17:39 +0200
Subject: [PATCH 51/93] Created utoa10 with smaller memory footprint.

---
 ...pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm |   8 +
 ...pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm |   8 +
 ...vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm |   7 +
 ...vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm |   7 +
 src/main/fragment/vwuz1_le_vwuz2_then_la1.asm |   2 +-
 src/test/kc/hex2dec.kc                        |  82 ++++-
 src/test/ref/hex2dec.asm                      | 305 +++++++-----------
 7 files changed, 208 insertions(+), 211 deletions(-)
 create mode 100644 src/main/fragment/pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm
 create mode 100644 src/main/fragment/pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm
 create mode 100644 src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm
 create mode 100644 src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm

diff --git a/src/main/fragment/pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm b/src/main/fragment/pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm
new file mode 100644
index 000000000..ef873ab36
--- /dev/null
+++ b/src/main/fragment/pwuc1_derefidx_vbuxx_le_vwuz1_then_la1.asm
@@ -0,0 +1,8 @@
+lda {c1}+1,x
+cmp {z1}+1
+bne !+
+lda {c1},x
+cmp {z1}
+beq {la1}
+!:
+bcc {la1}
diff --git a/src/main/fragment/pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm b/src/main/fragment/pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm
new file mode 100644
index 000000000..427b691bd
--- /dev/null
+++ b/src/main/fragment/pwuc1_derefidx_vbuyy_le_vwuz1_then_la1.asm
@@ -0,0 +1,8 @@
+lda {c1}+1,y
+cmp {z1}+1
+bne !+
+lda {c1},y
+cmp {z1}
+beq {la1}
+!:
+bcc {la1}
diff --git a/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm b/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm
new file mode 100644
index 000000000..0b9a494d5
--- /dev/null
+++ b/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuxx.asm
@@ -0,0 +1,7 @@
+sec
+lda {z1}
+sbc {c1},x
+sta {z1}
+lda {z1}+1
+sbc {c1}+1,x
+sta {z1}+1
diff --git a/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm b/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm
new file mode 100644
index 000000000..001c5e74d
--- /dev/null
+++ b/src/main/fragment/vwuz1=vwuz1_minus_pwuc1_derefidx_vbuyy.asm
@@ -0,0 +1,7 @@
+sec
+lda {z1}
+sbc {c1},y
+sta {z1}
+lda {z1}+1
+sbc {c1}+1,y
+sta {z1}+1
diff --git a/src/main/fragment/vwuz1_le_vwuz2_then_la1.asm b/src/main/fragment/vwuz1_le_vwuz2_then_la1.asm
index 54a02388d..cc7e71a71 100644
--- a/src/main/fragment/vwuz1_le_vwuz2_then_la1.asm
+++ b/src/main/fragment/vwuz1_le_vwuz2_then_la1.asm
@@ -3,6 +3,6 @@ cmp {z2}+1
 bne !+
 lda {z1}
 cmp {z2}
+beq {la1}
 !:
 bcc {la1}
-beq {la1}
\ No newline at end of file
diff --git a/src/test/kc/hex2dec.kc b/src/test/kc/hex2dec.kc
index d1d838356..f27a6e7d4 100644
--- a/src/test/kc/hex2dec.kc
+++ b/src/test/kc/hex2dec.kc
@@ -13,12 +13,19 @@ void main() {
         } while (rst!=0x30);
         unsigned char *screen = 0x0400;
         *bordercol = 1;
-        utoa(00000, screen); (*bordercol)++; screen += 40;
-        utoa(01234, screen); (*bordercol)++; screen += 40;
-        utoa(05678, screen); (*bordercol)++; screen += 40;
-        utoa(09999, screen); (*bordercol)++; screen += 40;
-        utoa(59999, screen);
+        unsigned char time_start = *raster;
+        utoa10b(00000, screen); (*bordercol)++; screen += 40;
+        utoa10b(01234, screen); (*bordercol)++; screen += 40;
+        utoa10b(05678, screen); (*bordercol)++; screen += 40;
+        utoa10b(09999, screen); (*bordercol)++; screen += 40;
+        utoa10b(58888, screen);
+        unsigned char time_end = *raster;
         *bordercol = 0;
+        unsigned char time = time_end - time_start;
+        utoa10b((unsigned int)time, screen+80);
+        byte[] msg = "raster lines";
+        for( byte i=0; msg[i]!=0; i++ ) (screen+80+3)[i] = msg[i];
+        //for( byte* m="lines", s=screen+80+6 ;*m!=0;m++,s++) *s = *m;
     }
 
 }
@@ -28,29 +35,70 @@ void cls() {
     for( unsigned char *sc: screen..screen+999) *sc=' ';
 }
 
-unsigned char[] DIGITS = "0123456789abcdef";
 const unsigned char RADIX_BINARY = 2;
 const unsigned char RADIX_OCTAL = 8;
 const unsigned char RADIX_DECIMAL = 10;
 const unsigned char RADIX_HEX = 16;
 
-
-
 // simple 'utoa' without using multiply or divide
-unsigned int append(unsigned char *dst, unsigned int value, unsigned int sub){
-    *dst = '0';
+unsigned int utoa_digit(unsigned char *dst, unsigned int value, unsigned int sub){
+    unsigned char digit = 0;
     unsigned int sub3 = sub*2+sub;
-    while (value >= sub3){ *dst += 3; value -= sub3; }
-    while (value >= sub){ ++*dst; value -= sub; }
+    while (value >= sub3){ digit += 3; value -= sub3; }
+    while (value >= sub){ ++digit; value -= sub; }
+    *dst = DIGITS[digit];
     return value;
 }
 
 void utoa(unsigned int value, unsigned char *dst){
     unsigned char bStarted = 0;
-    if (bStarted == 1 || value >= 10000){ value = append(dst++, value, 10000); bStarted = 1; }
-    if (bStarted == 1 || value >= 1000){ value = append(dst++, value, 1000); bStarted = 1; }
-    if (bStarted == 1 || value >= 100){ value = append(dst++, value, 100); bStarted = 1; }
-    if (bStarted == 1 || value >= 10){ value = append(dst++, value, 10); bStarted = 1; }
+    if (bStarted == 1 || value >= 10000){ value = utoa_digit(dst++, value, 10000); bStarted = 1; }
+    if (bStarted == 1 || value >= 1000){ value = utoa_digit(dst++, value, 1000); bStarted = 1; }
+    if (bStarted == 1 || value >= 100){ value = utoa_digit(dst++, value, 100); bStarted = 1; }
+    if (bStarted == 1 || value >= 10){ value = utoa_digit(dst++, value, 10); bStarted = 1; }
     *dst++ = '0' + (unsigned char) value;
-    *dst = 0;
+    //*dst = 0;
 }
+
+unsigned char[] DIGITS = "0123456789abcdef";
+unsigned int[] SUB3 = { 30000, 3000, 300, 30 };
+unsigned int[] SUB1 = { 10000, 1000, 100, 10 };
+
+// Simple decimal utoa() without using multiply or divide
+void utoa10(unsigned int value, unsigned char* dst) {
+    unsigned char bStarted = 0;
+    for( unsigned char i: 0..3) {
+        unsigned char digit = 0;
+        unsigned int sub1 = SUB1[i];
+        if(value>=sub1) {
+            unsigned int sub3 = SUB3[i];
+            while(value>=sub3) { digit += 3; value -= sub3;  bStarted = 1; }
+            while(value>=sub1) { digit += 1; value -= sub1;  bStarted = 1; }
+        }
+        if(bStarted!=0) {
+            *dst++ = DIGITS[digit];
+        }
+    }
+    *dst++ = DIGITS[(unsigned char) value];
+    //*dst = 0;
+}
+
+unsigned int[] SUB = { 30000, 10000, 3000, 1000, 300, 100, 30, 10 };
+unsigned char[] VAL = { 3, 1, 3, 1, 3, 1, 3, 1 };
+
+// Decimal utoa() without using multiply or divide
+void utoa10b(unsigned int value, unsigned char* dst) {
+    unsigned char bStarted = 0;
+    unsigned char digit = 0;
+    for( unsigned char i: 0..7) {
+        while(value>=SUB[i]) { digit += VAL[i]; value -= SUB[i];  bStarted = 1; }
+        if((i&1)!=0) {
+            if(bStarted!=0) {
+                *dst++ = DIGITS[digit];
+            }
+            digit = 0;
+        }
+    }
+    *dst++ = DIGITS[(unsigned char) value];
+    *dst = 0;
+}
\ No newline at end of file
diff --git a/src/test/ref/hex2dec.asm b/src/test/ref/hex2dec.asm
index b080e5c44..4fbbca239 100644
--- a/src/test/ref/hex2dec.asm
+++ b/src/test/ref/hex2dec.asm
@@ -6,7 +6,8 @@
   .label raster = $d012
   .label bordercol = $d020
 main: {
-    .label _1 = 8
+    .label _1 = 4
+    .label time_start = 8
     sei
     jsr cls
   b1:
@@ -20,112 +21,129 @@ main: {
     bne b1
     lda #1
     sta bordercol
+    lda raster
+    sta time_start
     lda #<$400
-    sta utoa.dst
+    sta utoa10b.dst
     lda #>$400
-    sta utoa.dst+1
+    sta utoa10b.dst+1
     lda #0
-    sta utoa.value
-    sta utoa.value+1
-    jsr utoa
+    sta utoa10b.value
+    sta utoa10b.value+1
+    jsr utoa10b
     inc bordercol
     lda #<$400+$28
-    sta utoa.dst
+    sta utoa10b.dst
     lda #>$400+$28
-    sta utoa.dst+1
+    sta utoa10b.dst+1
     lda #<$4d2
-    sta utoa.value
+    sta utoa10b.value
     lda #>$4d2
-    sta utoa.value+1
-    jsr utoa
+    sta utoa10b.value+1
+    jsr utoa10b
     inc bordercol
     lda #<$400+$28+$28
-    sta utoa.dst
+    sta utoa10b.dst
     lda #>$400+$28+$28
-    sta utoa.dst+1
+    sta utoa10b.dst+1
     lda #<$162e
-    sta utoa.value
+    sta utoa10b.value
     lda #>$162e
-    sta utoa.value+1
-    jsr utoa
+    sta utoa10b.value+1
+    jsr utoa10b
     inc bordercol
     lda #<$400+$28+$28+$28
-    sta utoa.dst
+    sta utoa10b.dst
     lda #>$400+$28+$28+$28
-    sta utoa.dst+1
+    sta utoa10b.dst+1
     lda #<$270f
-    sta utoa.value
+    sta utoa10b.value
     lda #>$270f
-    sta utoa.value+1
-    jsr utoa
+    sta utoa10b.value+1
+    jsr utoa10b
     inc bordercol
     lda #<$400+$28+$28+$28+$28
-    sta utoa.dst
+    sta utoa10b.dst
     lda #>$400+$28+$28+$28+$28
-    sta utoa.dst+1
-    lda #<$ea5f
-    sta utoa.value
-    lda #>$ea5f
-    sta utoa.value+1
-    jsr utoa
+    sta utoa10b.dst+1
+    lda #<$e608
+    sta utoa10b.value
+    lda #>$e608
+    sta utoa10b.value+1
+    jsr utoa10b
+    ldx raster
     lda #0
     sta bordercol
-    jmp b1
-}
-// utoa(word zeropage(2) value, byte* zeropage(4) dst)
-utoa: {
-    .label value = 2
-    .label dst = 4
-    lda value+1
-    cmp #>$2710
-    bcc !+
-    beq !b5+
-    jmp b5
-  !b5:
-    lda value
-    cmp #<$2710
-    bcc !b5+
-    jmp b5
-  !b5:
-  !:
+    txa
+    sec
+    sbc time_start
+    sta utoa10b.value
+    lda #0
+    sta utoa10b.value+1
+    lda #<$400+$28+$28+$28+$28+$50
+    sta utoa10b.dst
+    lda #>$400+$28+$28+$28+$28+$50
+    sta utoa10b.dst+1
+    jsr utoa10b
     ldx #0
-  b1:
-    cpx #1
-    beq b6
-    lda value+1
-    cmp #>$3e8
-    bcc !+
-    bne b6
-    lda value
-    cmp #<$3e8
-    bcs b6
-  !:
-  b2:
-    cpx #1
-    beq b7
-    lda value+1
-    cmp #>$64
-    bcc !+
-    bne b7
-    lda value
-    cmp #<$64
-    bcs b7
-  !:
   b3:
-    cpx #1
-    beq b8
-    lda value+1
-    cmp #>$a
-    bcc !+
-    bne b8
-    lda value
-    cmp #<$a
-    bcs b8
+    lda msg,x
+    sta $400+$28+$28+$28+$28+$50+3,x
+    inx
+    lda msg,x
+    cmp #0
+    bne b3
+    jmp b1
+    msg: .text "raster lines@"
+}
+// Decimal utoa() without using multiply or divide
+// utoa10b(word zeropage(2) value, byte* zeropage(6) dst)
+utoa10b: {
+    .label value = 2
+    .label digit = 4
+    .label dst = 6
+    .label bStarted = 5
+    lda #0
+    sta bStarted
+    sta digit
+    tax
+  b1:
+    txa
+    asl
+    tay
+    lda SUB+1,y
+    cmp value+1
+    bne !+
+    lda SUB,y
+    cmp value
+    beq b2
   !:
-  b4:
+    bcc b2
+    txa
+    and #1
+    cmp #0
+    beq b6
+    lda bStarted
+    cmp #0
+    beq b7
+    ldy digit
+    lda DIGITS,y
+    ldy #0
+    sta (dst),y
+    inc dst
+    bne !+
+    inc dst+1
+  !:
+  b7:
+    lda #0
+    sta digit
+  b6:
+    inx
+    cpx #8
+    bne b1
     lda value
-    clc
-    adc #'0'
+    tay
+    lda DIGITS,y
     ldy #0
     sta (dst),y
     inc dst
@@ -136,125 +154,23 @@ utoa: {
     tay
     sta (dst),y
     rts
-  b8:
-    lda #$a
-    sta append.sub
-    lda #0
-    sta append.sub+1
-    jsr append
-    inc dst
-    bne !+
-    inc dst+1
-  !:
-    jmp b4
-  b7:
-    lda #$64
-    sta append.sub
-    lda #0
-    sta append.sub+1
-    jsr append
-    inc dst
-    bne !+
-    inc dst+1
-  !:
-    ldx #1
-    jmp b3
-  b6:
-    lda #<$3e8
-    sta append.sub
-    lda #>$3e8
-    sta append.sub+1
-    jsr append
-    inc dst
-    bne !+
-    inc dst+1
-  !:
-    ldx #1
-    jmp b2
-  b5:
-    lda #<$2710
-    sta append.sub
-    lda #>$2710
-    sta append.sub+1
-    jsr append
-    inc dst
-    bne !+
-    inc dst+1
-  !:
-    ldx #1
-    jmp b1
-}
-// simple 'utoa' without using multiply or divide
-// append(byte* zeropage(4) dst, word zeropage(2) value, word zeropage(6) sub)
-append: {
-    .label _0 = 9
-    .label sub3 = 9
-    .label value = 2
-    .label dst = 4
-    .label return = 2
-    .label sub = 6
-    lda #'0'
-    ldy #0
-    sta (dst),y
-    lda sub
-    asl
-    sta _0
-    lda sub+1
-    rol
-    sta _0+1
-    lda sub3
-    clc
-    adc sub
-    sta sub3
-    lda sub3+1
-    adc sub+1
-    sta sub3+1
-  b1:
-    lda sub3+1
-    cmp value+1
-    bne !+
-    lda sub3
-    cmp value
-  !:
-    bcc b2
-    beq b2
-  b3:
-    lda sub+1
-    cmp value+1
-    bne !+
-    lda sub
-    cmp value
-  !:
-    bcc b4
-    beq b4
-    rts
-  b4:
-    ldy #0
-    lda (dst),y
-    clc
-    adc #1
-    sta (dst),y
-    lda value
-    sec
-    sbc sub
-    sta value
-    lda value+1
-    sbc sub+1
-    sta value+1
-    jmp b3
   b2:
-    lda #3
+    lda VAL,x
     clc
-    ldy #0
-    adc (dst),y
-    sta (dst),y
-    lda value
+    adc digit
+    sta digit
+    txa
+    asl
+    tay
     sec
-    sbc sub3
+    lda value
+    sbc SUB,y
     sta value
     lda value+1
-    sbc sub3+1
+    sbc SUB+1,y
     sta value+1
+    lda #1
+    sta bStarted
     jmp b1
 }
 cls: {
@@ -280,3 +196,6 @@ cls: {
     bne b1
     rts
 }
+  DIGITS: .text "0123456789abcdef@"
+  SUB: .word $7530, $2710, $bb8, $3e8, $12c, $64, $1e, $a
+  VAL: .byte 3, 1, 3, 1, 3, 1, 3, 1

From 5d988dd859a1169fc4faaeabeb6fc04f6c6c8ceb Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Mon, 20 May 2019 10:36:58 +0200
Subject: [PATCH 52/93] Rafactoring pass 2

---
 .../java/dk/camelot64/kickc/Compiler.java     |  9 +--
 .../dk/camelot64/kickc/test/TestPrograms.java |  1 -
 src/test/ref/pointer-plus-0.asm               |  8 +-
 src/test/ref/sandbox.asm                      |  2 +-
 src/test/ref/semi-struct-1.asm                | 16 ++--
 src/test/ref/semi-struct-2.asm                | 74 +++++++++----------
 src/test/ref/sizeof-expr.asm                  |  2 +-
 src/test/ref/test-comparisons-word.asm        |  4 +-
 8 files changed, 55 insertions(+), 61 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index d7e23c9c2..ca1139264 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -231,12 +231,12 @@ public class Compiler {
 
    private void pass2Optimize() {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
-      optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new PassNAddNumberTypeConversions(program));
       optimizations.add(new PassNAddArrayNumberTypeConversions(program));
       optimizations.add(new PassNDowngradeBytePlusWord(program));
       optimizations.add(new PassNTypeInference(program));
       optimizations.add(new PassNTypeIdSimplification(program));
+      optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new Pass2CullEmptyBlocks(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
@@ -257,21 +257,18 @@ public class Compiler {
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
       optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new Pass2TypeInference(program));
-      optimizations.add(new PassNEliminateUnusedVars(program, true));
       optimizations.add(new Pass2EliminateRedundantCasts(program));
-      optimizations.add(new Pass2EliminateUnusedBlocks(program));
       optimizations.add(new Pass2RangeResolving(program));
       optimizations.add(new Pass2ComparisonOptimization(program));
       optimizations.add(new Pass2ConstantCallPointerIdentification(program));
-      optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new Pass2InlineCast(program));
       optimizations.add(new PassNCastSimplification(program));
-      optimizations.add(new PassNStatementIndices(program));
-      optimizations.add(new PassNVariableReferenceInfos(program));
       optimizations.add(new Pass2InlineDerefIdx(program));
       optimizations.add(new Pass2DeInlineWordDerefIdx(program));
       optimizations.add(new PassNSimplifyConstantZero(program));
       optimizations.add(new PassNSimplifyExpressionWithZero(program));
+      optimizations.add(new PassNEliminateUnusedVars(program, true));
+      optimizations.add(new Pass2EliminateUnusedBlocks(program));
       pass2Execute(optimizations);
    }
 
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index c4a10ab7a..39ac64c0b 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,7 +63,6 @@ public class TestPrograms {
 
     */
 
-
    @Test
    public void testHex2Dec() throws IOException, URISyntaxException {
       compileAndCompare("hex2dec");
diff --git a/src/test/ref/pointer-plus-0.asm b/src/test/ref/pointer-plus-0.asm
index 3670d3426..8fc352c78 100644
--- a/src/test/ref/pointer-plus-0.asm
+++ b/src/test/ref/pointer-plus-0.asm
@@ -4,15 +4,15 @@
 .pc = $80d "Program"
 main: {
     .label SCREEN = $400
-    .label _1 = 2
-    .label _3 = 2
+    .label _0 = 2
+    .label _2 = 2
     lda #<msg1
     sta first.msg
     lda #>msg1
     sta first.msg+1
     jsr first
     ldy #0
-    lda (_1),y
+    lda (_0),y
     sta SCREEN
     lda #<msg2
     sta first.msg
@@ -20,7 +20,7 @@ main: {
     sta first.msg+1
     jsr first
     ldy #0
-    lda (_3),y
+    lda (_2),y
     sta SCREEN+1
     rts
 }
diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm
index 559fa3c11..7abbd0312 100644
--- a/src/test/ref/sandbox.asm
+++ b/src/test/ref/sandbox.asm
@@ -545,9 +545,9 @@ append: {
     bne !+
     lda sub
     cmp value
+    beq b2
   !:
     bcc b2
-    beq b2
     rts
   b2:
     ldy #0
diff --git a/src/test/ref/semi-struct-1.asm b/src/test/ref/semi-struct-1.asm
index 77e06cc4d..981c26588 100644
--- a/src/test/ref/semi-struct-1.asm
+++ b/src/test/ref/semi-struct-1.asm
@@ -22,7 +22,7 @@ main: {
 }
 // Print points
 print_points: {
-    .label pointXpos1__0 = 9
+    .label point = 9
     .label i = 2
     jsr print_cls
     lda #<$400
@@ -42,15 +42,15 @@ print_points: {
     tya
     clc
     adc #<points
-    sta pointXpos1__0
+    sta point
     lda #>points
     adc #0
-    sta pointXpos1__0+1
+    sta point+1
     ldx points,y
     jsr print_byte
     jsr print_str
     ldy #1
-    lda (pointXpos1__0),y
+    lda (point),y
     tax
     jsr print_byte
     jsr print_ln
@@ -168,7 +168,7 @@ print_cls: {
 }
 // Initialize points
 init_points: {
-    .label pointXpos1__0 = 3
+    .label getPoint1_return = 3
     .label pos = 2
     lda #$a
     sta pos
@@ -180,17 +180,17 @@ init_points: {
     tya
     clc
     adc #<points
-    sta pointXpos1__0
+    sta getPoint1_return
     lda #>points
     adc #0
-    sta pointXpos1__0+1
+    sta getPoint1_return+1
     lda pos
     sta points,y
     lda #$a
     clc
     adc pos
     ldy #1
-    sta (pointXpos1__0),y
+    sta (getPoint1_return),y
     clc
     adc #$a
     sta pos
diff --git a/src/test/ref/semi-struct-2.asm b/src/test/ref/semi-struct-2.asm
index 0429bcc2f..03cc33c2c 100644
--- a/src/test/ref/semi-struct-2.asm
+++ b/src/test/ref/semi-struct-2.asm
@@ -301,7 +301,6 @@ print_ln: {
 // printEntry(byte* zeropage(4) entry)
 printEntry: {
     .label entry = 4
-    .label entryBufDisk1__0 = 4
     lda print_line_cursor
     sta print_char_cursor
     lda print_line_cursor+1
@@ -312,10 +311,10 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #0
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w
     iny
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
@@ -333,10 +332,10 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #2
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w
     iny
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
@@ -354,10 +353,10 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #4
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w
     iny
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
@@ -375,10 +374,10 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #6
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w
     iny
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
@@ -396,7 +395,7 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #8
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     tax
     jsr print_byte
     lda print_line_cursor
@@ -414,7 +413,7 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #9
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     tax
     jsr print_byte
     lda print_line_cursor
@@ -432,7 +431,7 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #$a
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     tax
     jsr print_byte
     lda print_line_cursor
@@ -450,7 +449,7 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #$b
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     tax
     jsr print_byte
     lda print_line_cursor
@@ -468,10 +467,10 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #$c
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w
     iny
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
@@ -489,7 +488,7 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #$e
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     tax
     jsr print_byte
     lda print_line_cursor
@@ -507,7 +506,7 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #$f
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     tax
     jsr print_byte
     lda print_line_cursor
@@ -525,7 +524,7 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #$10
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     tax
     jsr print_byte
     lda print_line_cursor
@@ -543,7 +542,7 @@ printEntry: {
     sta print_str.str+1
     jsr print_str
     ldy #$11
-    lda (entryBufDisk1__0),y
+    lda (entry),y
     tax
     jsr print_byte
     lda print_line_cursor
@@ -616,7 +615,6 @@ initEntry: {
     .label _7 = 6
     .label _17 = 6
     .label entry = 2
-    .label entryBufDisk1__0 = 2
     txa
     clc
     adc #<$1111
@@ -626,10 +624,10 @@ initEntry: {
     sta _1+1
     ldy #0
     lda _1
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     iny
     lda _1+1
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #<$2222
@@ -639,10 +637,10 @@ initEntry: {
     sta _3+1
     ldy #2
     lda _3
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     iny
     lda _3+1
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #<$3333
@@ -652,10 +650,10 @@ initEntry: {
     sta _5+1
     ldy #4
     lda _5
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     iny
     lda _5+1
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #<$4444
@@ -665,30 +663,30 @@ initEntry: {
     sta _7+1
     ldy #6
     lda _7
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     iny
     lda _7+1
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #$55
     ldy #8
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #$66
     ldy #9
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #$77
     ldy #$a
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #$88
     ldy #$b
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #<$9999
@@ -698,30 +696,30 @@ initEntry: {
     sta _17+1
     ldy #$c
     lda _17
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     iny
     lda _17+1
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #$aa
     ldy #$e
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #$bb
     ldy #$f
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #$cc
     ldy #$10
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     txa
     clc
     adc #$dd
     ldy #$11
-    sta (entryBufDisk1__0),y
+    sta (entry),y
     rts
 }
 // Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word
diff --git a/src/test/ref/sizeof-expr.asm b/src/test/ref/sizeof-expr.asm
index 5720d470d..06f2d6a54 100644
--- a/src/test/ref/sizeof-expr.asm
+++ b/src/test/ref/sizeof-expr.asm
@@ -2,10 +2,10 @@
 .pc = $801 "Basic"
 :BasicUpstart(main)
 .pc = $80d "Program"
-  .label SCREEN = $400
   .const SIZEOF_BYTE = 1
   .const SIZEOF_WORD = 2
   .const SIZEOF_POINTER = 2
+  .label SCREEN = $400
   .const SIZEOF_NUMBER = $ff
 main: {
     .const sz = $f
diff --git a/src/test/ref/test-comparisons-word.asm b/src/test/ref/test-comparisons-word.asm
index 05ed548ab..fed328414 100644
--- a/src/test/ref/test-comparisons-word.asm
+++ b/src/test/ref/test-comparisons-word.asm
@@ -205,9 +205,9 @@ compare: {
     bne !+
     lda w1
     cmp w2
+    beq b11
   !:
     bcc b11
-    beq b11
     lda #TT
     sta r
     jmp b22
@@ -247,9 +247,9 @@ compare: {
     bne !+
     lda w2
     cmp w1
+    beq b13
   !:
     bcc b13
-    beq b13
     lda #TT
     sta r
     jmp b24

From 77d24eddc654032b0a5899526a733ea708c7c80a Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Mon, 20 May 2019 10:47:53 +0200
Subject: [PATCH 53/93] Rafactoring pass 2

---
 .../java/dk/camelot64/kickc/Compiler.java     |  1 -
 .../kickc/passes/Pass2TypeInference.java      | 33 -------------------
 src/test/ref/inline-pointer-2.asm             |  3 +-
 3 files changed, 2 insertions(+), 35 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2TypeInference.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index ca1139264..d988613f4 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -256,7 +256,6 @@ public class Compiler {
       optimizations.add(new Pass2ConstantStringConsolidation(program));
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
       optimizations.add(new PassNAddTypeConversionAssignment(program));
-      optimizations.add(new Pass2TypeInference(program));
       optimizations.add(new Pass2EliminateRedundantCasts(program));
       optimizations.add(new Pass2RangeResolving(program));
       optimizations.add(new Pass2ComparisonOptimization(program));
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2TypeInference.java b/src/main/java/dk/camelot64/kickc/passes/Pass2TypeInference.java
deleted file mode 100644
index b59532300..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2TypeInference.java
+++ /dev/null
@@ -1,33 +0,0 @@
-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.StatementAssignment;
-import dk.camelot64.kickc.model.statements.StatementCall;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-
-/**
- * Pass through the all statements (re-)inferring types of variables.
- */
-public class Pass2TypeInference extends Pass2SsaOptimization {
-
-   public Pass2TypeInference(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
-         for(Statement statement : block.getStatements()) {
-            if(statement instanceof StatementAssignment) {
-               SymbolTypeInference.inferAssignmentLValue(getProgram(), (StatementAssignment) statement, true);
-            } else if(statement instanceof StatementCall) {
-               SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, true);
-            }
-         }
-      }
-      return false;
-   }
-
-}
diff --git a/src/test/ref/inline-pointer-2.asm b/src/test/ref/inline-pointer-2.asm
index 32a924a78..8cd4e7021 100644
--- a/src/test/ref/inline-pointer-2.asm
+++ b/src/test/ref/inline-pointer-2.asm
@@ -3,7 +3,8 @@
 :BasicUpstart(main)
 .pc = $80d "Program"
 main: {
+    .label screen = 4*$100+$28
     lda #'a'
-    sta 4*$100+$28
+    sta screen
     rts
 }

From 27c6c3fb8651a72a63928746b6e96a83f4fc770c Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Mon, 20 May 2019 10:54:06 +0200
Subject: [PATCH 54/93] Rafactoring pass 2

---
 src/main/java/dk/camelot64/kickc/Compiler.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index d988613f4..252e07f27 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -250,16 +250,16 @@ public class Compiler {
       optimizations.add(new Pass2ConstantRValueConsolidation(program));
       optimizations.add(new Pass2ConstantIdentification(program));
       optimizations.add(new Pass2ConstantValues(program));
-      optimizations.add(new PassNStatementIndices(program));
-      optimizations.add(new PassNVariableReferenceInfos(program));
+      optimizations.add(new Pass2ConstantCallPointerIdentification(program));
       optimizations.add(new Pass2ConstantIfs(program));
       optimizations.add(new Pass2ConstantStringConsolidation(program));
+      optimizations.add(new PassNStatementIndices(program));
+      optimizations.add(new PassNVariableReferenceInfos(program));
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
       optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new Pass2EliminateRedundantCasts(program));
       optimizations.add(new Pass2RangeResolving(program));
       optimizations.add(new Pass2ComparisonOptimization(program));
-      optimizations.add(new Pass2ConstantCallPointerIdentification(program));
       optimizations.add(new Pass2InlineCast(program));
       optimizations.add(new PassNCastSimplification(program));
       optimizations.add(new Pass2InlineDerefIdx(program));

From 2b26c813d989907f0ead3bed66e975c0b0aebfca Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Mon, 20 May 2019 11:01:58 +0200
Subject: [PATCH 55/93] Rafactoring pass 2

---
 src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm             | 8 ++++----
 src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm             | 8 ++++++++
 src/main/java/dk/camelot64/kickc/Compiler.java            | 2 +-
 ...rd.java => PassNDowngradeConstantTypeConversions.java} | 4 ++--
 src/test/ref/linegen.asm                                  | 5 ++---
 5 files changed, 17 insertions(+), 10 deletions(-)
 create mode 100644 src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm
 rename src/main/java/dk/camelot64/kickc/passes/{PassNDowngradeBytePlusWord.java => PassNDowngradeConstantTypeConversions.java} (96%)

diff --git a/src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm b/src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm
index a704a0e79..ee4169530 100644
--- a/src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm
+++ b/src/main/fragment/vduz1=vwuz2_dword_vbuc1.asm
@@ -1,8 +1,8 @@
-lda #<{c1}
-sta {z1}
-lda #>{c1}
-sta {z1}+1
 lda {z2}
 sta {z1}+2
 lda {z2}+1
 sta {z1}+3
+lda #{c1}
+sta {z1}
+lda #0
+sta {z1}+1
diff --git a/src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm b/src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm
new file mode 100644
index 000000000..a704a0e79
--- /dev/null
+++ b/src/main/fragment/vduz1=vwuz2_dword_vwuc1.asm
@@ -0,0 +1,8 @@
+lda #<{c1}
+sta {z1}
+lda #>{c1}
+sta {z1}+1
+lda {z2}
+sta {z1}+2
+lda {z2}+1
+sta {z1}+3
diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 252e07f27..5c86cc61e 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -233,7 +233,7 @@ public class Compiler {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
       optimizations.add(new PassNAddNumberTypeConversions(program));
       optimizations.add(new PassNAddArrayNumberTypeConversions(program));
-      optimizations.add(new PassNDowngradeBytePlusWord(program));
+      optimizations.add(new PassNDowngradeConstantTypeConversions(program));
       optimizations.add(new PassNTypeInference(program));
       optimizations.add(new PassNTypeIdSimplification(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java
similarity index 96%
rename from src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java
rename to src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java
index b3f819d53..85a6db2cb 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeBytePlusWord.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java
@@ -13,9 +13,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
 /**
  * Downgrade any number expression cast that are part of a WORD+NUMBER expression to BYTE if the number is small enough to fit in the byte.
  */
-public class PassNDowngradeBytePlusWord extends Pass2SsaOptimization {
+public class PassNDowngradeConstantTypeConversions extends Pass2SsaOptimization {
 
-   public PassNDowngradeBytePlusWord(Program program) {
+   public PassNDowngradeConstantTypeConversions(Program program) {
       super(program);
    }
 
diff --git a/src/test/ref/linegen.asm b/src/test/ref/linegen.asm
index 4cbd79681..4b4fcd8a9 100644
--- a/src/test/ref/linegen.asm
+++ b/src/test/ref/linegen.asm
@@ -335,14 +335,13 @@ lin16u_gen: {
     sta step
     lda stepf+1
     sta step+1
-    lda #<0
-    sta val
-    sta val+1
     lda min
     sta val+2
     lda min+1
     sta val+3
     lda #0
+    sta val
+    sta val+1
     sta i
     sta i+1
   b1:

From bc699a9e2727f26f84e0b3612265fc6101cf3092 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Mon, 20 May 2019 23:41:58 +0200
Subject: [PATCH 56/93] Added utoa16(). Fixed early constant identification not
 taking procedure parameters into account.

---
 .../Pass1EarlyConstantIdentification.java     |  46 +++--
 src/test/kc/hex2dec.kc                        |  91 ++++------
 src/test/ref/hex2dec.asm                      | 166 ++++++++++++------
 3 files changed, 187 insertions(+), 116 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1EarlyConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass1EarlyConstantIdentification.java
index faceeca37..8c8339dd9 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1EarlyConstantIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass1EarlyConstantIdentification.java
@@ -6,12 +6,15 @@ import dk.camelot64.kickc.model.operators.OperatorCastPtr;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementLValue;
+import dk.camelot64.kickc.model.symbols.Procedure;
+import dk.camelot64.kickc.model.symbols.Scope;
 import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.values.ConstantValue;
 import dk.camelot64.kickc.model.values.VariableRef;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 /** Identify any variable that are clearly constant. */
 public class Pass1EarlyConstantIdentification extends Pass1Base {
@@ -26,18 +29,20 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
       for(Variable variable : getProgram().getScope().getAllVariables(true)) {
          VariableRef variableRef = variable.getRef();
          if(!variable.isDeclaredConstant() && !variable.isDeclaredVolatile() && !variableRef.isIntermediate()) {
-            Collection<StatementLValue> assignments = getAssignments(variable);
-            if(assignments.size() == 1) {
-               if(!Pass2ConstantIdentification.isAddressOfUsed(variableRef, getProgram())) {
-                  StatementLValue assignment = assignments.iterator().next();
-                  if(assignment instanceof StatementAssignment) {
-                     StatementAssignment assign = (StatementAssignment) assignment;
-                     if(assign.getrValue1() == null && assign.getOperator() == null && assign.getrValue2() instanceof ConstantValue) {
-                        getLog().append("Identified constant variable " + variable.toString(getProgram()));
-                        earlyConstants.add(variableRef);
-                     } else if(assign.getrValue1() == null && assign.getOperator() instanceof OperatorCastPtr && assign.getrValue2() instanceof ConstantValue) {
-                        getLog().append("Identified constant variable " + variable.toString(getProgram()));
-                        earlyConstants.add(variableRef);
+            if(!isParameter(variableRef)) {
+               Collection<StatementLValue> assignments = getAssignments(variable);
+               if(assignments.size() == 1) {
+                  if(!Pass2ConstantIdentification.isAddressOfUsed(variableRef, getProgram())) {
+                     StatementLValue assignment = assignments.iterator().next();
+                     if(assignment instanceof StatementAssignment) {
+                        StatementAssignment assign = (StatementAssignment) assignment;
+                        if(assign.getrValue1() == null && assign.getOperator() == null && assign.getrValue2() instanceof ConstantValue) {
+                           getLog().append("Identified constant variable " + variable.toString(getProgram()));
+                           earlyConstants.add(variableRef);
+                        } else if(assign.getrValue1() == null && assign.getOperator() instanceof OperatorCastPtr && assign.getrValue2() instanceof ConstantValue) {
+                           getLog().append("Identified constant variable " + variable.toString(getProgram()));
+                           earlyConstants.add(variableRef);
+                        }
                      }
                   }
                }
@@ -48,6 +53,23 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
       return false;
    }
 
+   /**
+    * Examines whether a variale is a procedure parameter
+    * @param variableRef The variable
+    * @return true if the variable is a procedure parameter
+    */
+   public boolean isParameter(VariableRef variableRef) {
+      Variable var = getScope().getVariable(variableRef);
+      Scope varScope = var.getScope();
+      if(varScope instanceof Procedure) {
+         List<Variable> parameters = ((Procedure) varScope).getParameters();
+         if(parameters.contains(var))
+            return true;
+
+      }
+      return false;
+   }
+
    /**
     * Find all assignments of a variable.
     *
diff --git a/src/test/kc/hex2dec.kc b/src/test/kc/hex2dec.kc
index f27a6e7d4..d44d936df 100644
--- a/src/test/kc/hex2dec.kc
+++ b/src/test/kc/hex2dec.kc
@@ -14,15 +14,15 @@ void main() {
         unsigned char *screen = 0x0400;
         *bordercol = 1;
         unsigned char time_start = *raster;
-        utoa10b(00000, screen); (*bordercol)++; screen += 40;
-        utoa10b(01234, screen); (*bordercol)++; screen += 40;
-        utoa10b(05678, screen); (*bordercol)++; screen += 40;
-        utoa10b(09999, screen); (*bordercol)++; screen += 40;
-        utoa10b(58888, screen);
+        utoa16w(00000, screen); (*bordercol)++; screen += 40;
+        utoa16w(01234, screen); (*bordercol)++; screen += 40;
+        utoa16w(05678, screen); (*bordercol)++; screen += 40;
+        utoa16w(09999, screen); (*bordercol)++; screen += 40;
+        utoa16w(58888, screen);
         unsigned char time_end = *raster;
         *bordercol = 0;
         unsigned char time = time_end - time_start;
-        utoa10b((unsigned int)time, screen+80);
+        utoa10w((unsigned int)time, screen+80);
         byte[] msg = "raster lines";
         for( byte i=0; msg[i]!=0; i++ ) (screen+80+3)[i] = msg[i];
         //for( byte* m="lines", s=screen+80+6 ;*m!=0;m++,s++) *s = *m;
@@ -40,58 +40,20 @@ const unsigned char RADIX_OCTAL = 8;
 const unsigned char RADIX_DECIMAL = 10;
 const unsigned char RADIX_HEX = 16;
 
-// simple 'utoa' without using multiply or divide
-unsigned int utoa_digit(unsigned char *dst, unsigned int value, unsigned int sub){
-    unsigned char digit = 0;
-    unsigned int sub3 = sub*2+sub;
-    while (value >= sub3){ digit += 3; value -= sub3; }
-    while (value >= sub){ ++digit; value -= sub; }
-    *dst = DIGITS[digit];
-    return value;
-}
-
-void utoa(unsigned int value, unsigned char *dst){
-    unsigned char bStarted = 0;
-    if (bStarted == 1 || value >= 10000){ value = utoa_digit(dst++, value, 10000); bStarted = 1; }
-    if (bStarted == 1 || value >= 1000){ value = utoa_digit(dst++, value, 1000); bStarted = 1; }
-    if (bStarted == 1 || value >= 100){ value = utoa_digit(dst++, value, 100); bStarted = 1; }
-    if (bStarted == 1 || value >= 10){ value = utoa_digit(dst++, value, 10); bStarted = 1; }
-    *dst++ = '0' + (unsigned char) value;
-    //*dst = 0;
-}
-
+// Digits used for utoa()
 unsigned char[] DIGITS = "0123456789abcdef";
-unsigned int[] SUB3 = { 30000, 3000, 300, 30 };
-unsigned int[] SUB1 = { 10000, 1000, 100, 10 };
 
-// Simple decimal utoa() without using multiply or divide
-void utoa10(unsigned int value, unsigned char* dst) {
-    unsigned char bStarted = 0;
-    for( unsigned char i: 0..3) {
-        unsigned char digit = 0;
-        unsigned int sub1 = SUB1[i];
-        if(value>=sub1) {
-            unsigned int sub3 = SUB3[i];
-            while(value>=sub3) { digit += 3; value -= sub3;  bStarted = 1; }
-            while(value>=sub1) { digit += 1; value -= sub1;  bStarted = 1; }
-        }
-        if(bStarted!=0) {
-            *dst++ = DIGITS[digit];
-        }
-    }
-    *dst++ = DIGITS[(unsigned char) value];
-    //*dst = 0;
-}
-
-unsigned int[] SUB = { 30000, 10000, 3000, 1000, 300, 100, 30, 10 };
-unsigned char[] VAL = { 3, 1, 3, 1, 3, 1, 3, 1 };
+// Subtraction values used for decimal utoa()
+unsigned int[] UTOA10_SUB = { 30000, 10000, 3000, 1000, 300, 100, 30, 10 };
+// Digit addition values used for decimal utoa()
+unsigned char[] UTOA10_VAL = { 3, 1, 3, 1, 3, 1, 3, 1 };
 
 // Decimal utoa() without using multiply or divide
-void utoa10b(unsigned int value, unsigned char* dst) {
+void utoa10w(unsigned int value, unsigned char* dst) {
     unsigned char bStarted = 0;
     unsigned char digit = 0;
     for( unsigned char i: 0..7) {
-        while(value>=SUB[i]) { digit += VAL[i]; value -= SUB[i];  bStarted = 1; }
+        while(value>=UTOA10_SUB[i]) { digit += UTOA10_VAL[i]; value -= UTOA10_SUB[i];  bStarted = 1; }
         if((i&1)!=0) {
             if(bStarted!=0) {
                 *dst++ = DIGITS[digit];
@@ -101,4 +63,29 @@ void utoa10b(unsigned int value, unsigned char* dst) {
     }
     *dst++ = DIGITS[(unsigned char) value];
     *dst = 0;
-}
\ No newline at end of file
+}
+
+// Holds the destination address for the hexadecimal utoa()
+unsigned char* utoa16_dst;
+// Holds whether the hexadecimal utoa() has started outputting digits
+unsigned char utoa16_started;
+
+// Hexadecimal utoa() for an unsigned int (16bits)
+void utoa16w(unsigned int value, unsigned char* dst) {
+    utoa16_dst = dst;
+    utoa16_started = 0;
+    utoa16n((>value)>>4);
+    utoa16n((>value)&0x0f);
+    utoa16n((<value)>>4);
+    utoa16_started = 1;
+    utoa16n((<value)&0x0f);
+    *utoa16_dst = 0;
+}
+
+// Hexadecimal utoa() for a single nybble
+void utoa16n(unsigned char nybble) {
+    if(nybble!=0) utoa16_started=1;
+    if(utoa16_started!=0) {
+        *utoa16_dst++ = DIGITS[nybble];
+    }
+}
diff --git a/src/test/ref/hex2dec.asm b/src/test/ref/hex2dec.asm
index 4fbbca239..373a47ff5 100644
--- a/src/test/ref/hex2dec.asm
+++ b/src/test/ref/hex2dec.asm
@@ -5,9 +5,11 @@
   .label control = $d011
   .label raster = $d012
   .label bordercol = $d020
+  .label utoa16_dst = 2
+  .label utoa16_started = 4
 main: {
     .label _1 = 4
-    .label time_start = 8
+    .label time_start = 5
     sei
     jsr cls
   b1:
@@ -23,68 +25,64 @@ main: {
     sta bordercol
     lda raster
     sta time_start
-    lda #<$400
-    sta utoa10b.dst
-    lda #>$400
-    sta utoa10b.dst+1
     lda #0
-    sta utoa10b.value
-    sta utoa10b.value+1
-    jsr utoa10b
+    sta utoa16w.value
+    sta utoa16w.value+1
+    lda #<$400
+    sta utoa16w.dst
+    lda #>$400
+    sta utoa16w.dst+1
+    jsr utoa16w
     inc bordercol
-    lda #<$400+$28
-    sta utoa10b.dst
-    lda #>$400+$28
-    sta utoa10b.dst+1
     lda #<$4d2
-    sta utoa10b.value
+    sta utoa16w.value
     lda #>$4d2
-    sta utoa10b.value+1
-    jsr utoa10b
+    sta utoa16w.value+1
+    lda #<$400+$28
+    sta utoa16w.dst
+    lda #>$400+$28
+    sta utoa16w.dst+1
+    jsr utoa16w
     inc bordercol
-    lda #<$400+$28+$28
-    sta utoa10b.dst
-    lda #>$400+$28+$28
-    sta utoa10b.dst+1
     lda #<$162e
-    sta utoa10b.value
+    sta utoa16w.value
     lda #>$162e
-    sta utoa10b.value+1
-    jsr utoa10b
+    sta utoa16w.value+1
+    lda #<$400+$28+$28
+    sta utoa16w.dst
+    lda #>$400+$28+$28
+    sta utoa16w.dst+1
+    jsr utoa16w
     inc bordercol
-    lda #<$400+$28+$28+$28
-    sta utoa10b.dst
-    lda #>$400+$28+$28+$28
-    sta utoa10b.dst+1
     lda #<$270f
-    sta utoa10b.value
+    sta utoa16w.value
     lda #>$270f
-    sta utoa10b.value+1
-    jsr utoa10b
+    sta utoa16w.value+1
+    lda #<$400+$28+$28+$28
+    sta utoa16w.dst
+    lda #>$400+$28+$28+$28
+    sta utoa16w.dst+1
+    jsr utoa16w
     inc bordercol
-    lda #<$400+$28+$28+$28+$28
-    sta utoa10b.dst
-    lda #>$400+$28+$28+$28+$28
-    sta utoa10b.dst+1
     lda #<$e608
-    sta utoa10b.value
+    sta utoa16w.value
     lda #>$e608
-    sta utoa10b.value+1
-    jsr utoa10b
+    sta utoa16w.value+1
+    lda #<$400+$28+$28+$28+$28
+    sta utoa16w.dst
+    lda #>$400+$28+$28+$28+$28
+    sta utoa16w.dst+1
+    jsr utoa16w
     ldx raster
     lda #0
     sta bordercol
     txa
     sec
     sbc time_start
-    sta utoa10b.value
+    sta utoa10w.value
     lda #0
-    sta utoa10b.value+1
-    lda #<$400+$28+$28+$28+$28+$50
-    sta utoa10b.dst
-    lda #>$400+$28+$28+$28+$28+$50
-    sta utoa10b.dst+1
-    jsr utoa10b
+    sta utoa10w.value+1
+    jsr utoa10w
     ldx #0
   b3:
     lda msg,x
@@ -97,12 +95,16 @@ main: {
     msg: .text "raster lines@"
 }
 // Decimal utoa() without using multiply or divide
-// utoa10b(word zeropage(2) value, byte* zeropage(6) dst)
-utoa10b: {
+// utoa10w(word zeropage(2) value, byte* zeropage(6) dst)
+utoa10w: {
     .label value = 2
     .label digit = 4
     .label dst = 6
     .label bStarted = 5
+    lda #<$400+$28+$28+$28+$28+$50
+    sta dst
+    lda #>$400+$28+$28+$28+$28+$50
+    sta dst+1
     lda #0
     sta bStarted
     sta digit
@@ -111,10 +113,10 @@ utoa10b: {
     txa
     asl
     tay
-    lda SUB+1,y
+    lda UTOA10_SUB+1,y
     cmp value+1
     bne !+
-    lda SUB,y
+    lda UTOA10_SUB,y
     cmp value
     beq b2
   !:
@@ -155,7 +157,7 @@ utoa10b: {
     sta (dst),y
     rts
   b2:
-    lda VAL,x
+    lda UTOA10_VAL,x
     clc
     adc digit
     sta digit
@@ -164,15 +166,72 @@ utoa10b: {
     tay
     sec
     lda value
-    sbc SUB,y
+    sbc UTOA10_SUB,y
     sta value
     lda value+1
-    sbc SUB+1,y
+    sbc UTOA10_SUB+1,y
     sta value+1
     lda #1
     sta bStarted
     jmp b1
 }
+// Hexadecimal utoa() for an unsigned int (16bits)
+// utoa16w(word zeropage(6) value, byte* zeropage(2) dst)
+utoa16w: {
+    .label dst = 2
+    .label value = 6
+    lda value+1
+    lsr
+    lsr
+    lsr
+    lsr
+    tax
+    lda #0
+    sta utoa16_started
+    jsr utoa16n
+    lda value+1
+    ldx #$f
+    axs #0
+    jsr utoa16n
+    lda value
+    lsr
+    lsr
+    lsr
+    lsr
+    tax
+    jsr utoa16n
+    lda value
+    ldx #$f
+    axs #0
+    lda #1
+    sta utoa16_started
+    jsr utoa16n
+    lda #0
+    tay
+    sta (utoa16_dst),y
+    rts
+}
+// Hexadecimal utoa() for a single nybble
+// utoa16n(byte register(X) nybble)
+utoa16n: {
+    cpx #0
+    beq b1
+    lda #1
+    sta utoa16_started
+  b1:
+    lda utoa16_started
+    cmp #0
+    beq breturn
+    lda DIGITS,x
+    ldy #0
+    sta (utoa16_dst),y
+    inc utoa16_dst
+    bne !+
+    inc utoa16_dst+1
+  !:
+  breturn:
+    rts
+}
 cls: {
     .label screen = $400
     .label sc = 2
@@ -196,6 +255,9 @@ cls: {
     bne b1
     rts
 }
+  // Digits used for utoa()
   DIGITS: .text "0123456789abcdef@"
-  SUB: .word $7530, $2710, $bb8, $3e8, $12c, $64, $1e, $a
-  VAL: .byte 3, 1, 3, 1, 3, 1, 3, 1
+  // Subtraction values used for decimal utoa()
+  UTOA10_SUB: .word $7530, $2710, $bb8, $3e8, $12c, $64, $1e, $a
+  // Digit addition values used for decimal utoa()
+  UTOA10_VAL: .byte 3, 1, 3, 1, 3, 1, 3, 1

From b3041e326d2654b21a362019062aa709859f0e89 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 21 May 2019 00:05:17 +0200
Subject: [PATCH 57/93] Optimizing compiler passes

---
 src/main/java/dk/camelot64/kickc/Compiler.java | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 5c86cc61e..67ca190b1 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -378,7 +378,6 @@ public class Compiler {
       new Pass3AssertConstants(program).check();
       new Pass3AssertArrayLengths(program).check();
       new Pass3AssertNoMulDivMod(program).check();
-      new PassNCastSimplification(program).execute();
       new PassNBlockSequencePlanner(program).step();
       // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes
       new Pass3PhiLifting(program).perform();

From 3132790ab5a3450bdc064ec7de9ec42f2e0e3c8a Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 21 May 2019 00:33:36 +0200
Subject: [PATCH 58/93] Added very naive heap implementation.

---
 .../dk/camelot64/kickc/test/TestPrograms.java |  5 ++
 src/test/kc/memory-heap.kc                    | 34 ++++++++++
 src/test/ref/memory-heap.asm                  | 66 +++++++++++++++++++
 3 files changed, 105 insertions(+)
 create mode 100644 src/test/kc/memory-heap.kc
 create mode 100644 src/test/ref/memory-heap.asm

diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 39ac64c0b..4a2357ddc 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -68,6 +68,11 @@ public class TestPrograms {
       compileAndCompare("hex2dec");
    }
 
+   @Test
+   public void testMemoryHeap() throws IOException, URISyntaxException {
+      compileAndCompare("memory-heap");
+   }
+
    @Test
    public void testTernaryInference() throws IOException, URISyntaxException {
       compileAndCompare("ternary-inference");
diff --git a/src/test/kc/memory-heap.kc b/src/test/kc/memory-heap.kc
new file mode 100644
index 000000000..2fa915342
--- /dev/null
+++ b/src/test/kc/memory-heap.kc
@@ -0,0 +1,34 @@
+// Experiments with malloc()
+
+void main() {
+    unsigned char* buf1 = (unsigned char*) malloc(100);
+    unsigned char* buf2 = (unsigned char*) malloc(100);
+    for(unsigned char i:0..99) {
+        buf1[i] = i;
+        buf2[i] = 255-i;
+    }
+    free(buf1);
+    free(buf2);
+    unsigned char* screen = 0x0400;
+    screen[0] = *buf1;
+    screen[1] = *buf2;
+}
+
+// Start of the heap used by malloc()
+unsigned char* HEAP_START = 0xc000;
+
+// Head of the heap. Moved forward for each malloc()
+unsigned char* heap_head = HEAP_START;
+
+// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
+// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
+unsigned char* malloc(unsigned int size) {
+    unsigned char* mem = heap_head;
+    heap_head+= size;
+    return mem;
+}
+
+// A block of memory previously allocated by a call to malloc is deallocated, making it available again for further allocations.
+// If ptr is a null pointer, the function does nothing.
+void free(unsigned char* ptr) {
+}
\ No newline at end of file
diff --git a/src/test/ref/memory-heap.asm b/src/test/ref/memory-heap.asm
new file mode 100644
index 000000000..769942503
--- /dev/null
+++ b/src/test/ref/memory-heap.asm
@@ -0,0 +1,66 @@
+// Experiments with malloc()
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  // Start of the heap used by malloc()
+  .label HEAP_START = $c000
+  .label heap_head = 2
+main: {
+    .label screen = $400
+    .label buf1 = 4
+    .label buf2 = 6
+    lda #<HEAP_START
+    sta heap_head
+    lda #>HEAP_START
+    sta heap_head+1
+    jsr malloc
+    lda malloc.return_2
+    sta malloc.return
+    lda malloc.return_2+1
+    sta malloc.return+1
+    jsr malloc
+    ldy #0
+  b1:
+    tya
+    sta (buf1),y
+    tya
+    eor #$ff
+    clc
+    adc #$ff+1
+    sta (buf2),y
+    iny
+    cpy #$64
+    bne b1
+    jsr free
+    jsr free
+    ldy #0
+    lda (buf1),y
+    sta screen
+    lda (buf2),y
+    sta screen+1
+    rts
+}
+// A block of memory previously allocated by a call to malloc is deallocated, making it available again for further allocations.
+// If ptr is a null pointer, the function does nothing.
+free: {
+    rts
+}
+// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
+// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
+malloc: {
+    .label return = 4
+    .label return_1 = 6
+    .label return_2 = 6
+    lda heap_head
+    sta return_2
+    lda heap_head+1
+    sta return_2+1
+    lda #$64
+    clc
+    adc heap_head
+    sta heap_head
+    bcc !+
+    inc heap_head+1
+  !:
+    rts
+}

From fd259fe47e6c0c7d438913d6e41b417863af80f2 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 21 May 2019 01:45:32 +0200
Subject: [PATCH 59/93] Added pointer to pointer test.

---
 ...eref__deref_pptz1=pbuc1_derefidx_vbuxx.asm |   5 +
 .../_deref_pptz1=_inc__deref_pptz1.asm        |   5 +
 .../dk/camelot64/kickc/test/TestPrograms.java |   5 +
 src/test/kc/hex2dec-ptrptr.kc                 |  38 ++++
 src/test/ref/hex2dec-ptrptr.asm               | 163 ++++++++++++++++++
 5 files changed, 216 insertions(+)
 create mode 100644 src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm
 create mode 100644 src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm
 create mode 100644 src/test/kc/hex2dec-ptrptr.kc
 create mode 100644 src/test/ref/hex2dec-ptrptr.asm

diff --git a/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm b/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm
new file mode 100644
index 000000000..8f14bd50e
--- /dev/null
+++ b/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm
@@ -0,0 +1,5 @@
+ldy #0
+lda {z1}
+sta !+ +1
+lda {c1},x
+!: sta ({z1}),y
diff --git a/src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm b/src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm
new file mode 100644
index 000000000..d066e7dc9
--- /dev/null
+++ b/src/main/fragment/_deref_pptz1=_inc__deref_pptz1.asm
@@ -0,0 +1,5 @@
+ldy #0
+lda ({z1}),y
+clc
+adc #1
+sta ({z1}),y
\ No newline at end of file
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 4a2357ddc..319f189f0 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,11 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testHex2DecPtrPtr() throws IOException, URISyntaxException {
+      compileAndCompare("hex2dec-ptrptr");
+   }
+
    @Test
    public void testHex2Dec() throws IOException, URISyntaxException {
       compileAndCompare("hex2dec");
diff --git a/src/test/kc/hex2dec-ptrptr.kc b/src/test/kc/hex2dec-ptrptr.kc
new file mode 100644
index 000000000..18665be48
--- /dev/null
+++ b/src/test/kc/hex2dec-ptrptr.kc
@@ -0,0 +1,38 @@
+// Testing binary to hex conversion using pointer to pointer
+
+void main() {
+    cls();
+    unsigned char *screen = 0x0400;
+    utoa16w(00000, screen); screen += 40;
+    utoa16w(01234, screen); screen += 40;
+    utoa16w(05678, screen); screen += 40;
+    utoa16w(09999, screen); screen += 40;
+    utoa16w(58888, screen);
+}
+
+void cls() {
+    unsigned char *screen = 0x0400;
+    for( unsigned char *sc: screen..screen+999) *sc=' ';
+}
+
+// Digits used for utoa()
+unsigned char[] DIGITS = "0123456789abcdef";
+
+// Hexadecimal utoa() for an unsigned int (16bits)
+void utoa16w(unsigned int value, unsigned char* dst) {
+    unsigned char started = 0;
+    started = utoa16n((>value)>>4, &dst, started);
+    started = utoa16n((>value)&0x0f, &dst, started);
+    started = utoa16n((<value)>>4, &dst, started);
+    utoa16n((<value)&0x0f, &dst, 1);
+    *dst = 0;
+}
+
+// Hexadecimal utoa() for a single nybble
+unsigned char utoa16n(unsigned char nybble, unsigned **dst, unsigned char started) {
+    if(nybble!=0) started=1;
+    if(started!=0) {
+        *(*dst)++ = DIGITS[nybble];
+    }
+    return started;
+}
diff --git a/src/test/ref/hex2dec-ptrptr.asm b/src/test/ref/hex2dec-ptrptr.asm
new file mode 100644
index 000000000..6dcb61501
--- /dev/null
+++ b/src/test/ref/hex2dec-ptrptr.asm
@@ -0,0 +1,163 @@
+// Testing binary to hex conversion using pointer to pointer
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    jsr cls
+    lda #<$400
+    sta utoa16w.dst
+    lda #>$400
+    sta utoa16w.dst+1
+    lda #0
+    sta utoa16w.value
+    sta utoa16w.value+1
+    jsr utoa16w
+    lda #<$400+$28
+    sta utoa16w.dst
+    lda #>$400+$28
+    sta utoa16w.dst+1
+    lda #<$4d2
+    sta utoa16w.value
+    lda #>$4d2
+    sta utoa16w.value+1
+    jsr utoa16w
+    lda #<$400+$28+$28
+    sta utoa16w.dst
+    lda #>$400+$28+$28
+    sta utoa16w.dst+1
+    lda #<$162e
+    sta utoa16w.value
+    lda #>$162e
+    sta utoa16w.value+1
+    jsr utoa16w
+    lda #<$400+$28+$28+$28
+    sta utoa16w.dst
+    lda #>$400+$28+$28+$28
+    sta utoa16w.dst+1
+    lda #<$270f
+    sta utoa16w.value
+    lda #>$270f
+    sta utoa16w.value+1
+    jsr utoa16w
+    lda #<$400+$28+$28+$28+$28
+    sta utoa16w.dst
+    lda #>$400+$28+$28+$28+$28
+    sta utoa16w.dst+1
+    lda #<$e608
+    sta utoa16w.value
+    lda #>$e608
+    sta utoa16w.value+1
+    jsr utoa16w
+    rts
+}
+// Hexadecimal utoa() for an unsigned int (16bits)
+// utoa16w(word zeropage(2) value, byte* zeropage(4) dst)
+utoa16w: {
+    .label value = 2
+    .label dst = 4
+    lda value+1
+    lsr
+    lsr
+    lsr
+    lsr
+    tax
+    lda #<dst
+    sta utoa16n.dst
+    lda #>dst
+    sta utoa16n.dst+1
+    lda #0
+    sta utoa16n.started
+    jsr utoa16n
+    lda utoa16n.return
+    tay
+    lda value+1
+    ldx #$f
+    axs #0
+    sty utoa16n.started
+    lda #<dst
+    sta utoa16n.dst
+    lda #>dst
+    sta utoa16n.dst+1
+    jsr utoa16n
+    lda utoa16n.return
+    tay
+    lda value
+    lsr
+    lsr
+    lsr
+    lsr
+    tax
+    sty utoa16n.started
+    lda #<dst
+    sta utoa16n.dst
+    lda #>dst
+    sta utoa16n.dst+1
+    jsr utoa16n
+    lda value
+    ldx #$f
+    axs #0
+    lda #<dst
+    sta utoa16n.dst
+    lda #>dst
+    sta utoa16n.dst+1
+    lda #1
+    sta utoa16n.started
+    jsr utoa16n
+    lda #0
+    tay
+    sta (dst),y
+    rts
+}
+// Hexadecimal utoa() for a single nybble
+// utoa16n(byte register(X) nybble, word** zeropage(6) dst, byte zeropage(8) started)
+utoa16n: {
+    .label started = 8
+    .label return = 8
+    .label dst = 6
+    cpx #0
+    beq b1
+    lda #1
+    sta return
+  b1:
+    lda return
+    cmp #0
+    beq breturn
+    ldy #0
+    lda dst
+    sta !++1
+    lda DIGITS,x
+  !:
+    sta (dst),y
+    ldy #0
+    lda (dst),y
+    clc
+    adc #1
+    sta (dst),y
+  breturn:
+    rts
+}
+cls: {
+    .label screen = $400
+    .label sc = 2
+    lda #<screen
+    sta sc
+    lda #>screen
+    sta sc+1
+  b1:
+    lda #' '
+    ldy #0
+    sta (sc),y
+    inc sc
+    bne !+
+    inc sc+1
+  !:
+    lda sc+1
+    cmp #>screen+$3e7+1
+    bne b1
+    lda sc
+    cmp #<screen+$3e7+1
+    bne b1
+    rts
+}
+  // Digits used for utoa()
+  DIGITS: .text "0123456789abcdef@"

From 5f2b798a8aeb763034e0b63b744a13302f322e03 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 21 May 2019 10:23:39 +0200
Subject: [PATCH 60/93] Added test for pointer-to-pointer optimization.

---
 .../fragment/_deref__deref_pptc1=vbuaa.asm    |  2 +
 ...eref__deref_pptz1=pbuc1_derefidx_vbuxx.asm |  2 +-
 .../fragment/_deref__deref_pptz1=vbuaa.asm    |  4 ++
 .../_deref_pptc1=_inc__deref_pptc1.asm        |  4 ++
 .../dk/camelot64/kickc/test/TestPrograms.java | 20 ++++++
 src/test/kc/ptrptr-optimize-0.kc              |  8 +++
 src/test/kc/ptrptr-optimize-1.kc              | 11 ++++
 src/test/kc/ptrptr-optimize-2.kc              | 11 ++++
 src/test/kc/subexpr-optimize-0.kc             | 10 +++
 src/test/ref/hex2dec-ptrptr.asm               | 62 ++++++++-----------
 src/test/ref/ptrptr-optimize-0.asm            | 23 +++++++
 src/test/ref/ptrptr-optimize-1.asm            | 27 ++++++++
 src/test/ref/ptrptr-optimize-2.asm            | 41 ++++++++++++
 src/test/ref/subexpr-optimize-0.asm           | 38 ++++++++++++
 14 files changed, 225 insertions(+), 38 deletions(-)
 create mode 100644 src/main/fragment/_deref__deref_pptc1=vbuaa.asm
 create mode 100644 src/main/fragment/_deref__deref_pptz1=vbuaa.asm
 create mode 100644 src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm
 create mode 100644 src/test/kc/ptrptr-optimize-0.kc
 create mode 100644 src/test/kc/ptrptr-optimize-1.kc
 create mode 100644 src/test/kc/ptrptr-optimize-2.kc
 create mode 100644 src/test/kc/subexpr-optimize-0.kc
 create mode 100644 src/test/ref/ptrptr-optimize-0.asm
 create mode 100644 src/test/ref/ptrptr-optimize-1.asm
 create mode 100644 src/test/ref/ptrptr-optimize-2.asm
 create mode 100644 src/test/ref/subexpr-optimize-0.asm

diff --git a/src/main/fragment/_deref__deref_pptc1=vbuaa.asm b/src/main/fragment/_deref__deref_pptc1=vbuaa.asm
new file mode 100644
index 000000000..a674d8937
--- /dev/null
+++ b/src/main/fragment/_deref__deref_pptc1=vbuaa.asm
@@ -0,0 +1,2 @@
+ldy #0
+sta ({c1}),y
diff --git a/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm b/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm
index 8f14bd50e..1d22175ee 100644
--- a/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm
+++ b/src/main/fragment/_deref__deref_pptz1=pbuc1_derefidx_vbuxx.asm
@@ -2,4 +2,4 @@ ldy #0
 lda {z1}
 sta !+ +1
 lda {c1},x
-!: sta ({z1}),y
+!: sta ($ff),y
diff --git a/src/main/fragment/_deref__deref_pptz1=vbuaa.asm b/src/main/fragment/_deref__deref_pptz1=vbuaa.asm
new file mode 100644
index 000000000..6516b7db1
--- /dev/null
+++ b/src/main/fragment/_deref__deref_pptz1=vbuaa.asm
@@ -0,0 +1,4 @@
+ldy {z1}
+sty !+ +1
+ldy #0
+!: sta ($ff),y
diff --git a/src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm b/src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm
new file mode 100644
index 000000000..39191f06b
--- /dev/null
+++ b/src/main/fragment/_deref_pptc1=_inc__deref_pptc1.asm
@@ -0,0 +1,4 @@
+inc {c1}
+bne !+
+inc {c1}+1
+!:
\ No newline at end of file
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 319f189f0..2b81406b6 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,26 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testSubExprOptimize0() throws IOException, URISyntaxException {
+      compileAndCompare("subexpr-optimize-0");
+   }
+
+   @Test
+   public void testPtrPtrOptimize2() throws IOException, URISyntaxException {
+      compileAndCompare("ptrptr-optimize-2");
+   }
+
+   @Test
+   public void testPtrPtrOptimize1() throws IOException, URISyntaxException {
+      compileAndCompare("ptrptr-optimize-1");
+   }
+
+   @Test
+   public void testPtrPtrOptimize0() throws IOException, URISyntaxException {
+      compileAndCompare("ptrptr-optimize-0");
+   }
+
    @Test
    public void testHex2DecPtrPtr() throws IOException, URISyntaxException {
       compileAndCompare("hex2dec-ptrptr");
diff --git a/src/test/kc/ptrptr-optimize-0.kc b/src/test/kc/ptrptr-optimize-0.kc
new file mode 100644
index 000000000..c615190e5
--- /dev/null
+++ b/src/test/kc/ptrptr-optimize-0.kc
@@ -0,0 +1,8 @@
+// Tests optimization of constant pointers to pointers
+void main() {
+    byte* screen = 0x400;
+    byte** pscreen = &screen;
+    **pscreen = 'a';
+    (*pscreen)++;
+    **pscreen = 'b';
+}
\ No newline at end of file
diff --git a/src/test/kc/ptrptr-optimize-1.kc b/src/test/kc/ptrptr-optimize-1.kc
new file mode 100644
index 000000000..5e78562a3
--- /dev/null
+++ b/src/test/kc/ptrptr-optimize-1.kc
@@ -0,0 +1,11 @@
+// Tests optimization of constant pointers to pointers
+void main() {
+    byte* screen = 0x400;
+    byte** pscreen = &screen;
+    sub('a',pscreen);
+    sub('b',pscreen);
+}
+
+void sub(unsigned char ch, unsigned char **dst) {
+    *(*dst)++ = ch;
+}
diff --git a/src/test/kc/ptrptr-optimize-2.kc b/src/test/kc/ptrptr-optimize-2.kc
new file mode 100644
index 000000000..5b76ac29e
--- /dev/null
+++ b/src/test/kc/ptrptr-optimize-2.kc
@@ -0,0 +1,11 @@
+// Tests (non-)optimization of constant pointers to pointers
+// The two examples of &screen is not detected as identical leading to ASM that could be optimized more
+void main() {
+    byte* screen = 0x400;
+    sub('a',&screen);
+    sub('b',&screen);
+}
+
+void sub(unsigned char ch, unsigned char **dst) {
+    *(*dst)++ = ch;
+}
diff --git a/src/test/kc/subexpr-optimize-0.kc b/src/test/kc/subexpr-optimize-0.kc
new file mode 100644
index 000000000..52588128f
--- /dev/null
+++ b/src/test/kc/subexpr-optimize-0.kc
@@ -0,0 +1,10 @@
+// Tests (non-)optimization of identical sub-expressions
+// The two examples of i+1 is not detected as identical leading to ASM that could be optimized more
+void main() {
+    byte* screen = 0x400;
+    for( byte i: 0..2) {
+        *screen++ = i+1;
+        *screen++ = i+1;
+    }
+}
+
diff --git a/src/test/ref/hex2dec-ptrptr.asm b/src/test/ref/hex2dec-ptrptr.asm
index 6dcb61501..3c58ffe2c 100644
--- a/src/test/ref/hex2dec-ptrptr.asm
+++ b/src/test/ref/hex2dec-ptrptr.asm
@@ -60,48 +60,40 @@ utoa16w: {
     lsr
     lsr
     lsr
-    tax
+    tay
     lda #<dst
     sta utoa16n.dst
     lda #>dst
     sta utoa16n.dst+1
-    lda #0
-    sta utoa16n.started
+    ldx #0
     jsr utoa16n
-    lda utoa16n.return
-    tay
     lda value+1
-    ldx #$f
-    axs #0
-    sty utoa16n.started
-    lda #<dst
-    sta utoa16n.dst
-    lda #>dst
-    sta utoa16n.dst+1
-    jsr utoa16n
-    lda utoa16n.return
+    and #$f
     tay
-    lda value
-    lsr
-    lsr
-    lsr
-    lsr
-    tax
-    sty utoa16n.started
     lda #<dst
     sta utoa16n.dst
     lda #>dst
     sta utoa16n.dst+1
     jsr utoa16n
     lda value
-    ldx #$f
-    axs #0
+    lsr
+    lsr
+    lsr
+    lsr
+    tay
     lda #<dst
     sta utoa16n.dst
     lda #>dst
     sta utoa16n.dst+1
-    lda #1
-    sta utoa16n.started
+    jsr utoa16n
+    lda value
+    and #$f
+    tay
+    lda #<dst
+    sta utoa16n.dst
+    lda #>dst
+    sta utoa16n.dst+1
+    ldx #1
     jsr utoa16n
     lda #0
     tay
@@ -109,25 +101,21 @@ utoa16w: {
     rts
 }
 // Hexadecimal utoa() for a single nybble
-// utoa16n(byte register(X) nybble, word** zeropage(6) dst, byte zeropage(8) started)
+// utoa16n(byte register(Y) nybble, word** zeropage(6) dst, byte register(X) started)
 utoa16n: {
-    .label started = 8
-    .label return = 8
     .label dst = 6
-    cpx #0
+    cpy #0
     beq b1
-    lda #1
-    sta return
+    ldx #1
   b1:
-    lda return
-    cmp #0
+    cpx #0
     beq breturn
+    lda DIGITS,y
+    ldy dst
+    sty !++1
     ldy #0
-    lda dst
-    sta !++1
-    lda DIGITS,x
   !:
-    sta (dst),y
+    sta ($ff),y
     ldy #0
     lda (dst),y
     clc
diff --git a/src/test/ref/ptrptr-optimize-0.asm b/src/test/ref/ptrptr-optimize-0.asm
new file mode 100644
index 000000000..bcfea43c8
--- /dev/null
+++ b/src/test/ref/ptrptr-optimize-0.asm
@@ -0,0 +1,23 @@
+// Tests optimization of constant pointers to pointers
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label pscreen = screen
+    .label screen = 2
+    lda #<$400
+    sta screen
+    lda #>$400
+    sta screen+1
+    lda #'a'
+    ldy #0
+    sta (pscreen),y
+    inc pscreen
+    bne !+
+    inc pscreen+1
+  !:
+    lda #'b'
+    ldy #0
+    sta (pscreen),y
+    rts
+}
diff --git a/src/test/ref/ptrptr-optimize-1.asm b/src/test/ref/ptrptr-optimize-1.asm
new file mode 100644
index 000000000..5bb1ace96
--- /dev/null
+++ b/src/test/ref/ptrptr-optimize-1.asm
@@ -0,0 +1,27 @@
+// Tests optimization of constant pointers to pointers
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label pscreen = screen
+    .label screen = 2
+    lda #<$400
+    sta screen
+    lda #>$400
+    sta screen+1
+    lda #'a'
+    jsr sub
+    lda #'b'
+    jsr sub
+    rts
+}
+// sub(byte register(A) ch)
+sub: {
+    ldy #0
+    sta (main.pscreen),y
+    inc main.pscreen
+    bne !+
+    inc main.pscreen+1
+  !:
+    rts
+}
diff --git a/src/test/ref/ptrptr-optimize-2.asm b/src/test/ref/ptrptr-optimize-2.asm
new file mode 100644
index 000000000..0105bd47d
--- /dev/null
+++ b/src/test/ref/ptrptr-optimize-2.asm
@@ -0,0 +1,41 @@
+// Tests (non-)optimization of constant pointers to pointers
+// The two examples of &screen is not detected as identical leading to ASM that could be optimized more
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = 2
+    lda #<$400
+    sta screen
+    lda #>$400
+    sta screen+1
+    lda #<screen
+    sta sub.dst
+    lda #>screen
+    sta sub.dst+1
+    ldx #'a'
+    jsr sub
+    lda #<screen
+    sta sub.dst
+    lda #>screen
+    sta sub.dst+1
+    ldx #'b'
+    jsr sub
+    rts
+}
+// sub(byte register(X) ch, byte** zeropage(2) dst)
+sub: {
+    .label dst = 2
+    txa
+    ldy dst
+    sty !++1
+    ldy #0
+  !:
+    sta ($ff),y
+    ldy #0
+    lda (dst),y
+    clc
+    adc #1
+    sta (dst),y
+    rts
+}
diff --git a/src/test/ref/subexpr-optimize-0.asm b/src/test/ref/subexpr-optimize-0.asm
new file mode 100644
index 000000000..c282ef851
--- /dev/null
+++ b/src/test/ref/subexpr-optimize-0.asm
@@ -0,0 +1,38 @@
+// Tests (non-)optimization of identical sub-expressions
+// The two examples of i+1 is not detected as identical leading to ASM that could be optimized more
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label screen = 2
+    lda #<$400
+    sta screen
+    lda #>$400
+    sta screen+1
+    ldx #0
+  b1:
+    txa
+    tay
+    iny
+    tya
+    ldy #0
+    sta (screen),y
+    inc screen
+    bne !+
+    inc screen+1
+  !:
+    txa
+    tay
+    iny
+    tya
+    ldy #0
+    sta (screen),y
+    inc screen
+    bne !+
+    inc screen+1
+  !:
+    inx
+    cpx #3
+    bne b1
+    rts
+}

From c1213f4d55d116ba6f6f831afbd975dfdfac78b2 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Tue, 21 May 2019 23:06:13 +0200
Subject: [PATCH 61/93] Added right side duplicate identification.

---
 .../java/dk/camelot64/kickc/Compiler.java     |   1 +
 .../kickc/model/iterator/ProgramValue.java    |   4 +-
 .../Pass2DuplicateRValueIdentification.java   | 132 ++++++++++++++++++
 3 files changed, 135 insertions(+), 2 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 67ca190b1..8449ab3f8 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -268,6 +268,7 @@ public class Compiler {
       optimizations.add(new PassNSimplifyExpressionWithZero(program));
       optimizations.add(new PassNEliminateUnusedVars(program, true));
       optimizations.add(new Pass2EliminateUnusedBlocks(program));
+      optimizations.add(new Pass2DuplicateRValueIdentification(program));
       pass2Execute(optimizations);
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
index 551863bf9..0477f39ef 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
@@ -23,7 +23,7 @@ public interface ProgramValue {
    class RValue1 implements ProgramValue {
       private final StatementAssignment statement;
 
-      RValue1(StatementAssignment statement) {
+      public RValue1(StatementAssignment statement) {
          this.statement = statement;
       }
 
@@ -41,7 +41,7 @@ public interface ProgramValue {
    class RValue2 implements ProgramValue {
       private final StatementAssignment statement;
 
-      RValue2(StatementAssignment statement) {
+      public RValue2(StatementAssignment statement) {
          this.statement = statement;
       }
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java
new file mode 100644
index 000000000..2abdb07f0
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java
@@ -0,0 +1,132 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.ControlFlowBlock;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.iterator.ProgramValue;
+import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
+import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
+import dk.camelot64.kickc.model.operators.Operator;
+import dk.camelot64.kickc.model.operators.OperatorCast;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.statements.Statement;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
+import dk.camelot64.kickc.model.symbols.Variable;
+import dk.camelot64.kickc.model.values.ConstantValue;
+import dk.camelot64.kickc.model.values.PointerDereference;
+import dk.camelot64.kickc.model.values.RValue;
+import dk.camelot64.kickc.model.values.VariableRef;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Compiler Pass identifying R-values that are duplicates of each other - and consolidates them to a single RValue.
+ */
+public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization {
+
+   public Pass2DuplicateRValueIdentification(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      boolean modified = false;
+
+      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
+         Set<AssignmentRValue> rValues = new HashSet<>();
+         for(Statement statement : block.getStatements()) {
+            if(statement instanceof StatementAssignment) {
+               StatementAssignment assignment = (StatementAssignment) statement;
+               AssignmentRValue assignmentRValue = new AssignmentRValue(assignment, block);
+               if(!assignmentRValue.isConstant() && !assignmentRValue.isTrivial() && !assignmentRValue.isVolatile()) {
+                  if(rValues.contains(assignmentRValue)) {
+                     AssignmentRValue firstAssignment = rValues.stream().filter(assignmentRValue1 -> assignmentRValue1.equals(assignmentRValue)).findFirst().get();
+                     if(firstAssignment.assignment.getlValue() instanceof VariableRef) {
+                        getLog().append("Identified duplicate assignment right side "+assignment.toString(getProgram(), false));
+                        assignment.setrValue1(null);
+                        assignment.setOperator(null);
+                        assignment.setrValue2(firstAssignment.assignment.getlValue());
+                        modified = true;
+                     } else {
+                        throw new InternalError("Complex lValue for duplicate rvalue "+firstAssignment.assignment.toString(getProgram(), false));
+                     }
+                  } else {
+                     rValues.add(assignmentRValue);
+                  }
+               }
+            }
+         }
+      }
+      return modified;
+   }
+
+
+   /**
+    * Represents an RValue of an assignment.
+    * Implements equals() and hashcode() to allow identification of duplicate RValues
+    */
+   private class AssignmentRValue {
+      private ControlFlowBlock block;
+      private StatementAssignment assignment;
+      private RValue rValue1;
+      private Operator operator;
+      private RValue rValue2;
+
+      public AssignmentRValue(StatementAssignment assignment, ControlFlowBlock block) {
+         this.block = block;
+         this.assignment = assignment;
+         this.rValue1 = assignment.getrValue1();
+         this.operator = assignment.getOperator();
+         this.rValue2 = assignment.getrValue2();
+      }
+
+      private boolean isConstant() {
+         if(rValue1 != null && !(rValue1 instanceof ConstantValue))
+            return false;
+         if(rValue2 != null && !(rValue2 instanceof ConstantValue))
+            return false;
+         return true;
+      }
+
+      private boolean isVolatile() {
+         AtomicBoolean isVol = new AtomicBoolean(false);
+         ProgramValueHandler identifyVolatiles = (programValue, currentStmt, stmtIt, currentBlock) -> {
+            if(programValue.get() instanceof PointerDereference)
+               isVol.set(true);
+            if(programValue.get() instanceof VariableRef) {
+               Variable variable = getScope().getVariable((VariableRef) programValue.get());
+               if(variable.isDeclaredVolatile())
+                  isVol.set(true);
+            }
+         };
+         ProgramValueIterator.execute(new ProgramValue.RValue1(assignment), identifyVolatiles, assignment, null, null);
+         ProgramValueIterator.execute(new ProgramValue.RValue2(assignment), identifyVolatiles, assignment, null, null);
+         if(Operators.DEREF.equals(operator) || Operators.DEREF_IDX.equals(operator))
+            isVol.set(true);
+         return isVol.get();
+      }
+
+      private boolean isTrivial() {
+         if(operator == null) return true;
+         if(operator instanceof OperatorCast) return true;
+         return false;
+      }
+
+
+      @Override
+      public boolean equals(Object o) {
+         if(this == o) return true;
+         if(o == null || getClass() != o.getClass()) return false;
+         AssignmentRValue that = (AssignmentRValue) o;
+         return Objects.equals(rValue1, that.rValue1) &&
+               Objects.equals(operator, that.operator) &&
+               Objects.equals(rValue2, that.rValue2);
+      }
+
+      @Override
+      public int hashCode() {
+         return Objects.hash(rValue1, operator, rValue2);
+      }
+
+   }
+}

From 2c808e59d6a9a6a2589ab4d379c24641710f017d Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Wed, 22 May 2019 08:06:54 +0200
Subject: [PATCH 62/93] Added tests for duplicate assignment right side
 optimization.

---
 .../Pass2DuplicateRValueIdentification.java   | 13 +++++
 .../dk/camelot64/kickc/test/TestPrograms.java |  5 ++
 src/test/kc/subexpr-optimize-0.kc             |  4 +-
 src/test/kc/subexpr-optimize-1.kc             | 12 +++++
 src/test/ref/complex/tetris/tetris.asm        | 21 ++++-----
 src/test/ref/examples/3d/perspective.asm      | 47 ++++++++-----------
 .../multiplexer/simple-multiplexer.asm        | 12 ++---
 src/test/ref/line-anim.asm                    | 34 +++++---------
 .../simple-multiplexer-irq.asm                | 12 ++---
 src/test/ref/roll-sprite-msb.asm              |  3 --
 src/test/ref/subexpr-optimize-0.asm           | 11 ++---
 src/test/ref/subexpr-optimize-1.asm           | 21 +++++++++
 src/test/ref/test-division.asm                | 30 +++++-------
 13 files changed, 117 insertions(+), 108 deletions(-)
 create mode 100644 src/test/kc/subexpr-optimize-1.kc
 create mode 100644 src/test/ref/subexpr-optimize-1.asm

diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java
index 2abdb07f0..3e3a5ebe3 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java
@@ -109,6 +109,19 @@ public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization {
       private boolean isTrivial() {
          if(operator == null) return true;
          if(operator instanceof OperatorCast) return true;
+         if(operator.equals(Operators.PLUS)) return true;
+         if(operator.equals(Operators.MINUS)) return true;
+         if(operator.equals(Operators.BOOL_AND)) return true;
+         if(operator.equals(Operators.BOOL_OR)) return true;
+         if(operator.equals(Operators.BOOL_XOR)) return true;
+         if(operator.equals(Operators.BOOL_NOT)) return true;
+         if(operator.equals(Operators.LE)) return true;
+         if(operator.equals(Operators.LT)) return true;
+         if(operator.equals(Operators.GE)) return true;
+         if(operator.equals(Operators.GT)) return true;
+         if(operator.equals(Operators.EQ)) return true;
+         if(operator.equals(Operators.NEQ)) return true;
+         if(operator.equals(Operators.LOGIC_NOT)) return true;
          return false;
       }
 
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 2b81406b6..338a622e5 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,11 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testSubExprOptimize1() throws IOException, URISyntaxException {
+      compileAndCompare("subexpr-optimize-1");
+   }
+
    @Test
    public void testSubExprOptimize0() throws IOException, URISyntaxException {
       compileAndCompare("subexpr-optimize-0");
diff --git a/src/test/kc/subexpr-optimize-0.kc b/src/test/kc/subexpr-optimize-0.kc
index 52588128f..78ec0430f 100644
--- a/src/test/kc/subexpr-optimize-0.kc
+++ b/src/test/kc/subexpr-optimize-0.kc
@@ -3,8 +3,8 @@
 void main() {
     byte* screen = 0x400;
     for( byte i: 0..2) {
-        *screen++ = i+1;
-        *screen++ = i+1;
+        *screen++ = i*2;
+        *screen++ = i*2;
     }
 }
 
diff --git a/src/test/kc/subexpr-optimize-1.kc b/src/test/kc/subexpr-optimize-1.kc
new file mode 100644
index 000000000..4fdabcfce
--- /dev/null
+++ b/src/test/kc/subexpr-optimize-1.kc
@@ -0,0 +1,12 @@
+// A sub-expression that should not be optimized (+1 to a pointer)
+
+void main() {
+    byte* SCREEN = 0x0400;
+    for(byte i: 0..38) {
+        SCREEN[i] = SCREEN[i+1];
+        (SCREEN+40)[i] = (SCREEN+40)[i+1];
+        (SCREEN+80)[i] = (SCREEN+80)[i+1];
+        (SCREEN+120)[i] = (SCREEN+120)[i+1];
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm
index 2ffbfb4d9..663c44f97 100644
--- a/src/test/ref/complex/tetris/tetris.asm
+++ b/src/test/ref/complex/tetris/tetris.asm
@@ -1412,22 +1412,19 @@ render_init: {
     sta li_1
     lda #>PLAYFIELD_SCREEN_1+2*$28+$10
     sta li_1+1
-    ldx #0
+    ldy #0
   b1:
-    txa
+    tya
     asl
-    tay
+    tax
     lda li_1
-    sta screen_lines_1,y
+    sta screen_lines_1,x
     lda li_1+1
-    sta screen_lines_1+1,y
-    txa
-    asl
-    tay
+    sta screen_lines_1+1,x
     lda li_2
-    sta screen_lines_2,y
+    sta screen_lines_2,x
     lda li_2+1
-    sta screen_lines_2+1,y
+    sta screen_lines_2+1,x
     lda #$28
     clc
     adc li_1
@@ -1442,8 +1439,8 @@ render_init: {
     bcc !+
     inc li_2+1
   !:
-    inx
-    cpx #PLAYFIELD_LINES-1+1
+    iny
+    cpy #PLAYFIELD_LINES-1+1
     bne b1
     rts
 }
diff --git a/src/test/ref/examples/3d/perspective.asm b/src/test/ref/examples/3d/perspective.asm
index 313e08cfb..878c3f046 100644
--- a/src/test/ref/examples/3d/perspective.asm
+++ b/src/test/ref/examples/3d/perspective.asm
@@ -244,42 +244,35 @@ mulf_init: {
     sta add
     lda #0
     sta add+1
-    tax
+    tay
     sta sqr
     sta sqr+1
   b1:
     lda sqr+1
     sta val
+    sta mulf_sqr1,y
+    sta mulf_sqr1+$100,y
+    tya
+    eor #$ff
+    tax
+    inx
+    lda val
     sta mulf_sqr1,x
     sta mulf_sqr1+$100,x
-    txa
+    sta mulf_sqr2+1,y
+    sta mulf_sqr2+$100+1,y
+    tya
     eor #$ff
-    tay
-    iny
+    tax
+    axs #1+1
     lda val
-    sta mulf_sqr1,y
-    txa
+    sta mulf_sqr2,x
+    tya
     eor #$ff
-    tay
-    iny
+    tax
+    axs #1+1
     lda val
-    sta mulf_sqr1+$100,y
-    sta mulf_sqr2+1,x
-    sta mulf_sqr2+$100+1,x
-    txa
-    eor #$ff
-    clc
-    adc #1+1
-    tay
-    lda val
-    sta mulf_sqr2,y
-    txa
-    eor #$ff
-    clc
-    adc #1+1
-    tay
-    lda val
-    sta mulf_sqr2+$100,y
+    sta mulf_sqr2+$100,x
     lda sqr
     clc
     adc add
@@ -294,8 +287,8 @@ mulf_init: {
     bcc !+
     inc add+1
   !:
-    inx
-    cpx #$81
+    iny
+    cpy #$81
     bne b1
     rts
 }
diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
index c581edf00..ab1e3bf7b 100644
--- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm
+++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
@@ -120,17 +120,13 @@ plexShowSprite: {
     ldx plex_sprite_idx
     sta PLEX_SCREEN_PTR,x
     ldy plex_show_idx
-    ldx PLEX_SORTED_IDX,y
-    txa
+    lda PLEX_SORTED_IDX,y
     asl
-    tay
-    lda PLEX_XPOS,y
+    tax
+    lda PLEX_XPOS,x
     ldy plex_sprite_idx2
     sta SPRITES_XPOS,y
-    txa
-    asl
-    tay
-    lda PLEX_XPOS+1,y
+    lda PLEX_XPOS+1,x
     cmp #0
     bne b1
     lda #$ff
diff --git a/src/test/ref/line-anim.asm b/src/test/ref/line-anim.asm
index bd6739ae0..796e154ef 100644
--- a/src/test/ref/line-anim.asm
+++ b/src/test/ref/line-anim.asm
@@ -127,17 +127,14 @@ point_init: {
     .label x_diff = 9
     lda point_idx
     asl
-    tay
-    lda x_end,y
+    tax
+    lda x_end,x
     sta _0
-    lda x_end+1,y
+    lda x_end+1,x
     sta _0+1
-    lda point_idx
-    asl
-    tay
-    lda x_start,y
+    lda x_start,x
     sta _1
-    lda x_start+1,y
+    lda x_start+1,x
     sta _1+1
     lda x_diff
     sec
@@ -191,10 +188,10 @@ point_init: {
   b2:
     lda point_idx
     asl
-    tay
-    lda x_start,y
+    tax
+    lda x_start,x
     sta _9
-    lda x_start+1,y
+    lda x_start+1,x
     sta _9+1
     asl _9
     rol _9+1
@@ -204,13 +201,10 @@ point_init: {
     rol _9+1
     asl _9
     rol _9+1
-    lda point_idx
-    asl
-    tay
     lda _9
-    sta x_cur,y
+    sta x_cur,x
     lda _9+1
-    sta x_cur+1,y
+    sta x_cur+1,x
     ldy point_idx
     lda y_start,y
     sta _10
@@ -224,15 +218,11 @@ point_init: {
     rol _11+1
     asl _11
     rol _11+1
-    tya
-    asl
-    tay
     lda _11
-    sta y_cur,y
+    sta y_cur,x
     lda _11+1
-    sta y_cur+1,y
+    sta y_cur+1,x
     lda #DELAY
-    ldy point_idx
     sta delay,y
     rts
   b1:
diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
index 8b97b383b..32a1fc283 100644
--- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
+++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
@@ -290,17 +290,13 @@ plexShowSprite: {
     ldx plex_sprite_idx
     sta PLEX_SCREEN_PTR,x
     ldy plex_show_idx
-    ldx PLEX_SORTED_IDX,y
-    txa
+    lda PLEX_SORTED_IDX,y
     asl
-    tay
-    lda PLEX_XPOS,y
+    tax
+    lda PLEX_XPOS,x
     ldy plex_sprite_idx2
     sta SPRITES_XPOS,y
-    txa
-    asl
-    tay
-    lda PLEX_XPOS+1,y
+    lda PLEX_XPOS+1,x
     cmp #0
     bne b1
     lda #$ff
diff --git a/src/test/ref/roll-sprite-msb.asm b/src/test/ref/roll-sprite-msb.asm
index 80b22ddde..e338a5605 100644
--- a/src/test/ref/roll-sprite-msb.asm
+++ b/src/test/ref/roll-sprite-msb.asm
@@ -37,9 +37,6 @@ position_sprite: {
     tay
     lda #y
     sta SPRITES_YPOS,y
-    lda spriteno
-    asl
-    tay
     lda x
     sta SPRITES_XPOS,y
     lda x+1
diff --git a/src/test/ref/subexpr-optimize-0.asm b/src/test/ref/subexpr-optimize-0.asm
index c282ef851..dd03a4605 100644
--- a/src/test/ref/subexpr-optimize-0.asm
+++ b/src/test/ref/subexpr-optimize-0.asm
@@ -4,6 +4,7 @@
 :BasicUpstart(main)
 .pc = $80d "Program"
 main: {
+    .label _1 = 4
     .label screen = 2
     lda #<$400
     sta screen
@@ -12,19 +13,15 @@ main: {
     ldx #0
   b1:
     txa
-    tay
-    iny
-    tya
+    asl
+    sta _1
     ldy #0
     sta (screen),y
     inc screen
     bne !+
     inc screen+1
   !:
-    txa
-    tay
-    iny
-    tya
+    lda _1
     ldy #0
     sta (screen),y
     inc screen
diff --git a/src/test/ref/subexpr-optimize-1.asm b/src/test/ref/subexpr-optimize-1.asm
new file mode 100644
index 000000000..df54827e6
--- /dev/null
+++ b/src/test/ref/subexpr-optimize-1.asm
@@ -0,0 +1,21 @@
+// A sub-expression that should not be optimized (+1 to a pointer)
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label SCREEN = $400
+    ldx #0
+  b1:
+    lda SCREEN+1,x
+    sta SCREEN,x
+    lda SCREEN+$28+1,x
+    sta SCREEN+$28,x
+    lda SCREEN+$50+1,x
+    sta SCREEN+$50,x
+    lda SCREEN+$78+1,x
+    sta SCREEN+$78,x
+    inx
+    cpx #$27
+    bne b1
+    rts
+}
diff --git a/src/test/ref/test-division.asm b/src/test/ref/test-division.asm
index d7b963748..cd75806a1 100644
--- a/src/test/ref/test-division.asm
+++ b/src/test/ref/test-division.asm
@@ -24,17 +24,14 @@ test_16s: {
   b1:
     lda i
     asl
-    tay
-    lda dividends,y
+    tax
+    lda dividends,x
     sta dividend
-    lda dividends+1,y
+    lda dividends+1,x
     sta dividend+1
-    lda i
-    asl
-    tay
-    lda divisors,y
+    lda divisors,x
     sta divisor
-    lda divisors+1,y
+    lda divisors+1,x
     sta divisor+1
     jsr div16s
     lda print_line_cursor
@@ -76,9 +73,7 @@ test_16s: {
     inc i
     lda #6
     cmp i
-    beq !b1+
-    jmp b1
-  !b1:
+    bne b1
     rts
     dividends: .word $7fff, $7fff, -$7fff, -$7fff, $7fff, -$7fff
     divisors: .word 5, -7, $b, -$d, -$11, $13
@@ -539,17 +534,14 @@ test_16u: {
   b1:
     lda i
     asl
-    tay
-    lda dividends,y
+    tax
+    lda dividends,x
     sta dividend
-    lda dividends+1,y
+    lda dividends+1,x
     sta dividend+1
-    lda i
-    asl
-    tay
-    lda divisors,y
+    lda divisors,x
     sta divisor
-    lda divisors+1,y
+    lda divisors+1,x
     sta divisor+1
     jsr div16u
     lda print_line_cursor

From 67db0f0f6f13df48edc56950758f0bd19ca06c3d Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Wed, 22 May 2019 08:19:43 +0200
Subject: [PATCH 63/93] Improved duplicate assignment right side optimization
 slightly.

---
 .../Pass2DuplicateRValueIdentification.java   |  6 ++----
 src/test/ref/bitmap-plotter.asm               | 11 +++++-----
 src/test/ref/bool-ifs.asm                     | 21 ++++++++-----------
 .../examples/bresenham/bitmap-bresenham.asm   | 11 +++++-----
 .../ref/examples/sinplotter/sine-plotter.asm  | 11 +++++-----
 src/test/ref/line-anim.asm                    | 11 +++++-----
 6 files changed, 31 insertions(+), 40 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java
index 3e3a5ebe3..09f8fa690 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DuplicateRValueIdentification.java
@@ -111,10 +111,6 @@ public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization {
          if(operator instanceof OperatorCast) return true;
          if(operator.equals(Operators.PLUS)) return true;
          if(operator.equals(Operators.MINUS)) return true;
-         if(operator.equals(Operators.BOOL_AND)) return true;
-         if(operator.equals(Operators.BOOL_OR)) return true;
-         if(operator.equals(Operators.BOOL_XOR)) return true;
-         if(operator.equals(Operators.BOOL_NOT)) return true;
          if(operator.equals(Operators.LE)) return true;
          if(operator.equals(Operators.LT)) return true;
          if(operator.equals(Operators.GE)) return true;
@@ -122,6 +118,8 @@ public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization {
          if(operator.equals(Operators.EQ)) return true;
          if(operator.equals(Operators.NEQ)) return true;
          if(operator.equals(Operators.LOGIC_NOT)) return true;
+         if(operator.equals(Operators.LOGIC_AND)) return true;
+         if(operator.equals(Operators.LOGIC_OR)) return true;
          return false;
       }
 
diff --git a/src/test/ref/bitmap-plotter.asm b/src/test/ref/bitmap-plotter.asm
index 4554d3c63..7762f5817 100644
--- a/src/test/ref/bitmap-plotter.asm
+++ b/src/test/ref/bitmap-plotter.asm
@@ -81,7 +81,7 @@ plot: {
     rts
 }
 init_plot_tables: {
-    .label _6 = 4
+    .label _10 = 4
     .label yoffs = 2
     ldy #$80
     ldx #0
@@ -109,15 +109,14 @@ init_plot_tables: {
     tax
   b3:
     lda #7
-    sax _6
+    sax _10
     lda yoffs
-    ora _6
+    ora _10
     sta plot_ylo,x
     lda yoffs+1
     sta plot_yhi,x
-    txa
-    and #7
-    cmp #7
+    lda #7
+    cmp _10
     bne b4
     clc
     lda yoffs
diff --git a/src/test/ref/bool-ifs.asm b/src/test/ref/bool-ifs.asm
index c5dacee64..0fc00115b 100644
--- a/src/test/ref/bool-ifs.asm
+++ b/src/test/ref/bool-ifs.asm
@@ -11,34 +11,31 @@ main: {
 }
 bool_complex: {
     .label screen = $478
-    ldy #0
+    ldx #0
   b1:
-    ldx #1
-    tya
-    axs #0
-    tya
+    txa
     and #1
-    cpy #$a
+    cpx #$a
     bcc b6
   b5:
-    cpy #$a
+    cpx #$a
     bcc b4
     cmp #0
     beq b4
   b2:
     lda #'*'
-    sta screen,y
+    sta screen,x
   b3:
-    iny
-    cpy #$15
+    inx
+    cpx #$15
     bne b1
     rts
   b4:
     lda #' '
-    sta screen,y
+    sta screen,x
     jmp b3
   b6:
-    cpx #0
+    cmp #0
     beq b2
     jmp b5
 }
diff --git a/src/test/ref/examples/bresenham/bitmap-bresenham.asm b/src/test/ref/examples/bresenham/bitmap-bresenham.asm
index 9c513d6a8..c6f38704b 100644
--- a/src/test/ref/examples/bresenham/bitmap-bresenham.asm
+++ b/src/test/ref/examples/bresenham/bitmap-bresenham.asm
@@ -364,7 +364,7 @@ bitmap_clear: {
 }
 // Initialize the bitmap plotter tables for a specific bitmap
 bitmap_init: {
-    .label _6 = 2
+    .label _10 = 2
     .label yoffs = 9
     ldy #$80
     ldx #0
@@ -392,15 +392,14 @@ bitmap_init: {
     tax
   b3:
     lda #7
-    sax _6
+    sax _10
     lda yoffs
-    ora _6
+    ora _10
     sta bitmap_plot_ylo,x
     lda yoffs+1
     sta bitmap_plot_yhi,x
-    txa
-    and #7
-    cmp #7
+    lda #7
+    cmp _10
     bne b4
     clc
     lda yoffs
diff --git a/src/test/ref/examples/sinplotter/sine-plotter.asm b/src/test/ref/examples/sinplotter/sine-plotter.asm
index 341d95d20..e86b7ba4e 100644
--- a/src/test/ref/examples/sinplotter/sine-plotter.asm
+++ b/src/test/ref/examples/sinplotter/sine-plotter.asm
@@ -757,7 +757,7 @@ bitmap_clear: {
 }
 // Initialize bitmap plotting tables
 bitmap_init: {
-    .label _3 = $16
+    .label _7 = $16
     .label yoffs = 2
     ldx #0
     lda #$80
@@ -778,15 +778,14 @@ bitmap_init: {
     ldx #0
   b3:
     lda #7
-    sax _3
+    sax _7
     lda yoffs
-    ora _3
+    ora _7
     sta bitmap_plot_ylo,x
     lda yoffs+1
     sta bitmap_plot_yhi,x
-    txa
-    and #7
-    cmp #7
+    lda #7
+    cmp _7
     bne b4
     clc
     lda yoffs
diff --git a/src/test/ref/line-anim.asm b/src/test/ref/line-anim.asm
index 796e154ef..e787357ed 100644
--- a/src/test/ref/line-anim.asm
+++ b/src/test/ref/line-anim.asm
@@ -455,7 +455,7 @@ bitmap_clear: {
     rts
 }
 bitmap_init: {
-    .label _3 = 2
+    .label _7 = 2
     .label yoffs = 3
     ldx #0
     lda #$80
@@ -476,15 +476,14 @@ bitmap_init: {
     ldx #0
   b3:
     lda #7
-    sax _3
+    sax _7
     lda yoffs
-    ora _3
+    ora _7
     sta bitmap_plot_ylo,x
     lda yoffs+1
     sta bitmap_plot_yhi,x
-    txa
-    and #7
-    cmp #7
+    lda #7
+    cmp _7
     bne b4
     clc
     lda yoffs

From 39c4f0d6b4d1a24bf76b8d5d3d048b7cb244e3f8 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Wed, 22 May 2019 15:29:47 +0200
Subject: [PATCH 64/93] Fixed identification of identical Phi RValues that are
 constant pointers to symbols.

---
 src/main/fragment/_deref_pptc1=pbuz1.asm      |  4 ++
 .../model/values/ConstantSymbolPointer.java   | 16 ++++++++
 src/test/ref/hex2dec-ptrptr.asm               | 38 ++++---------------
 src/test/ref/pointer-pointer-3.asm            | 19 ++--------
 src/test/ref/ptrptr-optimize-2.asm            | 28 ++++----------
 5 files changed, 38 insertions(+), 67 deletions(-)
 create mode 100644 src/main/fragment/_deref_pptc1=pbuz1.asm

diff --git a/src/main/fragment/_deref_pptc1=pbuz1.asm b/src/main/fragment/_deref_pptc1=pbuz1.asm
new file mode 100644
index 000000000..0e0382e79
--- /dev/null
+++ b/src/main/fragment/_deref_pptc1=pbuz1.asm
@@ -0,0 +1,4 @@
+lda {z1}
+sta {c1}
+lda {z1}+1
+sta {c1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantSymbolPointer.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantSymbolPointer.java
index 4474cb416..4f7c079a9 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantSymbolPointer.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantSymbolPointer.java
@@ -6,6 +6,8 @@ import dk.camelot64.kickc.model.symbols.Symbol;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
 
+import java.util.Objects;
+
 /** A pointer to a symbol (variable or procedure) */
 public class ConstantSymbolPointer implements ConstantValue {
 
@@ -44,4 +46,18 @@ public class ConstantSymbolPointer implements ConstantValue {
    public String toString() {
       return toString(null);
    }
+
+   @Override
+   public boolean equals(Object o) {
+      if(this == o) return true;
+      if(o == null || getClass() != o.getClass()) return false;
+      ConstantSymbolPointer that = (ConstantSymbolPointer) o;
+      return Objects.equals(toSymbol, that.toSymbol);
+   }
+
+   @Override
+   public int hashCode() {
+
+      return Objects.hash(toSymbol);
+   }
 }
diff --git a/src/test/ref/hex2dec-ptrptr.asm b/src/test/ref/hex2dec-ptrptr.asm
index 3c58ffe2c..af42a6775 100644
--- a/src/test/ref/hex2dec-ptrptr.asm
+++ b/src/test/ref/hex2dec-ptrptr.asm
@@ -60,39 +60,19 @@ utoa16w: {
     lsr
     lsr
     lsr
-    tay
-    lda #<dst
-    sta utoa16n.dst
-    lda #>dst
-    sta utoa16n.dst+1
     ldx #0
     jsr utoa16n
     lda value+1
     and #$f
-    tay
-    lda #<dst
-    sta utoa16n.dst
-    lda #>dst
-    sta utoa16n.dst+1
     jsr utoa16n
     lda value
     lsr
     lsr
     lsr
     lsr
-    tay
-    lda #<dst
-    sta utoa16n.dst
-    lda #>dst
-    sta utoa16n.dst+1
     jsr utoa16n
     lda value
     and #$f
-    tay
-    lda #<dst
-    sta utoa16n.dst
-    lda #>dst
-    sta utoa16n.dst+1
     ldx #1
     jsr utoa16n
     lda #0
@@ -101,26 +81,22 @@ utoa16w: {
     rts
 }
 // Hexadecimal utoa() for a single nybble
-// utoa16n(byte register(Y) nybble, word** zeropage(6) dst, byte register(X) started)
+// utoa16n(byte register(A) nybble, byte register(X) started)
 utoa16n: {
-    .label dst = 6
-    cpy #0
+    cmp #0
     beq b1
     ldx #1
   b1:
     cpx #0
     beq breturn
+    tay
     lda DIGITS,y
-    ldy dst
-    sty !++1
     ldy #0
+    sta (utoa16w.dst),y
+    inc utoa16w.dst
+    bne !+
+    inc utoa16w.dst+1
   !:
-    sta ($ff),y
-    ldy #0
-    lda (dst),y
-    clc
-    adc #1
-    sta (dst),y
   breturn:
     rts
 }
diff --git a/src/test/ref/pointer-pointer-3.asm b/src/test/ref/pointer-pointer-3.asm
index 8d95438d3..079d897cf 100644
--- a/src/test/ref/pointer-pointer-3.asm
+++ b/src/test/ref/pointer-pointer-3.asm
@@ -4,7 +4,7 @@
 .pc = $80d "Program"
   .label screen1 = $400
   .label screen2 = $400+$28
-  .label screen = 6
+  .label screen = 4
 bbegin:
   lda #<$400
   sta screen
@@ -13,10 +13,6 @@ bbegin:
   jsr main
   rts
 main: {
-    lda #<screen
-    sta setscreen.screen
-    lda #>screen
-    sta setscreen.screen+1
     lda #<screen1
     sta setscreen.val
     lda #>screen1
@@ -25,10 +21,6 @@ main: {
     lda #'a'
     ldy #0
     sta (screen),y
-    lda #<screen
-    sta setscreen.screen
-    lda #>screen
-    sta setscreen.screen+1
     lda #<screen2
     sta setscreen.val
     lda #>screen2
@@ -39,15 +31,12 @@ main: {
     sta (screen),y
     rts
 }
-// setscreen(byte** zeropage(4) screen, byte* zeropage(2) val)
+// setscreen(byte* zeropage(2) val)
 setscreen: {
     .label val = 2
-    .label screen = 4
-    ldy #0
     lda val
-    sta (screen),y
-    iny
+    sta screen
     lda val+1
-    sta (screen),y
+    sta screen+1
     rts
 }
diff --git a/src/test/ref/ptrptr-optimize-2.asm b/src/test/ref/ptrptr-optimize-2.asm
index 0105bd47d..afc340a19 100644
--- a/src/test/ref/ptrptr-optimize-2.asm
+++ b/src/test/ref/ptrptr-optimize-2.asm
@@ -9,33 +9,19 @@ main: {
     sta screen
     lda #>$400
     sta screen+1
-    lda #<screen
-    sta sub.dst
-    lda #>screen
-    sta sub.dst+1
-    ldx #'a'
+    lda #'a'
     jsr sub
-    lda #<screen
-    sta sub.dst
-    lda #>screen
-    sta sub.dst+1
-    ldx #'b'
+    lda #'b'
     jsr sub
     rts
 }
-// sub(byte register(X) ch, byte** zeropage(2) dst)
+// sub(byte register(A) ch)
 sub: {
-    .label dst = 2
-    txa
-    ldy dst
-    sty !++1
     ldy #0
+    sta (main.screen),y
+    inc main.screen
+    bne !+
+    inc main.screen+1
   !:
-    sta ($ff),y
-    ldy #0
-    lda (dst),y
-    clc
-    adc #1
-    sta (dst),y
     rts
 }

From ff7e4bff2a197521311d1289b503fc400f3e22a0 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Wed, 22 May 2019 15:32:42 +0200
Subject: [PATCH 65/93] Removed duplicate compiler step.

---
 .../java/dk/camelot64/kickc/Compiler.java     |  1 -
 .../passes/Pass2RedundantPhiElimination.java  | 75 -------------------
 2 files changed, 76 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 8449ab3f8..c1616481a 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -243,7 +243,6 @@ public class Compiler {
       optimizations.add(new Pass2UnaryNotSimplification(program));
       optimizations.add(new Pass2AliasElimination(program));
       optimizations.add(new Pass2SelfPhiElimination(program));
-      optimizations.add(new Pass2RedundantPhiElimination(program));
       optimizations.add(new Pass2IdenticalPhiElimination(program));
       optimizations.add(new Pass2ConditionalJumpSimplification(program));
       optimizations.add(new Pass2ConditionalAndOrRewriting(program));
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java
deleted file mode 100644
index 74371da2e..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.*;
-import dk.camelot64.kickc.model.values.LValue;
-import dk.camelot64.kickc.model.values.RValue;
-import dk.camelot64.kickc.model.values.VariableRef;
-import dk.camelot64.kickc.model.statements.StatementPhiBlock;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/** Compiler Pass eliminating redundant phi functions */
-public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
-
-   public Pass2RedundantPhiElimination(Program program) {
-      super(program);
-   }
-
-   /**
-    * Eliminate alias assignments replacing them with the aliased variable.
-    */
-   @Override
-   public boolean step() {
-      final Map<VariableRef, RValue> aliases = findRedundantPhis();
-      removeAssignments(getGraph(), aliases.keySet());
-      replaceVariables(aliases);
-      for(VariableRef var : aliases.keySet()) {
-         RValue alias = aliases.get(var);
-         getLog().append("Redundant Phi " + var.toString(getProgram()) + " " + alias.toString(getProgram()));
-      }
-      deleteSymbols(getScope(), aliases.keySet());
-      return aliases.size() > 0;
-   }
-
-   /**
-    * Find phi variables where all previous symbols are identical.
-    *
-    * @return Map from (phi) Variable to the previous value
-    */
-   private Map<VariableRef, RValue> findRedundantPhis() {
-      final Map<VariableRef, RValue> aliases = new LinkedHashMap<>();
-      ControlFlowGraphBaseVisitor<Void> visitor = new ControlFlowGraphBaseVisitor<Void>() {
-
-         @Override
-         public Void visitPhiBlock(StatementPhiBlock phi) {
-            for(StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) {
-               boolean found = true;
-               RValue rValue = null;
-               for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
-                  if(rValue == null) {
-                     rValue = phiRValue.getrValue();
-                  } else {
-                     if(!rValue.equals(phiRValue.getrValue())) {
-                        found = false;
-                        break;
-                     }
-                  }
-               }
-               if(found) {
-                  VariableRef variable = phiVariable.getVariable();
-                  if(rValue == null) {
-                     rValue = LValue.VOID;
-                  }
-                  aliases.put(variable, rValue);
-               }
-            }
-            return null;
-         }
-
-      };
-      visitor.visitGraph(getGraph());
-      return aliases;
-   }
-
-}

From aaf556abe166efa2d0942dd55182efcf8520b22d Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Wed, 22 May 2019 15:42:00 +0200
Subject: [PATCH 66/93] Improved utoa16 implementation using pointer to
 pointer.

---
 src/test/kc/hex2dec.kc   | 30 ++++++--------
 src/test/ref/hex2dec.asm | 85 ++++++++++++++++++----------------------
 2 files changed, 50 insertions(+), 65 deletions(-)

diff --git a/src/test/kc/hex2dec.kc b/src/test/kc/hex2dec.kc
index d44d936df..d2642974c 100644
--- a/src/test/kc/hex2dec.kc
+++ b/src/test/kc/hex2dec.kc
@@ -65,27 +65,21 @@ void utoa10w(unsigned int value, unsigned char* dst) {
     *dst = 0;
 }
 
-// Holds the destination address for the hexadecimal utoa()
-unsigned char* utoa16_dst;
-// Holds whether the hexadecimal utoa() has started outputting digits
-unsigned char utoa16_started;
-
 // Hexadecimal utoa() for an unsigned int (16bits)
 void utoa16w(unsigned int value, unsigned char* dst) {
-    utoa16_dst = dst;
-    utoa16_started = 0;
-    utoa16n((>value)>>4);
-    utoa16n((>value)&0x0f);
-    utoa16n((<value)>>4);
-    utoa16_started = 1;
-    utoa16n((<value)&0x0f);
-    *utoa16_dst = 0;
+    unsigned char started = 0;
+    started = utoa16n((>value)>>4, &dst, started);
+    started = utoa16n((>value)&0x0f, &dst, started);
+    started = utoa16n((<value)>>4, &dst, started);
+    utoa16n((<value)&0x0f, &dst, 1);
+    *dst = 0;
 }
 
 // Hexadecimal utoa() for a single nybble
-void utoa16n(unsigned char nybble) {
-    if(nybble!=0) utoa16_started=1;
-    if(utoa16_started!=0) {
-        *utoa16_dst++ = DIGITS[nybble];
+unsigned char utoa16n(unsigned char nybble, unsigned **dst, unsigned char started) {
+    if(nybble!=0) started=1;
+    if(started!=0) {
+        *(*dst)++ = DIGITS[nybble];
     }
-}
+    return started;
+}
\ No newline at end of file
diff --git a/src/test/ref/hex2dec.asm b/src/test/ref/hex2dec.asm
index 373a47ff5..1ff955992 100644
--- a/src/test/ref/hex2dec.asm
+++ b/src/test/ref/hex2dec.asm
@@ -5,11 +5,9 @@
   .label control = $d011
   .label raster = $d012
   .label bordercol = $d020
-  .label utoa16_dst = 2
-  .label utoa16_started = 4
 main: {
     .label _1 = 4
-    .label time_start = 5
+    .label time_start = 4
     sei
     jsr cls
   b1:
@@ -25,53 +23,53 @@ main: {
     sta bordercol
     lda raster
     sta time_start
-    lda #0
-    sta utoa16w.value
-    sta utoa16w.value+1
     lda #<$400
     sta utoa16w.dst
     lda #>$400
     sta utoa16w.dst+1
+    lda #0
+    sta utoa16w.value
+    sta utoa16w.value+1
     jsr utoa16w
     inc bordercol
-    lda #<$4d2
-    sta utoa16w.value
-    lda #>$4d2
-    sta utoa16w.value+1
     lda #<$400+$28
     sta utoa16w.dst
     lda #>$400+$28
     sta utoa16w.dst+1
+    lda #<$4d2
+    sta utoa16w.value
+    lda #>$4d2
+    sta utoa16w.value+1
     jsr utoa16w
     inc bordercol
-    lda #<$162e
-    sta utoa16w.value
-    lda #>$162e
-    sta utoa16w.value+1
     lda #<$400+$28+$28
     sta utoa16w.dst
     lda #>$400+$28+$28
     sta utoa16w.dst+1
+    lda #<$162e
+    sta utoa16w.value
+    lda #>$162e
+    sta utoa16w.value+1
     jsr utoa16w
     inc bordercol
-    lda #<$270f
-    sta utoa16w.value
-    lda #>$270f
-    sta utoa16w.value+1
     lda #<$400+$28+$28+$28
     sta utoa16w.dst
     lda #>$400+$28+$28+$28
     sta utoa16w.dst+1
+    lda #<$270f
+    sta utoa16w.value
+    lda #>$270f
+    sta utoa16w.value+1
     jsr utoa16w
     inc bordercol
-    lda #<$e608
-    sta utoa16w.value
-    lda #>$e608
-    sta utoa16w.value+1
     lda #<$400+$28+$28+$28+$28
     sta utoa16w.dst
     lda #>$400+$28+$28+$28+$28
     sta utoa16w.dst+1
+    lda #<$e608
+    sta utoa16w.value
+    lda #>$e608
+    sta utoa16w.value+1
     jsr utoa16w
     ldx raster
     lda #0
@@ -176,58 +174,51 @@ utoa10w: {
     jmp b1
 }
 // Hexadecimal utoa() for an unsigned int (16bits)
-// utoa16w(word zeropage(6) value, byte* zeropage(2) dst)
+// utoa16w(word zeropage(2) value, byte* zeropage(6) dst)
 utoa16w: {
-    .label dst = 2
-    .label value = 6
+    .label value = 2
+    .label dst = 6
     lda value+1
     lsr
     lsr
     lsr
     lsr
-    tax
-    lda #0
-    sta utoa16_started
+    ldx #0
     jsr utoa16n
     lda value+1
-    ldx #$f
-    axs #0
+    and #$f
     jsr utoa16n
     lda value
     lsr
     lsr
     lsr
     lsr
-    tax
     jsr utoa16n
     lda value
-    ldx #$f
-    axs #0
-    lda #1
-    sta utoa16_started
+    and #$f
+    ldx #1
     jsr utoa16n
     lda #0
     tay
-    sta (utoa16_dst),y
+    sta (dst),y
     rts
 }
 // Hexadecimal utoa() for a single nybble
-// utoa16n(byte register(X) nybble)
+// utoa16n(byte register(A) nybble, byte register(X) started)
 utoa16n: {
-    cpx #0
-    beq b1
-    lda #1
-    sta utoa16_started
-  b1:
-    lda utoa16_started
     cmp #0
+    beq b1
+    ldx #1
+  b1:
+    cpx #0
     beq breturn
-    lda DIGITS,x
+    tay
+    lda DIGITS,y
     ldy #0
-    sta (utoa16_dst),y
-    inc utoa16_dst
+    sta (utoa16w.dst),y
+    inc utoa16w.dst
     bne !+
-    inc utoa16_dst+1
+    inc utoa16w.dst+1
   !:
   breturn:
     rts

From 9636e261914fbc8ff0a8f749b5c51782dab37ebc Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Wed, 22 May 2019 15:53:48 +0200
Subject: [PATCH 67/93] Changed all type comparisons to use
 SymbolType.XXX.equals()

---
 .../kickc/model/operators/OperatorDivide.java    |  2 +-
 .../kickc/model/operators/OperatorMultiply.java  |  2 +-
 .../kickc/model/types/SymbolTypeConversion.java  | 16 ++++++++--------
 .../passes/Pass2ConstantIdentification.java      |  2 +-
 .../passes/PassNAddNumberTypeConversions.java    |  2 +-
 .../passes/PassNAddTypeConversionAssignment.java |  4 ++--
 .../PassNDowngradeConstantTypeConversions.java   |  6 +++---
 .../kickc/passes/PassNTypeIdSimplification.java  |  2 +-
 8 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
index f36dfdaca..e145eb480 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
@@ -29,7 +29,7 @@ public class OperatorDivide extends OperatorBinary {
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
       if(left instanceof SymbolTypePointer) {
-         if(right.equals(SymbolType.BYTE) || right.equals(SymbolType.WORD)|| right.equals(SymbolType.NUMBER)) {
+         if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) {
             return left;
          } else {
             throw new NoMatchingType("Cannot divide pointer by "+right.toString());
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
index a4a98d455..48b4cf2d4 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
@@ -23,7 +23,7 @@ public class OperatorMultiply extends OperatorBinary {
    @Override
    public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
       if(left instanceof SymbolTypePointer) {
-         if(right.equals(SymbolType.BYTE) || right.equals(SymbolType.WORD)|| right.equals(SymbolType.NUMBER)) {
+         if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) {
             return left;
          } else {
             throw new NoMatchingType("Cannot multiply pointer by "+right.toString());
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index 02b96b28c..b2f8c2356 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -155,17 +155,17 @@ public class SymbolTypeConversion {
    public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) {
       if(lValueType.equals(rValueType))
          return true;
-      if(lValueType.equals(SymbolType.WORD) && rValueType.equals(SymbolType.BYTE))
+      if(SymbolType.WORD.equals(lValueType) && SymbolType.BYTE.equals(rValueType))
          return true;
-      if(lValueType.equals(SymbolType.DWORD) && rValueType.equals(SymbolType.BYTE))
+      if(SymbolType.DWORD.equals(lValueType) && SymbolType.BYTE.equals(rValueType))
          return true;
-      if(lValueType.equals(SymbolType.DWORD) && rValueType.equals(SymbolType.WORD))
+      if(SymbolType.DWORD.equals(lValueType) && SymbolType.WORD.equals(rValueType))
          return true;
-      if(lValueType.equals(SymbolType.SWORD) && rValueType.equals(SymbolType.SBYTE))
+      if(SymbolType.SWORD.equals(lValueType) && SymbolType.SBYTE.equals(rValueType))
          return true;
-      if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SBYTE))
+      if(SymbolType.SDWORD.equals(lValueType) && SymbolType.SBYTE.equals(rValueType))
          return true;
-      if(lValueType.equals(SymbolType.SDWORD) && rValueType.equals(SymbolType.SWORD))
+      if(SymbolType.SDWORD.equals(lValueType) && SymbolType.SWORD.equals(rValueType))
          return true;
       if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
          // R-value is still a number - constants are probably not done being identified & typed
@@ -175,7 +175,7 @@ public class SymbolTypeConversion {
          // R-value is still a number - constants are probably not done being identified & typed
          return true;
       }
-      if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
+      if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) {
          // String value can be assigned into a pointer
          return true;
       }
@@ -198,7 +198,7 @@ public class SymbolTypeConversion {
          return false;
       else if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(((SymbolTypePointer) rValueType).getElementType()))
          return false;
-      else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE))
+      else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType()))
          return false;
       else
       return true;
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
index be3634d84..76affac0d 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
@@ -73,7 +73,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
          SymbolType valueType = SymbolTypeInference.inferType(getScope(), constVal);
          SymbolType variableType = variable.getType();
 
-         if(!variableType.equals(SymbolType.NUMBER) && valueType.equals(SymbolType.NUMBER)) {
+         if(!SymbolType.NUMBER.equals(variableType) && SymbolType.NUMBER.equals(valueType)) {
             // Value is number - wait til it is cast to a proper type
             constants.remove(constRef);
             continue;
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
index 7a69f1fd4..dcc576213 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -37,7 +37,7 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
                   modified.set(true);
                }
                SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
-               if(rightType.equals(SymbolType.NUMBER)) {
+               if(SymbolType.NUMBER.equals(rightType)) {
                   getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
                   binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
                   modified.set(true);
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
index 3fde76260..4b74e0e9c 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
@@ -40,7 +40,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
                   }
 
                   // Detect word literal constructor
-                  if(leftType.equals(SymbolType.WORD) && isLiteralWordCandidate(rightType)) {
+                  if(SymbolType.WORD.equals(leftType) && isLiteralWordCandidate(rightType)) {
                      SymbolType conversionType = SymbolType.WORD;
                      getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
                      binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
@@ -55,7 +55,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
                   }
 
                   // Detect dword literal constructor
-                  if(leftType.equals(SymbolType.DWORD) && isLiteralWordCandidate(rightType)) {
+                  if(SymbolType.DWORD.equals(leftType) && isLiteralWordCandidate(rightType)) {
                      SymbolType conversionType = SymbolType.DWORD;
                      getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
                      binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java
index 85a6db2cb..e87e6e748 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java
@@ -68,7 +68,7 @@ public class PassNDowngradeConstantTypeConversions extends Pass2SsaOptimization
     */
    public boolean isWordLike(RValue rValue) {
       SymbolType symbolType = SymbolTypeInference.inferType(getProgram().getScope(), rValue);
-      return symbolType.equals(SymbolType.WORD) || symbolType instanceof SymbolTypePointer;
+      return SymbolType.WORD.equals(symbolType) || symbolType instanceof SymbolTypePointer;
    }
 
 
@@ -79,10 +79,10 @@ public class PassNDowngradeConstantTypeConversions extends Pass2SsaOptimization
     * @return true if the value is a constant cast to word
     */
    public boolean isConstantWord(RValue rValue) {
-      if(rValue instanceof ConstantInteger && ((ConstantInteger) rValue).getType().equals(SymbolType.WORD)) {
+      if(rValue instanceof ConstantInteger && SymbolType.WORD.equals(((ConstantInteger) rValue).getType())) {
          return true;
       }
-      if((rValue instanceof ConstantCastValue) && ((ConstantCastValue) rValue).getToType().equals(SymbolType.WORD))
+      if((rValue instanceof ConstantCastValue) && SymbolType.WORD.equals(((ConstantCastValue) rValue).getToType()))
          return true;
       return false;
    }
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
index 43d47670d..1b110077d 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
@@ -30,7 +30,7 @@ public class PassNTypeIdSimplification extends Pass2SsaOptimization {
             if(Operators.TYPEID.equals(unary.getOperator())) {
                RValue rValue = unary.getOperand();
                SymbolType symbolType = SymbolTypeInference.inferType(getScope(), rValue);
-               if(symbolType.equals(SymbolType.VAR) || symbolType.equals(SymbolType.NUMBER)) {
+               if(SymbolType.VAR.equals(symbolType) || SymbolType.NUMBER.equals(symbolType)) {
 
                }  else {
                   getLog().append("Resolving typeid() " + currentStmt.toString(getProgram(), false));

From 2fb9a5baf3b33b9775864c301be18b5409964d1e Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Wed, 22 May 2019 23:38:34 +0200
Subject: [PATCH 68/93] Moved symbol table update functions to
 PassNTypeInference (cleaning up SymbolTypeInference).

---
 .../kickc/model/types/SymbolType.java         |   6 +-
 .../model/types/SymbolTypeInference.java      | 110 -------------
 .../kickc/passes/Pass1FixLValuesLoHi.java     |   3 +-
 .../kickc/passes/PassNTypeInference.java      | 149 +++++++++++++++---
 4 files changed, 135 insertions(+), 133 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
index 34747ed97..bff9cc686 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
@@ -15,8 +15,12 @@ public interface SymbolType {
    SymbolTypeIntegerFixed DWORD = new SymbolTypeIntegerFixed("dword", 0, 4_294_967_296L, false, 32);
    /** Signed double word (4 bytes, 32 bits). */
    SymbolTypeIntegerFixed SDWORD = new SymbolTypeIntegerFixed("signed dword", -2_147_483_648, 2_147_483_647, true, 32);
-   /** Integer with unknown size (used for constant expressions). */
+   /** Integer with unknown size and unknown signedness (used for constant expressions). */
    SymbolTypeIntegerAuto NUMBER = new SymbolTypeIntegerAuto("number");
+   /** Unsigned integer with unknown size (used for constant expressions). */
+   SymbolTypeIntegerAuto UNUMBER = new SymbolTypeIntegerAuto("unumber");
+   /** Signed integer with unknown size (used for constant expressions). */
+   SymbolTypeIntegerAuto SNUMBER = new SymbolTypeIntegerAuto("snumber");
    /** String value (treated like byte* ). */
    SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99);
    /** Boolean value. */
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index 4a244cbdb..6c308eec4 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -178,114 +178,4 @@ public class SymbolTypeInference {
       return rValueType;
    }
 
-   public static void inferCallLValue(Program program, StatementCall 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()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
-            Procedure procedure = programScope.getProcedure(call.getProcedure());
-            SymbolType type = procedure.getReturnType();
-            setInferedType(program, call, symbol, type);
-         }
-      }
-   }
-
-   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()) || SymbolType.NUMBER.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()) || SymbolType.NUMBER.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 if(!type.equals(valueType))
-               if(valueType instanceof SymbolTypeInteger && type instanceof SymbolTypeInteger) {
-                  type = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) valueType, (SymbolTypeInteger) type);
-               } else  {
-                  throw new CompileError("Phi value has type mismatch "+phiRValue.toString() + " not matching type " + type.getTypeName());
-               }
-         }
-         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();
-      if(lValue instanceof VariableRef) {
-         Variable symbol = programScope.getVariable((VariableRef) lValue);
-         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
-            // Unresolved symbol - perform inference
-            Operator operator = assignment.getOperator();
-            if(assignment.getrValue1() == null && operator == null) {
-               // Copy operation
-               RValue rValue = assignment.getrValue2();
-               SymbolType type = inferType(programScope, rValue);
-               setInferedType(program, assignment, symbol, type);
-            } else if(assignment.getrValue1() == null && operator instanceof OperatorUnary) {
-               // Unary operation
-               RValue rValue = assignment.getrValue2();
-               SymbolType type = inferType(programScope, (OperatorUnary) operator, rValue);
-               setInferedType(program, assignment, symbol, type);
-            } else if(operator instanceof OperatorBinary) {
-               // Binary operation
-               SymbolType type = inferType(
-                     programScope, assignment.getrValue1(),
-                     (OperatorBinary) assignment.getOperator(),
-                     assignment.getrValue2());
-               setInferedType(program, assignment, symbol, type);
-            } else {
-               throw new CompileError("Cannot infer type of " + assignment);
-            }
-            // If the type is an array or a string the symbol is constant
-            if(symbol.getType() instanceof SymbolTypeArray) {
-               symbol.setDeclaredConstant(true);
-            } else if(SymbolType.STRING.equals(symbol.getType())) {
-               symbol.setDeclaredConstant(true);
-            }
-         }
-      }
-   }
-
-   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 " + statement.toString(program, false));
-      }
-      symbol.setTypeInferred(type);
-   }
-
-   public static void inferLValue(Program program, StatementLValue statementLValue, boolean reinfer) {
-      if(statementLValue instanceof StatementAssignment) {
-         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);
-      }
-   }
-
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java
index 1b2f990e8..68d13d0e3 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java
@@ -12,7 +12,6 @@ import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.symbols.Scope;
 import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.symbols.VariableIntermediate;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -80,7 +79,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base {
       VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
       VariableRef tmpVarRef = tmpVar.getRef();
       statementLValue.setlValue(tmpVarRef);
-      SymbolTypeInference.inferLValue(getProgram(), statementLValue, false);
+      PassNTypeInference.inferLValue(getProgram(), statementLValue);
       // Insert an extra "set low" assignment statement
       Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef, statementLValue.getSource(), new ArrayList<>());
       statementsIt.add(setLoHiAssignment);
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
index d4baa4e7d..d37114431 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
@@ -3,10 +3,17 @@ 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.operators.Operator;
+import dk.camelot64.kickc.model.operators.OperatorBinary;
+import dk.camelot64.kickc.model.operators.OperatorUnary;
 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;
+import dk.camelot64.kickc.model.symbols.ProgramScope;
+import dk.camelot64.kickc.model.symbols.Variable;
+import dk.camelot64.kickc.model.types.*;
+import dk.camelot64.kickc.model.values.LValue;
+import dk.camelot64.kickc.model.values.RValue;
+import dk.camelot64.kickc.model.values.VariableRef;
 
 /**
  * Pass through the generated statements inferring types of unresolved variables.
@@ -18,34 +25,136 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       super(program);
    }
 
+
    @Override
    public boolean step() {
       for(ControlFlowBlock block : getGraph().getAllBlocks()) {
          for(Statement statement : block.getStatements()) {
-            if(statement instanceof StatementAssignment) {
-               StatementAssignment assignment = (StatementAssignment) statement;
-               try {
-                  SymbolTypeInference.inferAssignmentLValue(getProgram(), assignment, false);
-               } 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());
+            try {
+               if(statement instanceof StatementLValue) {
+                  inferLValue(getProgram(), (StatementLValue) statement);
+               } else if(statement instanceof StatementPhiBlock) {
+                  for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
+                     inferPhiVariable(getProgram(), phiVariable);
                   }
                }
-            } else if(statement instanceof StatementCall) {
-               SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, false);
-            } else if(statement instanceof StatementCallPointer) {
-               SymbolTypeInference.inferCallPointerLValue(getProgram(), (StatementCallPointer) statement, false);
+            } catch(CompileError e) {
+               throw new CompileError(e.getMessage(), statement.getSource());
             }
-
          }
       }
       return false;
    }
 
+   public static void inferLValue(Program program, StatementLValue statementLValue) {
+      if(statementLValue instanceof StatementAssignment) {
+         inferAssignmentLValue(program, (StatementAssignment) statementLValue);
+      } else if(statementLValue instanceof StatementCall) {
+         inferCallLValue(program, (StatementCall) statementLValue);
+      } else if(statementLValue instanceof StatementCallPointer) {
+         inferCallPointerLValue(program, (StatementCallPointer) statementLValue);
+      } else {
+         throw new RuntimeException("LValue statement not implemented " + statementLValue);
+      }
+   }
+
+
+   private static void inferCallLValue(Program program, StatementCall call) {
+      ProgramScope programScope = program.getScope();
+      LValue lValue = call.getlValue();
+      if(lValue instanceof VariableRef) {
+         Variable symbol = programScope.getVariable((VariableRef) lValue);
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
+            Procedure procedure = programScope.getProcedure(call.getProcedure());
+            SymbolType type = procedure.getReturnType();
+            setInferedType(program, call, symbol, type);
+         }
+      }
+   }
+
+   private static void inferCallPointerLValue(Program program, StatementCallPointer call) {
+      ProgramScope programScope = program.getScope();
+      LValue lValue = call.getlValue();
+      if(lValue instanceof VariableRef) {
+         Variable symbol = programScope.getVariable((VariableRef) lValue);
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
+            SymbolType procedureType = SymbolTypeInference.inferType(programScope, call.getProcedure());
+            if(procedureType instanceof SymbolTypeProcedure) {
+               SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType();
+               setInferedType(program, call, symbol, returnType);
+            }
+         }
+      }
+   }
+
+   private static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) {
+      ProgramScope programScope = program.getScope();
+      Variable symbol = programScope.getVariable(phiVariable.getVariable());
+      if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
+         SymbolType type = null;
+         for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
+            RValue rValue = phiRValue.getrValue();
+            SymbolType valueType = SymbolTypeInference.inferType(programScope, rValue);
+            if(type == null) {
+               type = valueType;
+            } else if(!type.equals(valueType))
+               if(valueType instanceof SymbolTypeInteger && type instanceof SymbolTypeInteger) {
+                  type = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) valueType, (SymbolTypeInteger) type);
+               } else {
+                  throw new CompileError("Phi value has type mismatch " + phiRValue.toString() + " not matching type " + type.getTypeName());
+               }
+         }
+         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);
+      }
+   }
+
+   private static void inferAssignmentLValue(Program program, StatementAssignment assignment) {
+      ProgramScope programScope = program.getScope();
+      LValue lValue = assignment.getlValue();
+      if(lValue instanceof VariableRef) {
+         Variable symbol = programScope.getVariable((VariableRef) lValue);
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
+            // Unresolved symbol - perform inference
+            Operator operator = assignment.getOperator();
+            if(assignment.getrValue1() == null && operator == null) {
+               // Copy operation
+               RValue rValue = assignment.getrValue2();
+               SymbolType type = SymbolTypeInference.inferType(programScope, rValue);
+               setInferedType(program, assignment, symbol, type);
+            } else if(assignment.getrValue1() == null && operator instanceof OperatorUnary) {
+               // Unary operation
+               RValue rValue = assignment.getrValue2();
+               SymbolType type = SymbolTypeInference.inferType(programScope, (OperatorUnary) operator, rValue);
+               setInferedType(program, assignment, symbol, type);
+            } else if(operator instanceof OperatorBinary) {
+               // Binary operation
+               SymbolType type = SymbolTypeInference.inferType(
+                     programScope, assignment.getrValue1(),
+                     (OperatorBinary) assignment.getOperator(),
+                     assignment.getrValue2());
+               setInferedType(program, assignment, symbol, type);
+            } else {
+               throw new CompileError("Cannot infer type of " + assignment);
+            }
+            // If the type is an array or a string the symbol is constant
+            if(symbol.getType() instanceof SymbolTypeArray) {
+               symbol.setDeclaredConstant(true);
+            } else if(SymbolType.STRING.equals(symbol.getType())) {
+               symbol.setDeclaredConstant(true);
+            }
+         }
+      }
+   }
+
+   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 " + statement.toString(program, false));
+      }
+      symbol.setTypeInferred(type);
+   }
+
+
 }

From 864b993f143845ef3538dc883322e6588f9339e8 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Wed, 22 May 2019 23:50:50 +0200
Subject: [PATCH 69/93] Eliminated SymbolTypeSimple. Eliminated
 SymbolTypeInference.infer(type, ...). Eliminiated most of
 SymbolTypeNumberInference.

---
 .../model/operators/OperatorAddressOf.java    |  3 +-
 .../model/operators/OperatorAssignment.java   |  4 +-
 .../kickc/model/operators/OperatorBinary.java |  3 +-
 .../model/operators/OperatorBitwiseAnd.java   |  2 +-
 .../model/operators/OperatorBitwiseNot.java   |  3 +-
 .../model/operators/OperatorBitwiseOr.java    |  2 +-
 .../model/operators/OperatorBitwiseXor.java   |  2 +-
 .../model/operators/OperatorCastBool.java     |  3 +-
 .../model/operators/OperatorCastByte.java     |  3 +-
 .../model/operators/OperatorCastDWord.java    |  3 +-
 .../model/operators/OperatorCastPtr.java      |  3 +-
 .../model/operators/OperatorCastSByte.java    |  3 +-
 .../model/operators/OperatorCastSDWord.java   |  3 +-
 .../model/operators/OperatorCastSWord.java    |  3 +-
 .../model/operators/OperatorCastWord.java     |  3 +-
 .../kickc/model/operators/OperatorDWord.java  |  3 +-
 .../model/operators/OperatorDecrement.java    |  3 +-
 .../kickc/model/operators/OperatorDeref.java  |  3 +-
 .../model/operators/OperatorDerefIdx.java     |  3 +-
 .../kickc/model/operators/OperatorDivide.java |  2 +-
 .../kickc/model/operators/OperatorEqual.java  |  3 +-
 .../model/operators/OperatorGetHigh.java      |  3 +-
 .../kickc/model/operators/OperatorGetLow.java |  3 +-
 .../model/operators/OperatorGreaterThan.java  |  3 +-
 .../operators/OperatorGreaterThanEqual.java   |  3 +-
 .../model/operators/OperatorIncrement.java    |  3 +-
 .../model/operators/OperatorLessThan.java     |  3 +-
 .../operators/OperatorLessThanEqual.java      |  3 +-
 .../model/operators/OperatorLogicAnd.java     |  3 +-
 .../model/operators/OperatorLogicNot.java     |  3 +-
 .../model/operators/OperatorLogicOr.java      |  3 +-
 .../kickc/model/operators/OperatorMinus.java  |  2 +-
 .../kickc/model/operators/OperatorModulo.java |  2 +-
 .../model/operators/OperatorMultiply.java     |  2 +-
 .../kickc/model/operators/OperatorNeg.java    |  3 +-
 .../model/operators/OperatorNotEqual.java     |  3 +-
 .../kickc/model/operators/OperatorPlus.java   |  4 +-
 .../kickc/model/operators/OperatorPos.java    |  3 +-
 .../model/operators/OperatorSetHigh.java      |  3 +-
 .../kickc/model/operators/OperatorSetLow.java |  3 +-
 .../model/operators/OperatorShiftLeft.java    |  6 +-
 .../model/operators/OperatorShiftRight.java   |  5 +-
 .../kickc/model/operators/OperatorSizeOf.java |  3 +-
 .../kickc/model/operators/OperatorTypeId.java |  2 +-
 .../kickc/model/operators/OperatorUnary.java  |  3 +-
 .../kickc/model/operators/OperatorWord.java   |  3 +-
 .../model/types/SymbolTypeBlockScope.java     |  2 +-
 .../model/types/SymbolTypeInference.java      | 29 +-----
 .../kickc/model/types/SymbolTypeInteger.java  |  2 +-
 .../kickc/model/types/SymbolTypeNamed.java    |  2 +-
 .../types/SymbolTypeNumberInference.java      | 94 -------------------
 .../kickc/model/types/SymbolTypePointer.java  |  2 +-
 .../model/types/SymbolTypeProcedure.java      |  2 +-
 .../kickc/model/types/SymbolTypeProgram.java  |  2 +-
 .../kickc/model/types/SymbolTypeSimple.java   |  5 -
 55 files changed, 55 insertions(+), 222 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeSimple.java

diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java
index 5b3c998dd..f0da75fec 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAddressOf.java
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Unary Address-of Operator (&p) */
@@ -20,7 +19,7 @@ public class OperatorAddressOf extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return new SymbolTypePointer(operandType);
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java
index b42c177eb..9e84e1b3d 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorAssignment.java
@@ -2,8 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
-import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Binary assignment operator ( x = y ) */
@@ -19,7 +17,7 @@ public class OperatorAssignment extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return left;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBinary.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBinary.java
index 0ae783a25..9a6a79d30 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBinary.java
@@ -1,7 +1,6 @@
 package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** A binary expression operator */
@@ -25,6 +24,6 @@ public abstract class OperatorBinary extends Operator {
     * @param right The type of the right operand
     * @return The type resulting from applying the operator to the operands
     */
-   public abstract SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right);
+   public abstract SymbolType inferType(SymbolType left, SymbolType right);
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
index 931576215..84af74049 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseAnd.java
@@ -21,7 +21,7 @@ public class OperatorBitwiseAnd extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
+   public SymbolType inferType(SymbolType type1, SymbolType type2) {
       // Handle pointers as words
       if(type1 instanceof SymbolTypePointer) {
          type1 = SymbolType.WORD;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java
index 3ef8aac69..690067238 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseNot.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorBitwiseNot extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return operandType;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
index 3e6a46208..9a0309952 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseOr.java
@@ -21,7 +21,7 @@ public class OperatorBitwiseOr extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
+   public SymbolType inferType(SymbolType type1, SymbolType type2) {
       // Handle pointers as words
       if(type1 instanceof SymbolTypePointer) {
          type1 = SymbolType.WORD;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
index 2d614f2ab..8c4d71d4a 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorBitwiseXor.java
@@ -21,7 +21,7 @@ public class OperatorBitwiseXor extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
+   public SymbolType inferType(SymbolType type1, SymbolType type2) {
       // Handle pointers as words
       if(type1 instanceof SymbolTypePointer) {
          type1 = SymbolType.WORD;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java
index 24b02a921..f0b17f0f6 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastBool.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
@@ -26,7 +25,7 @@ public class OperatorCastBool extends OperatorCast  {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.BOOLEAN;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
index b00ba311a..7b843b4c0 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastByte.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
@@ -26,7 +25,7 @@ public class OperatorCastByte extends OperatorCast {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.BYTE;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
index 111b94b7a..54cb2efc7 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastDWord.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
@@ -28,7 +27,7 @@ public class OperatorCastDWord extends OperatorCast {
 
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.DWORD;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java
index 142ecc533..041089cd9 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastPtr.java
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
@@ -33,7 +32,7 @@ public class OperatorCastPtr extends OperatorCast {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return new SymbolTypePointer(elementType);
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
index 9487eae97..7d020c032 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSByte.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorCastSByte extends OperatorCast {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.SBYTE;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
index 6ec765ca7..bea05b604 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSDWord.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorCastSDWord extends OperatorCast {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.SDWORD;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
index b8a618979..7954d4243 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSWord.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorCastSWord extends OperatorCast {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.SWORD;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
index 0b1097086..aa0b6c1b6 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastWord.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
@@ -27,7 +26,7 @@ public class OperatorCastWord extends OperatorCast {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.WORD;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java
index b0e06378c..9ef7fc18d 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDWord.java
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.NoMatchingType;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -24,7 +23,7 @@ public class OperatorDWord extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       // Handle pointers as words
       if(left instanceof SymbolTypePointer) {
          left = SymbolType.WORD;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java
index 76dbf6087..5dfd1a7a4 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorDecrement extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return operandType;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java
index c8a524b31..f14f87a66 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDeref.java
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Unary Pointer Dereference Operator (*p) */
@@ -20,7 +19,7 @@ public class OperatorDeref extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       if(operandType instanceof SymbolTypePointer) {
          return ((SymbolTypePointer) operandType).getElementType();
       }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDerefIdx.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDerefIdx.java
index c4cf2b56f..834e5c66b 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDerefIdx.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDerefIdx.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Binary Pointer Dereference with an index Operator ( p[i] / *(p+i) ) */
@@ -19,7 +18,7 @@ public class OperatorDerefIdx extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       if(left instanceof SymbolTypePointer) {
          return ((SymbolTypePointer) left).getElementType();
       }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
index e145eb480..eb3be39a8 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
@@ -27,7 +27,7 @@ public class OperatorDivide extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       if(left instanceof SymbolTypePointer) {
          if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) {
             return left;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorEqual.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorEqual.java
index 08777da59..cc990790f 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorEqual.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorEqual.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -25,7 +24,7 @@ public class OperatorEqual extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return SymbolType.BOOLEAN;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
index 79902c0c2..e7ad53157 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
@@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
@@ -40,7 +39,7 @@ public class OperatorGetHigh extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) {
          return SymbolType.BYTE;
       } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
index 7542903f6..6d8e03c03 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
@@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.ConstantNotLiteral;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
@@ -40,7 +39,7 @@ public class OperatorGetLow extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       if(operandType instanceof SymbolTypePointer || SymbolType.WORD.equals(operandType) || SymbolType.SWORD.equals(operandType)) {
          return SymbolType.BYTE;
       } else if(SymbolType.DWORD.equals(operandType) || SymbolType.SDWORD.equals(operandType)) {
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThan.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThan.java
index fcf503c84..f1614c0be 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThan.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThan.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -23,7 +22,7 @@ public class OperatorGreaterThan extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return SymbolType.BOOLEAN;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThanEqual.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThanEqual.java
index b195f1e40..2ce48f329 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThanEqual.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGreaterThanEqual.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -23,7 +22,7 @@ public class OperatorGreaterThanEqual extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return SymbolType.BOOLEAN;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java
index 70671914f..a7532ff7a 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantPointer;
@@ -26,7 +25,7 @@ public class OperatorIncrement extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return operandType;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThan.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThan.java
index a3d0c379f..ad61da0e8 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThan.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThan.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -23,7 +22,7 @@ public class OperatorLessThan extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return SymbolType.BOOLEAN;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThanEqual.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThanEqual.java
index af07b0378..cbf042583 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThanEqual.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLessThanEqual.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -23,7 +22,7 @@ public class OperatorLessThanEqual extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return SymbolType.BOOLEAN;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicAnd.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicAnd.java
index d755616a3..0088ec944 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicAnd.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicAnd.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -22,7 +21,7 @@ public class OperatorLogicAnd extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return SymbolType.BOOLEAN;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java
index 740f1ce01..990cab0f1 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicNot.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorLogicNot extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return operandType;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicOr.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicOr.java
index 5c838560a..5d5b92e68 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicOr.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorLogicOr.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -22,7 +21,7 @@ public class OperatorLogicOr extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return SymbolType.BOOLEAN;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
index ce472ffd7..50c1fb6f7 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMinus.java
@@ -29,7 +29,7 @@ public class OperatorMinus extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
+   public SymbolType inferType(SymbolType type1, SymbolType type2) {
       // Handle pointer types
       if(type1 instanceof SymbolTypePointer && SymbolType.isInteger(type2)) {
          return new SymbolTypePointer(((SymbolTypePointer) type1).getElementType());
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
index 4fc0a3388..7235c3fdc 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorModulo.java
@@ -24,7 +24,7 @@ public class OperatorModulo extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       // Handle numeric types through proper promotion
       if(SymbolType.isInteger(left) && SymbolType.isInteger(right)) {
          return SymbolTypeConversion.convertedMathType((SymbolTypeInteger) left, (SymbolTypeInteger) right);
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
index 48b4cf2d4..a32595647 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorMultiply.java
@@ -21,7 +21,7 @@ public class OperatorMultiply extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       if(left instanceof SymbolTypePointer) {
          if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) {
             return left;
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java
index ce736a9d1..2e777f4f1 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNeg.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorNeg extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return operandType;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNotEqual.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNotEqual.java
index 8b995c59e..7aba1389b 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorNotEqual.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorNotEqual.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
@@ -29,7 +28,7 @@ public class OperatorNotEqual extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       return SymbolType.BOOLEAN;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
index 0cb8ec7b8..7df7c77bd 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPlus.java
@@ -37,7 +37,7 @@ public class OperatorPlus extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple type1, SymbolTypeSimple type2) {
+   public SymbolType inferType(SymbolType type1, SymbolType type2) {
       // Handle all non-numeric types
       if(SymbolType.isInteger(type1) && type2 instanceof SymbolTypePointer) {
          return new SymbolTypePointer(((SymbolTypePointer) type2).getElementType());
@@ -59,7 +59,7 @@ public class OperatorPlus extends OperatorBinary {
     * @param type The type to check
     * @return true if the type is string like
     */
-   private boolean isStringLike(SymbolTypeSimple type) {
+   private boolean isStringLike(SymbolType type) {
       if(SymbolType.STRING.equals(type)) {
          return true;
       } else if(SymbolType.BYTE.equals(type)) {
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java
index 03acd3465..507bba6fc 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorPos.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorPos extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return operandType;
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java
index 19662e139..041322a18 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetHigh.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Binary SetHighByte Operator ( w hi= b ) */
@@ -19,7 +18,7 @@ public class OperatorSetHigh extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       if(left instanceof SymbolTypePointer) {
          return left;
       } else if(SymbolType.BYTE.equals(left)) {
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java
index bd4cd763a..180b4b5bd 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSetLow.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** Binary SetLowByte Operator ( w lo= b ) */
@@ -19,7 +18,7 @@ public class OperatorSetLow extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       if(left instanceof SymbolTypePointer) {
          return left;
       }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
index 3350f82f7..5d84970ef 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftLeft.java
@@ -2,10 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeConversion;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
-import dk.camelot64.kickc.model.values.ConstantBool;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -25,7 +21,7 @@ public class OperatorShiftLeft extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
          return left;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
index 2f8a9dca0..352dae6d5 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorShiftRight.java
@@ -2,9 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeConversion;
-import dk.camelot64.kickc.model.types.SymbolTypeInteger;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -24,7 +21,7 @@ public class OperatorShiftRight extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
          return left;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
index 11fa1b0a1..422f6a4c2 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorSizeOf.java
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.symbols.ConstantVar;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 import dk.camelot64.kickc.model.values.ConstantRef;
@@ -23,7 +22,7 @@ public class OperatorSizeOf extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.BYTE;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java
index c5dca47db..0d09c75e9 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorTypeId.java
@@ -24,7 +24,7 @@ public class OperatorTypeId extends OperatorUnary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple operandType) {
+   public SymbolType inferType(SymbolType operandType) {
       return SymbolType.BYTE;
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java
index d9efd026f..2c1775de7 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorUnary.java
@@ -2,7 +2,6 @@ package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
 /** A unary expression operator */
@@ -25,6 +24,6 @@ public abstract class OperatorUnary extends Operator {
     * @param operandType The type of the operand
     * @return The type resulting from applying the operator to the operand
     */
-   public abstract SymbolType inferType(SymbolTypeSimple operandType);
+   public abstract SymbolType inferType(SymbolType operandType);
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java
index c84710823..01f96476c 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorWord.java
@@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.operators;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.types.NoMatchingType;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeSimple;
 import dk.camelot64.kickc.model.values.ConstantInteger;
 import dk.camelot64.kickc.model.values.ConstantLiteral;
 
@@ -23,7 +22,7 @@ public class OperatorWord extends OperatorBinary {
    }
 
    @Override
-   public SymbolType inferType(SymbolTypeSimple left, SymbolTypeSimple right) {
+   public SymbolType inferType(SymbolType left, SymbolType right) {
       if(SymbolType.BYTE.equals(left) && SymbolType.BYTE.equals(right)) {
          return SymbolType.WORD;
       }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeBlockScope.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeBlockScope.java
index 8d5b113f4..4fc97f3cb 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeBlockScope.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeBlockScope.java
@@ -1,7 +1,7 @@
 package dk.camelot64.kickc.model.types;
 
 /** A block scope */
-public class SymbolTypeBlockScope implements SymbolTypeSimple {
+public class SymbolTypeBlockScope implements SymbolType {
 
    public SymbolTypeBlockScope() {
 
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index 6c308eec4..f2af3c947 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -1,8 +1,6 @@
 package dk.camelot64.kickc.model.types;
 
 import dk.camelot64.kickc.model.CompileError;
-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.*;
@@ -24,22 +22,7 @@ public class SymbolTypeInference {
     */
    public static SymbolType inferType(ProgramScope programScope, OperatorUnary operator, RValue rValue) {
       SymbolType valueType = inferType(programScope, rValue);
-      return inferType(operator, valueType);
-   }
-
-   /**
-    * Infer the type of a unary operator on an operand type
-    *
-    * @param operator The unary operator
-    * @param operandType The operand type
-    * @return The type of the result from applying the operator on the operand
-    */
-   public static SymbolType inferType(OperatorUnary operator, SymbolType operandType) {
-      if(operandType instanceof SymbolTypeSimple) {
-         return operator.inferType((SymbolTypeSimple) operandType);
-      } else {
-         throw new RuntimeException("Not implemented!");
-      }
+      return operator.inferType(valueType);
    }
 
    /**
@@ -54,15 +37,7 @@ public class SymbolTypeInference {
    public static SymbolType inferType(ProgramScope programScope, RValue left, OperatorBinary operator, RValue right) {
       SymbolType leftType = inferType(programScope, left);
       SymbolType rightType = inferType(programScope, right);
-      return inferType(leftType, operator, rightType);
-   }
-
-   public static SymbolType inferType(SymbolType left, OperatorBinary operator, SymbolType right) {
-      if(left instanceof SymbolTypeSimple && right instanceof SymbolTypeSimple) {
-         return operator.inferType((SymbolTypeSimple) left, (SymbolTypeSimple) right);
-      } else {
-         throw new RuntimeException("Not implemented!");
-      }
+      return operator.inferType(leftType, rightType);
    }
 
    public static SymbolType inferType(ProgramScope symbols, RValue rValue) {
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java
index 2a4cdfa7f..9a64e214d 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInteger.java
@@ -1,6 +1,6 @@
 package dk.camelot64.kickc.model.types;
 
 /** Integer type marker interface. */
-public interface  SymbolTypeInteger extends SymbolTypeSimple {
+public interface  SymbolTypeInteger extends SymbolType {
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNamed.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNamed.java
index fce17747e..5578a24bf 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNamed.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNamed.java
@@ -1,7 +1,7 @@
 package dk.camelot64.kickc.model.types;
 
 /** Basic named (string, char, ...) Symbol Types */
-public class SymbolTypeNamed implements SymbolTypeSimple {
+public class SymbolTypeNamed implements SymbolType {
 
    private String typeName;
 
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
index 983e6a21f..9a1519369 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
@@ -1,15 +1,5 @@
 package dk.camelot64.kickc.model.types;
 
-import dk.camelot64.kickc.model.InternalError;
-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.symbols.ProgramScope;
-import dk.camelot64.kickc.model.values.ConstantInteger;
-import dk.camelot64.kickc.model.values.ConstantLiteral;
-import dk.camelot64.kickc.model.values.ConstantValue;
-import dk.camelot64.kickc.model.values.RValue;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -19,90 +9,6 @@ import java.util.List;
  */
 public class SymbolTypeNumberInference {
 
-   /**
-    * Infer the potential types for an RValue with {@link SymbolType#NUMBER} type
-    *
-    * @return The potential types
-    */
-   public static List<SymbolTypeIntegerFixed> inferTypesRValue(ProgramScope symbols, StatementAssignment assignment) {
-      RValue rValue1 = assignment.getrValue1();
-      RValue rValue2 = assignment.getrValue2();
-      if(assignment.getrValue1() == null && assignment.getOperator() == null && assignment.getrValue2() instanceof ConstantValue) {
-         return inferTypes(symbols, (ConstantValue) rValue2);
-      } else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary && assignment.getrValue2() instanceof ConstantValue) {
-         return inferTypes(symbols, (OperatorUnary) assignment.getOperator(), (ConstantValue) rValue2);
-      } else if(assignment.getOperator() instanceof OperatorBinary && assignment.getrValue1() instanceof ConstantValue && assignment.getrValue2() instanceof ConstantValue) {
-         return inferTypes(symbols, (ConstantValue) rValue1, (OperatorBinary) assignment.getOperator(), (ConstantValue) rValue2);
-      } else {
-         return new ArrayList<>();
-      }
-   }
-
-   /**
-    * Infer the potential types for a binary operator with {@link SymbolType#NUMBER} type
-    *
-    * @return The potential types
-    */
-   public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantValue leftValue, OperatorBinary operator, ConstantValue rightValue) {
-      if(SymbolType.NUMBER.equals(leftValue.getType(programScope)) && SymbolType.NUMBER.equals(rightValue.getType(programScope))) {
-         // Calculate resulting constant literal
-         ConstantLiteral leftLiteral = leftValue.calculateLiteral(programScope);
-         ConstantLiteral rightLiteral = rightValue.calculateLiteral(programScope);
-         ConstantLiteral literal = operator.calculateLiteral(leftLiteral, rightLiteral);
-         if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) {
-            SymbolType literalType = SymbolTypeInference.inferType(programScope, leftValue, operator, rightValue);
-            ((ConstantInteger) literal).setType(literalType);
-            throw new InternalError("Unexpected advanced literal type calculation!");
-         }
-         return inferTypes(programScope, literal);
-      } else {
-         throw new InternalError("Both operands must be number type.");
-      }
-   }
-
-   /**
-    * Infer the potential types for a unary operator with {@link SymbolType#NUMBER} type
-    *
-    * @return The potential types
-    */
-   public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, OperatorUnary operator, ConstantValue constantValue) {
-      if(SymbolType.NUMBER.equals(constantValue.getType(programScope))) {
-         // Calculate resulting constant literal
-         ConstantLiteral operandLiteral = constantValue.calculateLiteral(programScope);
-         ConstantLiteral literal = operator.calculateLiteral(operandLiteral, programScope);
-         if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) {
-            SymbolType literalType = SymbolTypeInference.inferType(programScope, operator, constantValue);
-            ((ConstantInteger) literal).setType(literalType);
-            throw new InternalError("Unexpected advanced literal type calculation!");
-         }
-         return inferTypes(programScope, literal);
-      } else {
-         throw new InternalError("Operand must be number type.");
-      }
-   }
-
-   /**
-    * Infer the potential types for a constant value with {@link SymbolType#NUMBER} type
-    *
-    * @return The potential types
-    */
-   public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantValue constantValue) {
-      // Calculate resulting constant literal
-      ConstantLiteral constantLiteral = constantValue.calculateLiteral(programScope);
-      return inferTypes(programScope, constantLiteral);
-   }
-
-   /**
-    * Infer the potential types for a constant literal with {@link SymbolType#NUMBER} type
-    */
-   public static List<SymbolTypeIntegerFixed> inferTypes(ProgramScope programScope, ConstantLiteral literal) {
-      if(literal instanceof ConstantInteger && SymbolType.NUMBER.equals(literal.getType(programScope))) {
-         return inferTypes(((ConstantInteger) literal).getValue());
-      } else {
-         throw new InternalError("Literal must number type.");
-      }
-   }
-
    /**
     * Find any fixed integer types that can contain the passed integer value
     * @param value the value to examine
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java
index 8be80416d..451b04e87 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java
@@ -1,7 +1,7 @@
 package dk.camelot64.kickc.model.types;
 
 /** A pointer */
-public class SymbolTypePointer implements SymbolTypeSimple {
+public class SymbolTypePointer implements SymbolType {
 
    /** The number of bytes needed to represent a pointer in memory. */
    public static final int SIZE_BYTES = 2;
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java
index e97924672..30f9e25bd 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java
@@ -3,7 +3,7 @@ package dk.camelot64.kickc.model.types;
 import java.util.Objects;
 
 /** A function returning another type */
-public class SymbolTypeProcedure implements SymbolTypeSimple {
+public class SymbolTypeProcedure implements SymbolType {
 
    private SymbolType returnType;
 
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProgram.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProgram.java
index 489f81cc8..186ba98b5 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProgram.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProgram.java
@@ -1,7 +1,7 @@
 package dk.camelot64.kickc.model.types;
 
 /** A program */
-public class SymbolTypeProgram implements SymbolTypeSimple {
+public class SymbolTypeProgram implements SymbolType {
 
    public SymbolTypeProgram() {
 
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeSimple.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeSimple.java
deleted file mode 100644
index ea306056a..000000000
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeSimple.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package dk.camelot64.kickc.model.types;
-
-/** Marker interface for simple symbol types - ie. not a multi-type */
-public interface SymbolTypeSimple extends SymbolType {
-}

From 669064bd37dae72f3aa3e851b388263f865c020d Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Wed, 22 May 2019 23:59:43 +0200
Subject: [PATCH 70/93] Eliminated SymbolTypeNumberInference.

---
 .../fragment/AsmFragmentInstanceSpec.java     | 20 ++++++++++++--
 .../types/SymbolTypeNumberInference.java      | 27 -------------------
 .../passes/PassNTypeIdSimplification.java     | 25 -----------------
 3 files changed, 18 insertions(+), 54 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java

diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
index 09d9be44f..9a003f18b 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpec.java
@@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeIntegerFixed;
-import dk.camelot64.kickc.model.types.SymbolTypeNumberInference;
 import dk.camelot64.kickc.model.values.*;
 
 import java.util.*;
@@ -49,6 +48,7 @@ public class AsmFragmentInstanceSpec {
       this.codeScopeRef = codeScopeRef;
    }
 
+
    public String getSignature() {
       return signature;
    }
@@ -95,7 +95,7 @@ public class AsmFragmentInstanceSpec {
                if(value instanceof ConstantValue) {
                   ConstantLiteral constantLiteral = ((ConstantValue) value).calculateLiteral(program.getScope());
                   if(constantLiteral instanceof ConstantInteger) {
-                     List<SymbolTypeIntegerFixed> types = SymbolTypeNumberInference.inferTypes(((ConstantInteger) constantLiteral).getValue());
+                     List<SymbolTypeIntegerFixed> types = getVariationTypes(((ConstantInteger) constantLiteral).getValue());
                      if(types.size() > 1) {
                         // Found constant value with multiple types
                         variationConstant = (ConstantValue) value;
@@ -118,6 +118,22 @@ public class AsmFragmentInstanceSpec {
       return variationIterator.hasNext();
    }
 
+   /**
+    * Find any fixed integer types that can contain the passed integer value
+    * @param value the value to examine
+    * @return All fixed size integer types capable of representing the passed value
+    */
+   public static List<SymbolTypeIntegerFixed> getVariationTypes(Long value) {
+      ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>();
+      for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) {
+         if(typeInteger.contains(value)) {
+            potentialTypes.add(typeInteger);
+         }
+      }
+      return potentialTypes;
+   }
+
+
    /**
     * Updates the ASM fragment instance specification to the next available variation.
     * If no more variations exist the ASM fragment instance specification will become unusable.
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
deleted file mode 100644
index 9a1519369..000000000
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeNumberInference.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package dk.camelot64.kickc.model.types;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Interference of possible types for constant expressions with the {@link SymbolType#NUMBER} type.
- * This is done by evaluating the constant expression to find the literal value.
- */
-public class SymbolTypeNumberInference {
-
-   /**
-    * Find any fixed integer types that can contain the passed integer value
-    * @param value the value to examine
-    * @return All fixed size integer types capable of representing the passed value
-    */
-   public static List<SymbolTypeIntegerFixed> inferTypes(Long value) {
-      ArrayList<SymbolTypeIntegerFixed> potentialTypes = new ArrayList<>();
-      for(SymbolTypeIntegerFixed typeInteger : SymbolTypeIntegerFixed.getIntegerFixedTypes()) {
-         if(typeInteger.contains(value)) {
-            potentialTypes.add(typeInteger);
-         }
-      }
-      return potentialTypes;
-   }
-
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
index 1b110077d..1e6b5ffd0 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeIdSimplification.java
@@ -42,31 +42,6 @@ public class PassNTypeIdSimplification extends Pass2SsaOptimization {
          }
       });
 
-      /*
-      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
-         for(Statement statement : block.getStatements()) {
-            if(statement instanceof StatementAssignment) {
-               StatementAssignment assignment = (StatementAssignment) statement;
-               if(Operators.TYPEID.equals(assignment.getOperator())) {
-                  RValue rValue = assignment.getrValue2();
-                  SymbolType symbolType = SymbolTypeInference.inferType(getSymbols(), rValue);
-                  if(SymbolType.NUMBER.equals(symbolType)) {
-                     if(rValue instanceof ConstantValue) {
-                        List<SymbolTypeIntegerFixed> fixedTypes = SymbolTypeNumberInference.inferTypes(getSymbols(), (ConstantLiteral) rValue);
-                        throw new InternalError("TODO: Implement typeof(const)!");
-                     }
-                  } else {
-                     getLog().append("Resolving typeid() " + assignment.toString(getProgram(), false));
-                     ConstantRef typeIDConstantVar = OperatorTypeId.getTypeIdConstantVar(getSymbols(), symbolType);
-                     assignment.setrValue2(typeIDConstantVar);
-                     assignment.setOperator(null);
-                     modified = true;
-                  }
-               }
-            }
-         }
-      }
-      */
       return modified.get();
    }
 }

From 49a61ecbdd4f27957596ce2e7156a8e887d80471 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 00:28:34 +0200
Subject: [PATCH 71/93] Cleaning up type inference.

---
 .../model/types/SymbolTypeInference.java      |  2 +-
 .../kickc/passes/Pass2AssertTypeMatch.java    |  3 +-
 .../kickc/passes/PassNTypeInference.java      | 28 ++-----------------
 3 files changed, 6 insertions(+), 27 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index f2af3c947..6cb623454 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -137,7 +137,7 @@ public class SymbolTypeInference {
       }
    }
 
-   public static SymbolType inferTypeRValue(ProgramScope symbols, StatementAssignment assignment) {
+   private static SymbolType inferTypeRValue(ProgramScope symbols, StatementAssignment assignment) {
       SymbolType rValueType;
       RValue rValue1 = assignment.getrValue1();
       RValue rValue2 = assignment.getrValue2();
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
index 5e9e3157d..2a1e626af 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertTypeMatch.java
@@ -9,6 +9,7 @@ import dk.camelot64.kickc.model.statements.StatementConditionalJump;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeConversion;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.values.AssignmentRValue;
 import dk.camelot64.kickc.model.values.LValue;
 import dk.camelot64.kickc.model.values.RValue;
 
@@ -50,7 +51,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion {
    private void checkAssignment(StatementAssignment statement) {
       LValue lValue = statement.getlValue();
       SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
-      SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement);
+      SymbolType rValueType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(statement));
       if(SymbolTypeConversion.assignmentTypeMatch(lValueType, rValueType)) return;
       // Types do not match
       getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false));
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
index d37114431..365829e6a 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
@@ -3,14 +3,12 @@ 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.operators.Operator;
-import dk.camelot64.kickc.model.operators.OperatorBinary;
-import dk.camelot64.kickc.model.operators.OperatorUnary;
 import dk.camelot64.kickc.model.statements.*;
 import dk.camelot64.kickc.model.symbols.Procedure;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.types.*;
+import dk.camelot64.kickc.model.values.AssignmentRValue;
 import dk.camelot64.kickc.model.values.LValue;
 import dk.camelot64.kickc.model.values.RValue;
 import dk.camelot64.kickc.model.values.VariableRef;
@@ -117,28 +115,8 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       if(lValue instanceof VariableRef) {
          Variable symbol = programScope.getVariable((VariableRef) lValue);
          if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
-            // Unresolved symbol - perform inference
-            Operator operator = assignment.getOperator();
-            if(assignment.getrValue1() == null && operator == null) {
-               // Copy operation
-               RValue rValue = assignment.getrValue2();
-               SymbolType type = SymbolTypeInference.inferType(programScope, rValue);
-               setInferedType(program, assignment, symbol, type);
-            } else if(assignment.getrValue1() == null && operator instanceof OperatorUnary) {
-               // Unary operation
-               RValue rValue = assignment.getrValue2();
-               SymbolType type = SymbolTypeInference.inferType(programScope, (OperatorUnary) operator, rValue);
-               setInferedType(program, assignment, symbol, type);
-            } else if(operator instanceof OperatorBinary) {
-               // Binary operation
-               SymbolType type = SymbolTypeInference.inferType(
-                     programScope, assignment.getrValue1(),
-                     (OperatorBinary) assignment.getOperator(),
-                     assignment.getrValue2());
-               setInferedType(program, assignment, symbol, type);
-            } else {
-               throw new CompileError("Cannot infer type of " + assignment);
-            }
+            SymbolType type = SymbolTypeInference.inferType(programScope, new AssignmentRValue(assignment));
+            setInferedType(program, assignment, symbol, type);
             // If the type is an array or a string the symbol is constant
             if(symbol.getType() instanceof SymbolTypeArray) {
                symbol.setDeclaredConstant(true);

From 65c92716f03500a4e2aeaa59e6055ec811d679a2 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 00:38:35 +0200
Subject: [PATCH 72/93] Cleaning up type inference.

---
 .../model/types/SymbolTypeInference.java      | 76 +++++++------------
 .../kickc/model/values/ConstantBinary.java    |  4 +-
 .../kickc/model/values/ConstantUnary.java     |  3 +-
 .../passes/Pass2DeInlineWordDerefIdx.java     |  8 +-
 4 files changed, 37 insertions(+), 54 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index 6cb623454..c2875ef15 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -3,43 +3,15 @@ package dk.camelot64.kickc.model.types;
 import dk.camelot64.kickc.model.CompileError;
 import dk.camelot64.kickc.model.operators.OperatorBinary;
 import dk.camelot64.kickc.model.operators.OperatorUnary;
-import dk.camelot64.kickc.model.statements.*;
+import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.symbols.*;
 import dk.camelot64.kickc.model.values.*;
 
 /**
- * Type inference of expressions (rValues & unary/binary operators)
+ * Type inference of an RValue
  */
 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, OperatorUnary operator, RValue rValue) {
-      SymbolType valueType = inferType(programScope, rValue);
-      return operator.inferType(valueType);
-   }
-
-   /**
-    * Infer the type of a binary operator on a value
-    *
-    * @param programScope The program scope usable for accessing the symbol table
-    * @param left The left value
-    * @param operator The binary operator
-    * @param rValue The right value
-    * @return The type of the resulting value
-    */
-   public static SymbolType inferType(ProgramScope programScope, RValue left, OperatorBinary operator, RValue right) {
-      SymbolType leftType = inferType(programScope, left);
-      SymbolType rightType = inferType(programScope, right);
-      return operator.inferType(leftType, rightType);
-   }
-
    public static SymbolType inferType(ProgramScope symbols, RValue rValue) {
       SymbolType type = null;
       if(rValue instanceof VariableRef) {
@@ -61,10 +33,13 @@ public class SymbolTypeInference {
          type = SymbolType.BOOLEAN;
       } else if(rValue instanceof ConstantUnary) {
          ConstantUnary constUnary = (ConstantUnary) rValue;
-         return inferType(symbols, constUnary.getOperator(), constUnary.getOperand());
+         SymbolType valueType = inferType(symbols, constUnary.getOperand());
+         return constUnary.getOperator().inferType(valueType);
       } else if(rValue instanceof ConstantBinary) {
          ConstantBinary constBin = (ConstantBinary) rValue;
-         return inferType(symbols, constBin.getLeft(), constBin.getOperator(), constBin.getRight());
+         SymbolType leftType = inferType(symbols, constBin.getLeft());
+         SymbolType rightType = inferType(symbols, constBin.getRight());
+         return constBin.getOperator().inferType(leftType, rightType);
       } else if(rValue instanceof ValueList) {
          type = inferTypeList(symbols, (ValueList) rValue);
       } else if(rValue instanceof PointerDereference) {
@@ -103,7 +78,26 @@ public class SymbolTypeInference {
          Procedure procedure = symbols.getProcedure((ProcedureRef) rValue);
          return procedure.getType();
       } else if(rValue instanceof AssignmentRValue) {
-         return inferTypeRValue(symbols, ((AssignmentRValue) rValue).getAssignment());
+         StatementAssignment assignment = ((AssignmentRValue) rValue).getAssignment();
+         SymbolType rValueType;
+         RValue rValue1 = assignment.getrValue1();
+         RValue rValue2 = assignment.getrValue2();
+         if(assignment.getrValue1() == null && assignment.getOperator() == null) {
+            // Copy assignment
+            rValueType = inferType(symbols, rValue2);
+         } else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary) {
+            // Unary operation assignment
+            SymbolType valueType = inferType(symbols, rValue2);
+            rValueType = ((OperatorUnary) assignment.getOperator()).inferType(valueType);
+         } else if(assignment.getOperator() instanceof OperatorBinary) {
+            // Binary operation assignment
+            SymbolType leftType = inferType(symbols, rValue1);
+            SymbolType rightType = inferType(symbols, rValue2);
+            rValueType = ((OperatorBinary) assignment.getOperator()).inferType(leftType, rightType);
+         } else {
+            throw new CompileError("Cannot infer type of " + assignment.toString());
+         }
+         return rValueType;
       }
       if(type == null) {
          throw new RuntimeException("Cannot infer type for " + rValue.toString());
@@ -137,20 +131,4 @@ public class SymbolTypeInference {
       }
    }
 
-   private static SymbolType inferTypeRValue(ProgramScope symbols, StatementAssignment assignment) {
-      SymbolType rValueType;
-      RValue rValue1 = assignment.getrValue1();
-      RValue rValue2 = assignment.getrValue2();
-      if(assignment.getrValue1() == null && assignment.getOperator() == null) {
-         rValueType = inferType(symbols, rValue2);
-      } else if(assignment.getrValue1() == null && assignment.getOperator() instanceof OperatorUnary) {
-         rValueType = inferType(symbols, (OperatorUnary) assignment.getOperator(), rValue2);
-      } else if(assignment.getOperator() instanceof OperatorBinary) {
-         rValueType = inferType(symbols, rValue1, (OperatorBinary) assignment.getOperator(), rValue2);
-      } else {
-         throw new CompileError("Cannot infer type of " + assignment.toString());
-      }
-      return rValueType;
-   }
-
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java
index df51994a4..90896ad5e 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java
@@ -59,7 +59,9 @@ public class ConstantBinary implements ConstantValue {
 
    @Override
    public SymbolType getType(ProgramScope scope) {
-      return SymbolTypeInference.inferType(scope, left, operator, right);
+      SymbolType leftType = SymbolTypeInference.inferType(scope, left);
+      SymbolType rightType = SymbolTypeInference.inferType(scope, right);
+      return operator.inferType(leftType, rightType);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java
index a111b9c07..d6ca0a7f9 100644
--- a/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java
+++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantUnary.java
@@ -47,7 +47,8 @@ public class ConstantUnary implements ConstantValue {
 
    @Override
    public SymbolType getType(ProgramScope scope) {
-      return SymbolTypeInference.inferType(scope, operator, operand);
+      SymbolType valueType = SymbolTypeInference.inferType(scope, operand);
+      return operator.inferType(valueType);
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java
index 4bfcbac8a..2b0b96cce 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java
@@ -9,6 +9,7 @@ import dk.camelot64.kickc.model.symbols.Scope;
 import dk.camelot64.kickc.model.symbols.VariableIntermediate;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
+import dk.camelot64.kickc.model.values.AssignmentRValue;
 import dk.camelot64.kickc.model.values.PointerDereferenceIndexed;
 import dk.camelot64.kickc.model.values.PointerDereferenceSimple;
 import dk.camelot64.kickc.model.values.RValue;
@@ -35,12 +36,13 @@ public class Pass2DeInlineWordDerefIdx extends Pass2SsaOptimization {
                getLog().append("De-inlining pointer[w] to *(pointer+w)   "+currentStmt.toString(getProgram(), false));
                Scope currentScope = getScope().getScope(currentBlock.getScope());
                VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
-               SymbolType pointerType = SymbolTypeInference.inferType(getScope(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue);
-               tmpVar.setType(pointerType);
                stmtIt.previous();
-               stmtIt.add(new StatementAssignment(tmpVar.getRef(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue, currentStmt.getSource(), Comment.NO_COMMENTS));
+               StatementAssignment tmpVarAssignment = new StatementAssignment(tmpVar.getRef(), dereferenceIndexed.getPointer(), Operators.PLUS, indexValue, currentStmt.getSource(), Comment.NO_COMMENTS);
+               stmtIt.add(tmpVarAssignment);
                stmtIt.next();
                programValue.set(new PointerDereferenceSimple(tmpVar.getRef()));
+               SymbolType pointerType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(tmpVarAssignment));
+               tmpVar.setType(pointerType);
                optimized.set(true);
             }
          }

From 2a146714966bd978a6097d41ab8a2eefebc7b69c Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 00:46:43 +0200
Subject: [PATCH 73/93] Renamed for clarity

---
 .../kickc/passes/Pass1FixLValuesLoHi.java     |  2 +-
 .../kickc/passes/PassNTypeInference.java      | 22 +++++++++----------
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java
index 68d13d0e3..1e65038e9 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java
@@ -79,7 +79,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base {
       VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
       VariableRef tmpVarRef = tmpVar.getRef();
       statementLValue.setlValue(tmpVarRef);
-      PassNTypeInference.inferLValue(getProgram(), statementLValue);
+      PassNTypeInference.updateInferedTypeLValue(getProgram(), statementLValue);
       // Insert an extra "set low" assignment statement
       Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef, statementLValue.getSource(), new ArrayList<>());
       statementsIt.add(setLoHiAssignment);
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
index 365829e6a..4e135e916 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
@@ -15,7 +15,6 @@ import dk.camelot64.kickc.model.values.VariableRef;
 
 /**
  * Pass through the generated statements inferring types of unresolved variables.
- * Also updates procedure calls to point to the actual procedure called.
  */
 public class PassNTypeInference extends Pass2SsaOptimization {
 
@@ -23,17 +22,16 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       super(program);
    }
 
-
    @Override
    public boolean step() {
       for(ControlFlowBlock block : getGraph().getAllBlocks()) {
          for(Statement statement : block.getStatements()) {
             try {
                if(statement instanceof StatementLValue) {
-                  inferLValue(getProgram(), (StatementLValue) statement);
+                  updateInferedTypeLValue(getProgram(), (StatementLValue) statement);
                } else if(statement instanceof StatementPhiBlock) {
                   for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
-                     inferPhiVariable(getProgram(), phiVariable);
+                     updateInferedTypePhiVariable(getProgram(), phiVariable);
                   }
                }
             } catch(CompileError e) {
@@ -44,20 +42,20 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       return false;
    }
 
-   public static void inferLValue(Program program, StatementLValue statementLValue) {
+   static void updateInferedTypeLValue(Program program, StatementLValue statementLValue) {
       if(statementLValue instanceof StatementAssignment) {
-         inferAssignmentLValue(program, (StatementAssignment) statementLValue);
+         updateInferedTypeAssignmentLValue(program, (StatementAssignment) statementLValue);
       } else if(statementLValue instanceof StatementCall) {
-         inferCallLValue(program, (StatementCall) statementLValue);
+         updateInferedTypeCallLValue(program, (StatementCall) statementLValue);
       } else if(statementLValue instanceof StatementCallPointer) {
-         inferCallPointerLValue(program, (StatementCallPointer) statementLValue);
+         updateInferedTypeCallPointerLValue(program, (StatementCallPointer) statementLValue);
       } else {
          throw new RuntimeException("LValue statement not implemented " + statementLValue);
       }
    }
 
 
-   private static void inferCallLValue(Program program, StatementCall call) {
+   private static void updateInferedTypeCallLValue(Program program, StatementCall call) {
       ProgramScope programScope = program.getScope();
       LValue lValue = call.getlValue();
       if(lValue instanceof VariableRef) {
@@ -70,7 +68,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       }
    }
 
-   private static void inferCallPointerLValue(Program program, StatementCallPointer call) {
+   private static void updateInferedTypeCallPointerLValue(Program program, StatementCallPointer call) {
       ProgramScope programScope = program.getScope();
       LValue lValue = call.getlValue();
       if(lValue instanceof VariableRef) {
@@ -85,7 +83,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       }
    }
 
-   private static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) {
+   private static void updateInferedTypePhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) {
       ProgramScope programScope = program.getScope();
       Variable symbol = programScope.getVariable(phiVariable.getVariable());
       if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
@@ -109,7 +107,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       }
    }
 
-   private static void inferAssignmentLValue(Program program, StatementAssignment assignment) {
+   private static void updateInferedTypeAssignmentLValue(Program program, StatementAssignment assignment) {
       ProgramScope programScope = program.getScope();
       LValue lValue = assignment.getlValue();
       if(lValue instanceof VariableRef) {

From 009b141ef161423303ea1621d71c1d5c1d7128f7 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 01:07:59 +0200
Subject: [PATCH 74/93] Eliminated PassNDowngradeConstantTypeConversion.
 Simplified PassNAddTypeConversionAssignment.

---
 .../java/dk/camelot64/kickc/Compiler.java     |  1 -
 .../Pass0GenerateStatementSequence.java       |  4 +-
 .../PassNAddTypeConversionAssignment.java     |  9 --
 ...PassNDowngradeConstantTypeConversions.java | 90 -------------------
 src/test/ref/linegen.asm                      |  5 +-
 src/test/ref/signed-indexed-subtract.asm      | 51 +++++------
 6 files changed, 27 insertions(+), 133 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index c1616481a..b6217ad15 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -233,7 +233,6 @@ public class Compiler {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
       optimizations.add(new PassNAddNumberTypeConversions(program));
       optimizations.add(new PassNAddArrayNumberTypeConversions(program));
-      optimizations.add(new PassNDowngradeConstantTypeConversions(program));
       optimizations.add(new PassNTypeInference(program));
       optimizations.add(new PassNTypeIdSimplification(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index 3426efd3c..2a5e5faea 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -908,8 +908,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
       RValue rangeLastValue = (RValue) visit(rangeLastCtx);
       RValue rangeFirstValue = (RValue) visit(rangeFirstCtx);
       if(varType!=null) {
-         if(rangeFirstValue instanceof ConstantInteger) ((ConstantInteger) rangeFirstValue).setType(varType);
-         if(rangeLastValue instanceof ConstantInteger) ((ConstantInteger) rangeLastValue).setType(varType);
+         if(rangeFirstValue instanceof ConstantInteger) ((ConstantInteger) rangeFirstValue).setType(SymbolType.NUMBER);
+         if(rangeLastValue instanceof ConstantInteger) ((ConstantInteger) rangeLastValue).setType(SymbolType.NUMBER);
       }
       Statement stmtInit = new StatementAssignment(lValue.getRef(), rangeFirstValue, new StatementSource(ctx), Comment.NO_COMMENTS);
       sequence.addStatement(stmtInit);
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
index 4b74e0e9c..d34690762 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionAssignment.java
@@ -63,15 +63,6 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
                   }
 
                }
-               if(leftType instanceof SymbolTypeIntegerFixed && SymbolType.isInteger(rightType)) {
-                  SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
-                  // Add cast to the right Type if needed
-                  if(leftType.equals(conversionType) && !rightType.equals(conversionType)) {
-                     getLog().append("Adding type conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
-                     binary.addRightCast(conversionType, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
-                     modified.set(true);
-                  }
-               }
             }
          }
       });
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java
deleted file mode 100644
index e87e6e748..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/PassNDowngradeConstantTypeConversions.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
-import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.values.*;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Downgrade any number expression cast that are part of a WORD+NUMBER expression to BYTE if the number is small enough to fit in the byte.
- */
-public class PassNDowngradeConstantTypeConversions extends Pass2SsaOptimization {
-
-   public PassNDowngradeConstantTypeConversions(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      AtomicBoolean modified = new AtomicBoolean(false);
-      ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
-         if(binaryExpression instanceof ProgramExpressionBinary) {
-            ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression;
-            RValue left = binary.getLeft();
-            RValue right = binary.getRight();
-            if(isConstantWord(left) && isWordLike(right) && isByteLike((ConstantValue) left)) {
-               getLog().append("Downgrading number conversion cast to (byte) " + binary.getLeft().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
-               binary.addLeftCast(SymbolType.BYTE, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
-               modified.set(true);
-            } else if(isConstantWord(right) && isWordLike(left) && isByteLike((ConstantValue) right)) {
-               getLog().append("Downgrading number conversion cast to (byte) " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
-               binary.addRightCast(SymbolType.BYTE, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
-               modified.set(true);
-            }
-
-         }
-      });
-      return modified.get();
-   }
-
-   /**
-    * Determines if a constant value is a byte-like value (can be represented inside a BYTE)
-    *
-    * @param constantValue The value to examine
-    * @return true if the value is a byte-like value
-    */
-   public boolean isByteLike(ConstantValue constantValue) {
-      ConstantLiteral constantLiteral = (constantValue).calculateLiteral(getScope());
-      if(constantLiteral instanceof ConstantInteger) {
-         ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
-         Long value = constantInteger.getValue();
-         if(SymbolType.BYTE.contains(value)) {
-            return true;
-         }
-      }
-      return false;
-   }
-
-   /**
-    * Determines if a value is a word-like value (WORD or Pointer)
-    *
-    * @param rValue The value to examine
-    * @return true if the value is a word-like value
-    */
-   public boolean isWordLike(RValue rValue) {
-      SymbolType symbolType = SymbolTypeInference.inferType(getProgram().getScope(), rValue);
-      return SymbolType.WORD.equals(symbolType) || symbolType instanceof SymbolTypePointer;
-   }
-
-
-   /**
-    * Determines if the passed value is a constant cast to WORD
-    *
-    * @param rValue The value to examine
-    * @return true if the value is a constant cast to word
-    */
-   public boolean isConstantWord(RValue rValue) {
-      if(rValue instanceof ConstantInteger && SymbolType.WORD.equals(((ConstantInteger) rValue).getType())) {
-         return true;
-      }
-      if((rValue instanceof ConstantCastValue) && SymbolType.WORD.equals(((ConstantCastValue) rValue).getToType()))
-         return true;
-      return false;
-   }
-
-}
diff --git a/src/test/ref/linegen.asm b/src/test/ref/linegen.asm
index 4b4fcd8a9..4cbd79681 100644
--- a/src/test/ref/linegen.asm
+++ b/src/test/ref/linegen.asm
@@ -335,13 +335,14 @@ lin16u_gen: {
     sta step
     lda stepf+1
     sta step+1
+    lda #<0
+    sta val
+    sta val+1
     lda min
     sta val+2
     lda min+1
     sta val+3
     lda #0
-    sta val
-    sta val+1
     sta i
     sta i+1
   b1:
diff --git a/src/test/ref/signed-indexed-subtract.asm b/src/test/ref/signed-indexed-subtract.asm
index 7ca3ce033..8904aed68 100644
--- a/src/test/ref/signed-indexed-subtract.asm
+++ b/src/test/ref/signed-indexed-subtract.asm
@@ -2,25 +2,22 @@
 .pc = $801 "Basic"
 :BasicUpstart(main)
 .pc = $80d "Program"
-  .label print_line_cursor = 3
+  .label print_line_cursor = 2
   .label print_char_cursor = 7
 main: {
-    .label i = 2
-    lda #0
-    sta i
+    ldy #0
   b1:
-    lda i
+    tya
     ldx #$80
     jsr sub
-    lda i
+    tya
     ldx #$40
     jsr sub
-    lda i
+    tya
     ldx #$40
     jsr sub
-    inc i
-    lda #9
-    cmp i
+    iny
+    cpy #9
     bne b1
     jsr print_cls
     lda #<$400
@@ -74,9 +71,9 @@ print_ln: {
     rts
 }
 // Print a signed word as HEX
-// print_sword(signed word zeropage(5) w)
+// print_sword(signed word zeropage(4) w)
 print_sword: {
-    .label w = 5
+    .label w = 4
     lda w+1
     bpl b1
     lda #'-'
@@ -95,9 +92,9 @@ print_sword: {
     rts
 }
 // Print a word as HEX
-// print_word(word zeropage(5) w)
+// print_word(word zeropage(4) w)
 print_word: {
-    .label w = 5
+    .label w = 4
     lda w+1
     sta print_byte.b
     jsr print_byte
@@ -107,9 +104,9 @@ print_word: {
     rts
 }
 // Print a byte as HEX
-// print_byte(byte zeropage(2) b)
+// print_byte(byte zeropage(6) b)
 print_byte: {
-    .label b = 2
+    .label b = 6
     lda b
     lsr
     lsr
@@ -138,7 +135,7 @@ print_char: {
 }
 // Clear the screen. Also resets current line/char cursor.
 print_cls: {
-    .label sc = 3
+    .label sc = 2
     lda #<$400
     sta sc
     lda #>$400
@@ -161,20 +158,16 @@ print_cls: {
 }
 // sub(byte register(A) idx, byte register(X) s)
 sub: {
-    .label _1 = 3
     asl
-    tay
-    txa
-    sta _1
-    lda #0
-    sta _1+1
-    lda words,y
     sec
-    sbc _1
-    sta words,y
-    lda words+1,y
-    sbc _1+1
-    sta words+1,y
+    stx $ff
+    tax
+    lda words,x
+    sbc $ff
+    sta words,x
+    bcs !+
+    dec words+1,x
+  !:
     rts
 }
   print_hextab: .text "0123456789abcdef"

From fdbfa68c1c202c20961bd36d978f190e3a928f5a Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 07:12:52 +0200
Subject: [PATCH 75/93] Eliminated Pass2EliminateRedundantCasts.

---
 .../java/dk/camelot64/kickc/Compiler.java     |  1 -
 .../passes/Pass2EliminateRedundantCasts.java  | 75 -------------------
 2 files changed, 76 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2EliminateRedundantCasts.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index b6217ad15..6e35e5a99 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -255,7 +255,6 @@ public class Compiler {
       optimizations.add(new PassNVariableReferenceInfos(program));
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
       optimizations.add(new PassNAddTypeConversionAssignment(program));
-      optimizations.add(new Pass2EliminateRedundantCasts(program));
       optimizations.add(new Pass2RangeResolving(program));
       optimizations.add(new Pass2ComparisonOptimization(program));
       optimizations.add(new Pass2InlineCast(program));
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2EliminateRedundantCasts.java b/src/main/java/dk/camelot64/kickc/passes/Pass2EliminateRedundantCasts.java
deleted file mode 100644
index 40731c99a..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2EliminateRedundantCasts.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.model.ControlFlowBlock;
-import dk.camelot64.kickc.model.Program;
-import dk.camelot64.kickc.model.operators.OperatorCastPtr;
-import dk.camelot64.kickc.model.operators.Operators;
-import dk.camelot64.kickc.model.statements.Statement;
-import dk.camelot64.kickc.model.statements.StatementAssignment;
-import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
-import dk.camelot64.kickc.model.values.RValue;
-
-/**
- * Eliminate casts that are not necessary
- */
-public class Pass2EliminateRedundantCasts extends Pass2SsaOptimization {
-
-   public Pass2EliminateRedundantCasts(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      boolean modified = false;
-      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
-         for(Statement statement : block.getStatements()) {
-            if(statement instanceof StatementAssignment) {
-               StatementAssignment assignment = (StatementAssignment) statement;
-               if(isRedundantCast(assignment)) {
-                  // Redundant cast
-                  getLog().append("Removing redundant cast " + statement.toString(getProgram(), false));
-                  assignment.setOperator(null);
-                  modified = true;
-               }
-            }
-         }
-      }
-      return modified;
-   }
-
-   /**
-    * Determines if the assignment is a redundant cast
-    *
-    * @param assignment The assignment to examine
-    * @return true if is is a redundant cast
-    */
-   private boolean isRedundantCast(StatementAssignment assignment) {
-      RValue rValue2 = assignment.getrValue2();
-      SymbolType rValue2Type = SymbolTypeInference.inferType(getScope(), rValue2);
-      if(Operators.CAST_BYTE.equals(assignment.getOperator()) && SymbolType.BYTE.equals(rValue2Type)) {
-         return true;
-      } else if(Operators.CAST_SBYTE.equals(assignment.getOperator()) && SymbolType.SBYTE.equals(rValue2Type)) {
-         return true;
-      } else if(Operators.CAST_WORD.equals(assignment.getOperator()) && SymbolType.WORD.equals(rValue2Type)) {
-         return true;
-      } else if(Operators.CAST_SWORD.equals(assignment.getOperator()) && SymbolType.SWORD.equals(rValue2Type)) {
-         return true;
-      } else if(Operators.CAST_DWORD.equals(assignment.getOperator()) && SymbolType.DWORD.equals(rValue2Type)) {
-         return true;
-      } else if(Operators.CAST_SDWORD.equals(assignment.getOperator()) && SymbolType.SDWORD.equals(rValue2Type)) {
-         return true;
-      } else if(Operators.CAST_BOOL.equals(assignment.getOperator()) && SymbolType.BOOLEAN.equals(rValue2Type)) {
-         return true;
-      } else if(assignment.getOperator() instanceof OperatorCastPtr) {
-         // Casting to a pointer
-         OperatorCastPtr operatorCastPtr = (OperatorCastPtr) assignment.getOperator();
-         if(rValue2Type.equals(new SymbolTypePointer(operatorCastPtr.getElementType()))) {
-            return true;
-         }
-      }
-      return false;
-   }
-
-}

From 1df77d5ded1fc5b5de4988b85e4f907bbb30b94d Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 07:39:10 +0200
Subject: [PATCH 76/93] Collected all type inference in pass2 together.

---
 src/main/java/dk/camelot64/kickc/Compiler.java      | 13 ++++++++-----
 .../model/iterator/ProgramExpressionIterator.java   | 10 +++++-----
 .../kickc/passes/Pass2FixInlineConstructorsNew.java |  2 +-
 .../ref/examples/bresenham/bitmap-bresenham.asm     |  6 +++---
 src/test/ref/examples/sinplotter/sine-plotter.asm   | 12 ++++++------
 src/test/ref/inline-pointer-1.asm                   |  6 +++---
 src/test/ref/inline-string-3.asm                    |  6 +++---
 src/test/ref/line-anim.asm                          | 12 ++++++------
 src/test/ref/pointer-plus-0.asm                     | 10 ++++------
 9 files changed, 39 insertions(+), 38 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 6e35e5a99..0aff5a280 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -231,9 +231,16 @@ public class Compiler {
 
    private void pass2Optimize() {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
+
+      optimizations.add(new Pass2FixInlineConstructorsNew(program));
+
       optimizations.add(new PassNAddNumberTypeConversions(program));
       optimizations.add(new PassNAddArrayNumberTypeConversions(program));
       optimizations.add(new PassNTypeInference(program));
+      optimizations.add(new PassNAddTypeConversionAssignment(program));
+      optimizations.add(new Pass2InlineCast(program));
+      optimizations.add(new PassNCastSimplification(program));
+
       optimizations.add(new PassNTypeIdSimplification(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new Pass2CullEmptyBlocks(program));
@@ -243,6 +250,7 @@ public class Compiler {
       optimizations.add(new Pass2AliasElimination(program));
       optimizations.add(new Pass2SelfPhiElimination(program));
       optimizations.add(new Pass2IdenticalPhiElimination(program));
+      optimizations.add(new Pass2DuplicateRValueIdentification(program));
       optimizations.add(new Pass2ConditionalJumpSimplification(program));
       optimizations.add(new Pass2ConditionalAndOrRewriting(program));
       optimizations.add(new Pass2ConstantRValueConsolidation(program));
@@ -253,19 +261,14 @@ public class Compiler {
       optimizations.add(new Pass2ConstantStringConsolidation(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
-      optimizations.add(new Pass2FixInlineConstructorsNew(program));
-      optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new Pass2RangeResolving(program));
       optimizations.add(new Pass2ComparisonOptimization(program));
-      optimizations.add(new Pass2InlineCast(program));
-      optimizations.add(new PassNCastSimplification(program));
       optimizations.add(new Pass2InlineDerefIdx(program));
       optimizations.add(new Pass2DeInlineWordDerefIdx(program));
       optimizations.add(new PassNSimplifyConstantZero(program));
       optimizations.add(new PassNSimplifyExpressionWithZero(program));
       optimizations.add(new PassNEliminateUnusedVars(program, true));
       optimizations.add(new Pass2EliminateUnusedBlocks(program));
-      optimizations.add(new Pass2DuplicateRValueIdentification(program));
       pass2Execute(optimizations);
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
index 1995dbf5e..4411ffd80 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionIterator.java
@@ -27,15 +27,15 @@ public class ProgramExpressionIterator {
       // Iterate all symbols
       ProgramValueHandler programValueHandler = (programValue, currentStmt, stmtIt, currentBlock) -> {
          if(programValue.get() instanceof ConstantBinary) {
-            handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), null, null, null);
+            handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryConstant(programValue), currentStmt, stmtIt, currentBlock);
          } else if(programValue.get() instanceof ConstantUnary) {
-            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null);
+            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), currentStmt, stmtIt, currentBlock);
          } else if(programValue.get() instanceof PointerDereferenceIndexed) {
-            handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null);
+            handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), currentStmt, stmtIt, currentBlock);
          } else if(programValue.get() instanceof ConstantCastValue) {
-            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstantCast(programValue), null, null, null);
+            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstantCast(programValue), currentStmt, stmtIt, currentBlock);
          } else if(programValue.get() instanceof CastValue) {
-            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), null, null, null);
+            handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), currentStmt, stmtIt, currentBlock);
          }
       };
       ProgramValueIterator.execute(program.getScope(), programValueHandler);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
index e8c83cf29..9bb996f01 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2FixInlineConstructorsNew.java
@@ -77,7 +77,7 @@ public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization {
       // Convert list to a word constructor in a new tmp variable
       Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope());
       VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
-      tmpVar.setTypeInferred(constructType);
+      //tmpVar.setTypeInferred(constructType);
       // Move backward - to insert before the current statement
       stmtIt.previous();
       // Add assignment of the new tmpVar
diff --git a/src/test/ref/examples/bresenham/bitmap-bresenham.asm b/src/test/ref/examples/bresenham/bitmap-bresenham.asm
index c6f38704b..5c7a99cac 100644
--- a/src/test/ref/examples/bresenham/bitmap-bresenham.asm
+++ b/src/test/ref/examples/bresenham/bitmap-bresenham.asm
@@ -336,11 +336,11 @@ init_screen: {
 bitmap_clear: {
     .label bitmap = 9
     .label y = 2
-    .label _4 = 9
+    .label _3 = 9
     lda bitmap_plot_xlo
-    sta _4
+    sta _3
     lda bitmap_plot_xhi
-    sta _4+1
+    sta _3+1
     lda #0
     sta y
   b1:
diff --git a/src/test/ref/examples/sinplotter/sine-plotter.asm b/src/test/ref/examples/sinplotter/sine-plotter.asm
index e86b7ba4e..a7f77bdfb 100644
--- a/src/test/ref/examples/sinplotter/sine-plotter.asm
+++ b/src/test/ref/examples/sinplotter/sine-plotter.asm
@@ -178,11 +178,11 @@ bitmap_plot: {
     .label plotter = 6
     .label plotter_1 = $10
     .label x = 4
-    .label _4 = 6
+    .label _3 = 6
     lda bitmap_plot_yhi,x
-    sta _4+1
+    sta _3+1
     lda bitmap_plot_ylo,x
-    sta _4
+    sta _3
     lda x
     and #<$fff8
     sta _1
@@ -729,11 +729,11 @@ divr16u: {
 bitmap_clear: {
     .label bitmap = 2
     .label y = $16
-    .label _4 = 2
+    .label _3 = 2
     lda bitmap_plot_ylo
-    sta _4
+    sta _3
     lda bitmap_plot_yhi
-    sta _4+1
+    sta _3+1
     lda #0
     sta y
   b1:
diff --git a/src/test/ref/inline-pointer-1.asm b/src/test/ref/inline-pointer-1.asm
index 4da10ae54..3bf16934c 100644
--- a/src/test/ref/inline-pointer-1.asm
+++ b/src/test/ref/inline-pointer-1.asm
@@ -14,9 +14,9 @@ main: {
 // puta(byte register(A) ph, byte register(X) pl)
 puta: {
     .label screen = 2
-    .label _2 = 2
-    sta _2+1
-    stx _2
+    .label _1 = 2
+    sta _1+1
+    stx _1
     lda #'a'
     ldy #0
     sta (screen),y
diff --git a/src/test/ref/inline-string-3.asm b/src/test/ref/inline-string-3.asm
index 1e2abba8f..1881a03a3 100644
--- a/src/test/ref/inline-string-3.asm
+++ b/src/test/ref/inline-string-3.asm
@@ -8,15 +8,15 @@ main: {
     .label PTR = $9ffe
     .label SCREEN = $400
     .label ptr = 2
-    .label _7 = 2
+    .label _6 = 2
     lda #<STRING
     sta PTR
     lda #>STRING
     sta PTR+1
     lda PTR
-    sta _7
+    sta _6
     lda PTR+1
-    sta _7+1
+    sta _6+1
     ldy #0
     lda (ptr),y
     sta SCREEN
diff --git a/src/test/ref/line-anim.asm b/src/test/ref/line-anim.asm
index e787357ed..862d9a41b 100644
--- a/src/test/ref/line-anim.asm
+++ b/src/test/ref/line-anim.asm
@@ -81,11 +81,11 @@ bitmap_plot: {
     .label x = 3
     .label plotter = 5
     .label plotter_1 = 7
-    .label _4 = 5
+    .label _3 = 5
     lda bitmap_plot_yhi,x
-    sta _4+1
+    sta _3+1
     lda bitmap_plot_ylo,x
-    sta _4
+    sta _3
     lda x
     and #<$fff8
     sta _1
@@ -428,11 +428,11 @@ screen_fill: {
 bitmap_clear: {
     .label bitmap = 3
     .label y = 2
-    .label _4 = 3
+    .label _3 = 3
     lda bitmap_plot_ylo
-    sta _4
+    sta _3
     lda bitmap_plot_yhi
-    sta _4+1
+    sta _3+1
     lda #0
     sta y
   b1:
diff --git a/src/test/ref/pointer-plus-0.asm b/src/test/ref/pointer-plus-0.asm
index 8fc352c78..999a7535a 100644
--- a/src/test/ref/pointer-plus-0.asm
+++ b/src/test/ref/pointer-plus-0.asm
@@ -7,27 +7,25 @@ main: {
     .label _0 = 2
     .label _2 = 2
     lda #<msg1
-    sta first.msg
+    sta first.return
     lda #>msg1
-    sta first.msg+1
+    sta first.return+1
     jsr first
     ldy #0
     lda (_0),y
     sta SCREEN
     lda #<msg2
-    sta first.msg
+    sta first.return
     lda #>msg2
-    sta first.msg+1
+    sta first.return+1
     jsr first
     ldy #0
     lda (_2),y
     sta SCREEN+1
     rts
 }
-// first(byte* zeropage(2) msg)
 first: {
     .label return = 2
-    .label msg = 2
     rts
 }
   msg1: .text "hello world!@"

From d5ebe81c218655a24511669ee8494eb6d3088c0b Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 07:41:18 +0200
Subject: [PATCH 77/93] Eliminated two redundant pass2 steps

---
 src/main/java/dk/camelot64/kickc/Compiler.java | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 0aff5a280..84bd51381 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -259,8 +259,6 @@ public class Compiler {
       optimizations.add(new Pass2ConstantCallPointerIdentification(program));
       optimizations.add(new Pass2ConstantIfs(program));
       optimizations.add(new Pass2ConstantStringConsolidation(program));
-      optimizations.add(new PassNStatementIndices(program));
-      optimizations.add(new PassNVariableReferenceInfos(program));
       optimizations.add(new Pass2RangeResolving(program));
       optimizations.add(new Pass2ComparisonOptimization(program));
       optimizations.add(new Pass2InlineDerefIdx(program));

From 01e833681ac100297288fc1e8c1c59236f9ce816 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 12:02:52 +0200
Subject: [PATCH 78/93] Improved planned sequence for A->B->C sequences where B
 is conditional successor of A.

---
 .../java/dk/camelot64/kickc/Compiler.java     |  2 +-
 .../passes/PassNBlockSequencePlanner.java     | 22 ++++++--
 src/test/ref/bool-ifs.asm                     | 16 +++---
 src/test/ref/bool-vars.asm                    | 18 +++----
 src/test/ref/complex-conditional-problem.asm  |  6 +--
 src/test/ref/complex/tetris/tetris.asm        | 54 +++++++++----------
 .../multiplexer/simple-multiplexer.asm        | 17 +++---
 src/test/ref/loop-break-continue.asm          | 12 ++---
 src/test/ref/loop-break-nested.asm            | 14 ++---
 src/test/ref/loop-continue.asm                |  6 +--
 .../simple-multiplexer-irq.asm                | 20 +++----
 src/test/ref/no-recursion-heavy.asm           |  3 ++
 src/test/ref/sandbox.asm                      | 48 +++++++++--------
 src/test/ref/signed-words.asm                 |  6 +--
 src/test/ref/travis1.asm                      | 22 ++++----
 15 files changed, 143 insertions(+), 123 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 84bd51381..ae353382c 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -377,7 +377,7 @@ public class Compiler {
       new Pass3AssertConstants(program).check();
       new Pass3AssertArrayLengths(program).check();
       new Pass3AssertNoMulDivMod(program).check();
-      new PassNBlockSequencePlanner(program).step();
+      //new PassNBlockSequencePlanner(program).step();
       // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes
       new Pass3PhiLifting(program).perform();
       new PassNBlockSequencePlanner(program).step();
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNBlockSequencePlanner.java b/src/main/java/dk/camelot64/kickc/passes/PassNBlockSequencePlanner.java
index 810de150a..f020476a6 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNBlockSequencePlanner.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNBlockSequencePlanner.java
@@ -39,11 +39,25 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
          if(block.getCallSuccessor() != null) {
             pushTodo(getGraph().getCallSuccessor(block));
          }
-         if(block.getConditionalSuccessor() != null) {
+         ControlFlowBlock conditionalSuccessor = getGraph().getConditionalSuccessor(block);
+         ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block);
+         if(conditionalSuccessor != null && defaultSuccessor != null) {
+            // Both conditional and default successor
+            if(conditionalSuccessor.getDefaultSuccessor().equals(defaultSuccessor.getLabel())) {
+               // Best sequence is cond->default (resulting in better code locality)
+               pushTodo(defaultSuccessor);
+               pushTodo(getGraph().getConditionalSuccessor(block));
+            } else {
+               // Best sequence is default->cond
+               pushTodo(getGraph().getConditionalSuccessor(block));
+               pushTodo(defaultSuccessor);
+            }
+         } else if(conditionalSuccessor != null) {
+            // Only a conditional successor
             pushTodo(getGraph().getConditionalSuccessor(block));
-         }
-         if(getGraph().getDefaultSuccessor(block) != null) {
-            pushTodo(getGraph().getDefaultSuccessor(block));
+         } else if(defaultSuccessor != null) {
+            // Only a default successor
+            pushTodo(defaultSuccessor);
          }
 
       }
diff --git a/src/test/ref/bool-ifs.asm b/src/test/ref/bool-ifs.asm
index 0fc00115b..ef375b6fe 100644
--- a/src/test/ref/bool-ifs.asm
+++ b/src/test/ref/bool-ifs.asm
@@ -17,6 +17,10 @@ bool_complex: {
     and #1
     cpx #$a
     bcc b6
+    jmp b5
+  b6:
+    cmp #0
+    beq b2
   b5:
     cpx #$a
     bcc b4
@@ -34,10 +38,6 @@ bool_complex: {
     lda #' '
     sta screen,x
     jmp b3
-  b6:
-    cmp #0
-    beq b2
-    jmp b5
 }
 bool_not: {
     .label screen = $450
@@ -91,6 +91,10 @@ bool_and: {
     and #1
     cpx #$a
     bcc b5
+    jmp b4
+  b5:
+    cmp #0
+    beq b2
   b4:
     lda #' '
     sta screen,x
@@ -99,10 +103,6 @@ bool_and: {
     cpx #$15
     bne b1
     rts
-  b5:
-    cmp #0
-    beq b2
-    jmp b4
   b2:
     lda #'*'
     sta screen,x
diff --git a/src/test/ref/bool-vars.asm b/src/test/ref/bool-vars.asm
index 8d19ed6d0..65d8b579c 100644
--- a/src/test/ref/bool-vars.asm
+++ b/src/test/ref/bool-vars.asm
@@ -31,6 +31,11 @@ bool_complex: {
     lda o1
     cmp #0
     bne b6
+    jmp b5
+  b6:
+    lda o2
+    cmp #0
+    bne b2
   b5:
     lda o1
     cmp #0
@@ -50,11 +55,6 @@ bool_complex: {
     lda #' '
     sta screen,x
     jmp b3
-  b6:
-    lda o2
-    cmp #0
-    bne b2
-    jmp b5
 }
 bool_not: {
     .label screen = $450
@@ -108,6 +108,10 @@ bool_and: {
     and #1
     cpx #$a
     bcc b5
+    jmp b4
+  b5:
+    cmp #0
+    beq b2
   b4:
     lda #' '
     sta screen,x
@@ -116,10 +120,6 @@ bool_and: {
     cpx #$15
     bne b1
     rts
-  b5:
-    cmp #0
-    beq b2
-    jmp b4
   b2:
     lda #'*'
     sta screen,x
diff --git a/src/test/ref/complex-conditional-problem.asm b/src/test/ref/complex-conditional-problem.asm
index ec0d49551..46436158b 100644
--- a/src/test/ref/complex-conditional-problem.asm
+++ b/src/test/ref/complex-conditional-problem.asm
@@ -11,10 +11,10 @@ main: {
     bcs b3
     cmp #$40
     bcc b3
+    jmp b2
+  b3:
+    lda #0
   b2:
     sta SCREEN
     jmp b1
-  b3:
-    lda #0
-    jmp b2
 }
diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm
index 663c44f97..f0383be1a 100644
--- a/src/test/ref/complex/tetris/tetris.asm
+++ b/src/test/ref/complex/tetris/tetris.asm
@@ -145,18 +145,18 @@
   .label current_xpos_59 = $a
   .label current_piece_gfx_64 = 5
   .label current_piece_char_68 = $b
-  .label render_screen_render_69 = 9
-  .label current_xpos_130 = $a
-  .label current_xpos_131 = $a
-  .label current_piece_gfx_120 = 5
-  .label current_piece_gfx_121 = 5
-  .label current_piece_char_108 = $b
-  .label current_piece_char_109 = $b
-  .label current_piece_100 = 5
+  .label render_screen_render_68 = 9
+  .label current_xpos_127 = $a
+  .label current_xpos_128 = $a
+  .label current_piece_gfx_117 = 5
+  .label current_piece_gfx_118 = 5
+  .label current_piece_char_105 = $b
+  .label current_piece_char_106 = $b
   .label current_piece_101 = 5
   .label current_piece_102 = 5
   .label current_piece_103 = 5
   .label current_piece_104 = 5
+  .label current_piece_105 = 5
 bbegin:
   // The screen currently being showed to the user. $00 for screen 1 / $20 for screen 2.
   lda #0
@@ -192,13 +192,13 @@ main: {
     jsr render_playfield
     ldx current_ypos
     lda current_xpos
-    sta current_xpos_130
+    sta current_xpos_127
     lda current_piece_gfx
-    sta current_piece_gfx_120
+    sta current_piece_gfx_117
     lda current_piece_gfx+1
-    sta current_piece_gfx_120+1
+    sta current_piece_gfx_117+1
     lda current_piece_char
-    sta current_piece_char_108
+    sta current_piece_char_105
     lda #$20
     sta render_screen_render_33
     jsr render_moving
@@ -250,15 +250,15 @@ main: {
     jsr render_playfield
     ldx current_ypos
     lda render_screen_render
-    sta render_screen_render_69
+    sta render_screen_render_68
     lda current_xpos
-    sta current_xpos_131
+    sta current_xpos_128
     lda current_piece_gfx
-    sta current_piece_gfx_121
+    sta current_piece_gfx_118
     lda current_piece_gfx+1
-    sta current_piece_gfx_121+1
+    sta current_piece_gfx_118+1
     lda current_piece_char
-    sta current_piece_char_109
+    sta current_piece_char_106
     jsr render_moving
     lda render_screen_render
     ldx next_piece_idx
@@ -608,9 +608,9 @@ play_move_rotate: {
     sta play_collision.ypos
     ldx orientation
     lda current_piece
-    sta current_piece_103
+    sta current_piece_104
     lda current_piece+1
-    sta current_piece_103+1
+    sta current_piece_104+1
     jsr play_collision
     cmp #COLLISION_NONE
     bne b4
@@ -738,9 +738,9 @@ play_move_leftright: {
     sta play_collision.ypos
     ldx current_orientation
     lda current_piece
-    sta current_piece_102
+    sta current_piece_103
     lda current_piece+1
-    sta current_piece_102+1
+    sta current_piece_103+1
     jsr play_collision
     cmp #COLLISION_NONE
     bne b3
@@ -759,9 +759,9 @@ play_move_leftright: {
     sta play_collision.ypos
     ldx current_orientation
     lda current_piece
-    sta current_piece_101
+    sta current_piece_102
     lda current_piece+1
-    sta current_piece_101+1
+    sta current_piece_102+1
     jsr play_collision
     cmp #COLLISION_NONE
     bne b3
@@ -804,9 +804,9 @@ play_move_down: {
     sta play_collision.xpos
     ldx current_orientation
     lda current_piece
-    sta current_piece_100
+    sta current_piece_101
     lda current_piece+1
-    sta current_piece_100+1
+    sta current_piece_101+1
     jsr play_collision
     cmp #COLLISION_NONE
     beq b10
@@ -858,9 +858,9 @@ play_spawn_current: {
     lda current_ypos
     sta play_collision.ypos
     lda current_piece_gfx
-    sta current_piece_104
+    sta current_piece_105
     lda current_piece_gfx+1
-    sta current_piece_104+1
+    sta current_piece_105+1
     ldx #0
     jsr play_collision
     cmp #COLLISION_PLAYFIELD
diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
index ab1e3bf7b..cfcef75d5 100644
--- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm
+++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
@@ -142,10 +142,11 @@ plexShowSprite: {
     asl plex_sprite_msb
     lda plex_sprite_msb
     cmp #0
-    bne breturn
+    bne b5
     lda #1
     sta plex_sprite_msb
-  breturn:
+    rts
+  b5:
     rts
   b1:
     lda SPRITES_XMSB
@@ -185,6 +186,12 @@ plexSort: {
     dex
     cpx #$ff
     bne b5
+    jmp b4
+  b5:
+    lda nxt_y
+    ldy PLEX_SORTED_IDX,x
+    cmp PLEX_YPOS,y
+    bcc b3
   b4:
     inx
     lda nxt_idx
@@ -202,12 +209,6 @@ plexSort: {
     cpx #8
     bne plexFreePrepare1_b1
     rts
-  b5:
-    lda nxt_y
-    ldy PLEX_SORTED_IDX,x
-    cmp PLEX_YPOS,y
-    bcc b3
-    jmp b4
 }
 // Initialize the program
 init: {
diff --git a/src/test/ref/loop-break-continue.asm b/src/test/ref/loop-break-continue.asm
index 1ff20050e..c7a50bd37 100644
--- a/src/test/ref/loop-break-continue.asm
+++ b/src/test/ref/loop-break-continue.asm
@@ -19,11 +19,7 @@ main: {
     lda str,x
     cmp #' '
     bne b3
-  b4:
-    inx
-    cpx #0
-    bne b1
-    rts
+    jmp b4
   b3:
     lda str,x
     ldy #0
@@ -32,6 +28,10 @@ main: {
     bne !+
     inc screen+1
   !:
-    jmp b4
+  b4:
+    inx
+    cpx #0
+    bne b1
+    rts
     str: .text "hello brave new world@"
 }
diff --git a/src/test/ref/loop-break-nested.asm b/src/test/ref/loop-break-nested.asm
index 86284b28d..eb7d4bbcc 100644
--- a/src/test/ref/loop-break-nested.asm
+++ b/src/test/ref/loop-break-nested.asm
@@ -20,6 +20,13 @@ main: {
     lda (line),y
     cmp #'a'
     bne b3
+    jmp b4
+  b3:
+    lda #'a'
+    sta (line),y
+    iny
+    cpy #$28
+    bne b2
   b4:
     lda #$28
     clc
@@ -37,11 +44,4 @@ main: {
     bcc b1
   !:
     rts
-  b3:
-    lda #'a'
-    sta (line),y
-    iny
-    cpy #$28
-    bne b2
-    jmp b4
 }
diff --git a/src/test/ref/loop-continue.asm b/src/test/ref/loop-continue.asm
index c5abdab71..fe08e6e87 100644
--- a/src/test/ref/loop-continue.asm
+++ b/src/test/ref/loop-continue.asm
@@ -9,12 +9,12 @@ main: {
     lda SCREEN,x
     cmp #' '
     bne b2
+    jmp b3
+  b2:
+    inc SCREEN,x
   b3:
     inx
     cpx #$28*6+1
     bne b1
     rts
-  b2:
-    inc SCREEN,x
-    jmp b3
 }
diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
index 32a1fc283..d8dee23c8 100644
--- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
+++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
@@ -130,6 +130,12 @@ plexSort: {
     dex
     cpx #$ff
     bne b6
+    jmp b4
+  b6:
+    lda nxt_y
+    ldy PLEX_SORTED_IDX,x
+    cmp PLEX_YPOS,y
+    bcc b3
   b4:
     inx
     lda nxt_idx
@@ -154,12 +160,6 @@ plexSort: {
     bne plexFreePrepare1_b1
     sta plex_free_next
     rts
-  b6:
-    lda nxt_y
-    ldy PLEX_SORTED_IDX,x
-    cmp PLEX_YPOS,y
-    bcc b3
-    jmp b4
 }
 // Initialize the program
 init: {
@@ -242,6 +242,10 @@ plex_irq: {
     lda plex_show_idx
     cmp #PLEX_COUNT
     bcc b7
+    jmp b4
+  b7:
+    cpx _4
+    bcc b3
   b4:
     lda #IRQ_RASTER
     sta IRQ_STATUS
@@ -257,10 +261,6 @@ plex_irq: {
   b1:
     stx RASTER
     jmp b2
-  b7:
-    cpx _4
-    bcc b3
-    jmp b4
 }
 // Show the next sprite.
 // plexSort() prepares showing the sprites
diff --git a/src/test/ref/no-recursion-heavy.asm b/src/test/ref/no-recursion-heavy.asm
index 9b94f1c33..a64e0d602 100644
--- a/src/test/ref/no-recursion-heavy.asm
+++ b/src/test/ref/no-recursion-heavy.asm
@@ -270,5 +270,8 @@ fc: {
     cmp #7
     cmp #8
     cmp #9
+    bne b10
+    rts
+  b10:
     rts
 }
diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm
index 7abbd0312..0c0bcc277 100644
--- a/src/test/ref/sandbox.asm
+++ b/src/test/ref/sandbox.asm
@@ -202,9 +202,16 @@ myprintf: {
     rts
   b3:
     cpx #'1'
-    bcc !b37+
-    jmp b37
-  !b37:
+    bcs b37
+    jmp b4
+  b37:
+    cpx #'9'
+    bcs !b23+
+    jmp b23
+  !b23:
+    bne !b23+
+    jmp b23
+  !b23:
   b4:
     cpx #'-'
     bne b5
@@ -280,6 +287,11 @@ myprintf: {
     lda bTrailing
     cmp #0
     beq b39
+    jmp b15
+  b39:
+    lda b
+    cmp bDigits
+    bcc b16
   b15:
     ldx #0
   b19:
@@ -309,18 +321,13 @@ myprintf: {
     cmp bDigits
     bcc b21
     jmp b22
-  b39:
-    lda b
-    cmp bDigits
-    bcc b16
-    jmp b15
   b16:
     lda bLeadZero
     cmp #0
-    beq b14
+    beq b17
     lda #'0'
     jmp b18
-  b14:
+  b17:
     lda #' '
   b18:
     ldy bLen
@@ -341,11 +348,6 @@ myprintf: {
     sta strTemp,y
     inc bLen
     jmp b22
-  b37:
-    cpx #'9'
-    bcc b23
-    beq b23
-    jmp b4
   b23:
     txa
     axs #'0'
@@ -392,13 +394,7 @@ myprintf: {
   b28:
     cpx #$41
     bcs b41
-  b30:
-    // swap 0x41 / 0x61 when in lower case mode
-    ldy bLen
-    txa
-    sta strTemp,y
-    inc bLen
-    jmp b27
+    jmp b30
   b41:
     cpx #$5a+1
     bcc b35
@@ -406,7 +402,13 @@ myprintf: {
   b35:
     txa
     axs #-[$20]
-    jmp b30
+  b30:
+    // swap 0x41 / 0x61 when in lower case mode
+    ldy bLen
+    txa
+    sta strTemp,y
+    inc bLen
+    jmp b27
     buf6: .fill 6, 0
 }
 // utoa(word zeropage($12) value, byte* zeropage($14) dst)
diff --git a/src/test/ref/signed-words.asm b/src/test/ref/signed-words.asm
index 1f3826b81..cd5577b6e 100644
--- a/src/test/ref/signed-words.asm
+++ b/src/test/ref/signed-words.asm
@@ -22,7 +22,7 @@
   .label yvel_10 = 6
   .label xvel = 2
   .label yvel_12 = 6
-  .label yvel_22 = 6
+  .label yvel_21 = 6
 main: {
     jsr init
     lda #$64
@@ -93,9 +93,9 @@ anim: {
     sta yvel+1
   b3:
     lda yvel
-    sta yvel_22
+    sta yvel_21
     lda yvel+1
-    sta yvel_22+1
+    sta yvel_21+1
     lda #0
     sta ypos
     sta ypos+1
diff --git a/src/test/ref/travis1.asm b/src/test/ref/travis1.asm
index a73fc4f30..12531614c 100644
--- a/src/test/ref/travis1.asm
+++ b/src/test/ref/travis1.asm
@@ -22,6 +22,17 @@ main: {
     jsr game_ready
     cmp #0
     bne b3
+    jmp b2
+  b3:
+    lda print_line_cursor
+    sta print_char_cursor
+    lda print_line_cursor+1
+    sta print_char_cursor+1
+    lda #<str
+    sta print_str_ln.str
+    lda #>str
+    sta print_str_ln.str+1
+    jsr print_str_ln
   b2:
     inc i
     lda #6
@@ -34,17 +45,6 @@ main: {
     lda print_line_cursor+1
     sta print_char_cursor+1
     jmp b1
-  b3:
-    lda print_line_cursor
-    sta print_char_cursor
-    lda print_line_cursor+1
-    sta print_char_cursor+1
-    lda #<str
-    sta print_str_ln.str
-    lda #>str
-    sta print_str_ln.str+1
-    jsr print_str_ln
-    jmp b2
     str: .text "ready!@"
 }
 // Print a zero-terminated string followed by a newline

From 682d007ba8b9349ad81f7cb615f4afeae62ff854 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 12:19:20 +0200
Subject: [PATCH 79/93] Replaced Pass1EliminiateEmptyBlocks with
 PassNCullEmptyBlocks (which was removed from pass 2).

---
 .../java/dk/camelot64/kickc/Compiler.java     |  6 +-
 .../passes/Pass1EliminateEmptyBlocks.java     | 66 --------------
 ...yBlocks.java => PassNCullEmptyBlocks.java} |  4 +-
 src/test/ref/complex/tetris/tetris.asm        | 86 +++++++++----------
 .../ref/examples/chargen/chargen-analysis.asm | 24 +++---
 .../multiplexer/simple-multiplexer.asm        |  6 +-
 src/test/ref/function-pointer-noarg-3.asm     |  8 +-
 .../ref/function-pointer-noarg-call-2.asm     |  8 +-
 src/test/ref/function-pointer-return.asm      |  8 +-
 src/test/ref/inline-string-2.asm              |  8 +-
 .../simple-multiplexer-irq.asm                |  4 +-
 src/test/ref/no-recursion-heavy.asm           | 23 +++--
 src/test/ref/sandbox-ternary-error.asm        |  8 +-
 src/test/ref/sandbox.asm                      | 40 ++++-----
 src/test/ref/semi-struct-2.asm                | 76 ++++++++--------
 src/test/ref/signed-words.asm                 |  6 +-
 src/test/ref/test-comparisons-sword.asm       |  5 +-
 src/test/ref/test-comparisons-word.asm        |  5 +-
 18 files changed, 161 insertions(+), 230 deletions(-)
 delete mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java
 rename src/main/java/dk/camelot64/kickc/passes/{Pass2CullEmptyBlocks.java => PassNCullEmptyBlocks.java} (97%)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index ae353382c..ac82bc58f 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -183,7 +183,7 @@ public class Compiler {
       new Pass1EliminateUncalledProcedures(program).execute();
       new PassNEliminateUnusedVars(program, false).execute();
       new Pass1ExtractInlineStrings(program).execute();
-      new Pass1EliminateEmptyBlocks(program).execute();
+      new PassNCullEmptyBlocks(program).execute();
 
       new Pass1ModifiedVarsAnalysis(program).execute();
       if(getLog().isVerbosePass1CreateSsa()) {
@@ -243,7 +243,6 @@ public class Compiler {
 
       optimizations.add(new PassNTypeIdSimplification(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
-      optimizations.add(new Pass2CullEmptyBlocks(program));
       optimizations.add(new PassNStatementIndices(program));
       optimizations.add(new PassNVariableReferenceInfos(program));
       optimizations.add(new Pass2UnaryNotSimplification(program));
@@ -377,7 +376,6 @@ public class Compiler {
       new Pass3AssertConstants(program).check();
       new Pass3AssertArrayLengths(program).check();
       new Pass3AssertNoMulDivMod(program).check();
-      //new PassNBlockSequencePlanner(program).step();
       // Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes
       new Pass3PhiLifting(program).perform();
       new PassNBlockSequencePlanner(program).step();
@@ -404,7 +402,7 @@ public class Compiler {
 
       // Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap
       new Pass3PhiMemCoalesce(program).step();
-      new Pass2CullEmptyBlocks(program).step();
+      new PassNCullEmptyBlocks(program).step();
       new PassNRenumberLabels(program).execute();
       new PassNBlockSequencePlanner(program).step();
       new Pass3AddNopBeforeCallOns(program).generate();
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java b/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java
deleted file mode 100644
index 9cfc9095d..000000000
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package dk.camelot64.kickc.passes;
-
-import dk.camelot64.kickc.CompileLog;
-import dk.camelot64.kickc.model.*;
-import dk.camelot64.kickc.model.symbols.Label;
-import dk.camelot64.kickc.model.symbols.Symbol;
-import dk.camelot64.kickc.model.values.LabelRef;
-import dk.camelot64.kickc.model.values.SymbolRef;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Eliminate empty blocks in pass 1 (before creating SSA)
- */
-public class Pass1EliminateEmptyBlocks extends Pass1Base {
-
-   public Pass1EliminateEmptyBlocks(Program program) {
-      super(program);
-   }
-
-   @Override
-   public boolean step() {
-      CompileLog log = getLog();
-      ControlFlowGraph graph = getProgram().getGraph();
-      Collection<ControlFlowBlock> blocks = graph.getAllBlocks();
-      List<LabelRef> removeList = new ArrayList<>();
-      for(ControlFlowBlock block : blocks) {
-         if(block.getLabel().getFullName().equals(SymbolRef.END_BLOCK_NAME)) {
-            continue;
-         } else if(block.getLabel().getFullName().equals(SymbolRef.BEGIN_BLOCK_NAME)) {
-            continue;
-         }
-         if(block.getStatements().isEmpty()) {
-            List<ControlFlowBlock> predecessors = graph.getPredecessors(block);
-            boolean remove = true;
-            for(ControlFlowBlock predecessor : predecessors) {
-               if(predecessor.getDefaultSuccessor().equals(block.getLabel())) {
-                  predecessor.setDefaultSuccessor(block.getDefaultSuccessor());
-               } else {
-                  remove = false;
-               }
-            }
-            if(remove) {
-               removeList.add(block.getLabel());
-            }
-         }
-      }
-      boolean modified = false;
-      for(LabelRef labelRef : removeList) {
-         Symbol removeSymbol = getScope().getSymbol(labelRef);
-         if(removeSymbol instanceof Label) {
-            Label label = (Label) removeSymbol;
-            graph.remove(labelRef);
-            label.getScope().remove(label);
-            if(log.isVerbosePass1CreateSsa()) {
-               log.append("Removing empty block " + labelRef);
-            }
-            modified = true;
-         }
-      }
-      return modified;
-   }
-
-}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java b/src/main/java/dk/camelot64/kickc/passes/PassNCullEmptyBlocks.java
similarity index 97%
rename from src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java
rename to src/main/java/dk/camelot64/kickc/passes/PassNCullEmptyBlocks.java
index 679d87eb3..c9c067215 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNCullEmptyBlocks.java
@@ -12,9 +12,9 @@ import java.util.List;
 import java.util.Map;
 
 /** Pass that culls empty control flow blocks from the program */
-public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
+public class PassNCullEmptyBlocks extends Pass2SsaOptimization {
 
-   public Pass2CullEmptyBlocks(Program program) {
+   public PassNCullEmptyBlocks(Program program) {
       super(program);
    }
 
diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm
index f0383be1a..df178a3ac 100644
--- a/src/test/ref/complex/tetris/tetris.asm
+++ b/src/test/ref/complex/tetris/tetris.asm
@@ -145,18 +145,18 @@
   .label current_xpos_59 = $a
   .label current_piece_gfx_64 = 5
   .label current_piece_char_68 = $b
-  .label render_screen_render_68 = 9
-  .label current_xpos_127 = $a
-  .label current_xpos_128 = $a
-  .label current_piece_gfx_117 = 5
-  .label current_piece_gfx_118 = 5
-  .label current_piece_char_105 = $b
-  .label current_piece_char_106 = $b
-  .label current_piece_101 = 5
-  .label current_piece_102 = 5
-  .label current_piece_103 = 5
-  .label current_piece_104 = 5
-  .label current_piece_105 = 5
+  .label render_screen_render_65 = 9
+  .label current_xpos_119 = $a
+  .label current_xpos_120 = $a
+  .label current_piece_gfx_112 = 5
+  .label current_piece_gfx_113 = 5
+  .label current_piece_char_100 = $b
+  .label current_piece_char_101 = $b
+  .label current_piece_96 = 5
+  .label current_piece_97 = 5
+  .label current_piece_98 = 5
+  .label current_piece_99 = 5
+  .label current_piece_100 = 5
 bbegin:
   // The screen currently being showed to the user. $00 for screen 1 / $20 for screen 2.
   lda #0
@@ -192,13 +192,13 @@ main: {
     jsr render_playfield
     ldx current_ypos
     lda current_xpos
-    sta current_xpos_127
+    sta current_xpos_119
     lda current_piece_gfx
-    sta current_piece_gfx_117
+    sta current_piece_gfx_112
     lda current_piece_gfx+1
-    sta current_piece_gfx_117+1
+    sta current_piece_gfx_112+1
     lda current_piece_char
-    sta current_piece_char_105
+    sta current_piece_char_100
     lda #$20
     sta render_screen_render_33
     jsr render_moving
@@ -250,15 +250,15 @@ main: {
     jsr render_playfield
     ldx current_ypos
     lda render_screen_render
-    sta render_screen_render_68
+    sta render_screen_render_65
     lda current_xpos
-    sta current_xpos_128
+    sta current_xpos_120
     lda current_piece_gfx
-    sta current_piece_gfx_118
+    sta current_piece_gfx_113
     lda current_piece_gfx+1
-    sta current_piece_gfx_118+1
+    sta current_piece_gfx_113+1
     lda current_piece_char
-    sta current_piece_char_106
+    sta current_piece_char_101
     jsr render_moving
     lda render_screen_render
     ldx next_piece_idx
@@ -286,18 +286,18 @@ render_score: {
     .label screen = 5
     lda render_screen_render
     cmp #0
-    beq b2
+    beq b1
     lda #<PLAYFIELD_SCREEN_2
     sta screen
     lda #>PLAYFIELD_SCREEN_2
     sta screen+1
-    jmp b1
-  b2:
+    jmp b2
+  b1:
     lda #<PLAYFIELD_SCREEN_1
     sta screen
     lda #>PLAYFIELD_SCREEN_1
     sta screen+1
-  b1:
+  b2:
     ldx score_bytes+2
     ldy #0
     lda #<score_offset
@@ -394,18 +394,18 @@ render_next: {
     .label screen_next_area = 7
     .label l = 9
     cmp #0
-    beq b2
+    beq b1
     lda #<PLAYFIELD_SCREEN_2+next_area_offset
     sta screen_next_area
     lda #>PLAYFIELD_SCREEN_2+next_area_offset
     sta screen_next_area+1
-    jmp b1
-  b2:
+    jmp b2
+  b1:
     lda #<PLAYFIELD_SCREEN_1+next_area_offset
     sta screen_next_area
     lda #>PLAYFIELD_SCREEN_1+next_area_offset
     sta screen_next_area+1
-  b1:
+  b2:
     txa
     asl
     // Render the next piece
@@ -608,9 +608,9 @@ play_move_rotate: {
     sta play_collision.ypos
     ldx orientation
     lda current_piece
-    sta current_piece_104
+    sta current_piece_99
     lda current_piece+1
-    sta current_piece_104+1
+    sta current_piece_99+1
     jsr play_collision
     cmp #COLLISION_NONE
     bne b4
@@ -645,8 +645,8 @@ play_collision: {
     .label l = $d
     .label i_2 = $e
     .label i_3 = $e
-    .label i_11 = $e
-    .label i_13 = $e
+    .label i_10 = $e
+    .label i_12 = $e
     txa
     clc
     adc piece_gfx
@@ -715,11 +715,11 @@ play_collision: {
     rts
   b9:
     lda i
-    sta i_11
+    sta i_10
     jmp b1
   b10:
     lda i
-    sta i_13
+    sta i_12
     jmp b2
 }
 // Move left/right or rotate the current piece
@@ -738,9 +738,9 @@ play_move_leftright: {
     sta play_collision.ypos
     ldx current_orientation
     lda current_piece
-    sta current_piece_103
+    sta current_piece_98
     lda current_piece+1
-    sta current_piece_103+1
+    sta current_piece_98+1
     jsr play_collision
     cmp #COLLISION_NONE
     bne b3
@@ -759,9 +759,9 @@ play_move_leftright: {
     sta play_collision.ypos
     ldx current_orientation
     lda current_piece
-    sta current_piece_102
+    sta current_piece_97
     lda current_piece+1
-    sta current_piece_102+1
+    sta current_piece_97+1
     jsr play_collision
     cmp #COLLISION_NONE
     bne b3
@@ -804,9 +804,9 @@ play_move_down: {
     sta play_collision.xpos
     ldx current_orientation
     lda current_piece
-    sta current_piece_101
+    sta current_piece_96
     lda current_piece+1
-    sta current_piece_101+1
+    sta current_piece_96+1
     jsr play_collision
     cmp #COLLISION_NONE
     beq b10
@@ -858,9 +858,9 @@ play_spawn_current: {
     lda current_ypos
     sta play_collision.ypos
     lda current_piece_gfx
-    sta current_piece_105
+    sta current_piece_100
     lda current_piece_gfx+1
-    sta current_piece_105+1
+    sta current_piece_100+1
     ldx #0
     jsr play_collision
     cmp #COLLISION_PLAYFIELD
diff --git a/src/test/ref/examples/chargen/chargen-analysis.asm b/src/test/ref/examples/chargen/chargen-analysis.asm
index 3acea7f3d..591a0f78e 100644
--- a/src/test/ref/examples/chargen/chargen-analysis.asm
+++ b/src/test/ref/examples/chargen/chargen-analysis.asm
@@ -174,39 +174,39 @@ main: {
     ldx #KEY_LSHIFT
     jsr keyboard_key_pressed
     cmp #0
-    bne b2
+    bne b9
     lda #0
     sta shift
-    jmp b9
-  b2:
+    jmp b10
+  b9:
     lda #1
     sta shift
-  b9:
+  b10:
     lda #0
     sta ch
   // Check for key presses - and plot char if found
-  b10:
+  b11:
     ldx ch
     jsr keyboard_get_keycode
     cmp #$3f
-    beq b13
+    beq b2
     tax
     jsr keyboard_key_pressed
-    jmp b11
-  b13:
+    jmp b12
+  b2:
     lda #0
-  b11:
+  b12:
     cmp #0
-    beq b12
+    beq b13
     ldy cur_pos
     lda ch
     ldx shift
     jsr plot_chargen
-  b12:
+  b13:
     inc ch
     lda #$40
     cmp ch
-    bne b10
+    bne b11
     jmp b4
     str: .text "f1@"
     str1: .text "f3@"
diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
index cfcef75d5..6016bd1d2 100644
--- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm
+++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
@@ -23,10 +23,10 @@
   .label SPRITE = $2000
   .label YSIN = $2100
   .label PLEX_SCREEN_PTR = SCREEN+$3f8
+  .label plex_sprite_msb = 6
   .label plex_free_next = 3
   .label plex_sprite_idx = 4
   .label plex_show_idx = 5
-  .label plex_sprite_msb = 6
 main: {
     sei
     jsr init
@@ -185,9 +185,9 @@ plexSort: {
     sta PLEX_SORTED_IDX+1,x
     dex
     cpx #$ff
-    bne b5
+    bne b6
     jmp b4
-  b5:
+  b6:
     lda nxt_y
     ldy PLEX_SORTED_IDX,x
     cmp PLEX_YPOS,y
diff --git a/src/test/ref/function-pointer-noarg-3.asm b/src/test/ref/function-pointer-noarg-3.asm
index a5efe51f9..6ef9b4501 100644
--- a/src/test/ref/function-pointer-noarg-3.asm
+++ b/src/test/ref/function-pointer-noarg-3.asm
@@ -13,18 +13,18 @@ main: {
     txa
     and #1
     cmp #0
-    beq b1
+    beq b3
     lda #<fn2
     sta f
     lda #>fn2
     sta f+1
-    jmp b3
-  b1:
+    jmp b4
+  b3:
     lda #<fn1
     sta f
     lda #>fn1
     sta f+1
-  b3:
+  b4:
     jsr ff
         
     jmp b2
diff --git a/src/test/ref/function-pointer-noarg-call-2.asm b/src/test/ref/function-pointer-noarg-call-2.asm
index f751aa759..9d047951b 100644
--- a/src/test/ref/function-pointer-noarg-call-2.asm
+++ b/src/test/ref/function-pointer-noarg-call-2.asm
@@ -12,18 +12,18 @@ main: {
     lda #1
     and i
     cmp #0
-    beq b1
+    beq b3
     lda #<fn2
     sta f
     lda #>fn2
     sta f+1
-    jmp b3
-  b1:
+    jmp b4
+  b3:
     lda #<fn1
     sta f
     lda #>fn1
     sta f+1
-  b3:
+  b4:
     jsr bi_f
     jmp b2
   bi_f:
diff --git a/src/test/ref/function-pointer-return.asm b/src/test/ref/function-pointer-return.asm
index 13febb158..c244eb54d 100644
--- a/src/test/ref/function-pointer-return.asm
+++ b/src/test/ref/function-pointer-return.asm
@@ -11,18 +11,18 @@ main: {
     txa
     and #1
     cmp #0
-    beq b1
+    beq b3
     lda #<fn2
     sta f
     lda #>fn2
     sta f+1
-    jmp b3
-  b1:
+    jmp b4
+  b3:
     lda #<fn1
     sta f
     lda #>fn1
     sta f+1
-  b3:
+  b4:
     lda f
     sta SCREEN
     jmp b2
diff --git a/src/test/ref/inline-string-2.asm b/src/test/ref/inline-string-2.asm
index 9f5927b68..0bbdcd2b0 100644
--- a/src/test/ref/inline-string-2.asm
+++ b/src/test/ref/inline-string-2.asm
@@ -18,18 +18,18 @@ main: {
 print_msg: {
     .label msg = 4
     cpx #1
-    beq b2
+    beq b1
     lda #<msg_2
     sta msg
     lda #>msg_2
     sta msg+1
-    jmp b1
-  b2:
+    jmp b2
+  b1:
     lda #<msg_1
     sta msg
     lda #>msg_1
     sta msg+1
-  b1:
+  b2:
     jsr print
     rts
     msg_1: .text "Hello @"
diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
index d8dee23c8..52e162f4a 100644
--- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
+++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
@@ -129,9 +129,9 @@ plexSort: {
     sta PLEX_SORTED_IDX+1,x
     dex
     cpx #$ff
-    bne b6
+    bne b7
     jmp b4
-  b6:
+  b7:
     lda nxt_y
     ldy PLEX_SORTED_IDX,x
     cmp PLEX_YPOS,y
diff --git a/src/test/ref/no-recursion-heavy.asm b/src/test/ref/no-recursion-heavy.asm
index a64e0d602..ec7449e53 100644
--- a/src/test/ref/no-recursion-heavy.asm
+++ b/src/test/ref/no-recursion-heavy.asm
@@ -5,6 +5,7 @@
   .label bb = 3
   .label bb_27 = 4
   .label bc = 5
+  .label bb_100 = 4
   .label bb_101 = 4
   .label bb_102 = 4
   .label bb_103 = 4
@@ -13,7 +14,6 @@
   .label bb_106 = 4
   .label bb_107 = 4
   .label bb_108 = 4
-  .label bb_109 = 4
 main: {
     lda #0
     sta ba
@@ -31,7 +31,7 @@ f0: {
     bne b1
     inc bb
     lda bb
-    sta bb_101
+    sta bb_100
     jsr fa
   b1:
     lda #1
@@ -39,7 +39,7 @@ f0: {
     bne b2
     inc bb
     lda bb
-    sta bb_102
+    sta bb_101
     jsr fa
   b2:
     lda #2
@@ -47,7 +47,7 @@ f0: {
     bne b3
     inc bb
     lda bb
-    sta bb_103
+    sta bb_102
     jsr fa
   b3:
     lda #3
@@ -55,7 +55,7 @@ f0: {
     bne b4
     inc bb
     lda bb
-    sta bb_104
+    sta bb_103
     jsr fa
   b4:
     lda #4
@@ -63,7 +63,7 @@ f0: {
     bne b5
     inc bb
     lda bb
-    sta bb_105
+    sta bb_104
     jsr fa
   b5:
     lda #5
@@ -71,7 +71,7 @@ f0: {
     bne b6
     inc bb
     lda bb
-    sta bb_106
+    sta bb_105
     jsr fa
   b6:
     lda #6
@@ -79,7 +79,7 @@ f0: {
     bne b7
     inc bb
     lda bb
-    sta bb_107
+    sta bb_106
     jsr fa
   b7:
     lda #7
@@ -87,7 +87,7 @@ f0: {
     bne b8
     inc bb
     lda bb
-    sta bb_108
+    sta bb_107
     jsr fa
   b8:
     lda #8
@@ -95,7 +95,7 @@ f0: {
     bne b9
     inc bb
     lda bb
-    sta bb_109
+    sta bb_108
     jsr fa
   b9:
     lda #9
@@ -270,8 +270,5 @@ fc: {
     cmp #7
     cmp #8
     cmp #9
-    bne b10
-    rts
-  b10:
     rts
 }
diff --git a/src/test/ref/sandbox-ternary-error.asm b/src/test/ref/sandbox-ternary-error.asm
index cf9c393e2..a599c7f2c 100644
--- a/src/test/ref/sandbox-ternary-error.asm
+++ b/src/test/ref/sandbox-ternary-error.asm
@@ -7,15 +7,15 @@ main: {
     ldx #0
   b1:
     cpx #0
-    beq b4
-    cpx #1
     beq b2
+    cpx #1
+    beq b4
     lda #'c'
     jmp b3
-  b2:
+  b4:
     lda #'b'
     jmp b3
-  b4:
+  b2:
     lda #'a'
   b3:
     sta SCREEN
diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm
index 0c0bcc277..3597c7029 100644
--- a/src/test/ref/sandbox.asm
+++ b/src/test/ref/sandbox.asm
@@ -202,9 +202,9 @@ myprintf: {
     rts
   b3:
     cpx #'1'
-    bcs b37
+    bcs b39
     jmp b4
-  b37:
+  b39:
     cpx #'9'
     bcs !b23+
     jmp b23
@@ -286,9 +286,9 @@ myprintf: {
     bne b13
     lda bTrailing
     cmp #0
-    beq b39
+    beq b41
     jmp b15
-  b39:
+  b41:
     lda b
     cmp bDigits
     bcc b16
@@ -304,9 +304,9 @@ myprintf: {
     bcc b19
     lda bTrailing
     cmp #0
-    bne b40
+    bne b42
     jmp b22
-  b40:
+  b42:
     lda b
     cmp bDigits
     bcc b21
@@ -360,15 +360,15 @@ myprintf: {
     //w = (bArg == 0) ? w1 : ((bArg == 1) ? w2 : w3); -- "?" is the normal way, but error "sequence does not contain all blocks" -- https://gitlab.com/camelot/kickc/issues/185 [FIXED]
     lda bArg
     cmp #0
-    beq b42
+    beq b29
     lda #1
     cmp bArg
-    beq b43
+    beq b30
     lda w3
     sta w
     lda w3+1
     sta w+1
-  b29:
+  b31:
     inc bArg
     lda #0
     sta bLeadZero
@@ -379,30 +379,30 @@ myprintf: {
     lda #1
     sta bFormat
     jmp b27
-  b43:
+  b30:
     lda w2
     sta w
     lda w2+1
     sta w+1
-    jmp b29
-  b42:
+    jmp b31
+  b29:
     lda w1
     sta w
     lda w1+1
     sta w+1
-    jmp b29
+    jmp b31
   b28:
     cpx #$41
-    bcs b41
-    jmp b30
-  b41:
+    bcs b43
+    jmp b32
+  b43:
     cpx #$5a+1
-    bcc b35
-    jmp b30
-  b35:
+    bcc b37
+    jmp b32
+  b37:
     txa
     axs #-[$20]
-  b30:
+  b32:
     // swap 0x41 / 0x61 when in lower case mode
     ldy bLen
     txa
diff --git a/src/test/ref/semi-struct-2.asm b/src/test/ref/semi-struct-2.asm
index 03cc33c2c..6d4e8534f 100644
--- a/src/test/ref/semi-struct-2.asm
+++ b/src/test/ref/semi-struct-2.asm
@@ -37,6 +37,8 @@
   .label print_line_cursor = $a
   .label print_line_cursor_32 = 2
   .label print_line_cursor_63 = 2
+  .label print_line_cursor_157 = 2
+  .label print_line_cursor_158 = 2
   .label print_line_cursor_159 = 2
   .label print_line_cursor_160 = 2
   .label print_line_cursor_161 = 2
@@ -52,9 +54,7 @@
   .label print_line_cursor_171 = 2
   .label print_line_cursor_172 = 2
   .label print_line_cursor_173 = 2
-  .label print_line_cursor_174 = 2
   .label print_line_cursor_175 = 2
-  .label print_line_cursor_177 = 2
 // Initialize 2 file entries and print them
 main: {
     .const fileEntry1_idx = 1
@@ -114,9 +114,9 @@ main: {
     sta print_line_cursor_63+1
     jsr print_ln
     lda print_line_cursor
-    sta print_line_cursor_159
+    sta print_line_cursor_157
     lda print_line_cursor+1
-    sta print_line_cursor_159+1
+    sta print_line_cursor_157+1
     lda print_line_cursor
     sta print_char_cursor
     lda print_line_cursor+1
@@ -124,9 +124,9 @@ main: {
     jsr print_ln
     jsr printEntry
     lda print_line_cursor
-    sta print_line_cursor_160
+    sta print_line_cursor_158
     lda print_line_cursor+1
-    sta print_line_cursor_160+1
+    sta print_line_cursor_158+1
     lda print_line_cursor
     sta print_char_cursor
     lda print_line_cursor+1
@@ -161,9 +161,9 @@ main: {
     sta print_line_cursor_63+1
     jsr print_ln
     lda print_line_cursor
-    sta print_line_cursor_161
+    sta print_line_cursor_159
     lda print_line_cursor+1
-    sta print_line_cursor_161+1
+    sta print_line_cursor_159+1
     lda print_line_cursor
     sta print_char_cursor
     lda print_line_cursor+1
@@ -175,9 +175,9 @@ main: {
     sta printEntry.entry+1
     jsr printEntry
     lda print_line_cursor
-    sta print_line_cursor_162
+    sta print_line_cursor_160
     lda print_line_cursor+1
-    sta print_line_cursor_162+1
+    sta print_line_cursor_160+1
     lda print_line_cursor
     sta print_char_cursor
     lda print_line_cursor+1
@@ -292,9 +292,9 @@ print_ln: {
     rts
   b2:
     lda print_line_cursor
-    sta print_line_cursor_177
+    sta print_line_cursor_175
     lda print_line_cursor+1
-    sta print_line_cursor_177+1
+    sta print_line_cursor_175+1
     jmp b1
 }
 // Print the contents of a file entry
@@ -318,9 +318,9 @@ printEntry: {
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
-    sta print_line_cursor_163
+    sta print_line_cursor_161
     lda print_line_cursor+1
-    sta print_line_cursor_163+1
+    sta print_line_cursor_161+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -339,9 +339,9 @@ printEntry: {
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
-    sta print_line_cursor_164
+    sta print_line_cursor_162
     lda print_line_cursor+1
-    sta print_line_cursor_164+1
+    sta print_line_cursor_162+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -360,9 +360,9 @@ printEntry: {
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
-    sta print_line_cursor_165
+    sta print_line_cursor_163
     lda print_line_cursor+1
-    sta print_line_cursor_165+1
+    sta print_line_cursor_163+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -381,9 +381,9 @@ printEntry: {
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
-    sta print_line_cursor_166
+    sta print_line_cursor_164
     lda print_line_cursor+1
-    sta print_line_cursor_166+1
+    sta print_line_cursor_164+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -399,9 +399,9 @@ printEntry: {
     tax
     jsr print_byte
     lda print_line_cursor
-    sta print_line_cursor_167
+    sta print_line_cursor_165
     lda print_line_cursor+1
-    sta print_line_cursor_167+1
+    sta print_line_cursor_165+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -417,9 +417,9 @@ printEntry: {
     tax
     jsr print_byte
     lda print_line_cursor
-    sta print_line_cursor_168
+    sta print_line_cursor_166
     lda print_line_cursor+1
-    sta print_line_cursor_168+1
+    sta print_line_cursor_166+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -435,9 +435,9 @@ printEntry: {
     tax
     jsr print_byte
     lda print_line_cursor
-    sta print_line_cursor_169
+    sta print_line_cursor_167
     lda print_line_cursor+1
-    sta print_line_cursor_169+1
+    sta print_line_cursor_167+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -453,9 +453,9 @@ printEntry: {
     tax
     jsr print_byte
     lda print_line_cursor
-    sta print_line_cursor_170
+    sta print_line_cursor_168
     lda print_line_cursor+1
-    sta print_line_cursor_170+1
+    sta print_line_cursor_168+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -474,9 +474,9 @@ printEntry: {
     sta print_word.w+1
     jsr print_word
     lda print_line_cursor
-    sta print_line_cursor_171
+    sta print_line_cursor_169
     lda print_line_cursor+1
-    sta print_line_cursor_171+1
+    sta print_line_cursor_169+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -492,9 +492,9 @@ printEntry: {
     tax
     jsr print_byte
     lda print_line_cursor
-    sta print_line_cursor_172
+    sta print_line_cursor_170
     lda print_line_cursor+1
-    sta print_line_cursor_172+1
+    sta print_line_cursor_170+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -510,9 +510,9 @@ printEntry: {
     tax
     jsr print_byte
     lda print_line_cursor
-    sta print_line_cursor_173
+    sta print_line_cursor_171
     lda print_line_cursor+1
-    sta print_line_cursor_173+1
+    sta print_line_cursor_171+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -528,9 +528,9 @@ printEntry: {
     tax
     jsr print_byte
     lda print_line_cursor
-    sta print_line_cursor_174
+    sta print_line_cursor_172
     lda print_line_cursor+1
-    sta print_line_cursor_174+1
+    sta print_line_cursor_172+1
     jsr print_ln
     lda print_line_cursor
     sta print_char_cursor
@@ -546,9 +546,9 @@ printEntry: {
     tax
     jsr print_byte
     lda print_line_cursor
-    sta print_line_cursor_175
+    sta print_line_cursor_173
     lda print_line_cursor+1
-    sta print_line_cursor_175+1
+    sta print_line_cursor_173+1
     jsr print_ln
     rts
     str: .text "bufdisk   @"
diff --git a/src/test/ref/signed-words.asm b/src/test/ref/signed-words.asm
index cd5577b6e..765fcee02 100644
--- a/src/test/ref/signed-words.asm
+++ b/src/test/ref/signed-words.asm
@@ -22,7 +22,7 @@
   .label yvel_10 = 6
   .label xvel = 2
   .label yvel_12 = 6
-  .label yvel_21 = 6
+  .label yvel_20 = 6
 main: {
     jsr init
     lda #$64
@@ -93,9 +93,9 @@ anim: {
     sta yvel+1
   b3:
     lda yvel
-    sta yvel_21
+    sta yvel_20
     lda yvel+1
-    sta yvel_21+1
+    sta yvel_20+1
     lda #0
     sta ypos
     sta ypos+1
diff --git a/src/test/ref/test-comparisons-sword.asm b/src/test/ref/test-comparisons-sword.asm
index 7040fecd8..243347b6b 100644
--- a/src/test/ref/test-comparisons-sword.asm
+++ b/src/test/ref/test-comparisons-sword.asm
@@ -80,8 +80,9 @@ main: {
     inc i
     cmp i
     bne b1
-  b8:
-    jmp b8
+  b5:
+  // loop forever
+    jmp b5
 }
 // Print a newline
 print_ln: {
diff --git a/src/test/ref/test-comparisons-word.asm b/src/test/ref/test-comparisons-word.asm
index fed328414..3b0d79f32 100644
--- a/src/test/ref/test-comparisons-word.asm
+++ b/src/test/ref/test-comparisons-word.asm
@@ -73,8 +73,9 @@ main: {
     inc i
     cmp i
     bne b1
-  b8:
-    jmp b8
+  b5:
+  // loop forever
+    jmp b5
 }
 // Print a newline
 print_ln: {

From 430c128cc3c4664e999e735a2032e5ab78e6ce50 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 12:33:15 +0200
Subject: [PATCH 80/93] Simplified constant inlining pass2

---
 .../java/dk/camelot64/kickc/Compiler.java     | 25 ++++++-------------
 .../ref/function-pointer-noarg-call-8.asm     |  7 +++---
 2 files changed, 11 insertions(+), 21 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index ac82bc58f..8d964707d 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -230,17 +230,19 @@ public class Compiler {
    }
 
    private void pass2Optimize() {
+      List<Pass2SsaOptimization> optimizations = getPass2Optimizations();
+      pass2Execute(optimizations);
+   }
+
+   private List<Pass2SsaOptimization> getPass2Optimizations() {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
-
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
-
       optimizations.add(new PassNAddNumberTypeConversions(program));
       optimizations.add(new PassNAddArrayNumberTypeConversions(program));
       optimizations.add(new PassNTypeInference(program));
       optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new Pass2InlineCast(program));
       optimizations.add(new PassNCastSimplification(program));
-
       optimizations.add(new PassNTypeIdSimplification(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new PassNStatementIndices(program));
@@ -266,7 +268,7 @@ public class Compiler {
       optimizations.add(new PassNSimplifyExpressionWithZero(program));
       optimizations.add(new PassNEliminateUnusedVars(program, true));
       optimizations.add(new Pass2EliminateUnusedBlocks(program));
-      pass2Execute(optimizations);
+      return optimizations;
    }
 
    private void pass2UnrollLoops() {
@@ -297,26 +299,15 @@ public class Compiler {
 
    private void pass2InlineConstants() {
       // Constant inlining optimizations - as the last step to ensure that constant identification has been completed
+
       List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>();
       constantOptimizations.add(new PassNStatementIndices(program));
       constantOptimizations.add(new PassNVariableReferenceInfos(program));
       constantOptimizations.add(new Pass2MultiplyToShiftRewriting(program));
-      constantOptimizations.add(new Pass2AliasElimination(program));
       constantOptimizations.add(new Pass2ConstantInlining(program));
-      constantOptimizations.add(new Pass2ConstantStringConsolidation(program));
-      constantOptimizations.add(new Pass2IdenticalPhiElimination(program));
-      constantOptimizations.add(new Pass2ConstantRValueConsolidation(program));
-      constantOptimizations.add(new Pass2ConstantIdentification(program));
-      constantOptimizations.add(new Pass2ConstantValues(program));
       constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
       constantOptimizations.add(new Pass2ConstantSimplification(program));
-      constantOptimizations.add(new PassNCastSimplification(program));
-      constantOptimizations.add(new Pass2ConstantIfs(program));
-      constantOptimizations.add(new Pass2InlineDerefIdx(program));
-      constantOptimizations.add(new PassNEliminateUnusedVars(program, true));
-      constantOptimizations.add(new PassNSimplifyConstantZero(program));
-      constantOptimizations.add(new PassNSimplifyExpressionWithZero(program));
-
+      constantOptimizations.addAll(getPass2Optimizations());
       pass2Execute(constantOptimizations);
 
    }
diff --git a/src/test/ref/function-pointer-noarg-call-8.asm b/src/test/ref/function-pointer-noarg-call-8.asm
index 6ea60224a..c90b2daa7 100644
--- a/src/test/ref/function-pointer-noarg-call-8.asm
+++ b/src/test/ref/function-pointer-noarg-call-8.asm
@@ -3,8 +3,8 @@
 :BasicUpstart(bbegin)
 .pc = $80d "Program"
   .label SCREEN = $400
-  .label msg = 4
-  .label idx = 3
+  .label msg = 3
+  .label idx = 5
 bbegin:
   lda #<0
   sta msg
@@ -13,7 +13,6 @@ bbegin:
   jsr main
   rts
 main: {
-    .label f = hello
     lda #<msg1
     sta msg
     lda #>msg1
@@ -31,7 +30,7 @@ do10: {
     lda #0
     sta i
   b1:
-    jsr main.f
+    jsr hello
     inc i
     lda #$a
     cmp i

From 06147e2634bf189a207bc9844c3b4fe6135db8fa Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 15:48:34 +0200
Subject: [PATCH 81/93] Moved malloc/free trivial implementations to stdlib

---
 .../java/dk/camelot64/kickc/Compiler.java     | 11 +++++-----
 src/main/kc/stdlib/stdlib.kc                  | 20 ++++++++++++++++++
 src/test/kc/memory-heap.kc                    | 21 ++-----------------
 src/test/ref/memory-heap.asm                  | 17 +++++++--------
 4 files changed, 35 insertions(+), 34 deletions(-)
 create mode 100644 src/main/kc/stdlib/stdlib.kc

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 8d964707d..667ad696e 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -229,11 +229,6 @@ public class Compiler {
       }
    }
 
-   private void pass2Optimize() {
-      List<Pass2SsaOptimization> optimizations = getPass2Optimizations();
-      pass2Execute(optimizations);
-   }
-
    private List<Pass2SsaOptimization> getPass2Optimizations() {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
@@ -271,6 +266,11 @@ public class Compiler {
       return optimizations;
    }
 
+   private void pass2Optimize() {
+      List<Pass2SsaOptimization> optimizations = getPass2Optimizations();
+      pass2Execute(optimizations);
+   }
+
    private void pass2UnrollLoops() {
       List<Pass2SsaOptimization> loopUnrolling = new ArrayList<>();
       loopUnrolling.add(new PassNStatementIndices(program));
@@ -299,7 +299,6 @@ public class Compiler {
 
    private void pass2InlineConstants() {
       // Constant inlining optimizations - as the last step to ensure that constant identification has been completed
-
       List<Pass2SsaOptimization> constantOptimizations = new ArrayList<>();
       constantOptimizations.add(new PassNStatementIndices(program));
       constantOptimizations.add(new PassNVariableReferenceInfos(program));
diff --git a/src/main/kc/stdlib/stdlib.kc b/src/main/kc/stdlib/stdlib.kc
new file mode 100644
index 000000000..bd6686a8f
--- /dev/null
+++ b/src/main/kc/stdlib/stdlib.kc
@@ -0,0 +1,20 @@
+// Implementation of functions found int C stdlib.h / stdlib.c
+
+// Start of the heap used by malloc()
+unsigned char* HEAP_START = 0xc000;
+
+// Head of the heap. Moved forward for each malloc()
+unsigned char* heap_head = HEAP_START;
+
+// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
+// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
+unsigned char* malloc(unsigned int size) {
+    unsigned char* mem = heap_head;
+    heap_head+= size;
+    return mem;
+}
+
+// A block of memory previously allocated by a call to malloc is deallocated, making it available again for further allocations.
+// If ptr is a null pointer, the function does nothing.
+void free(unsigned char* ptr) {
+}
\ No newline at end of file
diff --git a/src/test/kc/memory-heap.kc b/src/test/kc/memory-heap.kc
index 2fa915342..5c62db2fd 100644
--- a/src/test/kc/memory-heap.kc
+++ b/src/test/kc/memory-heap.kc
@@ -1,5 +1,7 @@
 // Experiments with malloc()
 
+import "stdlib"
+
 void main() {
     unsigned char* buf1 = (unsigned char*) malloc(100);
     unsigned char* buf2 = (unsigned char*) malloc(100);
@@ -13,22 +15,3 @@ void main() {
     screen[0] = *buf1;
     screen[1] = *buf2;
 }
-
-// Start of the heap used by malloc()
-unsigned char* HEAP_START = 0xc000;
-
-// Head of the heap. Moved forward for each malloc()
-unsigned char* heap_head = HEAP_START;
-
-// Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
-// The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
-unsigned char* malloc(unsigned int size) {
-    unsigned char* mem = heap_head;
-    heap_head+= size;
-    return mem;
-}
-
-// A block of memory previously allocated by a call to malloc is deallocated, making it available again for further allocations.
-// If ptr is a null pointer, the function does nothing.
-void free(unsigned char* ptr) {
-}
\ No newline at end of file
diff --git a/src/test/ref/memory-heap.asm b/src/test/ref/memory-heap.asm
index 769942503..c07e8c978 100644
--- a/src/test/ref/memory-heap.asm
+++ b/src/test/ref/memory-heap.asm
@@ -14,10 +14,10 @@ main: {
     lda #>HEAP_START
     sta heap_head+1
     jsr malloc
-    lda malloc.return_2
-    sta malloc.return
-    lda malloc.return_2+1
-    sta malloc.return+1
+    lda malloc.return
+    sta malloc.return_2
+    lda malloc.return+1
+    sta malloc.return_2+1
     jsr malloc
     ldy #0
   b1:
@@ -48,13 +48,12 @@ free: {
 // Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
 // The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
 malloc: {
-    .label return = 4
-    .label return_1 = 6
-    .label return_2 = 6
+    .label return = 6
+    .label return_2 = 4
     lda heap_head
-    sta return_2
+    sta return
     lda heap_head+1
-    sta return_2+1
+    sta return+1
     lda #$64
     clc
     adc heap_head

From 9ef7c69c3e0d836f8c2ba1ba213fcf4db18bfe4f Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Thu, 23 May 2019 17:50:44 +0200
Subject: [PATCH 82/93] Improved comparisons to avoid branch/jmp sequences by
 negating comparisons.

---
 src/main/fragment/vbuaa_le_0_then_la1.asm     |  2 +
 src/main/fragment/vbuxx_le_0_then_la1.asm     |  2 +
 src/main/fragment/vbuyy_le_0_then_la1.asm     |  2 +
 src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm |  7 ++
 .../java/dk/camelot64/kickc/Compiler.java     |  1 +
 .../model/operators/OperatorDecrement.java    |  3 +-
 .../model/operators/OperatorIncrement.java    |  4 +-
 ...ss2ConditionalJumpSequenceImprovement.java | 79 +++++++++++++++++++
 .../dk/camelot64/kickc/test/TestPrograms.java |  5 ++
 src/test/kc/statement-sequence-1.kc           | 15 ++++
 src/test/ref/bool-ifs.asm                     |  8 +-
 src/test/ref/bool-vars.asm                    |  4 +-
 src/test/ref/complex-conditional-problem.asm  |  3 +-
 src/test/ref/duplicate-loop-problem.asm       |  4 +-
 .../multiplexer/simple-multiplexer.asm        |  4 +-
 src/test/ref/keyboard-glitch.asm              |  4 +-
 src/test/ref/loop-break-continue.asm          |  9 +--
 src/test/ref/loop-break-nested.asm            | 17 ++--
 src/test/ref/loop-break.asm                   |  5 +-
 src/test/ref/loop-continue.asm                |  4 +-
 src/test/ref/loop-while-continue.asm          |  4 +-
 .../simple-multiplexer-irq.asm                |  8 +-
 src/test/ref/sandbox.asm                      | 25 +++---
 src/test/ref/statement-sequence-1.asm         | 27 +++++++
 24 files changed, 180 insertions(+), 66 deletions(-)
 create mode 100644 src/main/fragment/vbuaa_le_0_then_la1.asm
 create mode 100644 src/main/fragment/vbuxx_le_0_then_la1.asm
 create mode 100644 src/main/fragment/vbuyy_le_0_then_la1.asm
 create mode 100644 src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSequenceImprovement.java
 create mode 100644 src/test/kc/statement-sequence-1.kc
 create mode 100644 src/test/ref/statement-sequence-1.asm

diff --git a/src/main/fragment/vbuaa_le_0_then_la1.asm b/src/main/fragment/vbuaa_le_0_then_la1.asm
new file mode 100644
index 000000000..118295957
--- /dev/null
+++ b/src/main/fragment/vbuaa_le_0_then_la1.asm
@@ -0,0 +1,2 @@
+cmp #0
+beq {la1}
\ No newline at end of file
diff --git a/src/main/fragment/vbuxx_le_0_then_la1.asm b/src/main/fragment/vbuxx_le_0_then_la1.asm
new file mode 100644
index 000000000..d1d800f7b
--- /dev/null
+++ b/src/main/fragment/vbuxx_le_0_then_la1.asm
@@ -0,0 +1,2 @@
+cpx #0
+beq {la1}
\ No newline at end of file
diff --git a/src/main/fragment/vbuyy_le_0_then_la1.asm b/src/main/fragment/vbuyy_le_0_then_la1.asm
new file mode 100644
index 000000000..9af1697e9
--- /dev/null
+++ b/src/main/fragment/vbuyy_le_0_then_la1.asm
@@ -0,0 +1,2 @@
+cpy #0
+beq {la1}
\ No newline at end of file
diff --git a/src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm b/src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm
new file mode 100644
index 000000000..5afd41846
--- /dev/null
+++ b/src/main/fragment/vwuz1_eq_vwuc1_then_la1.asm
@@ -0,0 +1,7 @@
+lda {z1}
+cmp #<{c1}
+bne !+
+lda {z1}+1
+cmp #>{c1}
+beq {la1}
+!:
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 667ad696e..fd5051bd2 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -249,6 +249,7 @@ public class Compiler {
       optimizations.add(new Pass2DuplicateRValueIdentification(program));
       optimizations.add(new Pass2ConditionalJumpSimplification(program));
       optimizations.add(new Pass2ConditionalAndOrRewriting(program));
+      optimizations.add(new Pass2ConditionalJumpSequenceImprovement(program)); 
       optimizations.add(new Pass2ConstantRValueConsolidation(program));
       optimizations.add(new Pass2ConstantIdentification(program));
       optimizations.add(new Pass2ConstantValues(program));
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java
index 5dfd1a7a4..1ea0a32b1 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDecrement.java
@@ -1,6 +1,7 @@
 package dk.camelot64.kickc.model.operators;
 
 import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.ConstantNotLiteral;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.values.ConstantInteger;
@@ -18,7 +19,7 @@ public class OperatorDecrement extends OperatorUnary {
       if(operand instanceof ConstantInteger ) {
          return new ConstantInteger(((ConstantInteger) operand).getInteger() -1);
       }
-      throw new CompileError("Calculation not implemented " + getOperator() + " " + operand );
+      throw new ConstantNotLiteral("Calculation not literal " + getOperator() + " " + operand );
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java
index a7532ff7a..bd63496d0 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorIncrement.java
@@ -1,6 +1,6 @@
 package dk.camelot64.kickc.model.operators;
 
-import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.ConstantNotLiteral;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.values.ConstantInteger;
@@ -21,7 +21,7 @@ public class OperatorIncrement extends OperatorUnary {
       } else if(operand instanceof ConstantPointer) {
          return new ConstantPointer(((ConstantPointer) operand).getLocation()+1, ((ConstantPointer) operand).getElementType());
       }
-      throw new CompileError("Calculation not implemented " + getOperator() + " " + operand );
+      throw new ConstantNotLiteral("Calculation not literal " + getOperator() + " " + operand );
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSequenceImprovement.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSequenceImprovement.java
new file mode 100644
index 000000000..0bbd1fd33
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSequenceImprovement.java
@@ -0,0 +1,79 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.ControlFlowBlock;
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.operators.Operator;
+import dk.camelot64.kickc.model.operators.Operators;
+import dk.camelot64.kickc.model.statements.Statement;
+import dk.camelot64.kickc.model.statements.StatementConditionalJump;
+import dk.camelot64.kickc.model.values.LabelRef;
+
+// If a conditional (on block A)  jumps to a block (B) that has the same default successor (C) as the current block (A) then
+// negate the conditional to ensure sequence A->B->C, which generates optimal ASM.
+public class Pass2ConditionalJumpSequenceImprovement extends Pass2SsaOptimization {
+
+   public Pass2ConditionalJumpSequenceImprovement(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      boolean modified = false;
+      for(ControlFlowBlock block : getGraph().getAllBlocks()) {
+         ControlFlowBlock conditionalSuccessor = getGraph().getConditionalSuccessor(block);
+         ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block);
+         if(conditionalSuccessor != null && defaultSuccessor != null) {
+            if(conditionalSuccessor.getDefaultSuccessor().equals(defaultSuccessor.getLabel())) {
+               if(conditionalSuccessor.equals(block)) continue;
+               // conditional successor is current blocks default successor
+               // Negate condition and swap conditional/default successor.
+               modified = negateCondition(block);
+            }
+
+         }
+      }
+      return modified;
+   }
+
+   private boolean negateCondition(ControlFlowBlock block) {
+      LabelRef defaultSuccessor = block.getDefaultSuccessor();
+      LabelRef conditionalSuccessor = block.getConditionalSuccessor();
+      for(Statement statement : block.getStatements()) {
+         if(statement instanceof StatementConditionalJump) {
+            StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
+            if(negateOperator(conditionalJump.getOperator()) != null) {
+               Operator negatedOperator = negateOperator(conditionalJump.getOperator());
+               conditionalJump.setOperator(negatedOperator);
+               conditionalJump.setDestination(defaultSuccessor);
+               block.setConditionalSuccessor(defaultSuccessor);
+               block.setDefaultSuccessor(conditionalSuccessor);
+               getLog().append("Negating conditional jump and destination " + conditionalJump.toString(getProgram(), false));
+               return true;
+            }
+         }
+      }
+      return false;
+   }
+
+   /**
+    * Find the logic operator that returns the opposite result
+    *
+    * @param operator The operator to negate
+    * @return The opposite logic operator. Null if not found.
+    */
+   private Operator negateOperator(Operator operator) {
+      if(Operators.EQ.equals(operator))
+         return Operators.NEQ;
+      if(Operators.NEQ.equals(operator))
+         return Operators.EQ;
+      if(Operators.LT.equals(operator))
+         return Operators.GE;
+      if(Operators.LE.equals(operator))
+         return Operators.GT;
+      if(Operators.GT.equals(operator))
+         return Operators.LE;
+      if(Operators.GE.equals(operator))
+         return Operators.LT;
+      return null;
+   }
+}
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 338a622e5..23c2cc2b7 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -63,6 +63,11 @@ public class TestPrograms {
 
     */
 
+   @Test
+   public void testStatementSequence1() throws IOException, URISyntaxException {
+      compileAndCompare("statement-sequence-1");
+   }
+
    @Test
    public void testSubExprOptimize1() throws IOException, URISyntaxException {
       compileAndCompare("subexpr-optimize-1");
diff --git a/src/test/kc/statement-sequence-1.kc b/src/test/kc/statement-sequence-1.kc
new file mode 100644
index 000000000..396b7b3cf
--- /dev/null
+++ b/src/test/kc/statement-sequence-1.kc
@@ -0,0 +1,15 @@
+// Tests statement sequence  generation
+
+void main() {
+
+    const byte* SCREEN = 0x0400;
+
+    for(byte i: 0..10) {
+        byte c = i+5;
+        if((i&1)==0 || i>5)
+            c++;
+        SCREEN[i] = c;
+    }
+
+
+}
diff --git a/src/test/ref/bool-ifs.asm b/src/test/ref/bool-ifs.asm
index ef375b6fe..8b9c1b158 100644
--- a/src/test/ref/bool-ifs.asm
+++ b/src/test/ref/bool-ifs.asm
@@ -16,9 +16,7 @@ bool_complex: {
     txa
     and #1
     cpx #$a
-    bcc b6
-    jmp b5
-  b6:
+    bcs b5
     cmp #0
     beq b2
   b5:
@@ -90,9 +88,7 @@ bool_and: {
     txa
     and #1
     cpx #$a
-    bcc b5
-    jmp b4
-  b5:
+    bcs b4
     cmp #0
     beq b2
   b4:
diff --git a/src/test/ref/bool-vars.asm b/src/test/ref/bool-vars.asm
index 65d8b579c..e4b28d49a 100644
--- a/src/test/ref/bool-vars.asm
+++ b/src/test/ref/bool-vars.asm
@@ -107,9 +107,7 @@ bool_and: {
     txa
     and #1
     cpx #$a
-    bcc b5
-    jmp b4
-  b5:
+    bcs b4
     cmp #0
     beq b2
   b4:
diff --git a/src/test/ref/complex-conditional-problem.asm b/src/test/ref/complex-conditional-problem.asm
index 46436158b..12fdbcac5 100644
--- a/src/test/ref/complex-conditional-problem.asm
+++ b/src/test/ref/complex-conditional-problem.asm
@@ -10,8 +10,7 @@ main: {
     cmp #$20+1
     bcs b3
     cmp #$40
-    bcc b3
-    jmp b2
+    bcs b2
   b3:
     lda #0
   b2:
diff --git a/src/test/ref/duplicate-loop-problem.asm b/src/test/ref/duplicate-loop-problem.asm
index d2dc774fa..0a2aa7631 100644
--- a/src/test/ref/duplicate-loop-problem.asm
+++ b/src/test/ref/duplicate-loop-problem.asm
@@ -10,9 +10,7 @@ main: {
     txa
     and #$1f
     cpx #0
-    beq b3
-    jmp b1
-  b3:
+    bne b1
     cmp #$1f
     beq b1
     jmp b1
diff --git a/src/test/ref/examples/multiplexer/simple-multiplexer.asm b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
index 6016bd1d2..b0ac841db 100644
--- a/src/test/ref/examples/multiplexer/simple-multiplexer.asm
+++ b/src/test/ref/examples/multiplexer/simple-multiplexer.asm
@@ -185,9 +185,7 @@ plexSort: {
     sta PLEX_SORTED_IDX+1,x
     dex
     cpx #$ff
-    bne b6
-    jmp b4
-  b6:
+    beq b4
     lda nxt_y
     ldy PLEX_SORTED_IDX,x
     cmp PLEX_YPOS,y
diff --git a/src/test/ref/keyboard-glitch.asm b/src/test/ref/keyboard-glitch.asm
index e557715bc..e9466358d 100644
--- a/src/test/ref/keyboard-glitch.asm
+++ b/src/test/ref/keyboard-glitch.asm
@@ -95,7 +95,9 @@ pressed: {
     ldx #KEY_SPACE
     jsr keyboard_key_pressed
     cmp #0
-    beq b1
+    bne breturn
+    jmp b1
+  breturn:
     rts
 }
   // Keyboard row bitmask as expected by CIA#1 Port A when reading a specific keyboard matrix row (rows are numbered 0-7)
diff --git a/src/test/ref/loop-break-continue.asm b/src/test/ref/loop-break-continue.asm
index c7a50bd37..66faad93f 100644
--- a/src/test/ref/loop-break-continue.asm
+++ b/src/test/ref/loop-break-continue.asm
@@ -14,13 +14,12 @@ main: {
     lda str,x
     cmp #'@'
     bne b2
+  breturn:
     rts
   b2:
     lda str,x
     cmp #' '
-    bne b3
-    jmp b4
-  b3:
+    beq b4
     lda str,x
     ldy #0
     sta (screen),y
@@ -31,7 +30,7 @@ main: {
   b4:
     inx
     cpx #0
-    bne b1
-    rts
+    beq breturn
+    jmp b1
     str: .text "hello brave new world@"
 }
diff --git a/src/test/ref/loop-break-nested.asm b/src/test/ref/loop-break-nested.asm
index eb7d4bbcc..9de10c039 100644
--- a/src/test/ref/loop-break-nested.asm
+++ b/src/test/ref/loop-break-nested.asm
@@ -12,16 +12,15 @@ main: {
     ldy #0
     lda (line),y
     cmp #'a'
-    bne b5
+    bne b3
+  breturn:
     rts
-  b5:
+  b3:
     ldy #0
   b2:
     lda (line),y
     cmp #'a'
-    bne b3
-    jmp b4
-  b3:
+    beq b4
     lda #'a'
     sta (line),y
     iny
@@ -37,11 +36,11 @@ main: {
   !:
     lda line+1
     cmp #>$400+$28*$19
-    bcc b1
-    bne !+
+    bcc !+
+    bne breturn
     lda line
     cmp #<$400+$28*$19
-    bcc b1
+    bcs breturn
   !:
-    rts
+    jmp b1
 }
diff --git a/src/test/ref/loop-break.asm b/src/test/ref/loop-break.asm
index e1e305c19..9be966560 100644
--- a/src/test/ref/loop-break.asm
+++ b/src/test/ref/loop-break.asm
@@ -8,13 +8,12 @@ main: {
   b1:
     lda SCREEN,x
     cmp #'a'
-    bne b2
-    rts
-  b2:
+    beq breturn
     lda #'a'
     sta SCREEN,x
     inx
     cpx #$28*6+1
     bne b1
+  breturn:
     rts
 }
diff --git a/src/test/ref/loop-continue.asm b/src/test/ref/loop-continue.asm
index fe08e6e87..bd86c60aa 100644
--- a/src/test/ref/loop-continue.asm
+++ b/src/test/ref/loop-continue.asm
@@ -8,9 +8,7 @@ main: {
   b1:
     lda SCREEN,x
     cmp #' '
-    bne b2
-    jmp b3
-  b2:
+    beq b3
     inc SCREEN,x
   b3:
     inx
diff --git a/src/test/ref/loop-while-continue.asm b/src/test/ref/loop-while-continue.asm
index 1424862f5..8529f855a 100644
--- a/src/test/ref/loop-while-continue.asm
+++ b/src/test/ref/loop-while-continue.asm
@@ -13,9 +13,7 @@ main: {
   b2:
     lda SCREEN,x
     cmp #' '
-    bne b3
-    jmp b1
-  b3:
+    beq b1
     inc SCREEN,x
     jmp b1
 }
diff --git a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
index 52e162f4a..64cf59ca2 100644
--- a/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
+++ b/src/test/ref/multiplexer-irq/simple-multiplexer-irq.asm
@@ -129,9 +129,7 @@ plexSort: {
     sta PLEX_SORTED_IDX+1,x
     dex
     cpx #$ff
-    bne b7
-    jmp b4
-  b7:
+    beq b4
     lda nxt_y
     ldy PLEX_SORTED_IDX,x
     cmp PLEX_YPOS,y
@@ -241,9 +239,7 @@ plex_irq: {
     sta _4
     lda plex_show_idx
     cmp #PLEX_COUNT
-    bcc b7
-    jmp b4
-  b7:
+    bcs b4
     cpx _4
     bcc b3
   b4:
diff --git a/src/test/ref/sandbox.asm b/src/test/ref/sandbox.asm
index 3597c7029..c3437f972 100644
--- a/src/test/ref/sandbox.asm
+++ b/src/test/ref/sandbox.asm
@@ -202,9 +202,7 @@ myprintf: {
     rts
   b3:
     cpx #'1'
-    bcs b39
-    jmp b4
-  b39:
+    bcc b4
     cpx #'9'
     bcs !b23+
     jmp b23
@@ -286,10 +284,8 @@ myprintf: {
     bne b13
     lda bTrailing
     cmp #0
-    beq b41
-    jmp b15
-  b41:
-    lda b
+    bne b15
+    tya
     cmp bDigits
     bcc b16
   b15:
@@ -304,13 +300,14 @@ myprintf: {
     bcc b19
     lda bTrailing
     cmp #0
-    bne b42
+    bne !b22+
     jmp b22
-  b42:
+  !b22:
     lda b
     cmp bDigits
-    bcc b21
+    bcc !b22+
     jmp b22
+  !b22:
   b21:
     lda #' '
     ldy bLen
@@ -393,13 +390,9 @@ myprintf: {
     jmp b31
   b28:
     cpx #$41
-    bcs b43
-    jmp b32
-  b43:
+    bcc b32
     cpx #$5a+1
-    bcc b37
-    jmp b32
-  b37:
+    bcs b32
     txa
     axs #-[$20]
   b32:
diff --git a/src/test/ref/statement-sequence-1.asm b/src/test/ref/statement-sequence-1.asm
new file mode 100644
index 000000000..4ba57981e
--- /dev/null
+++ b/src/test/ref/statement-sequence-1.asm
@@ -0,0 +1,27 @@
+// Tests statement sequence  generation
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label SCREEN = $400
+    ldy #0
+  b1:
+    tya
+    tax
+    axs #-[5]
+    tya
+    and #1
+    cmp #0
+    beq b3
+    cpy #5+1
+    bcc b2
+  b3:
+    inx
+  b2:
+    txa
+    sta SCREEN,y
+    iny
+    cpy #$b
+    bne b1
+    rts
+}

From f574bb676c467717d9710b99268deb075d997952 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Fri, 24 May 2019 00:50:48 +0200
Subject: [PATCH 83/93] Working in unumber/snumber. Only few failing tests.

---
 .../java/dk/camelot64/kickc/Compiler.java     |   7 +-
 .../iterator/ProgramExpressionBinary.java     |  58 +++++---
 .../model/operators/OperatorCastSNumber.java  |  27 ++++
 .../model/operators/OperatorCastUNumber.java  |  28 ++++
 .../kickc/model/operators/OperatorDivide.java |   2 +-
 .../model/operators/OperatorGetHigh.java      |   4 +
 .../kickc/model/operators/OperatorGetLow.java |   4 +
 .../kickc/model/operators/Operators.java      |   6 +
 .../kickc/model/symbols/VariableVersion.java  |   1 +
 .../kickc/model/types/SymbolType.java         |   2 +-
 .../model/types/SymbolTypeConversion.java     | 129 ++++++++++++------
 .../kickc/passes/Pass1PointerSizeofFix.java   |   4 +-
 .../passes/Pass2ConstantIdentification.java   |   1 +
 .../kickc/passes/Pass2ConstantInlining.java   |   3 +-
 .../passes/Pass2DeInlineWordDerefIdx.java     |   2 +-
 .../passes/PassNAddNumberTypeConversions.java |   1 +
 .../kickc/passes/PassNCastSimplification.java |   9 +-
 .../PassNFinalizeNumberTypeConversions.java   |  65 +++++++++
 .../kickc/passes/PassNTypeInference.java      |   8 +-
 src/test/kc/sandbox.kc                        |   4 +-
 src/test/kc/ternary-inference.kc              |   2 +-
 21 files changed, 290 insertions(+), 77 deletions(-)
 create mode 100644 src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSNumber.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/operators/OperatorCastUNumber.java
 create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index fd5051bd2..fcfc80bcb 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -232,12 +232,15 @@ public class Compiler {
    private List<Pass2SsaOptimization> getPass2Optimizations() {
       List<Pass2SsaOptimization> optimizations = new ArrayList<>();
       optimizations.add(new Pass2FixInlineConstructorsNew(program));
+
       optimizations.add(new PassNAddNumberTypeConversions(program));
       optimizations.add(new PassNAddArrayNumberTypeConversions(program));
-      optimizations.add(new PassNTypeInference(program));
-      optimizations.add(new PassNAddTypeConversionAssignment(program));
       optimizations.add(new Pass2InlineCast(program));
       optimizations.add(new PassNCastSimplification(program));
+      optimizations.add(new PassNFinalizeNumberTypeConversions(program));
+      optimizations.add(new PassNTypeInference(program));
+      optimizations.add(new PassNAddTypeConversionAssignment(program));
+
       optimizations.add(new PassNTypeIdSimplification(program));
       optimizations.add(new Pass2SizeOfSimplification(program));
       optimizations.add(new PassNStatementIndices(program));
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
index e0b959796..f21ea8348 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramExpressionBinary.java
@@ -10,6 +10,7 @@ import dk.camelot64.kickc.model.statements.StatementConditionalJump;
 import dk.camelot64.kickc.model.statements.StatementPhiBlock;
 import dk.camelot64.kickc.model.symbols.ProgramScope;
 import dk.camelot64.kickc.model.symbols.Scope;
+import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.symbols.VariableIntermediate;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
@@ -96,7 +97,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
          } else {
             Scope blockScope = symbols.getScope(currentScope);
             VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
-            tmpVar.setType(toType);
+            tmpVar.setTypeInferred(toType);
             StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue1(), assignment.getSource(), Comment.NO_COMMENTS);
             assignment.setrValue1(tmpVar.getRef());
             stmtIt.previous();
@@ -112,7 +113,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
          } else {
             Scope blockScope = symbols.getScope(currentScope);
             VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
-            tmpVar.setType(toType);
+            tmpVar.setTypeInferred(toType);
             StatementAssignment newAssignment = new StatementAssignment(tmpVar.getRef(), Operators.getCastUnary(toType), assignment.getrValue2(), assignment.getSource(), Comment.NO_COMMENTS);
             assignment.setrValue2(tmpVar.getRef());
             stmtIt.previous();
@@ -156,13 +157,21 @@ public interface ProgramExpressionBinary extends ProgramExpression {
 
       @Override
       public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
-         Scope blockScope = symbols.getScope(currentScope);
-         VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
-         SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
-         tmpVar.setType(rightType);
-         StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
-         assignment.setlValue(tmpVar.getRef());
-         stmtIt.add(newAssignment);
+         if(assignment.getlValue() instanceof VariableRef) {
+            Variable variable = symbols.getVariable((VariableRef) assignment.getlValue());
+            if(variable.isInferredType())
+               variable.setTypeInferred(toType);
+            else
+               throw new InternalError("Cannot cast declared type!" + variable.toString());
+         } else {
+            Scope blockScope = symbols.getScope(currentScope);
+            VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
+            SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
+            tmpVar.setTypeInferred(rightType);
+            StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
+            assignment.setlValue(tmpVar.getRef());
+            stmtIt.add(newAssignment);
+         }
       }
 
       @Override
@@ -173,7 +182,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
             Scope blockScope = symbols.getScope(currentScope);
             VariableIntermediate tmpVar = blockScope.addVariableIntermediate();
             SymbolType rightType = SymbolTypeInference.inferType(symbols, getRight());
-            tmpVar.setType(rightType);
+            tmpVar.setTypeInferred(rightType);
             StatementAssignment newAssignment = new StatementAssignment(assignment.getlValue(), Operators.getCastUnary(toType), tmpVar.getRef(), assignment.getSource(), Comment.NO_COMMENTS);
             assignment.setlValue(tmpVar.getRef());
             stmtIt.add(newAssignment);
@@ -314,7 +323,7 @@ public interface ProgramExpressionBinary extends ProgramExpression {
       public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
          if(getPointerDereferenceIndexed().getPointer() instanceof ConstantValue) {
             getPointerDereferenceIndexed().setPointer(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getPointer()));
-         }  else {
+         } else {
             // Try to use CastValue - may later have to be supported!
             getPointerDereferenceIndexed().setPointer(new CastValue(toType, getPointerDereferenceIndexed().getPointer()));
          }
@@ -324,7 +333,14 @@ public interface ProgramExpressionBinary extends ProgramExpression {
       public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
          if(getPointerDereferenceIndexed().getIndex() instanceof ConstantValue) {
             getPointerDereferenceIndexed().setIndex(new ConstantCastValue(toType, (ConstantValue) getPointerDereferenceIndexed().getIndex()));
-         }  else {
+         } else if( getPointerDereferenceIndexed().getIndex() instanceof VariableRef) {
+            Variable variable = symbols.getVariable((VariableRef) getPointerDereferenceIndexed().getIndex());
+            if(variable.isInferredType())
+               variable.setTypeInferred(toType);
+            else
+               throw new InternalError("Cannot cast declared type!" + variable.toString());
+
+         } else {
             // Try to use CastValue - may later have to be supported!
             getPointerDereferenceIndexed().setIndex(new CastValue(toType, getPointerDereferenceIndexed().getIndex()));
          }
@@ -360,15 +376,22 @@ public interface ProgramExpressionBinary extends ProgramExpression {
 
       @Override
       public void addLeftCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
-         throw new InternalError("Not supported!");
+         Variable variable = symbols.getVariable(phiVariable.getVariable());
+         if(variable.isInferredType())
+            variable.setTypeInferred(toType);
+         else
+            throw new InternalError("Cannot cast declared type!" + variable.toString());
       }
 
       @Override
       public void addRightCast(SymbolType toType, ListIterator<Statement> stmtIt, ScopeRef currentScope, ProgramScope symbols) {
-         if(getRight() instanceof ConstantValue) {
+         if(getRight() instanceof VariableRef) {
+            Variable variable = symbols.getVariable((VariableRef) getRight());
+            if(variable.isInferredType())
+               variable.setTypeInferred(toType);
+         } else if(getRight() instanceof ConstantValue) {
             value.setrValue(new ConstantCastValue(toType, (ConstantValue) getRight()));
-         }  else {
-            // Try to use CastValue - may later have to be supported!
+         } else {
             value.setrValue(new CastValue(toType, getRight()));
          }
       }
@@ -380,7 +403,4 @@ public interface ProgramExpressionBinary extends ProgramExpression {
    }
 
 
-
-
-
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSNumber.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSNumber.java
new file mode 100644
index 000000000..f63a5c264
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastSNumber.java
@@ -0,0 +1,27 @@
+package dk.camelot64.kickc.model.operators;
+
+import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.symbols.ProgramScope;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.ConstantLiteral;
+
+/** Unary Cast to signed number  operator ( (snumber) x ) */
+public class OperatorCastSNumber extends OperatorCast {
+
+   public OperatorCastSNumber(int precedence) {
+      super("((snumber))", "_snumber_", precedence, SymbolType.SNUMBER);
+   }
+
+   @Override
+   public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
+      if(value instanceof ConstantInteger)
+         return new ConstantInteger(((ConstantInteger) value).getValue(), SymbolType.SNUMBER);
+      throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
+   }
+
+   @Override
+   public SymbolType inferType(SymbolType operandType) {
+      return SymbolType.SNUMBER;
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastUNumber.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastUNumber.java
new file mode 100644
index 000000000..d6ea9e832
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorCastUNumber.java
@@ -0,0 +1,28 @@
+package dk.camelot64.kickc.model.operators;
+
+import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.symbols.ProgramScope;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.values.ConstantInteger;
+import dk.camelot64.kickc.model.values.ConstantLiteral;
+import dk.camelot64.kickc.model.values.ConstantPointer;
+
+/** Unary Cast to unsigned number  operator ( (unumber) x ) */
+public class OperatorCastUNumber extends OperatorCast {
+
+   public OperatorCastUNumber(int precedence) {
+      super("((unumber))", "_unumber_", precedence, SymbolType.UNUMBER);
+   }
+
+   @Override
+   public ConstantLiteral calculateLiteral(ConstantLiteral value, ProgramScope scope) {
+      if(value instanceof ConstantInteger)
+         return new ConstantInteger(((ConstantInteger) value).getValue(), SymbolType.UNUMBER);
+      throw new CompileError("Calculation not implemented " + getOperator() + " " + value );
+   }
+
+   @Override
+   public SymbolType inferType(SymbolType operandType) {
+      return SymbolType.UNUMBER;
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
index eb3be39a8..e771d3bb4 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorDivide.java
@@ -29,7 +29,7 @@ public class OperatorDivide extends OperatorBinary {
    @Override
    public SymbolType inferType(SymbolType left, SymbolType right) {
       if(left instanceof SymbolTypePointer) {
-         if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)) {
+         if(SymbolType.BYTE.equals(right) || SymbolType.WORD.equals(right) || SymbolType.NUMBER.equals(right)|| SymbolType.UNUMBER.equals(right)|| SymbolType.SNUMBER.equals(right)) {
             return left;
          } else {
             throw new NoMatchingType("Cannot divide pointer by "+right.toString());
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
index e7ad53157..82367f396 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetHigh.java
@@ -50,6 +50,10 @@ public class OperatorGetHigh extends OperatorUnary {
          return SymbolType.BYTE;
       } else if(SymbolType.NUMBER.equals(operandType)) {
          return SymbolType.NUMBER;
+      } else if(SymbolType.UNUMBER.equals(operandType)) {
+         return SymbolType.UNUMBER;
+      } else if(SymbolType.SNUMBER.equals(operandType)) {
+         return SymbolType.UNUMBER;
       }
       throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
index 6d8e03c03..e162f4d0d 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/OperatorGetLow.java
@@ -50,6 +50,10 @@ public class OperatorGetLow extends OperatorUnary {
          return SymbolType.BYTE;
       } else if(SymbolType.NUMBER.equals(operandType)) {
          return SymbolType.NUMBER;
+      } else if(SymbolType.UNUMBER.equals(operandType)) {
+         return SymbolType.UNUMBER;
+      } else if(SymbolType.SNUMBER.equals(operandType)) {
+         return SymbolType.UNUMBER;
       }
       throw new CompileError("Type inference not implemented "+getOperator()+" "+operandType);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
index 173ab0e8c..0afad2224 100644
--- a/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
+++ b/src/main/java/dk/camelot64/kickc/model/operators/Operators.java
@@ -26,6 +26,8 @@ public class Operators {
    public static final OperatorUnary CAST_DWORD = new OperatorCastDWord(2);
    public static final OperatorUnary CAST_SDWORD = new OperatorCastSDWord(2);
    public static final OperatorUnary CAST_BOOL= new OperatorCastBool(2);
+   public static final OperatorUnary CAST_UNUMBER = new OperatorCastUNumber(2);
+   public static final OperatorUnary CAST_SNUMBER = new OperatorCastSNumber(2);
    public static final OperatorUnary SIZEOF = new OperatorSizeOf(2);
    public static final OperatorUnary TYPEID = new OperatorTypeId(2);
    public static final OperatorBinary MULTIPLY = new OperatorMultiply(3);
@@ -149,6 +151,10 @@ public class Operators {
          return CAST_DWORD;
       } else if(SymbolType.SDWORD.equals(castType)) {
          return CAST_SDWORD;
+      } else if(SymbolType.UNUMBER.equals(castType)) {
+         return CAST_UNUMBER;
+      } else if(SymbolType.SNUMBER.equals(castType)) {
+         return CAST_SNUMBER;
       } else if(SymbolType.BOOLEAN.equals(castType)) {
          return CAST_BOOL;
       } else if(castType instanceof SymbolTypePointer) {
diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/VariableVersion.java b/src/main/java/dk/camelot64/kickc/model/symbols/VariableVersion.java
index 7aca0fd3a..47c67dc0f 100644
--- a/src/main/java/dk/camelot64/kickc/model/symbols/VariableVersion.java
+++ b/src/main/java/dk/camelot64/kickc/model/symbols/VariableVersion.java
@@ -12,6 +12,7 @@ public class VariableVersion extends Variable {
       this.setDeclaredAlignment(versionOf.getDeclaredAlignment());
       this.setDeclaredRegister(versionOf.getDeclaredRegister());
       this.setDeclaredVolatile(versionOf.isDeclaredVolatile());
+      this.setInferredType(versionOf.isInferredType());
       this.versionOfName = versionOf.getLocalName();
       this.setComments(versionOf.getComments());
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
index bff9cc686..c0abe5d1b 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java
@@ -117,7 +117,7 @@ public interface SymbolType {
     * @return true if the type is integer
     */
    static boolean isInteger(SymbolType type) {
-      return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type);
+      return SDWORD.equals(type) || DWORD.equals(type) || SWORD.equals(type) || WORD.equals(type) || SBYTE.equals(type) || BYTE.equals(type) || NUMBER.equals(type)|| UNUMBER.equals(type)|| SNUMBER.equals(type);
    }
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index b2f8c2356..e37c240d9 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -32,6 +32,16 @@ public class SymbolTypeConversion {
       if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) {
          return SymbolType.NUMBER;
       }
+      // If any of the two types are unresolved unsigned - return an unresolved unsigned result
+      if(SymbolType.UNUMBER.equals(type1) || SymbolType.UNUMBER.equals(type2)) {
+         return SymbolType.UNUMBER;
+      }
+      // If any of the two types are unresolved signed - return an unresolved signed result
+      if(SymbolType.SNUMBER.equals(type1) || SymbolType.SNUMBER.equals(type2)) {
+         return SymbolType.SNUMBER;
+      }
+
+      // Both types are resolved (fixed) integer types
       SymbolTypeIntegerFixed fixed1 = (SymbolTypeIntegerFixed) type1;
       SymbolTypeIntegerFixed fixed2 = (SymbolTypeIntegerFixed) type2;
       // C99 6.3.1.8 a. If two operands have the same type no conversion is performed
@@ -82,6 +92,13 @@ public class SymbolTypeConversion {
             return null;
          }
 
+         // a) If any the two operands are unsigned numbers the result is an unsigned number
+         if(SymbolType.UNUMBER.equals(leftType) || SymbolType.UNUMBER.equals(rightType))
+            return SymbolType.UNUMBER;
+         // a) If any the two operands are signed numbers the result is an signed number
+         if(SymbolType.SNUMBER.equals(leftType) || SymbolType.SNUMBER.equals(rightType))
+            return SymbolType.SNUMBER;
+
          // Treat pointers like WORD
          if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD;
          if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD;
@@ -102,52 +119,70 @@ public class SymbolTypeConversion {
             return null;
          }
 
-         // Find the cast type if possible
-         if(numberVal instanceof ConstantValue) {
-            ConstantLiteral constantLiteral;
-            try {
-               constantLiteral = ((ConstantValue) numberVal).calculateLiteral(symbols);
-            } catch( ConstantNotLiteral e) {
-               // Postpone til later!
-               return null;
-            }
-            if(constantLiteral instanceof ConstantInteger) {
-               ConstantInteger constantInteger = (ConstantInteger) constantLiteral;
-               if(SymbolType.NUMBER.equals(constantInteger.getType())) {
-                  Long value = constantInteger.getValue();
-                  if(fixedType.isSigned()) {
-                     // b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
-                     SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value);
-                     if(smallestSignedType == null) {
-                        throw new CompileError("Number constant has value that cannot be represented by a signed type " + value, currentStmt);
-                     }
-                     return smallestSignedType;
-                  } else {
-                     // b) If one operand is a signed type and the other a number the number is converted to the smallest unsigned type that can hold its values.
-                     //    If the number value is negative it is converted to unsigned using two's complement.
-                     SymbolTypeIntegerFixed smallestUnsignedType;
-                     if(value < 0) {
-                        smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value);
-                     } else {
-                        smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
-                     }
-                     return smallestUnsignedType;
-                  }
-               } else {
-                  throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
-               }
-            }
+         if(fixedType.isSigned()) {
+            return SymbolType.SNUMBER;
          } else {
-            // Postpone til later!
-            return null;
+            return SymbolType.UNUMBER;
          }
       }
+
       // No number conversion
       return null;
+
+   }
+
+
+   public static  SymbolType getSmallestSignedFixedIntegerType(ConstantValue constantValue, ProgramScope symbols) {
+      ConstantLiteral constantLiteral;
+      try {
+         constantLiteral = constantValue.calculateLiteral(symbols);
+      } catch(ConstantNotLiteral e) {
+         // Postpone til later!
+         return null;
+      }
+      if(constantLiteral instanceof ConstantInteger) {
+         Long value = ((ConstantInteger) constantLiteral).getValue();
+         // b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
+         SymbolTypeIntegerFixed smallestSignedType = SymbolTypeIntegerFixed.getSmallestSigned(value);
+         if(smallestSignedType == null) {
+            throw new CompileError("Number constant has value that cannot be represented by a signed type " + constantValue.toString());
+         }
+         return smallestSignedType;
+      }
+      // Postpone til later!
+      return null;
    }
 
+   public static  SymbolType getSmallestUnsignedFixedIntegerType(ConstantValue constantValue, ProgramScope symbols) {
+      ConstantLiteral constantLiteral;
+      try {
+         constantLiteral = constantValue.calculateLiteral(symbols);
+      } catch(ConstantNotLiteral e) {
+         // Postpone til later!
+         return null;
+      }
+      if(constantLiteral instanceof ConstantInteger) {
+         Long value = ((ConstantInteger) constantLiteral).getValue();
+         // b) If one operand is a signed type and the other a number the number is converted to the smallest signed type that can hold its values.
+         SymbolTypeIntegerFixed smallestUnsignedType;
+         if(value < 0) {
+            smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(-value);
+         } else {
+            smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
+         }
+         if(smallestUnsignedType == null) {
+            throw new CompileError("Number constant has value that cannot be represented by a unsigned type " + constantValue.toString());
+         }
+         return smallestUnsignedType;
+      }
+      // Postpone til later!
+      return null;
+   }
+
+
    /**
     * Determines if the types of an assignment match up properly
+    *
     * @param lValueType The type of the LValue
     * @param rValueType The type of the RValue
     * @return true if the types match up
@@ -171,10 +206,26 @@ public class SymbolTypeConversion {
          // R-value is still a number - constants are probably not done being identified & typed
          return true;
       }
+      if(SymbolType.UNUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
+         // R-value is still a number - constants are probably not done being identified & typed
+         return true;
+      }
+      if(SymbolType.SNUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
+         // R-value is still a number - constants are probably not done being identified & typed
+         return true;
+      }
       if(SymbolType.NUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
          // R-value is still a number - constants are probably not done being identified & typed
          return true;
       }
+      if(SymbolType.UNUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
+         // R-value is still a number - constants are probably not done being identified & typed
+         return true;
+      }
+      if(SymbolType.SNUMBER.equals(lValueType) && SymbolType.isInteger(rValueType)) {
+         // R-value is still a number - constants are probably not done being identified & typed
+         return true;
+      }
       if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType())) {
          // String value can be assigned into a pointer
          return true;
@@ -189,6 +240,7 @@ public class SymbolTypeConversion {
 
    /**
     * Determines if the left side of an assignment needs a cast to be assigned to the right side
+    *
     * @param lValueType The type of the LValue
     * @param rValueType The type of the RValue
     * @return true if the left side needs a cast
@@ -201,9 +253,8 @@ public class SymbolTypeConversion {
       else if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && SymbolType.BYTE.equals(((SymbolTypePointer) lValueType).getElementType()))
          return false;
       else
-      return true;
+         return true;
    }
 
 
-
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java b/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java
index 9a840e3b4..c4caba00d 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass1PointerSizeofFix.java
@@ -64,7 +64,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
                   VariableRef idx2VarRef = handled.getOrDefault(currentStmt, new LinkedHashMap<>()).get(deref.getIndex());
                   if(idx2VarRef==null) {
                      VariableIntermediate idx2Var = getScope().getScope(currentBlock.getScope()).addVariableIntermediate();
-                     idx2Var.setType(SymbolTypeInference.inferType(getScope(), deref.getIndex()));
+                     idx2Var.setTypeInferred(SymbolTypeInference.inferType(getScope(), deref.getIndex()));
                      ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
                      StatementAssignment idx2 = new StatementAssignment(idx2Var.getRef(), deref.getIndex(), Operators.MULTIPLY, sizeOfTargetType, currentStmt.getSource(), Comment.NO_COMMENTS);
                      stmtIt.previous();
@@ -100,7 +100,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
                // Adding to a pointer - multiply by sizeof()
                getLog().append("Fixing pointer addition " + assignment.toString(getProgram(), false));
                VariableIntermediate tmpVar = getScope().getScope(block.getScope()).addVariableIntermediate();
-               tmpVar.setType(SymbolTypeInference.inferType(getScope(), assignment.getrValue2()));
+               tmpVar.setTypeInferred(SymbolTypeInference.inferType(getScope(), assignment.getrValue2()));
                stmtIt.remove();
                ConstantRef sizeOfTargetType = OperatorSizeOf.getSizeOfConstantVar(getProgram().getScope(), pointerType.getElementType());
                stmtIt.add(new StatementAssignment(tmpVar.getRef(), assignment.getrValue2(), Operators.MULTIPLY, sizeOfTargetType, assignment.getSource(), Comment.NO_COMMENTS));
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
index 76affac0d..58cbc1719 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java
@@ -92,6 +92,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
                constScope,
                variableType,
                constVal);
+         constantVar.setInferredType(variable.isInferredType());
          constantVar.setDeclaredAlignment(variable.getDeclaredAlignment());
          constantVar.setDeclaredRegister(variable.getDeclaredRegister());
          if(variable.getComments().size() > 0) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java
index 4686b3df3..801a63bb4 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java
@@ -33,8 +33,9 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
    @Override
    public boolean step() {
       Map<ConstantRef, ConstantValue> inline = new HashMap<>();
+      Map<ConstantRef, ConstantValue> aliasConstants = findAliasConstants();
+      inline.putAll(aliasConstants);
       inline.putAll(findUnnamedConstants());
-      inline.putAll(findAliasConstants());
       inline.putAll(findConstVarVersions());
 
       // Remove all string constants
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java b/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java
index 2b0b96cce..267a085ab 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2DeInlineWordDerefIdx.java
@@ -42,7 +42,7 @@ public class Pass2DeInlineWordDerefIdx extends Pass2SsaOptimization {
                stmtIt.next();
                programValue.set(new PointerDereferenceSimple(tmpVar.getRef()));
                SymbolType pointerType = SymbolTypeInference.inferType(getScope(), new AssignmentRValue(tmpVarAssignment));
-               tmpVar.setType(pointerType);
+               tmpVar.setTypeInferred(pointerType);
                optimized.set(true);
             }
          }
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
index dcc576213..7f05fe4f3 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -40,6 +40,7 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
                if(SymbolType.NUMBER.equals(rightType)) {
                   getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
                   binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+
                   modified.set(true);
                }
             }
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java b/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java
index 5661a8624..743d7cfe1 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNCastSimplification.java
@@ -11,10 +11,11 @@ import dk.camelot64.kickc.model.values.RValue;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
-/** Simplifies casts
+/**
+ * Simplifies casts
  * - Inlines casts of (number) constants
  * - Removes unnecessary casts
- * */
+ */
 public class PassNCastSimplification extends Pass2SsaOptimization {
 
    public PassNCastSimplification(Program program) {
@@ -39,12 +40,12 @@ public class PassNCastSimplification extends Pass2SsaOptimization {
             } else if(unaryOperand instanceof ConstantInteger) {
                ConstantInteger constantInteger = (ConstantInteger) unaryOperand;
                if(SymbolType.NUMBER.equals(constantInteger.getType())) {
-                  if(castType instanceof SymbolTypeIntegerFixed ) {
+                  if(castType instanceof SymbolTypeIntegerFixed || SymbolType.UNUMBER.equals(castType) || SymbolType.SNUMBER.equals(castType)) {
                      ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
                      programExpression.set(newConstInt);
                      getLog().append("Simplifying constant integer cast " + newConstInt.toString());
                      optimized.set(true);
-                  }  else if(castType instanceof SymbolTypePointer) {
+                  } else if(castType instanceof SymbolTypePointer) {
                      ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType());
                      programExpression.set(newConstPointer);
                      getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java
new file mode 100644
index 000000000..76b2b33a3
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java
@@ -0,0 +1,65 @@
+package dk.camelot64.kickc.passes;
+
+import dk.camelot64.kickc.model.InternalError;
+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.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeConversion;
+import dk.camelot64.kickc.model.values.*;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Finalize any constant integers to the smallest fixed size signed/unsigned type - if they have been resolved as snumber/unumber.
+ */
+public class PassNFinalizeNumberTypeConversions extends Pass2SsaOptimization {
+
+   public PassNFinalizeNumberTypeConversions(Program program) {
+      super(program);
+   }
+
+   @Override
+   public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
+      ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
+         if(programValue.get() instanceof ConstantInteger) {
+            ConstantInteger constantInteger = (ConstantInteger) programValue.get();
+            if(SymbolType.UNUMBER.equals(constantInteger.getType())) {
+               SymbolType integerType = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(constantInteger, getScope());
+               programValue.set(new ConstantInteger(constantInteger.getValue(), integerType));
+               getLog().append("Finalized unsigned number type "+programValue.get().toString(getProgram()));
+               modified.set(true);
+            } else  if(SymbolType.SNUMBER.equals(constantInteger.getType())) {
+               SymbolType integerType = SymbolTypeConversion.getSmallestSignedFixedIntegerType(constantInteger, getScope());
+               programValue.set(new ConstantInteger(constantInteger.getValue(), integerType));
+               getLog().append("Finalized signed number type "+programValue.get().toString(getProgram()));
+               modified.set(true);
+            }
+         } else if(programValue.get() instanceof ConstantCastValue) {
+            ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get();
+            SymbolType toType = constantCastValue.getToType();
+            if(SymbolType.UNUMBER.equals(toType)) {
+               if(constantCastValue.getValue() instanceof ConstantRef) {
+                  ConstantRef constRef = (ConstantRef) constantCastValue.getValue();
+                  ConstantVar constant = getScope().getConstant(constRef);
+                  if(constant.isInferredType())
+                     constant.setTypeInferred(toType);
+                  else
+                     throw new InternalError("Cannot cast declared type!" + constant.toString());
+               } else {
+                  ConstantLiteral constantLiteral = constantCastValue.getValue().calculateLiteral(getProgram().getScope());
+                  SymbolType smallestUnsigned = SymbolTypeConversion.getSmallestUnsignedFixedIntegerType(constantLiteral, getScope());
+                  if(smallestUnsigned!=null) {
+                     constantCastValue.setToType(smallestUnsigned);
+                  }
+               }
+            }
+            if(SymbolType.SNUMBER.equals(toType))
+               throw new InternalError("TODO: Finalize ConstantCast");
+         }
+      });
+      return modified.get();
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
index 4e135e916..39c586a4e 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java
@@ -60,7 +60,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       LValue lValue = call.getlValue();
       if(lValue instanceof VariableRef) {
          Variable symbol = programScope.getVariable((VariableRef) lValue);
-         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
             Procedure procedure = programScope.getProcedure(call.getProcedure());
             SymbolType type = procedure.getReturnType();
             setInferedType(program, call, symbol, type);
@@ -73,7 +73,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       LValue lValue = call.getlValue();
       if(lValue instanceof VariableRef) {
          Variable symbol = programScope.getVariable((VariableRef) lValue);
-         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
             SymbolType procedureType = SymbolTypeInference.inferType(programScope, call.getProcedure());
             if(procedureType instanceof SymbolTypeProcedure) {
                SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType();
@@ -86,7 +86,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
    private static void updateInferedTypePhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) {
       ProgramScope programScope = program.getScope();
       Variable symbol = programScope.getVariable(phiVariable.getVariable());
-      if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
+      if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType())|| SymbolType.SNUMBER.equals(symbol.getType())) {
          SymbolType type = null;
          for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
             RValue rValue = phiRValue.getrValue();
@@ -112,7 +112,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
       LValue lValue = assignment.getlValue();
       if(lValue instanceof VariableRef) {
          Variable symbol = programScope.getVariable((VariableRef) lValue);
-         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
+         if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())|| SymbolType.UNUMBER.equals(symbol.getType()) || SymbolType.SNUMBER.equals(symbol.getType())) {
             SymbolType type = SymbolTypeInference.inferType(programScope, new AssignmentRValue(assignment));
             setInferedType(program, assignment, symbol, type);
             // If the type is an array or a string the symbol is constant
diff --git a/src/test/kc/sandbox.kc b/src/test/kc/sandbox.kc
index 3ff3ae112..d84bb18f5 100644
--- a/src/test/kc/sandbox.kc
+++ b/src/test/kc/sandbox.kc
@@ -48,10 +48,10 @@ byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) {
 				if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' '; 
             } else if (b == 'x' || b == 'X'){ // hex
 				b = ((byte)w >> 4) & 0xF;
-				dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b;
+				dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
 				// "('a' - 10)" is the normal way -- not supported  -- https://gitlab.com/camelot/kickc/issues/184 [FIXED]
 				// (b < 10 ? '0' : 0x57) not supported
-				b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57ub) + b;
+				b = (byte)w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
 			}
             bFormat = 0;
 			continue;
diff --git a/src/test/kc/ternary-inference.kc b/src/test/kc/ternary-inference.kc
index 4f6e29973..30b892c79 100644
--- a/src/test/kc/ternary-inference.kc
+++ b/src/test/kc/ternary-inference.kc
@@ -3,6 +3,6 @@
 void main() {
     const byte* screen = 0x400;
     for(byte i: 0..10) {
-        screen[i] = (i<5?0x57ub:'0')+i;
+        screen[i] = (i<5?0x57:'0')+i;
     }
 }
\ No newline at end of file

From c42156c4e982b6f5862a306299435d98b1975212 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Fri, 24 May 2019 00:52:30 +0200
Subject: [PATCH 84/93] Working in unumber/snumber. Updated test files.

---
 src/test/ref/complex/tetris/tetris.asm |  1 +
 src/test/ref/examples/fire/fire.asm    | 12 ++++----
 src/test/ref/test-scroll-up.asm        | 42 +++++++++++++-------------
 src/test/ref/test-word-size-arrays.asm | 36 +++++++++++-----------
 4 files changed, 46 insertions(+), 45 deletions(-)

diff --git a/src/test/ref/complex/tetris/tetris.asm b/src/test/ref/complex/tetris/tetris.asm
index df178a3ac..ce2a47921 100644
--- a/src/test/ref/complex/tetris/tetris.asm
+++ b/src/test/ref/complex/tetris/tetris.asm
@@ -388,6 +388,7 @@ render_bcd: {
 }
 // Render the next tetromino in the "next" area
 render_next: {
+    // Find the screen area
     .const next_area_offset = $28*$c+$18+4
     .label next_piece_gfx = 5
     .label next_piece_char = $a
diff --git a/src/test/ref/examples/fire/fire.asm b/src/test/ref/examples/fire/fire.asm
index d14cf06e3..77c8919c1 100644
--- a/src/test/ref/examples/fire/fire.asm
+++ b/src/test/ref/examples/fire/fire.asm
@@ -182,7 +182,7 @@ makecharset: {
     .label ii = $a
     .label i = 9
     .label c = 8
-    .label _22 = 2
+    .label _26 = 2
     lda #<CHARSET
     sta font
     lda #>CHARSET
@@ -272,15 +272,15 @@ makecharset: {
     inc _19+1
   !:
     clc
-    lda _22
+    lda _26
     adc #<CHARSET+1*8
-    sta _22
-    lda _22+1
+    sta _26
+    lda _26+1
     adc #>CHARSET+1*8
-    sta _22+1
+    sta _26+1
     tya
     ldy #0
-    sta (_22),y
+    sta (_26),y
     inc i
     lda i
     cmp #8
diff --git a/src/test/ref/test-scroll-up.asm b/src/test/ref/test-scroll-up.asm
index 15c85f776..7e9d7c1b9 100644
--- a/src/test/ref/test-scroll-up.asm
+++ b/src/test/ref/test-scroll-up.asm
@@ -14,8 +14,8 @@ scrollup3: {
     .label l2_1 = 4
     .label line = 2
     .label l2_2 = 4
-    .label _4 = 7
-    .label _5 = 9
+    .label _5 = 7
+    .label _6 = 9
     .label l2_4 = 4
     lda #0
     sta l2
@@ -30,20 +30,20 @@ scrollup3: {
     lda l2_2
     clc
     adc #<screen+$28
-    sta _4
+    sta _5
     lda l2_2+1
     adc #>screen+$28
-    sta _4+1
+    sta _5+1
     lda l2_2
     clc
     adc #<screen
-    sta _5
+    sta _6
     lda l2_2+1
     adc #>screen
-    sta _5+1
+    sta _6+1
     ldy #0
-    lda (_4),y
-    sta (_5),y
+    lda (_5),y
+    sta (_6),y
     inc l2_1
     bne !+
     inc l2_1+1
@@ -109,8 +109,8 @@ scrollup1: {
     .label _0 = 4
     .label _2 = 7
     .label line = 2
-    .label _6 = 7
-    .label _7 = 4
+    .label _7 = 7
+    .label _8 = 4
     lda #0
     sta line
     sta line+1
@@ -132,22 +132,22 @@ scrollup1: {
     adc line+1
     sta _2+1
     clc
-    lda _6
-    adc #<screen+$28
-    sta _6
-    lda _6+1
-    adc #>screen+$28
-    sta _6+1
-    clc
     lda _7
-    adc #<screen
+    adc #<screen+$28
     sta _7
     lda _7+1
-    adc #>screen
+    adc #>screen+$28
     sta _7+1
+    clc
+    lda _8
+    adc #<screen
+    sta _8
+    lda _8+1
+    adc #>screen
+    sta _8+1
     ldy #0
-    lda (_6),y
-    sta (_7),y
+    lda (_7),y
+    sta (_8),y
     inx
     cpx #$28
     bcc b2
diff --git a/src/test/ref/test-word-size-arrays.asm b/src/test/ref/test-word-size-arrays.asm
index 34f29fa59..93a40e061 100644
--- a/src/test/ref/test-word-size-arrays.asm
+++ b/src/test/ref/test-word-size-arrays.asm
@@ -7,9 +7,9 @@ main: {
     .label _2 = 6
     .label _6 = 4
     .label line = 2
-    .label _8 = 6
-    .label _9 = 4
+    .label _9 = 6
     .label _10 = 4
+    .label _11 = 4
     lda #0
     sta line
     sta line+1
@@ -31,22 +31,22 @@ main: {
     adc line+1
     sta _2+1
     clc
-    lda _8
-    adc #<screen+$28
-    sta _8
-    lda _8+1
-    adc #>screen+$28
-    sta _8+1
-    clc
     lda _9
-    adc #<screen
+    adc #<screen+$28
     sta _9
     lda _9+1
-    adc #>screen
+    adc #>screen+$28
     sta _9+1
+    clc
+    lda _10
+    adc #<screen
+    sta _10
+    lda _10+1
+    adc #>screen
+    sta _10+1
     ldy #0
-    lda (_8),y
-    sta (_9),y
+    lda (_9),y
+    sta (_10),y
     inx
     cpx #$28
     bcc b2
@@ -76,15 +76,15 @@ main: {
     adc line+1
     sta _6+1
     clc
-    lda _10
+    lda _11
     adc #<screen
-    sta _10
-    lda _10+1
+    sta _11
+    lda _11+1
     adc #>screen
-    sta _10+1
+    sta _11+1
     lda #' '
     ldy #0
-    sta (_10),y
+    sta (_11),y
     inx
     cpx #$28
     bcc b4

From 999afdcbc725809dca40b77ae6e4d3d7fca75365 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Fri, 24 May 2019 09:02:31 +0200
Subject: [PATCH 85/93] Fixed 2/3. One remaining!

---
 .../PassNFinalizeNumberTypeConversions.java     | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java
index 76b2b33a3..b4f45b8f9 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNFinalizeNumberTypeConversions.java
@@ -54,9 +54,22 @@ public class PassNFinalizeNumberTypeConversions extends Pass2SsaOptimization {
                      constantCastValue.setToType(smallestUnsigned);
                   }
                }
+            } else if(SymbolType.SNUMBER.equals(toType)) {
+               if(constantCastValue.getValue() instanceof ConstantRef) {
+                  ConstantRef constRef = (ConstantRef) constantCastValue.getValue();
+                  ConstantVar constant = getScope().getConstant(constRef);
+                  if(constant.isInferredType())
+                     constant.setTypeInferred(toType);
+                  else
+                     throw new InternalError("Cannot cast declared type!" + constant.toString());
+               } else {
+                  ConstantLiteral constantLiteral = constantCastValue.getValue().calculateLiteral(getProgram().getScope());
+                  SymbolType smallestSigned = SymbolTypeConversion.getSmallestSignedFixedIntegerType(constantLiteral, getScope());
+                  if(smallestSigned!=null) {
+                     constantCastValue.setToType(smallestSigned);
+                  }
+               }
             }
-            if(SymbolType.SNUMBER.equals(toType))
-               throw new InternalError("TODO: Finalize ConstantCast");
          }
       });
       return modified.get();

From 3376a462fc80e4cc70c22223dec56a07fcdb47d3 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Fri, 24 May 2019 18:02:42 +0200
Subject: [PATCH 86/93] Fixed number range test

---
 src/test/kc/invalid-consttype.kc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/test/kc/invalid-consttype.kc b/src/test/kc/invalid-consttype.kc
index 3fcef26c4..fb4c21b72 100644
--- a/src/test/kc/invalid-consttype.kc
+++ b/src/test/kc/invalid-consttype.kc
@@ -1,5 +1,5 @@
 void main() {
-    signed byte b = -127-127;
+    signed byte b = -400;
     byte* SCREEN = $0400;
     *SCREEN = (byte)b;
 }
\ No newline at end of file

From e46fd03ec57bf60923bd7683ba03699beb3806f7 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Fri, 24 May 2019 20:57:43 +0200
Subject: [PATCH 87/93] Added support for string concatenation C style (using
 simple space separation).

Fixed tests.
---
 .../java/dk/camelot64/kickc/parser/KickC.g4   |   2 +-
 .../kickc/parser/KickCBaseListener.java       |   2 +-
 .../kickc/parser/KickCBaseVisitor.java        |   2 +-
 .../dk/camelot64/kickc/parser/KickCLexer.java |   2 +-
 .../camelot64/kickc/parser/KickCListener.java |   2 +-
 .../camelot64/kickc/parser/KickCParser.java   | 773 +++++++++---------
 .../camelot64/kickc/parser/KickCVisitor.java  |   2 +-
 .../Pass0GenerateStatementSequence.java       |  18 +-
 .../dk/camelot64/kickc/test/TestPrograms.java |  33 +-
 src/test/kc/c64dtv-gfxexplorer.kc             |  66 +-
 src/test/kc/c64dtv-gfxmodes.kc                |  43 +-
 src/test/kc/concat-char.kc                    |  10 -
 src/test/kc/constant-string-concat-0.kc       |   8 +
 src/test/kc/constant-string-concat.kc         |  11 +-
 src/test/kc/literals.kc                       |   2 +-
 src/test/ref/c64dtv-gfxexplorer.asm           | 601 +++++++-------
 src/test/ref/c64dtv-gfxmodes.asm              |  94 +--
 src/test/ref/concat-char.asm                  |  16 -
 src/test/ref/concat-char.cfg                  |  21 -
 src/test/ref/concat-char.log                  | 338 --------
 src/test/ref/concat-char.sym                  |  16 -
 src/test/ref/constant-string-concat-0.asm     |  17 +
 src/test/ref/constant-string-concat.asm       |   7 +-
 src/test/ref/literals.asm                     |   2 +-
 24 files changed, 848 insertions(+), 1240 deletions(-)
 delete mode 100644 src/test/kc/concat-char.kc
 create mode 100644 src/test/kc/constant-string-concat-0.kc
 delete mode 100644 src/test/ref/concat-char.asm
 delete mode 100644 src/test/ref/concat-char.cfg
 delete mode 100644 src/test/ref/concat-char.log
 delete mode 100644 src/test/ref/concat-char.sym
 create mode 100644 src/test/ref/constant-string-concat-0.asm

diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4
index 9c0cbfe03..a30ea0b67 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4
+++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4
@@ -146,7 +146,7 @@ expr
     | '{' expr (',' expr )* '}' #initList
     | NAME  #exprId
     | NUMBER #exprNumber
-    | STRING #exprString
+    | STRING+ #exprString
     | CHAR #exprChar
     | BOOLEAN #exprBool
     ;
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
index 64996623d..02bba947a 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
@@ -1,4 +1,4 @@
-// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
+// Generated from C:/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;
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
index 984232061..709766578 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
@@ -1,4 +1,4 @@
-// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
+// Generated from C:/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;
 
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
index 4b9fc4407..951b0e72e 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
@@ -1,4 +1,4 @@
-// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
+// Generated from C:/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;
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
index aef2c95a7..54517c054 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
@@ -1,4 +1,4 @@
-// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
+// Generated from C:/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;
 
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
index 383fd8a0a..807940f33 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
@@ -1,4 +1,4 @@
-// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
+// Generated from C:/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.atn.*;
 import org.antlr.v4.runtime.dfa.DFA;
@@ -2820,7 +2820,10 @@ public class KickCParser extends Parser {
 		}
 	}
 	public static class ExprStringContext extends ExprContext {
-		public TerminalNode STRING() { return getToken(KickCParser.STRING, 0); }
+		public List<TerminalNode> STRING() { return getTokens(KickCParser.STRING); }
+		public TerminalNode STRING(int i) {
+			return getToken(KickCParser.STRING, i);
+		}
 		public ExprStringContext(ExprContext ctx) { copyFrom(ctx); }
 		@Override
 		public void enterRule(ParseTreeListener listener) {
@@ -2975,9 +2978,9 @@ public class KickCParser extends Parser {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(388);
+			setState(392);
 			_errHandler.sync(this);
-			switch ( getInterpreter().adaptivePredict(_input,37,_ctx) ) {
+			switch ( getInterpreter().adaptivePredict(_input,38,_ctx) ) {
 			case 1:
 				{
 				_localctx = new ExprParContext(_localctx);
@@ -3185,8 +3188,26 @@ public class KickCParser extends Parser {
 				_localctx = new ExprStringContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(385);
-				match(STRING);
+				setState(386); 
+				_errHandler.sync(this);
+				_alt = 1;
+				do {
+					switch (_alt) {
+					case 1:
+						{
+						{
+						setState(385);
+						match(STRING);
+						}
+						}
+						break;
+					default:
+						throw new NoViableAltException(this);
+					}
+					setState(388); 
+					_errHandler.sync(this);
+					_alt = getInterpreter().adaptivePredict(_input,37,_ctx);
+				} while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER );
 				}
 				break;
 			case 13:
@@ -3194,7 +3215,7 @@ public class KickCParser extends Parser {
 				_localctx = new ExprCharContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(386);
+				setState(390);
 				match(CHAR);
 				}
 				break;
@@ -3203,30 +3224,30 @@ public class KickCParser extends Parser {
 				_localctx = new ExprBoolContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(387);
+				setState(391);
 				match(BOOLEAN);
 				}
 				break;
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(444);
+			setState(448);
 			_errHandler.sync(this);
-			_alt = getInterpreter().adaptivePredict(_input,40,_ctx);
+			_alt = getInterpreter().adaptivePredict(_input,41,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 				if ( _alt==1 ) {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
 					_prevctx = _localctx;
 					{
-					setState(442);
+					setState(446);
 					_errHandler.sync(this);
-					switch ( getInterpreter().adaptivePredict(_input,39,_ctx) ) {
+					switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) {
 					case 1:
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(390);
+						setState(394);
 						if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)");
-						setState(391);
+						setState(395);
 						_la = _input.LA(1);
 						if ( !(_la==T__41 || _la==T__42) ) {
 						_errHandler.recoverInline(this);
@@ -3236,7 +3257,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(392);
+						setState(396);
 						expr(20);
 						}
 						break;
@@ -3244,9 +3265,9 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(393);
+						setState(397);
 						if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)");
-						setState(394);
+						setState(398);
 						_la = _input.LA(1);
 						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__43) | (1L << T__44))) != 0)) ) {
 						_errHandler.recoverInline(this);
@@ -3256,7 +3277,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(395);
+						setState(399);
 						expr(19);
 						}
 						break;
@@ -3264,9 +3285,9 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(396);
+						setState(400);
 						if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)");
-						setState(397);
+						setState(401);
 						_la = _input.LA(1);
 						if ( !(_la==T__36 || _la==T__37) ) {
 						_errHandler.recoverInline(this);
@@ -3276,7 +3297,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(398);
+						setState(402);
 						expr(18);
 						}
 						break;
@@ -3284,9 +3305,9 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(399);
+						setState(403);
 						if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)");
-						setState(400);
+						setState(404);
 						_la = _input.LA(1);
 						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__45) | (1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50))) != 0)) ) {
 						_errHandler.recoverInline(this);
@@ -3296,7 +3317,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(401);
+						setState(405);
 						expr(16);
 						}
 						break;
@@ -3304,13 +3325,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(402);
+						setState(406);
 						if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)");
 						{
-						setState(403);
+						setState(407);
 						match(T__39);
 						}
-						setState(404);
+						setState(408);
 						expr(15);
 						}
 						break;
@@ -3318,13 +3339,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(405);
+						setState(409);
 						if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)");
 						{
-						setState(406);
+						setState(410);
 						match(T__51);
 						}
-						setState(407);
+						setState(411);
 						expr(14);
 						}
 						break;
@@ -3332,13 +3353,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(408);
+						setState(412);
 						if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
 						{
-						setState(409);
+						setState(413);
 						match(T__52);
 						}
-						setState(410);
+						setState(414);
 						expr(13);
 						}
 						break;
@@ -3346,13 +3367,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(411);
+						setState(415);
 						if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)");
 						{
-						setState(412);
+						setState(416);
 						match(T__53);
 						}
-						setState(413);
+						setState(417);
 						expr(12);
 						}
 						break;
@@ -3360,13 +3381,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(414);
+						setState(418);
 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
 						{
-						setState(415);
+						setState(419);
 						match(T__54);
 						}
-						setState(416);
+						setState(420);
 						expr(11);
 						}
 						break;
@@ -3374,15 +3395,15 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprTernaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(417);
-						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
-						setState(418);
-						match(T__55);
-						setState(419);
-						expr(0);
-						setState(420);
-						match(T__25);
 						setState(421);
+						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
+						setState(422);
+						match(T__55);
+						setState(423);
+						expr(0);
+						setState(424);
+						match(T__25);
+						setState(425);
 						expr(10);
 						}
 						break;
@@ -3390,11 +3411,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprAssignmentContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(423);
+						setState(427);
 						if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
-						setState(424);
+						setState(428);
 						match(T__3);
-						setState(425);
+						setState(429);
 						expr(8);
 						}
 						break;
@@ -3402,9 +3423,9 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprAssignmentCompoundContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(426);
+						setState(430);
 						if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
-						setState(427);
+						setState(431);
 						_la = _input.LA(1);
 						if ( !(((((_la - 57)) & ~0x3f) == 0 && ((1L << (_la - 57)) & ((1L << (T__56 - 57)) | (1L << (T__57 - 57)) | (1L << (T__58 - 57)) | (1L << (T__59 - 57)) | (1L << (T__60 - 57)) | (1L << (T__61 - 57)) | (1L << (T__62 - 57)) | (1L << (T__63 - 57)) | (1L << (T__64 - 57)) | (1L << (T__65 - 57)))) != 0)) ) {
 						_errHandler.recoverInline(this);
@@ -3414,7 +3435,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(428);
+						setState(432);
 						expr(7);
 						}
 						break;
@@ -3422,21 +3443,21 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(429);
+						setState(433);
 						if (!(precpred(_ctx, 28))) throw new FailedPredicateException(this, "precpred(_ctx, 28)");
-						setState(430);
+						setState(434);
 						match(T__4);
-						setState(432);
+						setState(436);
 						_errHandler.sync(this);
 						_la = _input.LA(1);
 						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) {
 							{
-							setState(431);
+							setState(435);
 							parameterList();
 							}
 						}
 
-						setState(434);
+						setState(438);
 						match(T__5);
 						}
 						break;
@@ -3444,13 +3465,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(435);
+						setState(439);
 						if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)");
-						setState(436);
+						setState(440);
 						match(T__30);
-						setState(437);
+						setState(441);
 						commaExpr(0);
-						setState(438);
+						setState(442);
 						match(T__31);
 						}
 						break;
@@ -3458,9 +3479,9 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(440);
+						setState(444);
 						if (!(precpred(_ctx, 22))) throw new FailedPredicateException(this, "precpred(_ctx, 22)");
-						setState(441);
+						setState(445);
 						_la = _input.LA(1);
 						if ( !(_la==T__34 || _la==T__35) ) {
 						_errHandler.recoverInline(this);
@@ -3475,9 +3496,9 @@ public class KickCParser extends Parser {
 					}
 					} 
 				}
-				setState(446);
+				setState(450);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,40,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,41,_ctx);
 			}
 			}
 		}
@@ -3525,21 +3546,21 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(447);
+			setState(451);
 			expr(0);
-			setState(452);
+			setState(456);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(448);
+				setState(452);
 				match(T__2);
-				setState(449);
+				setState(453);
 				expr(0);
 				}
 				}
-				setState(454);
+				setState(458);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -3587,19 +3608,19 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(455);
+			setState(459);
 			match(T__66);
-			setState(457);
+			setState(461);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			if (_la==T__4) {
 				{
-				setState(456);
+				setState(460);
 				asmDirectives();
 				}
 			}
 
-			setState(459);
+			setState(463);
 			match(KICKASM);
 			}
 		}
@@ -3647,27 +3668,27 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(461);
+			setState(465);
 			match(T__4);
-			setState(462);
+			setState(466);
 			asmDirective();
-			setState(467);
+			setState(471);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(463);
+				setState(467);
 				match(T__2);
-				setState(464);
+				setState(468);
 				asmDirective();
 				}
 				}
-				setState(469);
+				setState(473);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
-			setState(470);
+			setState(474);
 			match(T__5);
 			}
 		}
@@ -3806,16 +3827,16 @@ public class KickCParser extends Parser {
 		AsmDirectiveContext _localctx = new AsmDirectiveContext(_ctx, getState());
 		enterRule(_localctx, 52, RULE_asmDirective);
 		try {
-			setState(487);
+			setState(491);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case T__67:
 				_localctx = new AsmDirectiveResourceContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(472);
+				setState(476);
 				match(T__67);
-				setState(473);
+				setState(477);
 				match(STRING);
 				}
 				break;
@@ -3823,9 +3844,9 @@ public class KickCParser extends Parser {
 				_localctx = new AsmDirectiveUsesContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(474);
+				setState(478);
 				match(T__68);
-				setState(475);
+				setState(479);
 				match(NAME);
 				}
 				break;
@@ -3833,9 +3854,9 @@ public class KickCParser extends Parser {
 				_localctx = new AsmDirectiveClobberContext(_localctx);
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(476);
+				setState(480);
 				match(T__69);
-				setState(477);
+				setState(481);
 				match(STRING);
 				}
 				break;
@@ -3843,9 +3864,9 @@ public class KickCParser extends Parser {
 				_localctx = new AsmDirectiveBytesContext(_localctx);
 				enterOuterAlt(_localctx, 4);
 				{
-				setState(478);
+				setState(482);
 				match(T__70);
-				setState(479);
+				setState(483);
 				expr(0);
 				}
 				break;
@@ -3853,9 +3874,9 @@ public class KickCParser extends Parser {
 				_localctx = new AsmDirectiveCyclesContext(_localctx);
 				enterOuterAlt(_localctx, 5);
 				{
-				setState(480);
+				setState(484);
 				match(T__71);
-				setState(481);
+				setState(485);
 				expr(0);
 				}
 				break;
@@ -3863,14 +3884,14 @@ public class KickCParser extends Parser {
 				_localctx = new AsmDirectiveAddressContext(_localctx);
 				enterOuterAlt(_localctx, 6);
 				{
-				setState(482);
+				setState(486);
 				match(T__72);
-				setState(485);
+				setState(489);
 				_errHandler.sync(this);
 				switch (_input.LA(1)) {
 				case T__12:
 					{
-					setState(483);
+					setState(487);
 					match(T__12);
 					}
 					break;
@@ -3894,7 +3915,7 @@ public class KickCParser extends Parser {
 				case NUMBER:
 				case NAME:
 					{
-					setState(484);
+					setState(488);
 					expr(0);
 					}
 					break;
@@ -3951,17 +3972,17 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(492);
+			setState(496);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (((((_la - 39)) & ~0x3f) == 0 && ((1L << (_la - 39)) & ((1L << (T__38 - 39)) | (1L << (T__73 - 39)) | (1L << (MNEMONIC - 39)) | (1L << (NAME - 39)))) != 0)) {
 				{
 				{
-				setState(489);
+				setState(493);
 				asmLine();
 				}
 				}
-				setState(494);
+				setState(498);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -4011,28 +4032,28 @@ public class KickCParser extends Parser {
 		AsmLineContext _localctx = new AsmLineContext(_ctx, getState());
 		enterRule(_localctx, 56, RULE_asmLine);
 		try {
-			setState(498);
+			setState(502);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case T__38:
 			case NAME:
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(495);
+				setState(499);
 				asmLabel();
 				}
 				break;
 			case MNEMONIC:
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(496);
+				setState(500);
 				asmInstruction();
 				}
 				break;
 			case T__73:
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(497);
+				setState(501);
 				asmBytes();
 				}
 				break;
@@ -4102,16 +4123,16 @@ public class KickCParser extends Parser {
 		enterRule(_localctx, 58, RULE_asmLabel);
 		int _la;
 		try {
-			setState(507);
+			setState(511);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case NAME:
 				_localctx = new AsmLabelNameContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(500);
+				setState(504);
 				match(NAME);
-				setState(501);
+				setState(505);
 				match(T__25);
 				}
 				break;
@@ -4119,19 +4140,19 @@ public class KickCParser extends Parser {
 				_localctx = new AsmLabelMultiContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(502);
+				setState(506);
 				match(T__38);
-				setState(504);
+				setState(508);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				if (_la==NAME) {
 					{
-					setState(503);
+					setState(507);
 					match(NAME);
 					}
 				}
 
-				setState(506);
+				setState(510);
 				match(T__25);
 				}
 				break;
@@ -4180,14 +4201,14 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(509);
+			setState(513);
 			match(MNEMONIC);
-			setState(511);
+			setState(515);
 			_errHandler.sync(this);
-			switch ( getInterpreter().adaptivePredict(_input,50,_ctx) ) {
+			switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) {
 			case 1:
 				{
-				setState(510);
+				setState(514);
 				asmParamMode();
 				}
 				break;
@@ -4238,23 +4259,23 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(513);
+			setState(517);
 			match(T__73);
-			setState(514);
+			setState(518);
 			asmExpr(0);
-			setState(519);
+			setState(523);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(515);
+				setState(519);
 				match(T__2);
-				setState(516);
+				setState(520);
 				asmExpr(0);
 				}
 				}
-				setState(521);
+				setState(525);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -4404,14 +4425,14 @@ public class KickCParser extends Parser {
 		AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState());
 		enterRule(_localctx, 64, RULE_asmParamMode);
 		try {
-			setState(545);
+			setState(549);
 			_errHandler.sync(this);
-			switch ( getInterpreter().adaptivePredict(_input,52,_ctx) ) {
+			switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) {
 			case 1:
 				_localctx = new AsmModeAbsContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(522);
+				setState(526);
 				asmExpr(0);
 				}
 				break;
@@ -4419,9 +4440,9 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeImmContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(523);
+				setState(527);
 				match(T__74);
-				setState(524);
+				setState(528);
 				asmExpr(0);
 				}
 				break;
@@ -4429,11 +4450,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeAbsXYContext(_localctx);
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(525);
+				setState(529);
 				asmExpr(0);
-				setState(526);
+				setState(530);
 				match(T__2);
-				setState(527);
+				setState(531);
 				match(NAME);
 				}
 				break;
@@ -4441,15 +4462,15 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIndIdxXYContext(_localctx);
 				enterOuterAlt(_localctx, 4);
 				{
-				setState(529);
-				match(T__4);
-				setState(530);
-				asmExpr(0);
-				setState(531);
-				match(T__5);
-				setState(532);
-				match(T__2);
 				setState(533);
+				match(T__4);
+				setState(534);
+				asmExpr(0);
+				setState(535);
+				match(T__5);
+				setState(536);
+				match(T__2);
+				setState(537);
 				match(NAME);
 				}
 				break;
@@ -4457,15 +4478,15 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIdxIndXYContext(_localctx);
 				enterOuterAlt(_localctx, 5);
 				{
-				setState(535);
-				match(T__4);
-				setState(536);
-				asmExpr(0);
-				setState(537);
-				match(T__2);
-				setState(538);
-				match(NAME);
 				setState(539);
+				match(T__4);
+				setState(540);
+				asmExpr(0);
+				setState(541);
+				match(T__2);
+				setState(542);
+				match(NAME);
+				setState(543);
 				match(T__5);
 				}
 				break;
@@ -4473,11 +4494,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIndContext(_localctx);
 				enterOuterAlt(_localctx, 6);
 				{
-				setState(541);
+				setState(545);
 				match(T__4);
-				setState(542);
+				setState(546);
 				asmExpr(0);
-				setState(543);
+				setState(547);
 				match(T__5);
 				}
 				break;
@@ -4667,7 +4688,7 @@ public class KickCParser extends Parser {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(561);
+			setState(565);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case T__30:
@@ -4676,11 +4697,11 @@ public class KickCParser extends Parser {
 				_ctx = _localctx;
 				_prevctx = _localctx;
 
-				setState(548);
+				setState(552);
 				match(T__30);
-				setState(549);
+				setState(553);
 				asmExpr(0);
-				setState(550);
+				setState(554);
 				match(T__31);
 				}
 				break;
@@ -4692,7 +4713,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprUnaryContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(552);
+				setState(556);
 				_la = _input.LA(1);
 				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__36) | (1L << T__37) | (1L << T__45) | (1L << T__46))) != 0)) ) {
 				_errHandler.recoverInline(this);
@@ -4702,7 +4723,7 @@ public class KickCParser extends Parser {
 					_errHandler.reportMatch(this);
 					consume();
 				}
-				setState(553);
+				setState(557);
 				asmExpr(8);
 				}
 				break;
@@ -4711,7 +4732,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprLabelContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(554);
+				setState(558);
 				match(NAME);
 				}
 				break;
@@ -4720,7 +4741,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprLabelRelContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(555);
+				setState(559);
 				match(ASMREL);
 				}
 				break;
@@ -4729,11 +4750,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprReplaceContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(556);
+				setState(560);
 				match(T__6);
-				setState(557);
+				setState(561);
 				match(NAME);
-				setState(558);
+				setState(562);
 				match(T__7);
 				}
 				break;
@@ -4742,7 +4763,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprIntContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(559);
+				setState(563);
 				match(NUMBER);
 				}
 				break;
@@ -4751,7 +4772,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprCharContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(560);
+				setState(564);
 				match(CHAR);
 				}
 				break;
@@ -4759,28 +4780,28 @@ public class KickCParser extends Parser {
 				throw new NoViableAltException(this);
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(577);
+			setState(581);
 			_errHandler.sync(this);
-			_alt = getInterpreter().adaptivePredict(_input,55,_ctx);
+			_alt = getInterpreter().adaptivePredict(_input,56,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 				if ( _alt==1 ) {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
 					_prevctx = _localctx;
 					{
-					setState(575);
+					setState(579);
 					_errHandler.sync(this);
-					switch ( getInterpreter().adaptivePredict(_input,54,_ctx) ) {
+					switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) {
 					case 1:
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(563);
+						setState(567);
 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
 						{
-						setState(564);
+						setState(568);
 						match(T__75);
 						}
-						setState(565);
+						setState(569);
 						asmExpr(11);
 						}
 						break;
@@ -4788,9 +4809,9 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(566);
+						setState(570);
 						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
-						setState(567);
+						setState(571);
 						_la = _input.LA(1);
 						if ( !(_la==T__41 || _la==T__42) ) {
 						_errHandler.recoverInline(this);
@@ -4800,7 +4821,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(568);
+						setState(572);
 						asmExpr(10);
 						}
 						break;
@@ -4808,9 +4829,9 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(569);
+						setState(573);
 						if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
-						setState(570);
+						setState(574);
 						_la = _input.LA(1);
 						if ( !(_la==T__29 || _la==T__43) ) {
 						_errHandler.recoverInline(this);
@@ -4820,7 +4841,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(571);
+						setState(575);
 						asmExpr(8);
 						}
 						break;
@@ -4828,9 +4849,9 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(572);
+						setState(576);
 						if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
-						setState(573);
+						setState(577);
 						_la = _input.LA(1);
 						if ( !(_la==T__36 || _la==T__37) ) {
 						_errHandler.recoverInline(this);
@@ -4840,16 +4861,16 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(574);
+						setState(578);
 						asmExpr(7);
 						}
 						break;
 					}
 					} 
 				}
-				setState(579);
+				setState(583);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,55,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,56,_ctx);
 			}
 			}
 		}
@@ -4954,7 +4975,7 @@ public class KickCParser extends Parser {
 	}
 
 	public static final String _serializedATN =
-		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3b\u0247\4\2\t\2\4"+
+		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3b\u024b\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"+
@@ -4984,203 +5005,205 @@ public class KickCParser extends Parser {
 		"\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u015e\n\30\3\30\3\30"+
 		"\3\30\3\30\3\30\3\30\5\30\u0166\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
 		"\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u017b"+
-		"\n\30\f\30\16\30\u017e\13\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u0187"+
-		"\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
-		"\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
-		"\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
-		"\3\30\5\30\u01b3\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u01bd"+
-		"\n\30\f\30\16\30\u01c0\13\30\3\31\3\31\3\31\7\31\u01c5\n\31\f\31\16\31"+
-		"\u01c8\13\31\3\32\3\32\5\32\u01cc\n\32\3\32\3\32\3\33\3\33\3\33\3\33\7"+
-		"\33\u01d4\n\33\f\33\16\33\u01d7\13\33\3\33\3\33\3\34\3\34\3\34\3\34\3"+
-		"\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\5\34\u01e8\n\34\5\34\u01ea"+
-		"\n\34\3\35\7\35\u01ed\n\35\f\35\16\35\u01f0\13\35\3\36\3\36\3\36\5\36"+
-		"\u01f5\n\36\3\37\3\37\3\37\3\37\5\37\u01fb\n\37\3\37\5\37\u01fe\n\37\3"+
-		" \3 \5 \u0202\n \3!\3!\3!\3!\7!\u0208\n!\f!\16!\u020b\13!\3\"\3\"\3\""+
-		"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3"+
-		"\"\3\"\3\"\5\"\u0224\n\"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\5#"+
-		"\u0234\n#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\7#\u0242\n#\f#\16#\u0245"+
-		"\13#\3#\2\7\22*,.D$\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+
-		"\62\64\668:<>@BD\2\r\3\2\36\37\3\2%&\3\2\'+\3\2\60\61\3\2,-\4\2  ./\3"+
-		"\2\'(\3\2\60\65\3\2;D\4\2\'(\60\61\4\2  ..\2\u0299\2F\3\2\2\2\4J\3\2\2"+
-		"\2\6P\3\2\2\2\bS\3\2\2\2\nW\3\2\2\2\fa\3\2\2\2\16f\3\2\2\2\20p\3\2\2\2"+
-		"\22s\3\2\2\2\24~\3\2\2\2\26\u0083\3\2\2\2\30\u0090\3\2\2\2\32\u009c\3"+
-		"\2\2\2\34\u009e\3\2\2\2\36\u00b4\3\2\2\2 \u00b6\3\2\2\2\"\u00c3\3\2\2"+
-		"\2$\u0113\3\2\2\2&\u0125\3\2\2\2(\u012b\3\2\2\2*\u0137\3\2\2\2,\u0149"+
-		"\3\2\2\2.\u0186\3\2\2\2\60\u01c1\3\2\2\2\62\u01c9\3\2\2\2\64\u01cf\3\2"+
-		"\2\2\66\u01e9\3\2\2\28\u01ee\3\2\2\2:\u01f4\3\2\2\2<\u01fd\3\2\2\2>\u01ff"+
-		"\3\2\2\2@\u0203\3\2\2\2B\u0223\3\2\2\2D\u0233\3\2\2\2FG\5\6\4\2GH\5\n"+
-		"\6\2HI\7\2\2\3I\3\3\2\2\2JK\58\35\2KL\7\2\2\3L\5\3\2\2\2MO\5\b\5\2NM\3"+
-		"\2\2\2OR\3\2\2\2PN\3\2\2\2PQ\3\2\2\2Q\7\3\2\2\2RP\3\2\2\2ST\7\3\2\2TU"+
-		"\7R\2\2U\t\3\2\2\2VX\5\f\7\2WV\3\2\2\2XY\3\2\2\2YW\3\2\2\2YZ\3\2\2\2Z"+
-		"\13\3\2\2\2[\\\5\20\t\2\\]\7\4\2\2]b\3\2\2\2^b\5\26\f\2_b\5\62\32\2`b"+
-		"\5\34\17\2a[\3\2\2\2a^\3\2\2\2a_\3\2\2\2a`\3\2\2\2b\r\3\2\2\2ce\5\36\20"+
-		"\2dc\3\2\2\2eh\3\2\2\2fd\3\2\2\2fg\3\2\2\2gi\3\2\2\2hf\3\2\2\2im\5*\26"+
-		"\2jl\5\36\20\2kj\3\2\2\2lo\3\2\2\2mk\3\2\2\2mn\3\2\2\2n\17\3\2\2\2om\3"+
-		"\2\2\2pq\5\16\b\2qr\5\22\n\2r\21\3\2\2\2st\b\n\1\2tu\5\24\13\2u{\3\2\2"+
-		"\2vw\f\3\2\2wx\7\5\2\2xz\5\24\13\2yv\3\2\2\2z}\3\2\2\2{y\3\2\2\2{|\3\2"+
-		"\2\2|\23\3\2\2\2}{\3\2\2\2~\u0081\7^\2\2\177\u0080\7\6\2\2\u0080\u0082"+
-		"\5.\30\2\u0081\177\3\2\2\2\u0081\u0082\3\2\2\2\u0082\25\3\2\2\2\u0083"+
-		"\u0084\5\16\b\2\u0084\u0085\7^\2\2\u0085\u0087\7\7\2\2\u0086\u0088\5\30"+
-		"\r\2\u0087\u0086\3\2\2\2\u0087\u0088\3\2\2\2\u0088\u0089\3\2\2\2\u0089"+
-		"\u008a\7\b\2\2\u008a\u008c\7\t\2\2\u008b\u008d\5\"\22\2\u008c\u008b\3"+
-		"\2\2\2\u008c\u008d\3\2\2\2\u008d\u008e\3\2\2\2\u008e\u008f\7\n\2\2\u008f"+
-		"\27\3\2\2\2\u0090\u0095\5\32\16\2\u0091\u0092\7\5\2\2\u0092\u0094\5\32"+
-		"\16\2\u0093\u0091\3\2\2\2\u0094\u0097\3\2\2\2\u0095\u0093\3\2\2\2\u0095"+
-		"\u0096\3\2\2\2\u0096\31\3\2\2\2\u0097\u0095\3\2\2\2\u0098\u0099\5\16\b"+
-		"\2\u0099\u009a\7^\2\2\u009a\u009d\3\2\2\2\u009b\u009d\7Q\2\2\u009c\u0098"+
-		"\3\2\2\2\u009c\u009b\3\2\2\2\u009d\33\3\2\2\2\u009e\u009f\5 \21\2\u009f"+
-		"\u00a0\7\4\2\2\u00a0\35\3\2\2\2\u00a1\u00b5\7\13\2\2\u00a2\u00b5\7\f\2"+
-		"\2\u00a3\u00a4\7\r\2\2\u00a4\u00a5\7\7\2\2\u00a5\u00a6\7U\2\2\u00a6\u00b5"+
-		"\7\b\2\2\u00a7\u00a8\7\16\2\2\u00a8\u00a9\7\7\2\2\u00a9\u00aa\7^\2\2\u00aa"+
-		"\u00b5\7\b\2\2\u00ab\u00b5\7\17\2\2\u00ac\u00b5\7\20\2\2\u00ad\u00b1\7"+
-		"\21\2\2\u00ae\u00af\7\7\2\2\u00af\u00b0\7^\2\2\u00b0\u00b2\7\b\2\2\u00b1"+
-		"\u00ae\3\2\2\2\u00b1\u00b2\3\2\2\2\u00b2\u00b5\3\2\2\2\u00b3\u00b5\5 "+
-		"\21\2\u00b4\u00a1\3\2\2\2\u00b4\u00a2\3\2\2\2\u00b4\u00a3\3\2\2\2\u00b4"+
-		"\u00a7\3\2\2\2\u00b4\u00ab\3\2\2\2\u00b4\u00ac\3\2\2\2\u00b4\u00ad\3\2"+
-		"\2\2\u00b4\u00b3\3\2\2\2\u00b5\37\3\2\2\2\u00b6\u00b7\7\22\2\2\u00b7\u00b8"+
-		"\7\7\2\2\u00b8\u00bd\7U\2\2\u00b9\u00ba\7\5\2\2\u00ba\u00bc\7U\2\2\u00bb"+
-		"\u00b9\3\2\2\2\u00bc\u00bf\3\2\2\2\u00bd\u00bb\3\2\2\2\u00bd\u00be\3\2"+
-		"\2\2\u00be\u00c0\3\2\2\2\u00bf\u00bd\3\2\2\2\u00c0\u00c1\7\b\2\2\u00c1"+
-		"!\3\2\2\2\u00c2\u00c4\5$\23\2\u00c3\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2"+
-		"\u00c5\u00c3\3\2\2\2\u00c5\u00c6\3\2\2\2\u00c6#\3\2\2\2\u00c7\u00c8\5"+
-		"\20\t\2\u00c8\u00c9\7\4\2\2\u00c9\u0114\3\2\2\2\u00ca\u00cc\7\t\2\2\u00cb"+
-		"\u00cd\5\"\22\2\u00cc\u00cb\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cd\u00ce\3"+
-		"\2\2\2\u00ce\u0114\7\n\2\2\u00cf\u00d0\5,\27\2\u00d0\u00d1\7\4\2\2\u00d1"+
-		"\u0114\3\2\2\2\u00d2\u00d3\7\23\2\2\u00d3\u00d4\7\7\2\2\u00d4\u00d5\5"+
-		",\27\2\u00d5\u00d6\7\b\2\2\u00d6\u00d9\5$\23\2\u00d7\u00d8\7\24\2\2\u00d8"+
-		"\u00da\5$\23\2\u00d9\u00d7\3\2\2\2\u00d9\u00da\3\2\2\2\u00da\u0114\3\2"+
-		"\2\2\u00db\u00dd\5\36\20\2\u00dc\u00db\3\2\2\2\u00dd\u00e0\3\2\2\2\u00de"+
-		"\u00dc\3\2\2\2\u00de\u00df\3\2\2\2\u00df\u00e1\3\2\2\2\u00e0\u00de\3\2"+
-		"\2\2\u00e1\u00e2\7\25\2\2\u00e2\u00e3\7\7\2\2\u00e3\u00e4\5,\27\2\u00e4"+
-		"\u00e5\7\b\2\2\u00e5\u00e6\5$\23\2\u00e6\u0114\3\2\2\2\u00e7\u00e9\5\36"+
-		"\20\2\u00e8\u00e7\3\2\2\2\u00e9\u00ec\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea"+
-		"\u00eb\3\2\2\2\u00eb\u00ed\3\2\2\2\u00ec\u00ea\3\2\2\2\u00ed\u00ee\7\26"+
-		"\2\2\u00ee\u00ef\5$\23\2\u00ef\u00f0\7\25\2\2\u00f0\u00f1\7\7\2\2\u00f1"+
-		"\u00f2\5,\27\2\u00f2\u00f3\7\b\2\2\u00f3\u00f4\7\4\2\2\u00f4\u0114\3\2"+
-		"\2\2\u00f5\u00f7\5\36\20\2\u00f6\u00f5\3\2\2\2\u00f7\u00fa\3\2\2\2\u00f8"+
-		"\u00f6\3\2\2\2\u00f8\u00f9\3\2\2\2\u00f9\u00fb\3\2\2\2\u00fa\u00f8\3\2"+
-		"\2\2\u00fb\u00fc\7\27\2\2\u00fc\u00fd\7\7\2\2\u00fd\u00fe\5&\24\2\u00fe"+
-		"\u00ff\7\b\2\2\u00ff\u0100\5$\23\2\u0100\u0114\3\2\2\2\u0101\u0103\7\30"+
-		"\2\2\u0102\u0104\5,\27\2\u0103\u0102\3\2\2\2\u0103\u0104\3\2\2\2\u0104"+
-		"\u0105\3\2\2\2\u0105\u0114\7\4\2\2\u0106\u0107\7\31\2\2\u0107\u0114\7"+
-		"\4\2\2\u0108\u0109\7\32\2\2\u0109\u0114\7\4\2\2\u010a\u010c\7\33\2\2\u010b"+
-		"\u010d\5\64\33\2\u010c\u010b\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3"+
-		"\2\2\2\u010e\u010f\7\t\2\2\u010f\u0110\58\35\2\u0110\u0111\7\n\2\2\u0111"+
-		"\u0114\3\2\2\2\u0112\u0114\5\62\32\2\u0113\u00c7\3\2\2\2\u0113\u00ca\3"+
-		"\2\2\2\u0113\u00cf\3\2\2\2\u0113\u00d2\3\2\2\2\u0113\u00de\3\2\2\2\u0113"+
-		"\u00ea\3\2\2\2\u0113\u00f8\3\2\2\2\u0113\u0101\3\2\2\2\u0113\u0106\3\2"+
-		"\2\2\u0113\u0108\3\2\2\2\u0113\u010a\3\2\2\2\u0113\u0112\3\2\2\2\u0114"+
-		"%\3\2\2\2\u0115\u0116\5(\25\2\u0116\u0117\7\4\2\2\u0117\u0118\5,\27\2"+
-		"\u0118\u011a\7\4\2\2\u0119\u011b\5,\27\2\u011a\u0119\3\2\2\2\u011a\u011b"+
-		"\3\2\2\2\u011b\u0126\3\2\2\2\u011c\u011e\5\16\b\2\u011d\u011c\3\2\2\2"+
-		"\u011d\u011e\3\2\2\2\u011e\u011f\3\2\2\2\u011f\u0120\7^\2\2\u0120\u0121"+
-		"\7\34\2\2\u0121\u0122\5.\30\2\u0122\u0123\7\35\2\2\u0123\u0124\5.\30\2"+
-		"\u0124\u0126\3\2\2\2\u0125\u0115\3\2\2\2\u0125\u011d\3\2\2\2\u0126\'\3"+
-		"\2\2\2\u0127\u0129\5\20\t\2\u0128\u0127\3\2\2\2\u0128\u0129\3\2\2\2\u0129"+
-		"\u012c\3\2\2\2\u012a\u012c\5,\27\2\u012b\u0128\3\2\2\2\u012b\u012a\3\2"+
-		"\2\2\u012c)\3\2\2\2\u012d\u012e\b\26\1\2\u012e\u012f\7\7\2\2\u012f\u0130"+
-		"\5*\26\2\u0130\u0131\7\b\2\2\u0131\u0138\3\2\2\2\u0132\u0138\7Q\2\2\u0133"+
-		"\u0135\t\2\2\2\u0134\u0136\7Q\2\2\u0135\u0134\3\2\2\2\u0135\u0136\3\2"+
-		"\2\2\u0136\u0138\3\2\2\2\u0137\u012d\3\2\2\2\u0137\u0132\3\2\2\2\u0137"+
-		"\u0133\3\2\2\2\u0138\u0146\3\2\2\2\u0139\u013a\f\5\2\2\u013a\u0145\7 "+
-		"\2\2\u013b\u013c\f\4\2\2\u013c\u013e\7!\2\2\u013d\u013f\5.\30\2\u013e"+
-		"\u013d\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u0140\3\2\2\2\u0140\u0145\7\""+
-		"\2\2\u0141\u0142\f\3\2\2\u0142\u0143\7\7\2\2\u0143\u0145\7\b\2\2\u0144"+
-		"\u0139\3\2\2\2\u0144\u013b\3\2\2\2\u0144\u0141\3\2\2\2\u0145\u0148\3\2"+
-		"\2\2\u0146\u0144\3\2\2\2\u0146\u0147\3\2\2\2\u0147+\3\2\2\2\u0148\u0146"+
-		"\3\2\2\2\u0149\u014a\b\27\1\2\u014a\u014b\5.\30\2\u014b\u0151\3\2\2\2"+
-		"\u014c\u014d\f\3\2\2\u014d\u014e\7\5\2\2\u014e\u0150\5.\30\2\u014f\u014c"+
-		"\3\2\2\2\u0150\u0153\3\2\2\2\u0151\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152"+
-		"-\3\2\2\2\u0153\u0151\3\2\2\2\u0154\u0155\b\30\1\2\u0155\u0156\7\7\2\2"+
-		"\u0156\u0157\5,\27\2\u0157\u0158\7\b\2\2\u0158\u0187\3\2\2\2\u0159\u015a"+
-		"\7#\2\2\u015a\u015d\7\7\2\2\u015b\u015e\5*\26\2\u015c\u015e\5.\30\2\u015d"+
-		"\u015b\3\2\2\2\u015d\u015c\3\2\2\2\u015e\u015f\3\2\2\2\u015f\u0160\7\b"+
-		"\2\2\u0160\u0187\3\2\2\2\u0161\u0162\7$\2\2\u0162\u0165\7\7\2\2\u0163"+
-		"\u0166\5*\26\2\u0164\u0166\5.\30\2\u0165\u0163\3\2\2\2\u0165\u0164\3\2"+
-		"\2\2\u0166\u0167\3\2\2\2\u0167\u0168\7\b\2\2\u0168\u0187\3\2\2\2\u0169"+
-		"\u016a\7\7\2\2\u016a\u016b\5*\26\2\u016b\u016c\7\b\2\2\u016c\u016d\5."+
-		"\30\32\u016d\u0187\3\2\2\2\u016e\u016f\t\3\2\2\u016f\u0187\5.\30\31\u0170"+
-		"\u0171\7 \2\2\u0171\u0187\5.\30\27\u0172\u0173\t\4\2\2\u0173\u0187\5."+
-		"\30\26\u0174\u0175\t\5\2\2\u0175\u0187\5.\30\22\u0176\u0177\7\t\2\2\u0177"+
-		"\u017c\5.\30\2\u0178\u0179\7\5\2\2\u0179\u017b\5.\30\2\u017a\u0178\3\2"+
-		"\2\2\u017b\u017e\3\2\2\2\u017c\u017a\3\2\2\2\u017c\u017d\3\2\2\2\u017d"+
-		"\u017f\3\2\2\2\u017e\u017c\3\2\2\2\u017f\u0180\7\n\2\2\u0180\u0187\3\2"+
-		"\2\2\u0181\u0187\7^\2\2\u0182\u0187\7U\2\2\u0183\u0187\7R\2\2\u0184\u0187"+
-		"\7S\2\2\u0185\u0187\7T\2\2\u0186\u0154\3\2\2\2\u0186\u0159\3\2\2\2\u0186"+
-		"\u0161\3\2\2\2\u0186\u0169\3\2\2\2\u0186\u016e\3\2\2\2\u0186\u0170\3\2"+
-		"\2\2\u0186\u0172\3\2\2\2\u0186\u0174\3\2\2\2\u0186\u0176\3\2\2\2\u0186"+
-		"\u0181\3\2\2\2\u0186\u0182\3\2\2\2\u0186\u0183\3\2\2\2\u0186\u0184\3\2"+
-		"\2\2\u0186\u0185\3\2\2\2\u0187\u01be\3\2\2\2\u0188\u0189\f\25\2\2\u0189"+
-		"\u018a\t\6\2\2\u018a\u01bd\5.\30\26\u018b\u018c\f\24\2\2\u018c\u018d\t"+
-		"\7\2\2\u018d\u01bd\5.\30\25\u018e\u018f\f\23\2\2\u018f\u0190\t\b\2\2\u0190"+
-		"\u01bd\5.\30\24\u0191\u0192\f\21\2\2\u0192\u0193\t\t\2\2\u0193\u01bd\5"+
-		".\30\22\u0194\u0195\f\20\2\2\u0195\u0196\7*\2\2\u0196\u01bd\5.\30\21\u0197"+
-		"\u0198\f\17\2\2\u0198\u0199\7\66\2\2\u0199\u01bd\5.\30\20\u019a\u019b"+
-		"\f\16\2\2\u019b\u019c\7\67\2\2\u019c\u01bd\5.\30\17\u019d\u019e\f\r\2"+
-		"\2\u019e\u019f\78\2\2\u019f\u01bd\5.\30\16\u01a0\u01a1\f\f\2\2\u01a1\u01a2"+
-		"\79\2\2\u01a2\u01bd\5.\30\r\u01a3\u01a4\f\13\2\2\u01a4\u01a5\7:\2\2\u01a5"+
-		"\u01a6\5.\30\2\u01a6\u01a7\7\34\2\2\u01a7\u01a8\5.\30\f\u01a8\u01bd\3"+
-		"\2\2\2\u01a9\u01aa\f\n\2\2\u01aa\u01ab\7\6\2\2\u01ab\u01bd\5.\30\n\u01ac"+
-		"\u01ad\f\t\2\2\u01ad\u01ae\t\n\2\2\u01ae\u01bd\5.\30\t\u01af\u01b0\f\36"+
-		"\2\2\u01b0\u01b2\7\7\2\2\u01b1\u01b3\5\60\31\2\u01b2\u01b1\3\2\2\2\u01b2"+
-		"\u01b3\3\2\2\2\u01b3\u01b4\3\2\2\2\u01b4\u01bd\7\b\2\2\u01b5\u01b6\f\33"+
-		"\2\2\u01b6\u01b7\7!\2\2\u01b7\u01b8\5,\27\2\u01b8\u01b9\7\"\2\2\u01b9"+
-		"\u01bd\3\2\2\2\u01ba\u01bb\f\30\2\2\u01bb\u01bd\t\3\2\2\u01bc\u0188\3"+
-		"\2\2\2\u01bc\u018b\3\2\2\2\u01bc\u018e\3\2\2\2\u01bc\u0191\3\2\2\2\u01bc"+
-		"\u0194\3\2\2\2\u01bc\u0197\3\2\2\2\u01bc\u019a\3\2\2\2\u01bc\u019d\3\2"+
-		"\2\2\u01bc\u01a0\3\2\2\2\u01bc\u01a3\3\2\2\2\u01bc\u01a9\3\2\2\2\u01bc"+
-		"\u01ac\3\2\2\2\u01bc\u01af\3\2\2\2\u01bc\u01b5\3\2\2\2\u01bc\u01ba\3\2"+
-		"\2\2\u01bd\u01c0\3\2\2\2\u01be\u01bc\3\2\2\2\u01be\u01bf\3\2\2\2\u01bf"+
-		"/\3\2\2\2\u01c0\u01be\3\2\2\2\u01c1\u01c6\5.\30\2\u01c2\u01c3\7\5\2\2"+
-		"\u01c3\u01c5\5.\30\2\u01c4\u01c2\3\2\2\2\u01c5\u01c8\3\2\2\2\u01c6\u01c4"+
-		"\3\2\2\2\u01c6\u01c7\3\2\2\2\u01c7\61\3\2\2\2\u01c8\u01c6\3\2\2\2\u01c9"+
-		"\u01cb\7E\2\2\u01ca\u01cc\5\64\33\2\u01cb\u01ca\3\2\2\2\u01cb\u01cc\3"+
-		"\2\2\2\u01cc\u01cd\3\2\2\2\u01cd\u01ce\7P\2\2\u01ce\63\3\2\2\2\u01cf\u01d0"+
-		"\7\7\2\2\u01d0\u01d5\5\66\34\2\u01d1\u01d2\7\5\2\2\u01d2\u01d4\5\66\34"+
-		"\2\u01d3\u01d1\3\2\2\2\u01d4\u01d7\3\2\2\2\u01d5\u01d3\3\2\2\2\u01d5\u01d6"+
-		"\3\2\2\2\u01d6\u01d8\3\2\2\2\u01d7\u01d5\3\2\2\2\u01d8\u01d9\7\b\2\2\u01d9"+
-		"\65\3\2\2\2\u01da\u01db\7F\2\2\u01db\u01ea\7R\2\2\u01dc\u01dd\7G\2\2\u01dd"+
-		"\u01ea\7^\2\2\u01de\u01df\7H\2\2\u01df\u01ea\7R\2\2\u01e0\u01e1\7I\2\2"+
-		"\u01e1\u01ea\5.\30\2\u01e2\u01e3\7J\2\2\u01e3\u01ea\5.\30\2\u01e4\u01e7"+
-		"\7K\2\2\u01e5\u01e8\7\17\2\2\u01e6\u01e8\5.\30\2\u01e7\u01e5\3\2\2\2\u01e7"+
-		"\u01e6\3\2\2\2\u01e8\u01ea\3\2\2\2\u01e9\u01da\3\2\2\2\u01e9\u01dc\3\2"+
-		"\2\2\u01e9\u01de\3\2\2\2\u01e9\u01e0\3\2\2\2\u01e9\u01e2\3\2\2\2\u01e9"+
-		"\u01e4\3\2\2\2\u01ea\67\3\2\2\2\u01eb\u01ed\5:\36\2\u01ec\u01eb\3\2\2"+
-		"\2\u01ed\u01f0\3\2\2\2\u01ee\u01ec\3\2\2\2\u01ee\u01ef\3\2\2\2\u01ef9"+
-		"\3\2\2\2\u01f0\u01ee\3\2\2\2\u01f1\u01f5\5<\37\2\u01f2\u01f5\5> \2\u01f3"+
-		"\u01f5\5@!\2\u01f4\u01f1\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f4\u01f3\3\2\2"+
-		"\2\u01f5;\3\2\2\2\u01f6\u01f7\7^\2\2\u01f7\u01fe\7\34\2\2\u01f8\u01fa"+
-		"\7)\2\2\u01f9\u01fb\7^\2\2\u01fa\u01f9\3\2\2\2\u01fa\u01fb\3\2\2\2\u01fb"+
-		"\u01fc\3\2\2\2\u01fc\u01fe\7\34\2\2\u01fd\u01f6\3\2\2\2\u01fd\u01f8\3"+
-		"\2\2\2\u01fe=\3\2\2\2\u01ff\u0201\7O\2\2\u0200\u0202\5B\"\2\u0201\u0200"+
-		"\3\2\2\2\u0201\u0202\3\2\2\2\u0202?\3\2\2\2\u0203\u0204\7L\2\2\u0204\u0209"+
-		"\5D#\2\u0205\u0206\7\5\2\2\u0206\u0208\5D#\2\u0207\u0205\3\2\2\2\u0208"+
-		"\u020b\3\2\2\2\u0209\u0207\3\2\2\2\u0209\u020a\3\2\2\2\u020aA\3\2\2\2"+
-		"\u020b\u0209\3\2\2\2\u020c\u0224\5D#\2\u020d\u020e\7M\2\2\u020e\u0224"+
-		"\5D#\2\u020f\u0210\5D#\2\u0210\u0211\7\5\2\2\u0211\u0212\7^\2\2\u0212"+
-		"\u0224\3\2\2\2\u0213\u0214\7\7\2\2\u0214\u0215\5D#\2\u0215\u0216\7\b\2"+
-		"\2\u0216\u0217\7\5\2\2\u0217\u0218\7^\2\2\u0218\u0224\3\2\2\2\u0219\u021a"+
-		"\7\7\2\2\u021a\u021b\5D#\2\u021b\u021c\7\5\2\2\u021c\u021d\7^\2\2\u021d"+
-		"\u021e\7\b\2\2\u021e\u0224\3\2\2\2\u021f\u0220\7\7\2\2\u0220\u0221\5D"+
-		"#\2\u0221\u0222\7\b\2\2\u0222\u0224\3\2\2\2\u0223\u020c\3\2\2\2\u0223"+
-		"\u020d\3\2\2\2\u0223\u020f\3\2\2\2\u0223\u0213\3\2\2\2\u0223\u0219\3\2"+
-		"\2\2\u0223\u021f\3\2\2\2\u0224C\3\2\2\2\u0225\u0226\b#\1\2\u0226\u0227"+
-		"\7!\2\2\u0227\u0228\5D#\2\u0228\u0229\7\"\2\2\u0229\u0234\3\2\2\2\u022a"+
-		"\u022b\t\13\2\2\u022b\u0234\5D#\n\u022c\u0234\7^\2\2\u022d\u0234\7_\2"+
-		"\2\u022e\u022f\7\t\2\2\u022f\u0230\7^\2\2\u0230\u0234\7\n\2\2\u0231\u0234"+
-		"\7U\2\2\u0232\u0234\7S\2\2\u0233\u0225\3\2\2\2\u0233\u022a\3\2\2\2\u0233"+
-		"\u022c\3\2\2\2\u0233\u022d\3\2\2\2\u0233\u022e\3\2\2\2\u0233\u0231\3\2"+
-		"\2\2\u0233\u0232\3\2\2\2\u0234\u0243\3\2\2\2\u0235\u0236\f\f\2\2\u0236"+
-		"\u0237\7N\2\2\u0237\u0242\5D#\r\u0238\u0239\f\13\2\2\u0239\u023a\t\6\2"+
-		"\2\u023a\u0242\5D#\f\u023b\u023c\f\t\2\2\u023c\u023d\t\f\2\2\u023d\u0242"+
-		"\5D#\n\u023e\u023f\f\b\2\2\u023f\u0240\t\b\2\2\u0240\u0242\5D#\t\u0241"+
-		"\u0235\3\2\2\2\u0241\u0238\3\2\2\2\u0241\u023b\3\2\2\2\u0241\u023e\3\2"+
-		"\2\2\u0242\u0245\3\2\2\2\u0243\u0241\3\2\2\2\u0243\u0244\3\2\2\2\u0244"+
-		"E\3\2\2\2\u0245\u0243\3\2\2\2:PYafm{\u0081\u0087\u008c\u0095\u009c\u00b1"+
+		"\n\30\f\30\16\30\u017e\13\30\3\30\3\30\3\30\3\30\3\30\6\30\u0185\n\30"+
+		"\r\30\16\30\u0186\3\30\3\30\5\30\u018b\n\30\3\30\3\30\3\30\3\30\3\30\3"+
+		"\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3"+
+		"\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3"+
+		"\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u01b7\n\30\3\30\3\30"+
+		"\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u01c1\n\30\f\30\16\30\u01c4\13\30"+
+		"\3\31\3\31\3\31\7\31\u01c9\n\31\f\31\16\31\u01cc\13\31\3\32\3\32\5\32"+
+		"\u01d0\n\32\3\32\3\32\3\33\3\33\3\33\3\33\7\33\u01d8\n\33\f\33\16\33\u01db"+
+		"\13\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34"+
+		"\3\34\3\34\5\34\u01ec\n\34\5\34\u01ee\n\34\3\35\7\35\u01f1\n\35\f\35\16"+
+		"\35\u01f4\13\35\3\36\3\36\3\36\5\36\u01f9\n\36\3\37\3\37\3\37\3\37\5\37"+
+		"\u01ff\n\37\3\37\5\37\u0202\n\37\3 \3 \5 \u0206\n \3!\3!\3!\3!\7!\u020c"+
+		"\n!\f!\16!\u020f\13!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3"+
+		"\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\5\"\u0228\n\"\3#\3#\3#\3#\3"+
+		"#\3#\3#\3#\3#\3#\3#\3#\3#\3#\5#\u0238\n#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3"+
+		"#\3#\3#\7#\u0246\n#\f#\16#\u0249\13#\3#\2\7\22*,.D$\2\4\6\b\n\f\16\20"+
+		"\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BD\2\r\3\2\36\37\3\2%&"+
+		"\3\2\'+\3\2\60\61\3\2,-\4\2  ./\3\2\'(\3\2\60\65\3\2;D\4\2\'(\60\61\4"+
+		"\2  ..\2\u029e\2F\3\2\2\2\4J\3\2\2\2\6P\3\2\2\2\bS\3\2\2\2\nW\3\2\2\2"+
+		"\fa\3\2\2\2\16f\3\2\2\2\20p\3\2\2\2\22s\3\2\2\2\24~\3\2\2\2\26\u0083\3"+
+		"\2\2\2\30\u0090\3\2\2\2\32\u009c\3\2\2\2\34\u009e\3\2\2\2\36\u00b4\3\2"+
+		"\2\2 \u00b6\3\2\2\2\"\u00c3\3\2\2\2$\u0113\3\2\2\2&\u0125\3\2\2\2(\u012b"+
+		"\3\2\2\2*\u0137\3\2\2\2,\u0149\3\2\2\2.\u018a\3\2\2\2\60\u01c5\3\2\2\2"+
+		"\62\u01cd\3\2\2\2\64\u01d3\3\2\2\2\66\u01ed\3\2\2\28\u01f2\3\2\2\2:\u01f8"+
+		"\3\2\2\2<\u0201\3\2\2\2>\u0203\3\2\2\2@\u0207\3\2\2\2B\u0227\3\2\2\2D"+
+		"\u0237\3\2\2\2FG\5\6\4\2GH\5\n\6\2HI\7\2\2\3I\3\3\2\2\2JK\58\35\2KL\7"+
+		"\2\2\3L\5\3\2\2\2MO\5\b\5\2NM\3\2\2\2OR\3\2\2\2PN\3\2\2\2PQ\3\2\2\2Q\7"+
+		"\3\2\2\2RP\3\2\2\2ST\7\3\2\2TU\7R\2\2U\t\3\2\2\2VX\5\f\7\2WV\3\2\2\2X"+
+		"Y\3\2\2\2YW\3\2\2\2YZ\3\2\2\2Z\13\3\2\2\2[\\\5\20\t\2\\]\7\4\2\2]b\3\2"+
+		"\2\2^b\5\26\f\2_b\5\62\32\2`b\5\34\17\2a[\3\2\2\2a^\3\2\2\2a_\3\2\2\2"+
+		"a`\3\2\2\2b\r\3\2\2\2ce\5\36\20\2dc\3\2\2\2eh\3\2\2\2fd\3\2\2\2fg\3\2"+
+		"\2\2gi\3\2\2\2hf\3\2\2\2im\5*\26\2jl\5\36\20\2kj\3\2\2\2lo\3\2\2\2mk\3"+
+		"\2\2\2mn\3\2\2\2n\17\3\2\2\2om\3\2\2\2pq\5\16\b\2qr\5\22\n\2r\21\3\2\2"+
+		"\2st\b\n\1\2tu\5\24\13\2u{\3\2\2\2vw\f\3\2\2wx\7\5\2\2xz\5\24\13\2yv\3"+
+		"\2\2\2z}\3\2\2\2{y\3\2\2\2{|\3\2\2\2|\23\3\2\2\2}{\3\2\2\2~\u0081\7^\2"+
+		"\2\177\u0080\7\6\2\2\u0080\u0082\5.\30\2\u0081\177\3\2\2\2\u0081\u0082"+
+		"\3\2\2\2\u0082\25\3\2\2\2\u0083\u0084\5\16\b\2\u0084\u0085\7^\2\2\u0085"+
+		"\u0087\7\7\2\2\u0086\u0088\5\30\r\2\u0087\u0086\3\2\2\2\u0087\u0088\3"+
+		"\2\2\2\u0088\u0089\3\2\2\2\u0089\u008a\7\b\2\2\u008a\u008c\7\t\2\2\u008b"+
+		"\u008d\5\"\22\2\u008c\u008b\3\2\2\2\u008c\u008d\3\2\2\2\u008d\u008e\3"+
+		"\2\2\2\u008e\u008f\7\n\2\2\u008f\27\3\2\2\2\u0090\u0095\5\32\16\2\u0091"+
+		"\u0092\7\5\2\2\u0092\u0094\5\32\16\2\u0093\u0091\3\2\2\2\u0094\u0097\3"+
+		"\2\2\2\u0095\u0093\3\2\2\2\u0095\u0096\3\2\2\2\u0096\31\3\2\2\2\u0097"+
+		"\u0095\3\2\2\2\u0098\u0099\5\16\b\2\u0099\u009a\7^\2\2\u009a\u009d\3\2"+
+		"\2\2\u009b\u009d\7Q\2\2\u009c\u0098\3\2\2\2\u009c\u009b\3\2\2\2\u009d"+
+		"\33\3\2\2\2\u009e\u009f\5 \21\2\u009f\u00a0\7\4\2\2\u00a0\35\3\2\2\2\u00a1"+
+		"\u00b5\7\13\2\2\u00a2\u00b5\7\f\2\2\u00a3\u00a4\7\r\2\2\u00a4\u00a5\7"+
+		"\7\2\2\u00a5\u00a6\7U\2\2\u00a6\u00b5\7\b\2\2\u00a7\u00a8\7\16\2\2\u00a8"+
+		"\u00a9\7\7\2\2\u00a9\u00aa\7^\2\2\u00aa\u00b5\7\b\2\2\u00ab\u00b5\7\17"+
+		"\2\2\u00ac\u00b5\7\20\2\2\u00ad\u00b1\7\21\2\2\u00ae\u00af\7\7\2\2\u00af"+
+		"\u00b0\7^\2\2\u00b0\u00b2\7\b\2\2\u00b1\u00ae\3\2\2\2\u00b1\u00b2\3\2"+
+		"\2\2\u00b2\u00b5\3\2\2\2\u00b3\u00b5\5 \21\2\u00b4\u00a1\3\2\2\2\u00b4"+
+		"\u00a2\3\2\2\2\u00b4\u00a3\3\2\2\2\u00b4\u00a7\3\2\2\2\u00b4\u00ab\3\2"+
+		"\2\2\u00b4\u00ac\3\2\2\2\u00b4\u00ad\3\2\2\2\u00b4\u00b3\3\2\2\2\u00b5"+
+		"\37\3\2\2\2\u00b6\u00b7\7\22\2\2\u00b7\u00b8\7\7\2\2\u00b8\u00bd\7U\2"+
+		"\2\u00b9\u00ba\7\5\2\2\u00ba\u00bc\7U\2\2\u00bb\u00b9\3\2\2\2\u00bc\u00bf"+
+		"\3\2\2\2\u00bd\u00bb\3\2\2\2\u00bd\u00be\3\2\2\2\u00be\u00c0\3\2\2\2\u00bf"+
+		"\u00bd\3\2\2\2\u00c0\u00c1\7\b\2\2\u00c1!\3\2\2\2\u00c2\u00c4\5$\23\2"+
+		"\u00c3\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\u00c3\3\2\2\2\u00c5\u00c6"+
+		"\3\2\2\2\u00c6#\3\2\2\2\u00c7\u00c8\5\20\t\2\u00c8\u00c9\7\4\2\2\u00c9"+
+		"\u0114\3\2\2\2\u00ca\u00cc\7\t\2\2\u00cb\u00cd\5\"\22\2\u00cc\u00cb\3"+
+		"\2\2\2\u00cc\u00cd\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u0114\7\n\2\2\u00cf"+
+		"\u00d0\5,\27\2\u00d0\u00d1\7\4\2\2\u00d1\u0114\3\2\2\2\u00d2\u00d3\7\23"+
+		"\2\2\u00d3\u00d4\7\7\2\2\u00d4\u00d5\5,\27\2\u00d5\u00d6\7\b\2\2\u00d6"+
+		"\u00d9\5$\23\2\u00d7\u00d8\7\24\2\2\u00d8\u00da\5$\23\2\u00d9\u00d7\3"+
+		"\2\2\2\u00d9\u00da\3\2\2\2\u00da\u0114\3\2\2\2\u00db\u00dd\5\36\20\2\u00dc"+
+		"\u00db\3\2\2\2\u00dd\u00e0\3\2\2\2\u00de\u00dc\3\2\2\2\u00de\u00df\3\2"+
+		"\2\2\u00df\u00e1\3\2\2\2\u00e0\u00de\3\2\2\2\u00e1\u00e2\7\25\2\2\u00e2"+
+		"\u00e3\7\7\2\2\u00e3\u00e4\5,\27\2\u00e4\u00e5\7\b\2\2\u00e5\u00e6\5$"+
+		"\23\2\u00e6\u0114\3\2\2\2\u00e7\u00e9\5\36\20\2\u00e8\u00e7\3\2\2\2\u00e9"+
+		"\u00ec\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb\u00ed\3\2"+
+		"\2\2\u00ec\u00ea\3\2\2\2\u00ed\u00ee\7\26\2\2\u00ee\u00ef\5$\23\2\u00ef"+
+		"\u00f0\7\25\2\2\u00f0\u00f1\7\7\2\2\u00f1\u00f2\5,\27\2\u00f2\u00f3\7"+
+		"\b\2\2\u00f3\u00f4\7\4\2\2\u00f4\u0114\3\2\2\2\u00f5\u00f7\5\36\20\2\u00f6"+
+		"\u00f5\3\2\2\2\u00f7\u00fa\3\2\2\2\u00f8\u00f6\3\2\2\2\u00f8\u00f9\3\2"+
+		"\2\2\u00f9\u00fb\3\2\2\2\u00fa\u00f8\3\2\2\2\u00fb\u00fc\7\27\2\2\u00fc"+
+		"\u00fd\7\7\2\2\u00fd\u00fe\5&\24\2\u00fe\u00ff\7\b\2\2\u00ff\u0100\5$"+
+		"\23\2\u0100\u0114\3\2\2\2\u0101\u0103\7\30\2\2\u0102\u0104\5,\27\2\u0103"+
+		"\u0102\3\2\2\2\u0103\u0104\3\2\2\2\u0104\u0105\3\2\2\2\u0105\u0114\7\4"+
+		"\2\2\u0106\u0107\7\31\2\2\u0107\u0114\7\4\2\2\u0108\u0109\7\32\2\2\u0109"+
+		"\u0114\7\4\2\2\u010a\u010c\7\33\2\2\u010b\u010d\5\64\33\2\u010c\u010b"+
+		"\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2\2\2\u010e\u010f\7\t\2\2\u010f"+
+		"\u0110\58\35\2\u0110\u0111\7\n\2\2\u0111\u0114\3\2\2\2\u0112\u0114\5\62"+
+		"\32\2\u0113\u00c7\3\2\2\2\u0113\u00ca\3\2\2\2\u0113\u00cf\3\2\2\2\u0113"+
+		"\u00d2\3\2\2\2\u0113\u00de\3\2\2\2\u0113\u00ea\3\2\2\2\u0113\u00f8\3\2"+
+		"\2\2\u0113\u0101\3\2\2\2\u0113\u0106\3\2\2\2\u0113\u0108\3\2\2\2\u0113"+
+		"\u010a\3\2\2\2\u0113\u0112\3\2\2\2\u0114%\3\2\2\2\u0115\u0116\5(\25\2"+
+		"\u0116\u0117\7\4\2\2\u0117\u0118\5,\27\2\u0118\u011a\7\4\2\2\u0119\u011b"+
+		"\5,\27\2\u011a\u0119\3\2\2\2\u011a\u011b\3\2\2\2\u011b\u0126\3\2\2\2\u011c"+
+		"\u011e\5\16\b\2\u011d\u011c\3\2\2\2\u011d\u011e\3\2\2\2\u011e\u011f\3"+
+		"\2\2\2\u011f\u0120\7^\2\2\u0120\u0121\7\34\2\2\u0121\u0122\5.\30\2\u0122"+
+		"\u0123\7\35\2\2\u0123\u0124\5.\30\2\u0124\u0126\3\2\2\2\u0125\u0115\3"+
+		"\2\2\2\u0125\u011d\3\2\2\2\u0126\'\3\2\2\2\u0127\u0129\5\20\t\2\u0128"+
+		"\u0127\3\2\2\2\u0128\u0129\3\2\2\2\u0129\u012c\3\2\2\2\u012a\u012c\5,"+
+		"\27\2\u012b\u0128\3\2\2\2\u012b\u012a\3\2\2\2\u012c)\3\2\2\2\u012d\u012e"+
+		"\b\26\1\2\u012e\u012f\7\7\2\2\u012f\u0130\5*\26\2\u0130\u0131\7\b\2\2"+
+		"\u0131\u0138\3\2\2\2\u0132\u0138\7Q\2\2\u0133\u0135\t\2\2\2\u0134\u0136"+
+		"\7Q\2\2\u0135\u0134\3\2\2\2\u0135\u0136\3\2\2\2\u0136\u0138\3\2\2\2\u0137"+
+		"\u012d\3\2\2\2\u0137\u0132\3\2\2\2\u0137\u0133\3\2\2\2\u0138\u0146\3\2"+
+		"\2\2\u0139\u013a\f\5\2\2\u013a\u0145\7 \2\2\u013b\u013c\f\4\2\2\u013c"+
+		"\u013e\7!\2\2\u013d\u013f\5.\30\2\u013e\u013d\3\2\2\2\u013e\u013f\3\2"+
+		"\2\2\u013f\u0140\3\2\2\2\u0140\u0145\7\"\2\2\u0141\u0142\f\3\2\2\u0142"+
+		"\u0143\7\7\2\2\u0143\u0145\7\b\2\2\u0144\u0139\3\2\2\2\u0144\u013b\3\2"+
+		"\2\2\u0144\u0141\3\2\2\2\u0145\u0148\3\2\2\2\u0146\u0144\3\2\2\2\u0146"+
+		"\u0147\3\2\2\2\u0147+\3\2\2\2\u0148\u0146\3\2\2\2\u0149\u014a\b\27\1\2"+
+		"\u014a\u014b\5.\30\2\u014b\u0151\3\2\2\2\u014c\u014d\f\3\2\2\u014d\u014e"+
+		"\7\5\2\2\u014e\u0150\5.\30\2\u014f\u014c\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+
+		"\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152-\3\2\2\2\u0153\u0151\3\2\2\2"+
+		"\u0154\u0155\b\30\1\2\u0155\u0156\7\7\2\2\u0156\u0157\5,\27\2\u0157\u0158"+
+		"\7\b\2\2\u0158\u018b\3\2\2\2\u0159\u015a\7#\2\2\u015a\u015d\7\7\2\2\u015b"+
+		"\u015e\5*\26\2\u015c\u015e\5.\30\2\u015d\u015b\3\2\2\2\u015d\u015c\3\2"+
+		"\2\2\u015e\u015f\3\2\2\2\u015f\u0160\7\b\2\2\u0160\u018b\3\2\2\2\u0161"+
+		"\u0162\7$\2\2\u0162\u0165\7\7\2\2\u0163\u0166\5*\26\2\u0164\u0166\5.\30"+
+		"\2\u0165\u0163\3\2\2\2\u0165\u0164\3\2\2\2\u0166\u0167\3\2\2\2\u0167\u0168"+
+		"\7\b\2\2\u0168\u018b\3\2\2\2\u0169\u016a\7\7\2\2\u016a\u016b\5*\26\2\u016b"+
+		"\u016c\7\b\2\2\u016c\u016d\5.\30\32\u016d\u018b\3\2\2\2\u016e\u016f\t"+
+		"\3\2\2\u016f\u018b\5.\30\31\u0170\u0171\7 \2\2\u0171\u018b\5.\30\27\u0172"+
+		"\u0173\t\4\2\2\u0173\u018b\5.\30\26\u0174\u0175\t\5\2\2\u0175\u018b\5"+
+		".\30\22\u0176\u0177\7\t\2\2\u0177\u017c\5.\30\2\u0178\u0179\7\5\2\2\u0179"+
+		"\u017b\5.\30\2\u017a\u0178\3\2\2\2\u017b\u017e\3\2\2\2\u017c\u017a\3\2"+
+		"\2\2\u017c\u017d\3\2\2\2\u017d\u017f\3\2\2\2\u017e\u017c\3\2\2\2\u017f"+
+		"\u0180\7\n\2\2\u0180\u018b\3\2\2\2\u0181\u018b\7^\2\2\u0182\u018b\7U\2"+
+		"\2\u0183\u0185\7R\2\2\u0184\u0183\3\2\2\2\u0185\u0186\3\2\2\2\u0186\u0184"+
+		"\3\2\2\2\u0186\u0187\3\2\2\2\u0187\u018b\3\2\2\2\u0188\u018b\7S\2\2\u0189"+
+		"\u018b\7T\2\2\u018a\u0154\3\2\2\2\u018a\u0159\3\2\2\2\u018a\u0161\3\2"+
+		"\2\2\u018a\u0169\3\2\2\2\u018a\u016e\3\2\2\2\u018a\u0170\3\2\2\2\u018a"+
+		"\u0172\3\2\2\2\u018a\u0174\3\2\2\2\u018a\u0176\3\2\2\2\u018a\u0181\3\2"+
+		"\2\2\u018a\u0182\3\2\2\2\u018a\u0184\3\2\2\2\u018a\u0188\3\2\2\2\u018a"+
+		"\u0189\3\2\2\2\u018b\u01c2\3\2\2\2\u018c\u018d\f\25\2\2\u018d\u018e\t"+
+		"\6\2\2\u018e\u01c1\5.\30\26\u018f\u0190\f\24\2\2\u0190\u0191\t\7\2\2\u0191"+
+		"\u01c1\5.\30\25\u0192\u0193\f\23\2\2\u0193\u0194\t\b\2\2\u0194\u01c1\5"+
+		".\30\24\u0195\u0196\f\21\2\2\u0196\u0197\t\t\2\2\u0197\u01c1\5.\30\22"+
+		"\u0198\u0199\f\20\2\2\u0199\u019a\7*\2\2\u019a\u01c1\5.\30\21\u019b\u019c"+
+		"\f\17\2\2\u019c\u019d\7\66\2\2\u019d\u01c1\5.\30\20\u019e\u019f\f\16\2"+
+		"\2\u019f\u01a0\7\67\2\2\u01a0\u01c1\5.\30\17\u01a1\u01a2\f\r\2\2\u01a2"+
+		"\u01a3\78\2\2\u01a3\u01c1\5.\30\16\u01a4\u01a5\f\f\2\2\u01a5\u01a6\79"+
+		"\2\2\u01a6\u01c1\5.\30\r\u01a7\u01a8\f\13\2\2\u01a8\u01a9\7:\2\2\u01a9"+
+		"\u01aa\5.\30\2\u01aa\u01ab\7\34\2\2\u01ab\u01ac\5.\30\f\u01ac\u01c1\3"+
+		"\2\2\2\u01ad\u01ae\f\n\2\2\u01ae\u01af\7\6\2\2\u01af\u01c1\5.\30\n\u01b0"+
+		"\u01b1\f\t\2\2\u01b1\u01b2\t\n\2\2\u01b2\u01c1\5.\30\t\u01b3\u01b4\f\36"+
+		"\2\2\u01b4\u01b6\7\7\2\2\u01b5\u01b7\5\60\31\2\u01b6\u01b5\3\2\2\2\u01b6"+
+		"\u01b7\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8\u01c1\7\b\2\2\u01b9\u01ba\f\33"+
+		"\2\2\u01ba\u01bb\7!\2\2\u01bb\u01bc\5,\27\2\u01bc\u01bd\7\"\2\2\u01bd"+
+		"\u01c1\3\2\2\2\u01be\u01bf\f\30\2\2\u01bf\u01c1\t\3\2\2\u01c0\u018c\3"+
+		"\2\2\2\u01c0\u018f\3\2\2\2\u01c0\u0192\3\2\2\2\u01c0\u0195\3\2\2\2\u01c0"+
+		"\u0198\3\2\2\2\u01c0\u019b\3\2\2\2\u01c0\u019e\3\2\2\2\u01c0\u01a1\3\2"+
+		"\2\2\u01c0\u01a4\3\2\2\2\u01c0\u01a7\3\2\2\2\u01c0\u01ad\3\2\2\2\u01c0"+
+		"\u01b0\3\2\2\2\u01c0\u01b3\3\2\2\2\u01c0\u01b9\3\2\2\2\u01c0\u01be\3\2"+
+		"\2\2\u01c1\u01c4\3\2\2\2\u01c2\u01c0\3\2\2\2\u01c2\u01c3\3\2\2\2\u01c3"+
+		"/\3\2\2\2\u01c4\u01c2\3\2\2\2\u01c5\u01ca\5.\30\2\u01c6\u01c7\7\5\2\2"+
+		"\u01c7\u01c9\5.\30\2\u01c8\u01c6\3\2\2\2\u01c9\u01cc\3\2\2\2\u01ca\u01c8"+
+		"\3\2\2\2\u01ca\u01cb\3\2\2\2\u01cb\61\3\2\2\2\u01cc\u01ca\3\2\2\2\u01cd"+
+		"\u01cf\7E\2\2\u01ce\u01d0\5\64\33\2\u01cf\u01ce\3\2\2\2\u01cf\u01d0\3"+
+		"\2\2\2\u01d0\u01d1\3\2\2\2\u01d1\u01d2\7P\2\2\u01d2\63\3\2\2\2\u01d3\u01d4"+
+		"\7\7\2\2\u01d4\u01d9\5\66\34\2\u01d5\u01d6\7\5\2\2\u01d6\u01d8\5\66\34"+
+		"\2\u01d7\u01d5\3\2\2\2\u01d8\u01db\3\2\2\2\u01d9\u01d7\3\2\2\2\u01d9\u01da"+
+		"\3\2\2\2\u01da\u01dc\3\2\2\2\u01db\u01d9\3\2\2\2\u01dc\u01dd\7\b\2\2\u01dd"+
+		"\65\3\2\2\2\u01de\u01df\7F\2\2\u01df\u01ee\7R\2\2\u01e0\u01e1\7G\2\2\u01e1"+
+		"\u01ee\7^\2\2\u01e2\u01e3\7H\2\2\u01e3\u01ee\7R\2\2\u01e4\u01e5\7I\2\2"+
+		"\u01e5\u01ee\5.\30\2\u01e6\u01e7\7J\2\2\u01e7\u01ee\5.\30\2\u01e8\u01eb"+
+		"\7K\2\2\u01e9\u01ec\7\17\2\2\u01ea\u01ec\5.\30\2\u01eb\u01e9\3\2\2\2\u01eb"+
+		"\u01ea\3\2\2\2\u01ec\u01ee\3\2\2\2\u01ed\u01de\3\2\2\2\u01ed\u01e0\3\2"+
+		"\2\2\u01ed\u01e2\3\2\2\2\u01ed\u01e4\3\2\2\2\u01ed\u01e6\3\2\2\2\u01ed"+
+		"\u01e8\3\2\2\2\u01ee\67\3\2\2\2\u01ef\u01f1\5:\36\2\u01f0\u01ef\3\2\2"+
+		"\2\u01f1\u01f4\3\2\2\2\u01f2\u01f0\3\2\2\2\u01f2\u01f3\3\2\2\2\u01f39"+
+		"\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f5\u01f9\5<\37\2\u01f6\u01f9\5> \2\u01f7"+
+		"\u01f9\5@!\2\u01f8\u01f5\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f8\u01f7\3\2\2"+
+		"\2\u01f9;\3\2\2\2\u01fa\u01fb\7^\2\2\u01fb\u0202\7\34\2\2\u01fc\u01fe"+
+		"\7)\2\2\u01fd\u01ff\7^\2\2\u01fe\u01fd\3\2\2\2\u01fe\u01ff\3\2\2\2\u01ff"+
+		"\u0200\3\2\2\2\u0200\u0202\7\34\2\2\u0201\u01fa\3\2\2\2\u0201\u01fc\3"+
+		"\2\2\2\u0202=\3\2\2\2\u0203\u0205\7O\2\2\u0204\u0206\5B\"\2\u0205\u0204"+
+		"\3\2\2\2\u0205\u0206\3\2\2\2\u0206?\3\2\2\2\u0207\u0208\7L\2\2\u0208\u020d"+
+		"\5D#\2\u0209\u020a\7\5\2\2\u020a\u020c\5D#\2\u020b\u0209\3\2\2\2\u020c"+
+		"\u020f\3\2\2\2\u020d\u020b\3\2\2\2\u020d\u020e\3\2\2\2\u020eA\3\2\2\2"+
+		"\u020f\u020d\3\2\2\2\u0210\u0228\5D#\2\u0211\u0212\7M\2\2\u0212\u0228"+
+		"\5D#\2\u0213\u0214\5D#\2\u0214\u0215\7\5\2\2\u0215\u0216\7^\2\2\u0216"+
+		"\u0228\3\2\2\2\u0217\u0218\7\7\2\2\u0218\u0219\5D#\2\u0219\u021a\7\b\2"+
+		"\2\u021a\u021b\7\5\2\2\u021b\u021c\7^\2\2\u021c\u0228\3\2\2\2\u021d\u021e"+
+		"\7\7\2\2\u021e\u021f\5D#\2\u021f\u0220\7\5\2\2\u0220\u0221\7^\2\2\u0221"+
+		"\u0222\7\b\2\2\u0222\u0228\3\2\2\2\u0223\u0224\7\7\2\2\u0224\u0225\5D"+
+		"#\2\u0225\u0226\7\b\2\2\u0226\u0228\3\2\2\2\u0227\u0210\3\2\2\2\u0227"+
+		"\u0211\3\2\2\2\u0227\u0213\3\2\2\2\u0227\u0217\3\2\2\2\u0227\u021d\3\2"+
+		"\2\2\u0227\u0223\3\2\2\2\u0228C\3\2\2\2\u0229\u022a\b#\1\2\u022a\u022b"+
+		"\7!\2\2\u022b\u022c\5D#\2\u022c\u022d\7\"\2\2\u022d\u0238\3\2\2\2\u022e"+
+		"\u022f\t\13\2\2\u022f\u0238\5D#\n\u0230\u0238\7^\2\2\u0231\u0238\7_\2"+
+		"\2\u0232\u0233\7\t\2\2\u0233\u0234\7^\2\2\u0234\u0238\7\n\2\2\u0235\u0238"+
+		"\7U\2\2\u0236\u0238\7S\2\2\u0237\u0229\3\2\2\2\u0237\u022e\3\2\2\2\u0237"+
+		"\u0230\3\2\2\2\u0237\u0231\3\2\2\2\u0237\u0232\3\2\2\2\u0237\u0235\3\2"+
+		"\2\2\u0237\u0236\3\2\2\2\u0238\u0247\3\2\2\2\u0239\u023a\f\f\2\2\u023a"+
+		"\u023b\7N\2\2\u023b\u0246\5D#\r\u023c\u023d\f\13\2\2\u023d\u023e\t\6\2"+
+		"\2\u023e\u0246\5D#\f\u023f\u0240\f\t\2\2\u0240\u0241\t\f\2\2\u0241\u0246"+
+		"\5D#\n\u0242\u0243\f\b\2\2\u0243\u0244\t\b\2\2\u0244\u0246\5D#\t\u0245"+
+		"\u0239\3\2\2\2\u0245\u023c\3\2\2\2\u0245\u023f\3\2\2\2\u0245\u0242\3\2"+
+		"\2\2\u0246\u0249\3\2\2\2\u0247\u0245\3\2\2\2\u0247\u0248\3\2\2\2\u0248"+
+		"E\3\2\2\2\u0249\u0247\3\2\2\2;PYafm{\u0081\u0087\u008c\u0095\u009c\u00b1"+
 		"\u00b4\u00bd\u00c5\u00cc\u00d9\u00de\u00ea\u00f8\u0103\u010c\u0113\u011a"+
 		"\u011d\u0125\u0128\u012b\u0135\u0137\u013e\u0144\u0146\u0151\u015d\u0165"+
-		"\u017c\u0186\u01b2\u01bc\u01be\u01c6\u01cb\u01d5\u01e7\u01e9\u01ee\u01f4"+
-		"\u01fa\u01fd\u0201\u0209\u0223\u0233\u0241\u0243";
+		"\u017c\u0186\u018a\u01b6\u01c0\u01c2\u01ca\u01cf\u01d9\u01eb\u01ed\u01f2"+
+		"\u01f8\u01fe\u0201\u0205\u020d\u0227\u0237\u0245\u0247";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
index 84d1ddcb7..98035b89e 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
@@ -1,4 +1,4 @@
-// Generated from /Users/jespergravgaard/c64/kickc/src/main/java/dk/camelot64/kickc/parser/KickC.g4 by ANTLR 4.7
+// Generated from C:/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;
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index 2a5e5faea..63febda6c 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -1307,12 +1307,18 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
 
    @Override
    public RValue visitExprString(KickCParser.ExprStringContext ctx) {
-      String text = ctx.getText();
-      String stringValue;
-      if(text.endsWith("z")) {
-         stringValue = text.substring(1, text.length() - 2);
-      }  else {
-         stringValue = text.substring(1, text.length() - 1)+"@";
+      String stringValue ="";
+      String subText = "";
+      for(TerminalNode stringNode : ctx.STRING()) {
+         subText = stringNode.getText();
+         if(subText.endsWith("z")) {
+            stringValue += subText.substring(1, subText.length() - 2);
+         }  else {
+            stringValue += subText.substring(1, subText.length() - 1);
+         }
+      }
+      if(!subText.endsWith("z")) {
+         stringValue += "@";
       }
       return new ConstantString(stringValue);
    }
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 23c2cc2b7..5fb692d96 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,23 +32,9 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
-   /*
-    * Avaiting String concatenation
-
    @Test
-   public void testLiterals() throws IOException, URISyntaxException {
-      compileAndCompare("literals");
-   }
-
-
-    @Test
-    public void testConstantStringConcat() throws IOException, URISyntaxException {
-      compileAndCompare("constant-string-concat");
-    }
-
-   @Test
-   public void testConcatChar() throws IOException, URISyntaxException {
-      compileAndCompare("concat-char");
+   public void testC64DtvGfxExplorer() throws IOException, URISyntaxException {
+      compileAndCompare("c64dtv-gfxexplorer", 10);
    }
 
    @Test
@@ -57,11 +43,20 @@ public class TestPrograms {
    }
 
    @Test
-   public void testC64DtvGfxExplorer() throws IOException, URISyntaxException {
-      compileAndCompare("c64dtv-gfxexplorer", 10);
+   public void testConstantStringConcat0() throws IOException, URISyntaxException {
+      compileAndCompare("constant-string-concat-0", log().verboseParse().verboseStatementSequence().verboseCreateSsa());
    }
 
-    */
+   @Test
+   public void testLiterals() throws IOException, URISyntaxException {
+      compileAndCompare("literals");
+   }
+
+
+   @Test
+   public void testConstantStringConcat() throws IOException, URISyntaxException {
+      compileAndCompare("constant-string-concat");
+   }
 
    @Test
    public void testStatementSequence1() throws IOException, URISyntaxException {
diff --git a/src/test/kc/c64dtv-gfxexplorer.kc b/src/test/kc/c64dtv-gfxexplorer.kc
index 0eba729d9..6c35edfb6 100644
--- a/src/test/kc/c64dtv-gfxexplorer.kc
+++ b/src/test/kc/c64dtv-gfxexplorer.kc
@@ -115,40 +115,40 @@ const byte* FORM_SCREEN = $0400;
 const byte* FORM_CHARSET = $1800; // Charset ROM
 
 byte[] FORM_TEXT =
-     " 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 ;
+     " 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  @"
+     ;
 byte[] FORM_COLS =
-     "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 ;
+     "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  @"
+     ;
 
 // Number of form fields
 byte form_fields_cnt = 36;
diff --git a/src/test/kc/c64dtv-gfxmodes.kc b/src/test/kc/c64dtv-gfxmodes.kc
index 79a3bd30c..87dcd7a88 100644
--- a/src/test/kc/c64dtv-gfxmodes.kc
+++ b/src/test/kc/c64dtv-gfxmodes.kc
@@ -18,27 +18,28 @@ void main() {
 }
 
 byte[] MENU_TEXT =
-     "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 ;
+     "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@"
+     ;
+
 
 void menu() {
     const byte* SCREEN = $8000;
diff --git a/src/test/kc/concat-char.kc b/src/test/kc/concat-char.kc
deleted file mode 100644
index c51f6ae5c..000000000
--- a/src/test/kc/concat-char.kc
+++ /dev/null
@@ -1,10 +0,0 @@
-// Concatenate a char to a string
-
-void main() {
-    byte* screen = $400;
-    byte l = 'l';
-    byte[] msg = "cm"z+l;
-    for( byte i: 0..2 ) {
-        screen[i] = msg[i];
-    }
-}
\ No newline at end of file
diff --git a/src/test/kc/constant-string-concat-0.kc b/src/test/kc/constant-string-concat-0.kc
new file mode 100644
index 000000000..f3b35771b
--- /dev/null
+++ b/src/test/kc/constant-string-concat-0.kc
@@ -0,0 +1,8 @@
+// Concatenates string constants in different ways
+void main() {
+    byte[] msg = "camel" "ot";
+    byte* SCREEN = 0x0400;
+    for( byte i=0;msg[i]!=0;i++) {
+        SCREEN[i] = msg[i];
+    }
+}
\ No newline at end of file
diff --git a/src/test/kc/constant-string-concat.kc b/src/test/kc/constant-string-concat.kc
index 218825e62..0acbe2a1a 100644
--- a/src/test/kc/constant-string-concat.kc
+++ b/src/test/kc/constant-string-concat.kc
@@ -1,13 +1,10 @@
 // Concatenates string constants in different ways
 void main() {
-    byte[] s = "e"z+"l"z;
-    byte[] s2 = s+'o';
-    byte[] s3 = "cam"z+s2;
-    byte e = '!';
-    byte[] s4 = ""z+'t'+ e;
-    byte[] s5 = s3+s4;
+    byte[] s = "c"
+               "ame"
+               "lot";
     byte* SCREEN = $400;
     for( byte i: 0..7) {
-        SCREEN[i] = s5[i];
+        SCREEN[i] = s[i];
     }
 }
\ No newline at end of file
diff --git a/src/test/kc/literals.kc b/src/test/kc/literals.kc
index e72097339..043c30658 100644
--- a/src/test/kc/literals.kc
+++ b/src/test/kc/literals.kc
@@ -2,7 +2,7 @@ byte* SCREEN = $0400;
 
 byte ch = 'a';
 byte num = 1;
-byte[] str = "bc"z+"d"z+'e';
+byte[] str = "bc" "d" "e";
 byte[] nums = { 2, 3, 4, 5};
 
 void main() {
diff --git a/src/test/ref/c64dtv-gfxexplorer.asm b/src/test/ref/c64dtv-gfxexplorer.asm
index a1a01b569..18ca5b0bb 100644
--- a/src/test/ref/c64dtv-gfxexplorer.asm
+++ b/src/test/ref/c64dtv-gfxexplorer.asm
@@ -130,41 +130,6 @@
   .const FORM_CURSOR_BLINK = $28
   // Any shift is pressed
   .const KEY_MODIFIER_SHIFT = KEY_MODIFIER_LSHIFT|KEY_MODIFIER_RSHIFT
-  .label form_ctrl_bmm = form_fields_val+1
-  .label form_ctrl_mcm = form_fields_val+2
-  .label form_ctrl_ecm = form_fields_val+3
-  .label form_ctrl_hicol = form_fields_val+4
-  .label form_ctrl_line = form_fields_val+5
-  .label form_ctrl_colof = form_fields_val+6
-  .label form_ctrl_chunk = form_fields_val+7
-  .label form_ctrl_borof = form_fields_val+8
-  .label form_ctrl_overs = form_fields_val+9
-  .label form_a_pattern = form_fields_val+$a
-  .label form_a_start_hi = form_fields_val+$b
-  .label form_a_start_lo = form_fields_val+$c
-  .label form_a_step_hi = form_fields_val+$d
-  .label form_a_step_lo = form_fields_val+$e
-  .label form_a_mod_hi = form_fields_val+$f
-  .label form_a_mod_lo = form_fields_val+$10
-  .label form_b_pattern = form_fields_val+$11
-  .label form_b_start_hi = form_fields_val+$12
-  .label form_b_start_lo = form_fields_val+$13
-  .label form_b_step_hi = form_fields_val+$14
-  .label form_b_step_lo = form_fields_val+$15
-  .label form_b_mod_hi = form_fields_val+$16
-  .label form_b_mod_lo = form_fields_val+$17
-  .label form_vic_screen = form_fields_val+$18
-  .label form_vic_gfx = form_fields_val+$19
-  .label form_vic_cols = form_fields_val+$1a
-  .label form_dtv_palet = form_fields_val+$1b
-  .label form_vic_bg0_hi = form_fields_val+$1c
-  .label form_vic_bg0_lo = form_fields_val+$1d
-  .label form_vic_bg1_hi = form_fields_val+$1e
-  .label form_vic_bg1_lo = form_fields_val+$1f
-  .label form_vic_bg2_hi = form_fields_val+$20
-  .label form_vic_bg2_lo = form_fields_val+$21
-  .label form_vic_bg3_hi = form_fields_val+$22
-  .label form_vic_bg3_lo = form_fields_val+$23
   .label print_char_cursor = 5
   .label print_line_cursor = $10
   .label keyboard_events_size = 8
@@ -196,61 +161,61 @@ main: {
 // Change graphics mode to show the selected graphics mode
 gfx_mode: {
     .label _22 = 9
-    .label _24 = 3
     .label _26 = 3
     .label _28 = 3
     .label _36 = 9
-    .label _38 = 3
     .label _40 = 3
     .label _42 = 3
     .label _52 = 3
+    .label _53 = 3
     .label _54 = 3
     .label _55 = 3
     .label _56 = 2
     .label _57 = 3
+    .label _58 = 3
     .label _59 = 3
     .label plane_a = 9
     .label plane_b = 9
     .label vic_colors = 3
     .label col = 5
     .label cy = 2
-    lda form_ctrl_line
+    lda form_fields_val+5
     cmp #0
     beq b10
-    ldx #0|DTV_LINEAR
+    ldx #DTV_LINEAR
     jmp b1
   b10:
     ldx #0
   b1:
-    lda form_ctrl_borof
+    lda form_fields_val+8
     cmp #0
     beq b2
     txa
     ora #DTV_BORDER_OFF
     tax
   b2:
-    lda form_ctrl_hicol
+    lda form_fields_val+4
     cmp #0
     beq b3
     txa
     ora #DTV_HIGHCOLOR
     tax
   b3:
-    lda form_ctrl_overs
+    lda form_fields_val+9
     cmp #0
     beq b4
     txa
     ora #DTV_OVERSCAN
     tax
   b4:
-    lda form_ctrl_colof
+    lda form_fields_val+6
     cmp #0
     beq b5
     txa
     ora #DTV_COLORRAM_OFF
     tax
   b5:
-    lda form_ctrl_chunk
+    lda form_fields_val+7
     cmp #0
     beq b6
     txa
@@ -258,7 +223,7 @@ gfx_mode: {
     tax
   b6:
     stx DTV_CONTROL
-    lda form_ctrl_ecm
+    lda form_fields_val+3
     cmp #0
     beq b11
     ldx #VIC_DEN|VIC_RSEL|3|VIC_ECM
@@ -266,7 +231,7 @@ gfx_mode: {
   b11:
     ldx #VIC_DEN|VIC_RSEL|3
   b7:
-    lda form_ctrl_bmm
+    lda form_fields_val+1
     cmp #0
     beq b8
     txa
@@ -274,7 +239,7 @@ gfx_mode: {
     tax
   b8:
     stx VIC_CONTROL
-    lda form_ctrl_mcm
+    lda form_fields_val+2
     cmp #0
     beq b12
     lda #VIC_CSEL|VIC_MCM
@@ -283,14 +248,14 @@ gfx_mode: {
     lda #VIC_CSEL
   b9:
     sta VIC_CONTROL2
-    lda form_a_start_hi
+    lda form_fields_val+$b
     asl
     asl
     asl
     asl
-    ora form_a_start_lo
+    ora form_fields_val+$c
     tax
-    lda form_a_pattern
+    lda form_fields_val+$a
     jsr get_plane
     txa
     clc
@@ -306,15 +271,12 @@ gfx_mode: {
     adc #0
     sta plane_a+3
     lda plane_a
-    sta _24
-    lda plane_a+1
-    sta _24+1
-    lda _24
-    sta DTV_PLANEA_START_LO
-    lda plane_a
     sta _26
     lda plane_a+1
     sta _26+1
+    lda _26
+    sta DTV_PLANEA_START_LO
+    lda _26+1
     sta DTV_PLANEA_START_MI
     lda plane_a+2
     sta _28
@@ -322,30 +284,30 @@ gfx_mode: {
     sta _28+1
     lda _28
     sta DTV_PLANEA_START_HI
-    lda form_a_step_hi
+    lda form_fields_val+$d
     asl
     asl
     asl
     asl
-    ora form_a_step_lo
+    ora form_fields_val+$e
     sta DTV_PLANEA_STEP
-    lda form_a_mod_hi
+    lda form_fields_val+$f
     asl
     asl
     asl
     asl
-    ora form_a_mod_lo
+    ora form_fields_val+$10
     sta DTV_PLANEA_MODULO_LO
     lda #0
     sta DTV_PLANEA_MODULO_HI
-    lda form_b_start_hi
+    lda form_fields_val+$12
     asl
     asl
     asl
     asl
-    ora form_b_start_lo
+    ora form_fields_val+$13
     tax
-    lda form_b_pattern
+    lda form_fields_val+$11
     jsr get_plane
     txa
     clc
@@ -361,15 +323,12 @@ gfx_mode: {
     adc #0
     sta plane_b+3
     lda plane_b
-    sta _38
-    lda plane_b+1
-    sta _38+1
-    lda _38
-    sta DTV_PLANEB_START_LO
-    lda plane_b
     sta _40
     lda plane_b+1
     sta _40+1
+    lda _40
+    sta DTV_PLANEB_START_LO
+    lda _40+1
     sta DTV_PLANEB_START_MI
     lda plane_b+2
     sta _42
@@ -377,19 +336,19 @@ gfx_mode: {
     sta _42+1
     lda _42
     sta DTV_PLANEB_START_HI
-    lda form_b_step_hi
+    lda form_fields_val+$14
     asl
     asl
     asl
     asl
-    ora form_b_step_lo
+    ora form_fields_val+$15
     sta DTV_PLANEB_STEP
-    lda form_b_mod_hi
+    lda form_fields_val+$16
     asl
     asl
     asl
     asl
-    ora form_b_mod_lo
+    ora form_fields_val+$17
     sta DTV_PLANEB_MODULO_LO
     lda #0
     sta DTV_PLANEB_MODULO_HI
@@ -399,7 +358,7 @@ gfx_mode: {
     // Set VIC Bank bits to output - all others to input
     lda #3^VIC_SCREEN0/$4000
     sta CIA2_PORT_A
-    lda form_vic_screen
+    lda form_fields_val+$18
     jsr get_vic_screen
     lda _54
     and #<$3fff
@@ -415,7 +374,7 @@ gfx_mode: {
     bne !-
     lda _55
     sta _56
-    lda form_vic_gfx
+    lda form_fields_val+$19
     jsr get_vic_charset
     lda _59
     and #<$3fff
@@ -429,7 +388,7 @@ gfx_mode: {
     // Set VIC Bank
     // VIC memory
     sta VIC_MEMORY
-    lda form_vic_cols
+    lda form_fields_val+$1a
     jsr get_vic_screen
     lda #0
     sta cy
@@ -461,36 +420,36 @@ gfx_mode: {
     // Background colors
     lda #0
     sta BORDERCOL
-    lda form_vic_bg0_hi
+    lda form_fields_val+$1c
     asl
     asl
     asl
     asl
-    ora form_vic_bg0_lo
+    ora form_fields_val+$1d
     sta BGCOL1
-    lda form_vic_bg1_hi
+    lda form_fields_val+$1e
     asl
     asl
     asl
     asl
-    ora form_vic_bg1_lo
+    ora form_fields_val+$1f
     sta BGCOL2
-    lda form_vic_bg2_hi
+    lda form_fields_val+$20
     asl
     asl
     asl
     asl
-    ora form_vic_bg2_lo
+    ora form_fields_val+$21
     sta BGCOL3
-    lda form_vic_bg3_hi
+    lda form_fields_val+$22
     asl
     asl
     asl
     asl
-    ora form_vic_bg3_lo
+    ora form_fields_val+$23
     sta BGCOL4
     // DTV Palette
-    lda form_dtv_palet
+    lda form_fields_val+$1b
     cmp #0
     beq b13
     ldx #0
@@ -508,7 +467,9 @@ gfx_mode: {
     jsr keyboard_event_scan
     jsr keyboard_event_get
     cmp #KEY_SPACE
-    bne b25
+    beq breturn
+    jmp b25
+  breturn:
     rts
   // DTV Palette - default
   b13:
@@ -567,7 +528,7 @@ keyboard_event_scan: {
     jsr keyboard_event_pressed
     cmp #0
     beq b4
-    ldx #0|KEY_MODIFIER_LSHIFT
+    ldx #KEY_MODIFIER_LSHIFT
     jmp b1
   b4:
     ldx #0
@@ -679,39 +640,39 @@ keyboard_matrix_read: {
 get_vic_screen: {
     .label return = 3
     cmp #0
-    beq b2
+    beq b1
     cmp #1
-    beq b3
+    beq b2
     cmp #2
-    beq b4
+    beq b3
     cmp #3
-    beq b5
+    beq b4
     cmp #4
-    bne b2
+    bne b1
     lda #<VIC_SCREEN4
     sta return
     lda #>VIC_SCREEN4
     sta return+1
     rts
-  b2:
+  b1:
     lda #<VIC_SCREEN0
     sta return
     lda #>VIC_SCREEN0
     sta return+1
     rts
-  b3:
+  b2:
     lda #<VIC_SCREEN1
     sta return
     lda #>VIC_SCREEN1
     sta return+1
     rts
-  b4:
+  b3:
     lda #<VIC_SCREEN2
     sta return
     lda #>VIC_SCREEN2
     sta return+1
     rts
-  b5:
+  b4:
     lda #<VIC_SCREEN3
     sta return
     lda #>VIC_SCREEN3
@@ -723,15 +684,15 @@ get_vic_screen: {
 get_vic_charset: {
     .label return = 3
     cmp #0
-    beq b2
+    beq b1
     cmp #1
-    bne b2
+    bne b1
     lda #<VIC_BITMAP
     sta return
     lda #>VIC_BITMAP
     sta return+1
     rts
-  b2:
+  b1:
     lda #<VIC_CHARSET_ROM
     sta return
     lda #>VIC_CHARSET_ROM
@@ -785,7 +746,7 @@ get_plane: {
     cmp #$c
     beq b6
     cmp #$d
-    bne b2
+    bne b1
     lda #<PLANE_FULL
     sta return
     lda #>PLANE_FULL
@@ -795,14 +756,24 @@ get_plane: {
     lda #>PLANE_FULL>>$10
     sta return+3
     rts
-  b2:
-    lda #<$ffffffff&VIC_SCREEN0
+  b1:
+    lda #<VIC_SCREEN0
     sta return
-    lda #>$ffffffff&VIC_SCREEN0
+    lda #>VIC_SCREEN0
     sta return+1
-    lda #<$ffffffff&VIC_SCREEN0>>$10
+    lda #<VIC_SCREEN0>>$10
     sta return+2
-    lda #>$ffffffff&VIC_SCREEN0>>$10
+    lda #>VIC_SCREEN0>>$10
+    sta return+3
+    rts
+  b2:
+    lda #<VIC_SCREEN0
+    sta return
+    lda #>VIC_SCREEN0
+    sta return+1
+    lda #<VIC_SCREEN0>>$10
+    sta return+2
+    lda #>VIC_SCREEN0>>$10
     sta return+3
     rts
   b3:
@@ -846,53 +817,53 @@ get_plane: {
     sta return+3
     rts
   b7:
-    lda #<$ffffffff&VIC_SCREEN1
+    lda #<VIC_SCREEN1
     sta return
-    lda #>$ffffffff&VIC_SCREEN1
+    lda #>VIC_SCREEN1
     sta return+1
-    lda #<$ffffffff&VIC_SCREEN1>>$10
+    lda #<VIC_SCREEN1>>$10
     sta return+2
-    lda #>$ffffffff&VIC_SCREEN1>>$10
+    lda #>VIC_SCREEN1>>$10
     sta return+3
     rts
   b8:
-    lda #<$ffffffff&VIC_SCREEN2
+    lda #<VIC_SCREEN2
     sta return
-    lda #>$ffffffff&VIC_SCREEN2
+    lda #>VIC_SCREEN2
     sta return+1
-    lda #<$ffffffff&VIC_SCREEN2>>$10
+    lda #<VIC_SCREEN2>>$10
     sta return+2
-    lda #>$ffffffff&VIC_SCREEN2>>$10
+    lda #>VIC_SCREEN2>>$10
     sta return+3
     rts
   b9:
-    lda #<$ffffffff&VIC_SCREEN3
+    lda #<VIC_SCREEN3
     sta return
-    lda #>$ffffffff&VIC_SCREEN3
+    lda #>VIC_SCREEN3
     sta return+1
-    lda #<$ffffffff&VIC_SCREEN3>>$10
+    lda #<VIC_SCREEN3>>$10
     sta return+2
-    lda #>$ffffffff&VIC_SCREEN3>>$10
+    lda #>VIC_SCREEN3>>$10
     sta return+3
     rts
   b10:
-    lda #<$ffffffff&VIC_BITMAP
+    lda #<VIC_BITMAP
     sta return
-    lda #>$ffffffff&VIC_BITMAP
+    lda #>VIC_BITMAP
     sta return+1
-    lda #<$ffffffff&VIC_BITMAP>>$10
+    lda #<VIC_BITMAP>>$10
     sta return+2
-    lda #>$ffffffff&VIC_BITMAP>>$10
+    lda #>VIC_BITMAP>>$10
     sta return+3
     rts
   b11:
-    lda #<$ffffffff&VIC_CHARSET_ROM
+    lda #<VIC_CHARSET_ROM
     sta return
-    lda #>$ffffffff&VIC_CHARSET_ROM
+    lda #>VIC_CHARSET_ROM
     sta return+1
-    lda #<$ffffffff&VIC_CHARSET_ROM>>$10
+    lda #<VIC_CHARSET_ROM>>$10
     sta return+2
-    lda #>$ffffffff&VIC_CHARSET_ROM>>$10
+    lda #>VIC_CHARSET_ROM>>$10
     sta return+3
     rts
   b12:
@@ -956,10 +927,10 @@ form_mode: {
     lda form_fields_val
     jsr render_preset_name
     // DTV Graphics Bank
-    lda #($ffffffff&FORM_CHARSET)/$10000
+    lda #0
     sta DTV_GRAPHICS_VIC_BANK
     // DTV Color Bank
-    lda #DTV_COLOR_BANK_DEFAULT/$400
+    lda #<DTV_COLOR_BANK_DEFAULT/$400
     sta DTV_COLOR_BANK_LO
     lda #0
     sta DTV_COLOR_BANK_HI
@@ -967,7 +938,6 @@ form_mode: {
     lda #3
     sta CIA2_PORT_A_DDR
     // Set VIC Bank bits to output - all others to input
-    lda #3^FORM_CHARSET/$4000
     sta CIA2_PORT_A
     // Set VIC Bank
     // DTV Graphics Mode
@@ -982,7 +952,7 @@ form_mode: {
     lda #(FORM_SCREEN&$3fff)/$40|(FORM_CHARSET&$3fff)/$400
     sta VIC_MEMORY
     // DTV Plane A to FORM_SCREEN also
-    lda #<FORM_SCREEN
+    lda #0
     sta DTV_PLANEA_START_LO
     lda #>FORM_SCREEN
     sta DTV_PLANEA_START_MI
@@ -1030,93 +1000,93 @@ form_mode: {
 render_preset_name: {
     .label name = 3
     cmp #0
-    beq b12
-    cmp #1
-    beq b4
-    cmp #2
-    beq b5
-    cmp #3
-    beq b6
-    cmp #4
-    beq b7
-    cmp #5
-    beq b8
-    cmp #6
-    beq b9
-    cmp #7
-    beq b10
-    cmp #8
-    beq b11
-    cmp #9
-    beq b2
-    cmp #$a
     beq b3
-  b12:
+    cmp #1
+    beq b6
+    cmp #2
+    beq b7
+    cmp #3
+    beq b8
+    cmp #4
+    beq b9
+    cmp #5
+    beq b10
+    cmp #6
+    beq b11
+    cmp #7
+    beq b12
+    cmp #8
+    beq b4
+    cmp #9
+    beq b5
+    cmp #$a
+    beq b1
+  b3:
     lda #<name_1
     sta name
     lda #>name_1
     sta name+1
-    jmp b1
-  b2:
-    lda #<name_10
-    sta name
-    lda #>name_10
-    sta name+1
-    jmp b1
-  b3:
+    jmp b2
+  b1:
     lda #<name_11
     sta name
     lda #>name_11
     sta name+1
-    jmp b1
+    jmp b2
   b4:
-    lda #<name_2
-    sta name
-    lda #>name_2
-    sta name+1
-    jmp b1
-  b5:
-    lda #<name_3
-    sta name
-    lda #>name_3
-    sta name+1
-    jmp b1
-  b6:
-    lda #<name_4
-    sta name
-    lda #>name_4
-    sta name+1
-    jmp b1
-  b7:
-    lda #<name_5
-    sta name
-    lda #>name_5
-    sta name+1
-    jmp b1
-  b8:
-    lda #<name_6
-    sta name
-    lda #>name_6
-    sta name+1
-    jmp b1
-  b9:
-    lda #<name_7
-    sta name
-    lda #>name_7
-    sta name+1
-    jmp b1
-  b10:
-    lda #<name_8
-    sta name
-    lda #>name_8
-    sta name+1
-    jmp b1
-  b11:
     lda #<name_9
     sta name
     lda #>name_9
     sta name+1
-  b1:
+    jmp b2
+  b5:
+    lda #<name_10
+    sta name
+    lda #>name_10
+    sta name+1
+    jmp b2
+  b6:
+    lda #<name_2
+    sta name
+    lda #>name_2
+    sta name+1
+    jmp b2
+  b7:
+    lda #<name_3
+    sta name
+    lda #>name_3
+    sta name+1
+    jmp b2
+  b8:
+    lda #<name_4
+    sta name
+    lda #>name_4
+    sta name+1
+    jmp b2
+  b9:
+    lda #<name_5
+    sta name
+    lda #>name_5
+    sta name+1
+    jmp b2
+  b10:
+    lda #<name_6
+    sta name
+    lda #>name_6
+    sta name+1
+    jmp b2
+  b11:
+    lda #<name_7
+    sta name
+    lda #>name_7
+    sta name+1
+    jmp b2
+  b12:
+    lda #<name_8
+    sta name
+    lda #>name_8
+    sta name+1
+  b2:
     jsr print_str_at
     rts
     name_1: .text "Standard Charset              @"
@@ -1168,7 +1138,7 @@ form_render_values: {
     ldy form_fields_val,x
     lda print_hextab,y
     ldy form_field_ptr.x
-    sta (form_field_ptr._2),y
+    sta (form_field_ptr.line),y
     inx
     cpx #form_fields_cnt
     bcc b1
@@ -1178,6 +1148,7 @@ form_render_values: {
 // field_idx is the index of the field to get the screen address for
 // form_field_ptr(byte register(X) field_idx)
 form_field_ptr: {
+    .label line = 3
     .label x = $13
     .label _2 = 3
     lda form_fields_y,x
@@ -1196,93 +1167,93 @@ form_field_ptr: {
 apply_preset: {
     .label preset = 3
     cmp #0
-    beq b12
-    cmp #1
-    beq b4
-    cmp #2
-    beq b5
-    cmp #3
-    beq b6
-    cmp #4
-    beq b7
-    cmp #5
-    beq b8
-    cmp #6
-    beq b9
-    cmp #7
-    beq b10
-    cmp #8
-    beq b11
-    cmp #9
-    beq b2
-    cmp #$a
     beq b3
-  b12:
+    cmp #1
+    beq b6
+    cmp #2
+    beq b7
+    cmp #3
+    beq b8
+    cmp #4
+    beq b9
+    cmp #5
+    beq b10
+    cmp #6
+    beq b11
+    cmp #7
+    beq b12
+    cmp #8
+    beq b4
+    cmp #9
+    beq b5
+    cmp #$a
+    beq b1
+  b3:
     lda #<preset_stdchar
     sta preset
     lda #>preset_stdchar
     sta preset+1
-    jmp b1
-  b2:
-    lda #<preset_sixsfred2
-    sta preset
-    lda #>preset_sixsfred2
-    sta preset+1
-    jmp b1
-  b3:
+    jmp b2
+  b1:
     lda #<preset_8bpppixelcell
     sta preset
     lda #>preset_8bpppixelcell
     sta preset+1
-    jmp b1
+    jmp b2
   b4:
-    lda #<preset_ecmchar
-    sta preset
-    lda #>preset_ecmchar
-    sta preset+1
-    jmp b1
-  b5:
-    lda #<preset_stdbm
-    sta preset
-    lda #>preset_stdbm
-    sta preset+1
-    jmp b1
-  b6:
-    lda #<preset_mcbm
-    sta preset
-    lda #>preset_mcbm
-    sta preset+1
-    jmp b1
-  b7:
-    lda #<preset_hi_stdchar
-    sta preset
-    lda #>preset_hi_stdchar
-    sta preset+1
-    jmp b1
-  b8:
-    lda #<preset_hi_ecmchar
-    sta preset
-    lda #>preset_hi_ecmchar
-    sta preset+1
-    jmp b1
-  b9:
-    lda #<preset_twoplane
-    sta preset
-    lda #>preset_twoplane
-    sta preset+1
-    jmp b1
-  b10:
-    lda #<preset_chunky
-    sta preset
-    lda #>preset_chunky
-    sta preset+1
-    jmp b1
-  b11:
     lda #<preset_sixsfred
     sta preset
     lda #>preset_sixsfred
     sta preset+1
-  b1:
+    jmp b2
+  b5:
+    lda #<preset_sixsfred2
+    sta preset
+    lda #>preset_sixsfred2
+    sta preset+1
+    jmp b2
+  b6:
+    lda #<preset_ecmchar
+    sta preset
+    lda #>preset_ecmchar
+    sta preset+1
+    jmp b2
+  b7:
+    lda #<preset_stdbm
+    sta preset
+    lda #>preset_stdbm
+    sta preset+1
+    jmp b2
+  b8:
+    lda #<preset_mcbm
+    sta preset
+    lda #>preset_mcbm
+    sta preset+1
+    jmp b2
+  b9:
+    lda #<preset_hi_stdchar
+    sta preset
+    lda #>preset_hi_stdchar
+    sta preset+1
+    jmp b2
+  b10:
+    lda #<preset_hi_ecmchar
+    sta preset
+    lda #>preset_hi_ecmchar
+    sta preset+1
+    jmp b2
+  b11:
+    lda #<preset_twoplane
+    sta preset
+    lda #>preset_twoplane
+    sta preset+1
+    jmp b2
+  b12:
+    lda #<preset_chunky
+    sta preset
+    lda #>preset_chunky
+    sta preset+1
+  b2:
     ldy #0
   // Copy preset values into the fields
   b13:
@@ -1316,8 +1287,8 @@ form_control: {
   !b2:
     lda #$7f
     ldy form_field_ptr.x
-    and (form_field_ptr._2),y
-    sta (form_field_ptr._2),y
+    and (form_field_ptr.line),y
+    sta (form_field_ptr.line),y
   b3:
     jsr keyboard_event_scan
     jsr keyboard_event_get
@@ -1325,78 +1296,78 @@ form_control: {
     bne b4
     lda #$7f
     ldy form_field_ptr.x
-    and (form_field_ptr._2),y
+    and (form_field_ptr.line),y
     // Unblink the cursor
-    sta (form_field_ptr._2),y
+    sta (form_field_ptr.line),y
     txa
     and #KEY_MODIFIER_SHIFT
     cmp #0
-    beq b12
+    beq b13
     dec form_field_idx
     lda #$ff
     cmp form_field_idx
-    bne b13
+    bne b14
     lda #form_fields_cnt-1
     sta form_field_idx
-  b13:
+  b14:
     lda #FORM_CURSOR_BLINK/2
     sta form_cursor_count
     ldx #0
     rts
-  b12:
+  b13:
     inc form_field_idx
     lda #form_fields_cnt
     cmp form_field_idx
-    bne b13
+    bne b14
     lda #0
     sta form_field_idx
-    jmp b13
+    jmp b14
   b4:
     cmp #KEY_CRSR_RIGHT
     bne b5
     txa
     and #KEY_MODIFIER_SHIFT
     cmp #0
-    beq b14
+    beq b15
     ldx form_field_idx
     dec form_fields_val,x
     lda #$ff
     ldy form_field_idx
     cmp form_fields_val,y
-    bne b15
+    bne b16
     lda form_fields_max,y
     sta form_fields_val,y
-  b15:
+  b16:
     // Render field value
     ldx form_field_idx
     ldy form_fields_val,x
     lda print_hextab,y
     ldy form_field_ptr.x
-    sta (form_field_ptr._2),y
-  b6:
+    sta (form_field_ptr.line),y
+  b7:
     ldx #0
     rts
-  b14:
+  b15:
     ldx form_field_idx
     inc form_fields_val,x
     ldy form_field_idx
     lda form_fields_val,y
     cmp form_fields_max,y
-    bcc b15
-    beq b15
+    bcc b16
+    beq b16
     lda #0
     sta form_fields_val,y
-    jmp b15
+    jmp b16
   b5:
     cmp #KEY_SPACE
-    bne b6
+    bne b7
     ldx #$ff
     rts
   b2:
     lda #$80
     ldy form_field_ptr.x
-    ora (form_field_ptr._2),y
-    sta (form_field_ptr._2),y
+    ora (form_field_ptr.line),y
+    sta (form_field_ptr.line),y
     jmp b3
 }
 // Set the screen to use for the form.
@@ -1680,9 +1651,9 @@ gfx_init_plane_horisontal2: {
     .label ay = 2
     lda #gfxbCpuBank
     jsr dtvSetCpuBankSegment1
-    lda #<$4000+(PLANE_HORISONTAL2&$3fff)
+    lda #<$4000
     sta gfxa
-    lda #>$4000+(PLANE_HORISONTAL2&$3fff)
+    lda #>$4000
     sta gfxa+1
     lda #0
     sta ay
@@ -1753,9 +1724,9 @@ gfx_init_plane_horisontal: {
     .label ay = 2
     lda #gfxbCpuBank
     jsr dtvSetCpuBankSegment1
-    lda #<$4000+(PLANE_HORISONTAL&$3fff)
+    lda #<$4000
     sta gfxa
-    lda #>$4000+(PLANE_HORISONTAL&$3fff)
+    lda #>$4000
     sta gfxa+1
     lda #0
     sta ay
@@ -1810,9 +1781,9 @@ gfx_init_plane_charset8: {
     lda #0
     sta ch
     sta col
-    lda #<$4000+(PLANE_CHARSET8&$3fff)
+    lda #<$4000
     sta gfxa
-    lda #>$4000+(PLANE_CHARSET8&$3fff)
+    lda #>$4000
     sta gfxa+1
     lda #<CHARGEN
     sta chargen
@@ -2104,6 +2075,7 @@ bitmap_plot: {
     .label _0 = 3
     .label plotter_x = 3
     .label plotter_y = 5
+    .label plotter = 3
     lda bitmap_plot_xhi,x
     sta plotter_x+1
     lda bitmap_plot_xlo,x
@@ -2121,8 +2093,8 @@ bitmap_plot: {
     sta _0+1
     lda bitmap_plot_bit,x
     ldy #0
-    ora (_0),y
-    sta (_0),y
+    ora (plotter),y
+    sta (plotter),y
     rts
 }
 // bitmap_line_ydxi(byte zeropage($e) y, byte register(X) x, byte zeropage($12) y1, byte zeropage(7) yd, byte zeropage(8) xd)
@@ -2260,7 +2232,7 @@ bitmap_clear: {
 }
 // Initialize the bitmap plotter tables for a specific bitmap
 bitmap_init: {
-    .label _6 = 2
+    .label _10 = 2
     .label yoffs = 3
     ldy #$80
     ldx #0
@@ -2288,15 +2260,14 @@ bitmap_init: {
     tax
   b3:
     lda #7
-    sax _6
+    sax _10
     lda yoffs
-    ora _6
+    ora _10
     sta bitmap_plot_ylo,x
     lda yoffs+1
     sta bitmap_plot_yhi,x
-    txa
-    and #7
-    cmp #7
+    lda #7
+    cmp _10
     bne b4
     clc
     lda yoffs
@@ -2563,6 +2534,9 @@ keyboard_init: {
   bitmap_plot_ylo: .fill $100, 0
   bitmap_plot_yhi: .fill $100, 0
   bitmap_plot_bit: .fill $100, 0
+  // Charset ROM
+  FORM_TEXT: .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  @@"
+  FORM_COLS: .text "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  @@"
   // Form fields x/y-positions
   form_fields_x: .byte 8, $c, $c, $c, $c, $c, $c, $c, $c, $c, $19, $18, $19, $18, $19, $18, $19, $19, $18, $19, $18, $19, $18, $19, $25, $25, $25, $25, $24, $25, $24, $25, $24, $25, $24, $25
   form_fields_y: .byte 2, 5, 6, 7, 8, 9, $a, $b, $c, $d, 5, 6, 6, 7, 7, 8, 8, $b, $c, $c, $d, $d, $e, $e, 5, 6, 7, $a, $b, $b, $c, $c, $d, $d, $e, $e
@@ -2595,6 +2569,3 @@ keyboard_init: {
   // Table with addresses of the y-lines of the form. The first line contains the address of the form screen.
   form_line_lo: .fill $19, 0
   form_line_hi: .fill $19, 0
-  // Charset ROM
-  FORM_TEXT: .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  @"+"@"
-  FORM_COLS: .text "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  @"+"@"
diff --git a/src/test/ref/c64dtv-gfxmodes.asm b/src/test/ref/c64dtv-gfxmodes.asm
index e496af02c..429e6c1c9 100644
--- a/src/test/ref/c64dtv-gfxmodes.asm
+++ b/src/test/ref/c64dtv-gfxmodes.asm
@@ -120,10 +120,10 @@ menu: {
     .label c = 2
     // Charset ROM
     // DTV Graphics Bank
-    lda #($ffffffff&CHARSET)/$10000
+    lda #0
     sta DTV_GRAPHICS_VIC_BANK
     // DTV Color Bank
-    lda #DTV_COLOR_BANK_DEFAULT/$400
+    lda #<DTV_COLOR_BANK_DEFAULT/$400
     sta DTV_COLOR_BANK_LO
     lda #0
     sta DTV_COLOR_BANK_HI
@@ -142,7 +142,7 @@ menu: {
     lda #VIC_CSEL
     sta VIC_CONTROL2
     // VIC Memory Pointers
-    lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400
+    lda #(CHARSET&$3fff)/$400
     sta VIC_MEMORY
     ldx #0
   // DTV Palette - default
@@ -286,11 +286,10 @@ mode_8bppchunkybmm: {
     lda #VIC_MCM|VIC_CSEL
     sta VIC_CONTROL2
     // Linear Graphics Plane B Counter
-    lda #PLANEB&$ffff
-    sta DTV_PLANEB_START_LO
     lda #0
+    sta DTV_PLANEB_START_LO
     sta DTV_PLANEB_START_MI
-    lda #PLANEB>>$10
+    lda #<PLANEB>>$10
     sta DTV_PLANEB_START_HI
     lda #8
     sta DTV_PLANEB_STEP
@@ -525,7 +524,7 @@ mode_8bpppixelcell: {
     lda #VIC_MCM|VIC_CSEL
     sta VIC_CONTROL2
     // Linear Graphics Plane A Counter
-    lda #<PLANEA
+    lda #0
     sta DTV_PLANEA_START_LO
     lda #>PLANEA
     sta DTV_PLANEA_START_MI
@@ -537,7 +536,6 @@ mode_8bpppixelcell: {
     sta DTV_PLANEA_MODULO_LO
     sta DTV_PLANEA_MODULO_HI
     // Linear Graphics Plane B Counter
-    lda #<PLANEB
     sta DTV_PLANEB_START_LO
     lda #>PLANEB
     sta DTV_PLANEB_START_MI
@@ -674,7 +672,7 @@ mode_sixsfred: {
     lda #VIC_MCM|VIC_CSEL
     sta VIC_CONTROL2
     // Linear Graphics Plane A Counter
-    lda #<PLANEA
+    lda #0
     sta DTV_PLANEA_START_LO
     lda #>PLANEA
     sta DTV_PLANEA_START_MI
@@ -686,7 +684,6 @@ mode_sixsfred: {
     sta DTV_PLANEA_MODULO_LO
     sta DTV_PLANEA_MODULO_HI
     // Linear Graphics Plane B Counter
-    lda #<PLANEB
     sta DTV_PLANEB_START_LO
     lda #>PLANEB
     sta DTV_PLANEB_START_MI
@@ -700,9 +697,9 @@ mode_sixsfred: {
     // DTV Color Bank
     lda #<COLORS/$400
     sta DTV_COLOR_BANK_LO
-    lda #>COLORS/$400
+    lda #0
     sta DTV_COLOR_BANK_HI
-    ldx #0
+    tax
   // DTV Palette - Grey Tones
   b1:
     txa
@@ -823,7 +820,7 @@ mode_twoplanebitmap: {
     lda #VIC_CSEL
     sta VIC_CONTROL2
     // Linear Graphics Plane A Counter
-    lda #<PLANEA
+    lda #0
     sta DTV_PLANEA_START_LO
     lda #>PLANEA
     sta DTV_PLANEA_START_MI
@@ -835,7 +832,6 @@ mode_twoplanebitmap: {
     sta DTV_PLANEA_MODULO_LO
     sta DTV_PLANEA_MODULO_HI
     // Linear Graphics Plane B Counter
-    lda #<PLANEB
     sta DTV_PLANEB_START_LO
     lda #>PLANEB
     sta DTV_PLANEB_START_MI
@@ -849,9 +845,9 @@ mode_twoplanebitmap: {
     // DTV Color Bank
     lda #<COLORS/$400
     sta DTV_COLOR_BANK_LO
-    lda #>COLORS/$400
+    lda #0
     sta DTV_COLOR_BANK_HI
-    ldx #0
+    tax
   // DTV Palette - Grey Tones
   b1:
     txa
@@ -989,7 +985,7 @@ mode_sixsfred2: {
     lda #VIC_MCM|VIC_CSEL
     sta VIC_CONTROL2
     // Linear Graphics Plane A Counter
-    lda #<PLANEA
+    lda #0
     sta DTV_PLANEA_START_LO
     lda #>PLANEA
     sta DTV_PLANEA_START_MI
@@ -1001,7 +997,6 @@ mode_sixsfred2: {
     sta DTV_PLANEA_MODULO_LO
     sta DTV_PLANEA_MODULO_HI
     // Linear Graphics Plane B Counter
-    lda #<PLANEB
     sta DTV_PLANEB_START_LO
     lda #>PLANEB
     sta DTV_PLANEB_START_MI
@@ -1015,9 +1010,9 @@ mode_sixsfred2: {
     // DTV Color Bank
     lda #<COLORS/$400
     sta DTV_COLOR_BANK_LO
-    lda #>COLORS/$400
+    lda #0
     sta DTV_COLOR_BANK_HI
-    ldx #0
+    tax
   // DTV Palette - Grey Tones
   b1:
     txa
@@ -1138,10 +1133,10 @@ mode_hicolmcchar: {
     .label ch = 5
     .label cy = 4
     // DTV Graphics Bank
-    lda #($ffffffff&CHARSET)/$10000
+    lda #0
     sta DTV_GRAPHICS_VIC_BANK
     // DTV Color Bank
-    lda #COLORS/$400
+    lda #<COLORS/$400
     sta DTV_COLOR_BANK_LO
     lda #0
     sta DTV_COLOR_BANK_HI
@@ -1160,7 +1155,7 @@ mode_hicolmcchar: {
     lda #VIC_CSEL|VIC_MCM
     sta VIC_CONTROL2
     // VIC Memory Pointers
-    lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400
+    lda #(CHARSET&$3fff)/$400
     sta VIC_MEMORY
     ldx #0
   // DTV Palette - Grey Tones
@@ -1247,10 +1242,10 @@ mode_hicolecmchar: {
     .label ch = 5
     .label cy = 4
     // DTV Graphics Bank
-    lda #($ffffffff&CHARSET)/$10000
+    lda #0
     sta DTV_GRAPHICS_VIC_BANK
     // DTV Color Bank
-    lda #COLORS/$400
+    lda #<COLORS/$400
     sta DTV_COLOR_BANK_LO
     lda #0
     sta DTV_COLOR_BANK_HI
@@ -1269,7 +1264,7 @@ mode_hicolecmchar: {
     lda #VIC_CSEL
     sta VIC_CONTROL2
     // VIC Memory Pointers
-    lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400
+    lda #(CHARSET&$3fff)/$400
     sta VIC_MEMORY
     ldx #0
   // DTV Palette - Grey Tones
@@ -1354,10 +1349,10 @@ mode_hicolstdchar: {
     .label ch = 5
     .label cy = 4
     // DTV Graphics Bank
-    lda #($ffffffff&CHARSET)/$10000
+    lda #0
     sta DTV_GRAPHICS_VIC_BANK
     // DTV Color Bank
-    lda #COLORS/$400
+    lda #<COLORS/$400
     sta DTV_COLOR_BANK_LO
     lda #0
     sta DTV_COLOR_BANK_HI
@@ -1376,7 +1371,7 @@ mode_hicolstdchar: {
     lda #VIC_CSEL
     sta VIC_CONTROL2
     // VIC Memory Pointers
-    lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400
+    lda #(CHARSET&$3fff)/$400
     sta VIC_MEMORY
     ldx #0
   // DTV Palette - Grey Tones
@@ -1453,9 +1448,8 @@ mode_stdbitmap: {
     .label cy = 4
     .label l = 4
     // DTV Graphics Bank
-    lda #($ffffffff&BITMAP)/$10000
-    sta DTV_GRAPHICS_VIC_BANK
     lda #0
+    sta DTV_GRAPHICS_VIC_BANK
     sta DTV_CONTROL
     // VIC Graphics Bank
     lda #3
@@ -1470,7 +1464,7 @@ mode_stdbitmap: {
     lda #VIC_CSEL
     sta VIC_CONTROL2
     // VIC Memory Pointers
-    lda #(SCREEN&$3fff)/$40|(BITMAP&$3fff)/$400
+    lda #(BITMAP&$3fff)/$400
     sta VIC_MEMORY
     ldx #0
   // DTV Palette - default
@@ -1694,6 +1688,7 @@ bitmap_plot: {
     .label _0 = 2
     .label plotter_x = 2
     .label plotter_y = 5
+    .label plotter = 2
     lda bitmap_plot_xhi,x
     sta plotter_x+1
     lda bitmap_plot_xlo,x
@@ -1711,8 +1706,8 @@ bitmap_plot: {
     sta _0+1
     lda bitmap_plot_bit,x
     ldy #0
-    ora (_0),y
-    sta (_0),y
+    ora (plotter),y
+    sta (plotter),y
     rts
 }
 // bitmap_line_ydxi(byte zeropage($a) y, byte register(X) x, byte zeropage($c) y1, byte zeropage(7) yd, byte zeropage(8) xd)
@@ -1850,7 +1845,7 @@ bitmap_clear: {
 }
 // Initialize the bitmap plotter tables for a specific bitmap
 bitmap_init: {
-    .label _6 = 4
+    .label _10 = 4
     .label yoffs = 2
     ldy #$80
     ldx #0
@@ -1878,15 +1873,14 @@ bitmap_init: {
     tax
   b3:
     lda #7
-    sax _6
+    sax _10
     lda yoffs
-    ora _6
+    ora _10
     sta bitmap_plot_ylo,x
     lda yoffs+1
     sta bitmap_plot_yhi,x
-    txa
-    and #7
-    cmp #7
+    lda #7
+    cmp _10
     bne b4
     clc
     lda yoffs
@@ -1923,10 +1917,10 @@ mode_mcchar: {
     .label ch = 5
     .label cy = 4
     // DTV Graphics Bank
-    lda #($ffffffff&CHARSET)/$10000
+    lda #0
     sta DTV_GRAPHICS_VIC_BANK
     // DTV Color Bank
-    lda #DTV_COLOR_BANK_DEFAULT/$400
+    lda #<DTV_COLOR_BANK_DEFAULT/$400
     sta DTV_COLOR_BANK_LO
     lda #0
     sta DTV_COLOR_BANK_HI
@@ -1944,7 +1938,7 @@ mode_mcchar: {
     lda #VIC_CSEL|VIC_MCM
     sta VIC_CONTROL2
     // VIC Memory Pointers
-    lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400
+    lda #(CHARSET&$3fff)/$400
     sta VIC_MEMORY
     ldx #0
   // DTV Palette - default
@@ -2035,10 +2029,10 @@ mode_ecmchar: {
     .label ch = 5
     .label cy = 4
     // DTV Graphics Bank
-    lda #($ffffffff&CHARSET)/$10000
+    lda #0
     sta DTV_GRAPHICS_VIC_BANK
     // DTV Color Bank
-    lda #DTV_COLOR_BANK_DEFAULT/$400
+    lda #<DTV_COLOR_BANK_DEFAULT/$400
     sta DTV_COLOR_BANK_LO
     lda #0
     sta DTV_COLOR_BANK_HI
@@ -2056,7 +2050,7 @@ mode_ecmchar: {
     lda #VIC_CSEL
     sta VIC_CONTROL2
     // VIC Memory Pointers
-    lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400
+    lda #(CHARSET&$3fff)/$400
     sta VIC_MEMORY
     ldx #0
   // DTV Palette - default
@@ -2144,10 +2138,10 @@ mode_stdchar: {
     .label ch = 5
     .label cy = 4
     // DTV Graphics Bank
-    lda #($ffffffff&CHARSET)/$10000
+    lda #0
     sta DTV_GRAPHICS_VIC_BANK
     // DTV Color Bank
-    lda #DTV_COLOR_BANK_DEFAULT/$400
+    lda #<DTV_COLOR_BANK_DEFAULT/$400
     sta DTV_COLOR_BANK_LO
     lda #0
     sta DTV_COLOR_BANK_HI
@@ -2165,7 +2159,7 @@ mode_stdchar: {
     lda #VIC_CSEL
     sta VIC_CONTROL2
     // VIC Memory Pointers
-    lda #(SCREEN&$3fff)/$40|(CHARSET&$3fff)/$400
+    lda #(CHARSET&$3fff)/$400
     sta VIC_MEMORY
     ldx #0
   // DTV Palette - default
@@ -2337,4 +2331,4 @@ print_set_screen: {
   bitmap_plot_ylo: .fill $100, 0
   bitmap_plot_yhi: .fill $100, 0
   bitmap_plot_bit: .fill $100, 0
-  MENU_TEXT: .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@"+"@"
+  MENU_TEXT: .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@@"
diff --git a/src/test/ref/concat-char.asm b/src/test/ref/concat-char.asm
deleted file mode 100644
index 921520657..000000000
--- a/src/test/ref/concat-char.asm
+++ /dev/null
@@ -1,16 +0,0 @@
-// Concatenate a char to a string
-.pc = $801 "Basic"
-:BasicUpstart(main)
-.pc = $80d "Program"
-main: {
-    .label screen = $400
-    ldx #0
-  b1:
-    lda msg,x
-    sta screen,x
-    inx
-    cpx #3
-    bne b1
-    rts
-    msg: .text "cm"+'l'
-}
diff --git a/src/test/ref/concat-char.cfg b/src/test/ref/concat-char.cfg
deleted file mode 100644
index d85c7528b..000000000
--- a/src/test/ref/concat-char.cfg
+++ /dev/null
@@ -1,21 +0,0 @@
-@begin: scope:[]  from
-  [0] phi()
-  to:@1
-@1: scope:[]  from @begin
-  [1] phi()
-  [2] call main 
-  to:@end
-@end: scope:[]  from @1
-  [3] phi()
-main: scope:[main]  from @1
-  [4] phi()
-  to:main::@1
-main::@1: scope:[main]  from main main::@1
-  [5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 )
-  [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2)
-  [7] (byte) main::i#1 ← ++ (byte) main::i#2
-  [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1
-  to:main::@return
-main::@return: scope:[main]  from main::@1
-  [9] return 
-  to:@return
diff --git a/src/test/ref/concat-char.log b/src/test/ref/concat-char.log
deleted file mode 100644
index 492facbb5..000000000
--- a/src/test/ref/concat-char.log
+++ /dev/null
@@ -1,338 +0,0 @@
-Identified constant variable (byte*) main::screen
-Identified constant variable (byte) main::l
-
-CONTROL FLOW GRAPH SSA
-@begin: scope:[]  from
-  to:@1
-main: scope:[main]  from @1
-  (byte*) main::screen#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
-  (byte) main::l#0 ← (byte) 'l'
-  (string~) main::$0 ← (const string) main::$2 + (byte) main::l#0
-  (byte[]) main::msg#0 ← (string~) main::$0
-  (byte) main::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
-  to:main::@1
-main::@1: scope:[main]  from main main::@1
-  (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
-  *((byte*) main::screen#0 + (byte) main::i#2) ← *((byte[]) main::msg#0 + (byte) main::i#2)
-  (byte) main::i#1 ← (byte) main::i#2 + rangenext(0,2)
-  (bool~) main::$1 ← (byte) main::i#1 != rangelast(0,2)
-  if((bool~) main::$1) goto main::@1
-  to:main::@return
-main::@return: scope:[main]  from main::@1
-  return 
-  to:@return
-@1: scope:[]  from @begin
-  call main 
-  to:@2
-@2: scope:[]  from @1
-  to:@end
-@end: scope:[]  from @2
-
-SYMBOL TABLE SSA
-(label) @1
-(label) @2
-(label) @begin
-(label) @end
-(void()) main()
-(string~) main::$0
-(bool~) main::$1
-(const string) main::$2 = (string) "cm"
-(label) main::@1
-(label) main::@return
-(byte) main::i
-(byte) main::i#0
-(byte) main::i#1
-(byte) main::i#2
-(byte) main::l
-(byte) main::l#0
-(byte[]) main::msg
-(byte[]) main::msg#0
-(byte*) main::screen
-(byte*) main::screen#0
-
-Culled Empty Block (label) @2
-Successful SSA optimization Pass2CullEmptyBlocks
-Alias (byte[]) main::msg#0 = (string~) main::$0 
-Successful SSA optimization Pass2AliasElimination
-Simple Condition (bool~) main::$1 [9] if((byte) main::i#1!=rangelast(0,2)) goto main::@1
-Successful SSA optimization Pass2ConditionalJumpSimplification
-Constant (const byte*) main::screen#0 = ((byte*))$400
-Constant (const byte) main::l#0 = 'l'
-Constant (const byte) main::i#0 = 0
-Successful SSA optimization Pass2ConstantIdentification
-Constant (const byte[]) main::msg#0 = "cm"+'l'
-Successful SSA optimization Pass2ConstantIdentification
-Eliminating unused constant (const string) main::$2
-Eliminating unused constant (const byte) main::l#0
-Successful SSA optimization PassNEliminateUnusedVars
-Resolved ranged next value main::i#1 ← ++ main::i#2 to ++
-Resolved ranged comparison value if(main::i#1!=rangelast(0,2)) goto main::@1 to (byte/signed byte/word/signed word/dword/signed dword) 3
-Inlining constant with var siblings (const byte) main::i#0
-Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
-Successful SSA optimization Pass2ConstantInlining
-Added new block during phi lifting main::@3(between main::@1 and main::@1)
-Adding NOP phi() at start of @begin
-Adding NOP phi() at start of @1
-Adding NOP phi() at start of @end
-Adding NOP phi() at start of main
-CALL GRAPH
-Calls in [] to main:2 
-
-Created 1 initial phi equivalence classes
-Coalesced [10] main::i#3 ← main::i#1
-Coalesced down to 1 phi equivalence classes
-Culled Empty Block (label) main::@3
-Adding NOP phi() at start of @begin
-Adding NOP phi() at start of @1
-Adding NOP phi() at start of @end
-Adding NOP phi() at start of main
-
-FINAL CONTROL FLOW GRAPH
-@begin: scope:[]  from
-  [0] phi()
-  to:@1
-@1: scope:[]  from @begin
-  [1] phi()
-  [2] call main 
-  to:@end
-@end: scope:[]  from @1
-  [3] phi()
-main: scope:[main]  from @1
-  [4] phi()
-  to:main::@1
-main::@1: scope:[main]  from main main::@1
-  [5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 )
-  [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2)
-  [7] (byte) main::i#1 ← ++ (byte) main::i#2
-  [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1
-  to:main::@return
-main::@return: scope:[main]  from main::@1
-  [9] return 
-  to:@return
-
-
-VARIABLE REGISTER WEIGHTS
-(void()) main()
-(byte) main::i
-(byte) main::i#1 16.5
-(byte) main::i#2 22.0
-(byte) main::l
-(byte[]) main::msg
-(byte*) main::screen
-
-Initial phi equivalence classes
-[ main::i#2 main::i#1 ]
-Complete equivalence classes
-[ main::i#2 main::i#1 ]
-Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
-
-INITIAL ASM
-//SEG0 File Comments
-// Concatenate a char to a string
-//SEG1 Basic Upstart
-.pc = $801 "Basic"
-:BasicUpstart(bbegin)
-.pc = $80d "Program"
-//SEG2 Global Constants & labels
-//SEG3 @begin
-bbegin:
-//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
-b1_from_bbegin:
-  jmp b1
-//SEG5 @1
-b1:
-//SEG6 [2] call main 
-//SEG7 [4] phi from @1 to main [phi:@1->main]
-main_from_b1:
-  jsr main
-//SEG8 [3] phi from @1 to @end [phi:@1->@end]
-bend_from_b1:
-  jmp bend
-//SEG9 @end
-bend:
-//SEG10 main
-main: {
-    .label screen = $400
-    .label i = 2
-  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
-  b1_from_main:
-  //SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 
-    lda #0
-    sta i
-    jmp b1
-  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
-  b1_from_b1:
-  //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy 
-    jmp b1
-  //SEG15 main::@1
-  b1:
-  //SEG16 [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz1 
-    ldy i
-    lda msg,y
-    sta screen,y
-  //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 
-    inc i
-  //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 
-    lda #3
-    cmp i
-    bne b1_from_b1
-    jmp breturn
-  //SEG19 main::@return
-  breturn:
-  //SEG20 [9] return 
-    rts
-    msg: .text "cm"+'l'
-}
-
-REGISTER UPLIFT POTENTIAL REGISTERS
-Statement [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a 
-Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
-Statement [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a 
-Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y , 
-
-REGISTER UPLIFT SCOPES
-Uplift Scope [main] 38.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 
-Uplift Scope [] 
-
-Uplifting [main] best 288 combination reg byte x [ main::i#2 main::i#1 ] 
-Uplifting [] best 288 combination 
-
-ASSEMBLER BEFORE OPTIMIZATION
-//SEG0 File Comments
-// Concatenate a char to a string
-//SEG1 Basic Upstart
-.pc = $801 "Basic"
-:BasicUpstart(bbegin)
-.pc = $80d "Program"
-//SEG2 Global Constants & labels
-//SEG3 @begin
-bbegin:
-//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
-b1_from_bbegin:
-  jmp b1
-//SEG5 @1
-b1:
-//SEG6 [2] call main 
-//SEG7 [4] phi from @1 to main [phi:@1->main]
-main_from_b1:
-  jsr main
-//SEG8 [3] phi from @1 to @end [phi:@1->@end]
-bend_from_b1:
-  jmp bend
-//SEG9 @end
-bend:
-//SEG10 main
-main: {
-    .label screen = $400
-  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
-  b1_from_main:
-  //SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 
-    ldx #0
-    jmp b1
-  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
-  b1_from_b1:
-  //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy 
-    jmp b1
-  //SEG15 main::@1
-  b1:
-  //SEG16 [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx 
-    lda msg,x
-    sta screen,x
-  //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx 
-    inx
-  //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 
-    cpx #3
-    bne b1_from_b1
-    jmp breturn
-  //SEG19 main::@return
-  breturn:
-  //SEG20 [9] return 
-    rts
-    msg: .text "cm"+'l'
-}
-
-ASSEMBLER OPTIMIZATIONS
-Removing instruction jmp b1
-Removing instruction jmp bend
-Removing instruction jmp b1
-Removing instruction jmp breturn
-Succesful ASM optimization Pass5NextJumpElimination
-Replacing label b1_from_b1 with b1
-Removing instruction b1_from_bbegin:
-Removing instruction b1:
-Removing instruction main_from_b1:
-Removing instruction bend_from_b1:
-Removing instruction b1_from_b1:
-Succesful ASM optimization Pass5RedundantLabelElimination
-Removing instruction bend:
-Removing instruction b1_from_main:
-Removing instruction breturn:
-Succesful ASM optimization Pass5UnusedLabelElimination
-Updating BasicUpstart to call main directly
-Removing instruction jsr main
-Succesful ASM optimization Pass5SkipBegin
-Removing instruction jmp b1
-Succesful ASM optimization Pass5NextJumpElimination
-Removing instruction bbegin:
-Succesful ASM optimization Pass5UnusedLabelElimination
-
-FINAL SYMBOL TABLE
-(label) @1
-(label) @begin
-(label) @end
-(void()) main()
-(label) main::@1
-(label) main::@return
-(byte) main::i
-(byte) main::i#1 reg byte x 16.5
-(byte) main::i#2 reg byte x 22.0
-(byte) main::l
-(byte[]) main::msg
-(const byte[]) main::msg#0 msg = (string) "cm"+(byte) 'l'
-(byte*) main::screen
-(const byte*) main::screen#0 screen = ((byte*))(word/signed word/dword/signed dword) $400
-
-reg byte x [ main::i#2 main::i#1 ]
-
-
-FINAL ASSEMBLER
-Score: 186
-
-//SEG0 File Comments
-// Concatenate a char to a string
-//SEG1 Basic Upstart
-.pc = $801 "Basic"
-:BasicUpstart(main)
-.pc = $80d "Program"
-//SEG2 Global Constants & labels
-//SEG3 @begin
-//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
-//SEG5 @1
-//SEG6 [2] call main 
-//SEG7 [4] phi from @1 to main [phi:@1->main]
-//SEG8 [3] phi from @1 to @end [phi:@1->@end]
-//SEG9 @end
-//SEG10 main
-main: {
-    .label screen = $400
-  //SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
-  //SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 
-    ldx #0
-  //SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
-  //SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy 
-  //SEG15 main::@1
-  b1:
-  //SEG16 [6] *((const byte*) main::screen#0 + (byte) main::i#2) ← *((const byte[]) main::msg#0 + (byte) main::i#2) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_vbuxx 
-    lda msg,x
-    sta screen,x
-  //SEG17 [7] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx 
-    inx
-  //SEG18 [8] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 
-    cpx #3
-    bne b1
-  //SEG19 main::@return
-  //SEG20 [9] return 
-    rts
-    msg: .text "cm"+'l'
-}
-
diff --git a/src/test/ref/concat-char.sym b/src/test/ref/concat-char.sym
deleted file mode 100644
index 118c86105..000000000
--- a/src/test/ref/concat-char.sym
+++ /dev/null
@@ -1,16 +0,0 @@
-(label) @1
-(label) @begin
-(label) @end
-(void()) main()
-(label) main::@1
-(label) main::@return
-(byte) main::i
-(byte) main::i#1 reg byte x 16.5
-(byte) main::i#2 reg byte x 22.0
-(byte) main::l
-(byte[]) main::msg
-(const byte[]) main::msg#0 msg = (string) "cm"+(byte) 'l'
-(byte*) main::screen
-(const byte*) main::screen#0 screen = ((byte*))(word/signed word/dword/signed dword) $400
-
-reg byte x [ main::i#2 main::i#1 ]
diff --git a/src/test/ref/constant-string-concat-0.asm b/src/test/ref/constant-string-concat-0.asm
new file mode 100644
index 000000000..7fff00ab2
--- /dev/null
+++ b/src/test/ref/constant-string-concat-0.asm
@@ -0,0 +1,17 @@
+// Concatenates string constants in different ways
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label SCREEN = $400
+    ldx #0
+  b1:
+    lda msg,x
+    sta SCREEN,x
+    inx
+    lda msg,x
+    cmp #0
+    bne b1
+    rts
+    msg: .text "camelot@"
+}
diff --git a/src/test/ref/constant-string-concat.asm b/src/test/ref/constant-string-concat.asm
index 4fa0ed741..c832a5567 100644
--- a/src/test/ref/constant-string-concat.asm
+++ b/src/test/ref/constant-string-concat.asm
@@ -6,14 +6,11 @@ main: {
     .label SCREEN = $400
     ldx #0
   b1:
-    lda s5,x
+    lda s,x
     sta SCREEN,x
     inx
     cpx #8
     bne b1
     rts
-    s: .text "e"+"l"
-    s4: .text ""+'t'+'!'
-    s3: .text "cam"+s+'o'
-    s5: .text s3+s4
+    s: .text "camelot@"
 }
diff --git a/src/test/ref/literals.asm b/src/test/ref/literals.asm
index 3ad59a6a7..31f1584a0 100644
--- a/src/test/ref/literals.asm
+++ b/src/test/ref/literals.asm
@@ -20,5 +20,5 @@ main: {
     bne b1
     rts
 }
+  str: .text "bcde@"
   nums: .byte 2, 3, 4, 5
-  str: .text "bc"+"d"+'e'

From 75af42ad3f6c6e8c8d090fed2fb81a925d82290c Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Fri, 24 May 2019 23:00:13 +0200
Subject: [PATCH 88/93] Added struct syntax

---
 .../java/dk/camelot64/kickc/parser/KickC.g4   |   15 +
 .../dk/camelot64/kickc/parser/KickC.tokens    |  130 +-
 .../kickc/parser/KickCBaseListener.java       |   60 +
 .../kickc/parser/KickCBaseVisitor.java        |   35 +
 .../dk/camelot64/kickc/parser/KickCLexer.java |  732 +++----
 .../camelot64/kickc/parser/KickCLexer.tokens  |  130 +-
 .../camelot64/kickc/parser/KickCListener.java |   54 +
 .../camelot64/kickc/parser/KickCParser.java   | 1738 ++++++++++-------
 .../camelot64/kickc/parser/KickCVisitor.java  |   32 +
 9 files changed, 1687 insertions(+), 1239 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4
index a30ea0b67..117fd6732 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4
+++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4
@@ -23,6 +23,7 @@ declSeq
 
 decl
     : declVariables ';'
+    | structDef ';'
     | declFunction
     | declKasm
     | globalDirective
@@ -112,6 +113,20 @@ typeDecl
     | typeDecl '*' #typePtr
     | typeDecl '[' (expr)? ']' #typeArray
     | typeDecl '(' ')' #typeProcedure
+    | structDef  #typeStructDef
+    | structRef  #typeStructRef
+    ;
+
+structRef
+    : 'struct' NAME
+    ;
+
+structDef
+    : 'struct' NAME? '{' structMembers+ '}'
+    ;
+
+structMembers
+    : declVariables ';'
     ;
 
 commaExpr
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.tokens b/src/main/java/dk/camelot64/kickc/parser/KickC.tokens
index c69744d23..a303b96fe 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickC.tokens
+++ b/src/main/java/dk/camelot64/kickc/parser/KickC.tokens
@@ -74,26 +74,27 @@ T__72=73
 T__73=74
 T__74=75
 T__75=76
-MNEMONIC=77
-KICKASM=78
-SIMPLETYPE=79
-STRING=80
-CHAR=81
-BOOLEAN=82
-NUMBER=83
-NUMFLOAT=84
-BINFLOAT=85
-DECFLOAT=86
-HEXFLOAT=87
-NUMINT=88
-BININTEGER=89
-DECINTEGER=90
-HEXINTEGER=91
-NAME=92
-ASMREL=93
-WS=94
-COMMENT_LINE=95
-COMMENT_BLOCK=96
+T__76=77
+MNEMONIC=78
+KICKASM=79
+SIMPLETYPE=80
+STRING=81
+CHAR=82
+BOOLEAN=83
+NUMBER=84
+NUMFLOAT=85
+BINFLOAT=86
+DECFLOAT=87
+HEXFLOAT=88
+NUMINT=89
+BININTEGER=90
+DECINTEGER=91
+HEXINTEGER=92
+NAME=93
+ASMREL=94
+WS=95
+COMMENT_LINE=96
+COMMENT_BLOCK=97
 'import'=1
 ';'=2
 ','=3
@@ -126,47 +127,48 @@ COMMENT_BLOCK=96
 '*'=30
 '['=31
 ']'=32
-'sizeof'=33
-'typeid'=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
-'&='=64
-'|='=65
-'^='=66
-'kickasm'=67
-'resource'=68
-'uses'=69
-'clobbers'=70
-'bytes'=71
-'cycles'=72
-'pc'=73
-'.byte'=74
-'#'=75
-'.'=76
+'struct'=33
+'sizeof'=34
+'typeid'=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
+'>>='=64
+'&='=65
+'|='=66
+'^='=67
+'kickasm'=68
+'resource'=69
+'uses'=70
+'clobbers'=71
+'bytes'=72
+'cycles'=73
+'pc'=74
+'.byte'=75
+'#'=76
+'.'=77
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
index 02bba947a..b8a02352a 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
@@ -551,6 +551,18 @@ public class KickCBaseListener implements KickCListener {
 	 * <p>The default implementation does nothing.</p>
 	 */
 	@Override public void exitTypeArray(KickCParser.TypeArrayContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterTypeStructRef(KickCParser.TypeStructRefContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitTypeStructRef(KickCParser.TypeStructRefContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
@@ -563,6 +575,18 @@ public class KickCBaseListener implements KickCListener {
 	 * <p>The default implementation does nothing.</p>
 	 */
 	@Override public void exitTypeSimple(KickCParser.TypeSimpleContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterTypeStructDef(KickCParser.TypeStructDefContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitTypeStructDef(KickCParser.TypeStructDefContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
@@ -575,6 +599,42 @@ public class KickCBaseListener implements KickCListener {
 	 * <p>The default implementation does nothing.</p>
 	 */
 	@Override public void exitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterStructRef(KickCParser.StructRefContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitStructRef(KickCParser.StructRefContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterStructDef(KickCParser.StructDefContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitStructDef(KickCParser.StructDefContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterStructMembers(KickCParser.StructMembersContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitStructMembers(KickCParser.StructMembersContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
index 709766578..2cba0e61e 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
@@ -326,6 +326,13 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
 	@Override public T visitTypeArray(KickCParser.TypeArrayContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitTypeStructRef(KickCParser.TypeStructRefContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
@@ -333,6 +340,13 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
 	@Override public T visitTypeSimple(KickCParser.TypeSimpleContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitTypeStructDef(KickCParser.TypeStructDefContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
@@ -340,6 +354,27 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
 	@Override public T visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitStructRef(KickCParser.StructRefContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitStructDef(KickCParser.StructDefContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitStructMembers(KickCParser.StructMembersContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
index 951b0e72e..594b24209 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
@@ -27,10 +27,10 @@ public class KickCLexer extends Lexer {
 		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, T__71=72, T__72=73, 
-		T__73=74, T__74=75, T__75=76, MNEMONIC=77, KICKASM=78, SIMPLETYPE=79, 
-		STRING=80, CHAR=81, BOOLEAN=82, NUMBER=83, NUMFLOAT=84, BINFLOAT=85, DECFLOAT=86, 
-		HEXFLOAT=87, NUMINT=88, BININTEGER=89, DECINTEGER=90, HEXINTEGER=91, NAME=92, 
-		ASMREL=93, WS=94, COMMENT_LINE=95, COMMENT_BLOCK=96;
+		T__73=74, T__74=75, T__75=76, T__76=77, MNEMONIC=78, KICKASM=79, SIMPLETYPE=80, 
+		STRING=81, CHAR=82, BOOLEAN=83, NUMBER=84, NUMFLOAT=85, BINFLOAT=86, DECFLOAT=87, 
+		HEXFLOAT=88, NUMINT=89, BININTEGER=90, DECINTEGER=91, HEXINTEGER=92, NAME=93, 
+		ASMREL=94, WS=95, COMMENT_LINE=96, COMMENT_BLOCK=97;
 	public static String[] channelNames = {
 		"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
 	};
@@ -49,11 +49,11 @@ public class KickCLexer extends Lexer {
 		"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", "T__71", "T__72", 
-		"T__73", "T__74", "T__75", "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__73", "T__74", "T__75", "T__76", "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 = {
@@ -61,12 +61,12 @@ public class KickCLexer extends Lexer {
 		"'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'", 
 		"'reserve'", "'if'", "'else'", "'while'", "'do'", "'for'", "'return'", 
 		"'break'", "'continue'", "'asm'", "':'", "'..'", "'signed'", "'unsigned'", 
-		"'*'", "'['", "']'", "'sizeof'", "'typeid'", "'--'", "'++'", "'+'", "'-'", 
-		"'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", "'>'", "'=='", 
-		"'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", "'+='", "'-='", 
-		"'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", "'^='", "'kickasm'", 
-		"'resource'", "'uses'", "'clobbers'", "'bytes'", "'cycles'", "'pc'", "'.byte'", 
-		"'#'", "'.'"
+		"'*'", "'['", "']'", "'struct'", "'sizeof'", "'typeid'", "'--'", "'++'", 
+		"'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", 
+		"'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", 
+		"'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", 
+		"'^='", "'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, 
@@ -75,10 +75,10 @@ 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, 
-		null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", 
-		"CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", 
-		"NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "ASMREL", 
-		"WS", "COMMENT_LINE", "COMMENT_BLOCK"
+		null, null, null, null, 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);
 
@@ -138,7 +138,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\2b\u03dc\b\1\4\2\t"+
+		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2c\u03e5\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"+
@@ -149,350 +149,354 @@ 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\4b\tb\4c\tc\4d\td\4e\te\4f\tf\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\21\3\21\3\21\3\21\3\21\3\22"+
-		"\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25"+
-		"\3\25\3\25\3\26\3\26\3\26\3\26\3\27\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\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+
-		"\3\32\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35"+
-		"\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\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,\3-\3-\3.\3.\3/"+
-		"\3/\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\62\3\63\3\63\3\63\3\64\3\64\3"+
-		"\64\3\65\3\65\3\66\3\66\3\67\3\67\3\67\38\38\38\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\3B\3B\3"+
-		"B\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F\3"+
-		"F\3F\3F\3G\3G\3G\3G\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3"+
-		"I\3I\3J\3J\3J\3K\3K\3K\3K\3K\3K\3L\3L\3M\3M\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3"+
-		"N\3N\3N\3N\3N\3N\3N\5N\u02e6\nN\3O\3O\3O\3O\7O\u02ec\nO\fO\16O\u02ef\13"+
-		"O\3O\3O\3O\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3"+
-		"P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\5P\u0319\nP\3Q\3"+
-		"Q\3Q\3Q\7Q\u031f\nQ\fQ\16Q\u0322\13Q\3Q\3Q\5Q\u0326\nQ\3R\3R\3R\3R\5R"+
-		"\u032c\nR\3R\3R\3S\3S\3S\3S\3S\3S\3S\3S\3S\5S\u0339\nS\3T\3T\5T\u033d"+
-		"\nT\3U\3U\3U\5U\u0342\nU\3V\3V\3V\3V\3V\5V\u0349\nV\3V\7V\u034c\nV\fV"+
-		"\16V\u034f\13V\3V\3V\6V\u0353\nV\rV\16V\u0354\3W\7W\u0358\nW\fW\16W\u035b"+
-		"\13W\3W\3W\6W\u035f\nW\rW\16W\u0360\3X\3X\3X\3X\3X\5X\u0368\nX\3X\7X\u036b"+
-		"\nX\fX\16X\u036e\13X\3X\3X\6X\u0372\nX\rX\16X\u0373\3Y\3Y\3Y\5Y\u0379"+
-		"\nY\3Y\3Y\3Y\5Y\u037e\nY\3Z\3Z\3Z\6Z\u0383\nZ\rZ\16Z\u0384\3Z\3Z\6Z\u0389"+
-		"\nZ\rZ\16Z\u038a\5Z\u038d\nZ\3[\6[\u0390\n[\r[\16[\u0391\3\\\3\\\3\\\3"+
-		"\\\3\\\5\\\u0399\n\\\3\\\6\\\u039c\n\\\r\\\16\\\u039d\3]\3]\3^\3^\3_\3"+
-		"_\3`\3`\7`\u03a8\n`\f`\16`\u03ab\13`\3a\3a\3b\3b\3c\3c\7c\u03b3\nc\fc"+
-		"\16c\u03b6\13c\3c\6c\u03b9\nc\rc\16c\u03ba\3d\6d\u03be\nd\rd\16d\u03bf"+
-		"\3d\3d\3e\3e\3e\3e\7e\u03c8\ne\fe\16e\u03cb\13e\3e\3e\3f\3f\3f\3f\7f\u03d3"+
-		"\nf\ff\16f\u03d6\13f\3f\3f\3f\3f\3f\4\u02ed\u03d4\2g\3\3\5\4\7\5\t\6\13"+
-		"\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'"+
-		"\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'"+
-		"M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177"+
-		"A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093"+
-		"K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7"+
-		"U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9\2\u00bb"+
-		"\2\u00bd\2\u00bf^\u00c1\2\u00c3\2\u00c5_\u00c7`\u00c9a\u00cbb\3\2\17\3"+
-		"\2$$\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHc"+
-		"h\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\u044b\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\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2"+
-		"\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k"+
-		"\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\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\u00af"+
-		"\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2"+
-		"\2\2\u00bf\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb"+
-		"\3\2\2\2\3\u00cd\3\2\2\2\5\u00d4\3\2\2\2\7\u00d6\3\2\2\2\t\u00d8\3\2\2"+
-		"\2\13\u00da\3\2\2\2\r\u00dc\3\2\2\2\17\u00de\3\2\2\2\21\u00e0\3\2\2\2"+
-		"\23\u00e2\3\2\2\2\25\u00e8\3\2\2\2\27\u00ef\3\2\2\2\31\u00f5\3\2\2\2\33"+
-		"\u00fe\3\2\2\2\35\u0105\3\2\2\2\37\u010e\3\2\2\2!\u0118\3\2\2\2#\u0120"+
-		"\3\2\2\2%\u0123\3\2\2\2\'\u0128\3\2\2\2)\u012e\3\2\2\2+\u0131\3\2\2\2"+
-		"-\u0135\3\2\2\2/\u013c\3\2\2\2\61\u0142\3\2\2\2\63\u014b\3\2\2\2\65\u014f"+
-		"\3\2\2\2\67\u0151\3\2\2\29\u0154\3\2\2\2;\u015b\3\2\2\2=\u0164\3\2\2\2"+
-		"?\u0166\3\2\2\2A\u0168\3\2\2\2C\u016a\3\2\2\2E\u0171\3\2\2\2G\u0178\3"+
-		"\2\2\2I\u017b\3\2\2\2K\u017e\3\2\2\2M\u0180\3\2\2\2O\u0182\3\2\2\2Q\u0184"+
-		"\3\2\2\2S\u0186\3\2\2\2U\u0188\3\2\2\2W\u018b\3\2\2\2Y\u018e\3\2\2\2["+
-		"\u0190\3\2\2\2]\u0192\3\2\2\2_\u0194\3\2\2\2a\u0196\3\2\2\2c\u0199\3\2"+
-		"\2\2e\u019c\3\2\2\2g\u019f\3\2\2\2i\u01a2\3\2\2\2k\u01a4\3\2\2\2m\u01a6"+
-		"\3\2\2\2o\u01a9\3\2\2\2q\u01ac\3\2\2\2s\u01ae\3\2\2\2u\u01b1\3\2\2\2w"+
-		"\u01b4\3\2\2\2y\u01b7\3\2\2\2{\u01ba\3\2\2\2}\u01bd\3\2\2\2\177\u01c1"+
-		"\3\2\2\2\u0081\u01c5\3\2\2\2\u0083\u01c8\3\2\2\2\u0085\u01cb\3\2\2\2\u0087"+
-		"\u01ce\3\2\2\2\u0089\u01d6\3\2\2\2\u008b\u01df\3\2\2\2\u008d\u01e4\3\2"+
-		"\2\2\u008f\u01ed\3\2\2\2\u0091\u01f3\3\2\2\2\u0093\u01fa\3\2\2\2\u0095"+
-		"\u01fd\3\2\2\2\u0097\u0203\3\2\2\2\u0099\u0205\3\2\2\2\u009b\u02e5\3\2"+
-		"\2\2\u009d\u02e7\3\2\2\2\u009f\u0318\3\2\2\2\u00a1\u031a\3\2\2\2\u00a3"+
-		"\u0327\3\2\2\2\u00a5\u0338\3\2\2\2\u00a7\u033c\3\2\2\2\u00a9\u0341\3\2"+
-		"\2\2\u00ab\u0348\3\2\2\2\u00ad\u0359\3\2\2\2\u00af\u0367\3\2\2\2\u00b1"+
-		"\u0378\3\2\2\2\u00b3\u038c\3\2\2\2\u00b5\u038f\3\2\2\2\u00b7\u0398\3\2"+
-		"\2\2\u00b9\u039f\3\2\2\2\u00bb\u03a1\3\2\2\2\u00bd\u03a3\3\2\2\2\u00bf"+
-		"\u03a5\3\2\2\2\u00c1\u03ac\3\2\2\2\u00c3\u03ae\3\2\2\2\u00c5\u03b0\3\2"+
-		"\2\2\u00c7\u03bd\3\2\2\2\u00c9\u03c3\3\2\2\2\u00cb\u03ce\3\2\2\2\u00cd"+
-		"\u00ce\7k\2\2\u00ce\u00cf\7o\2\2\u00cf\u00d0\7r\2\2\u00d0\u00d1\7q\2\2"+
-		"\u00d1\u00d2\7t\2\2\u00d2\u00d3\7v\2\2\u00d3\4\3\2\2\2\u00d4\u00d5\7="+
-		"\2\2\u00d5\6\3\2\2\2\u00d6\u00d7\7.\2\2\u00d7\b\3\2\2\2\u00d8\u00d9\7"+
-		"?\2\2\u00d9\n\3\2\2\2\u00da\u00db\7*\2\2\u00db\f\3\2\2\2\u00dc\u00dd\7"+
-		"+\2\2\u00dd\16\3\2\2\2\u00de\u00df\7}\2\2\u00df\20\3\2\2\2\u00e0\u00e1"+
-		"\7\177\2\2\u00e1\22\3\2\2\2\u00e2\u00e3\7e\2\2\u00e3\u00e4\7q\2\2\u00e4"+
-		"\u00e5\7p\2\2\u00e5\u00e6\7u\2\2\u00e6\u00e7\7v\2\2\u00e7\24\3\2\2\2\u00e8"+
-		"\u00e9\7g\2\2\u00e9\u00ea\7z\2\2\u00ea\u00eb\7v\2\2\u00eb\u00ec\7g\2\2"+
-		"\u00ec\u00ed\7t\2\2\u00ed\u00ee\7p\2\2\u00ee\26\3\2\2\2\u00ef\u00f0\7"+
-		"c\2\2\u00f0\u00f1\7n\2\2\u00f1\u00f2\7k\2\2\u00f2\u00f3\7i\2\2\u00f3\u00f4"+
-		"\7p\2\2\u00f4\30\3\2\2\2\u00f5\u00f6\7t\2\2\u00f6\u00f7\7g\2\2\u00f7\u00f8"+
-		"\7i\2\2\u00f8\u00f9\7k\2\2\u00f9\u00fa\7u\2\2\u00fa\u00fb\7v\2\2\u00fb"+
-		"\u00fc\7g\2\2\u00fc\u00fd\7t\2\2\u00fd\32\3\2\2\2\u00fe\u00ff\7k\2\2\u00ff"+
-		"\u0100\7p\2\2\u0100\u0101\7n\2\2\u0101\u0102\7k\2\2\u0102\u0103\7p\2\2"+
-		"\u0103\u0104\7g\2\2\u0104\34\3\2\2\2\u0105\u0106\7x\2\2\u0106\u0107\7"+
-		"q\2\2\u0107\u0108\7n\2\2\u0108\u0109\7c\2\2\u0109\u010a\7v\2\2\u010a\u010b"+
-		"\7k\2\2\u010b\u010c\7n\2\2\u010c\u010d\7g\2\2\u010d\36\3\2\2\2\u010e\u010f"+
-		"\7k\2\2\u010f\u0110\7p\2\2\u0110\u0111\7v\2\2\u0111\u0112\7g\2\2\u0112"+
-		"\u0113\7t\2\2\u0113\u0114\7t\2\2\u0114\u0115\7w\2\2\u0115\u0116\7r\2\2"+
-		"\u0116\u0117\7v\2\2\u0117 \3\2\2\2\u0118\u0119\7t\2\2\u0119\u011a\7g\2"+
-		"\2\u011a\u011b\7u\2\2\u011b\u011c\7g\2\2\u011c\u011d\7t\2\2\u011d\u011e"+
-		"\7x\2\2\u011e\u011f\7g\2\2\u011f\"\3\2\2\2\u0120\u0121\7k\2\2\u0121\u0122"+
-		"\7h\2\2\u0122$\3\2\2\2\u0123\u0124\7g\2\2\u0124\u0125\7n\2\2\u0125\u0126"+
-		"\7u\2\2\u0126\u0127\7g\2\2\u0127&\3\2\2\2\u0128\u0129\7y\2\2\u0129\u012a"+
-		"\7j\2\2\u012a\u012b\7k\2\2\u012b\u012c\7n\2\2\u012c\u012d\7g\2\2\u012d"+
-		"(\3\2\2\2\u012e\u012f\7f\2\2\u012f\u0130\7q\2\2\u0130*\3\2\2\2\u0131\u0132"+
-		"\7h\2\2\u0132\u0133\7q\2\2\u0133\u0134\7t\2\2\u0134,\3\2\2\2\u0135\u0136"+
-		"\7t\2\2\u0136\u0137\7g\2\2\u0137\u0138\7v\2\2\u0138\u0139\7w\2\2\u0139"+
-		"\u013a\7t\2\2\u013a\u013b\7p\2\2\u013b.\3\2\2\2\u013c\u013d\7d\2\2\u013d"+
-		"\u013e\7t\2\2\u013e\u013f\7g\2\2\u013f\u0140\7c\2\2\u0140\u0141\7m\2\2"+
-		"\u0141\60\3\2\2\2\u0142\u0143\7e\2\2\u0143\u0144\7q\2\2\u0144\u0145\7"+
-		"p\2\2\u0145\u0146\7v\2\2\u0146\u0147\7k\2\2\u0147\u0148\7p\2\2\u0148\u0149"+
-		"\7w\2\2\u0149\u014a\7g\2\2\u014a\62\3\2\2\2\u014b\u014c\7c\2\2\u014c\u014d"+
-		"\7u\2\2\u014d\u014e\7o\2\2\u014e\64\3\2\2\2\u014f\u0150\7<\2\2\u0150\66"+
-		"\3\2\2\2\u0151\u0152\7\60\2\2\u0152\u0153\7\60\2\2\u01538\3\2\2\2\u0154"+
-		"\u0155\7u\2\2\u0155\u0156\7k\2\2\u0156\u0157\7i\2\2\u0157\u0158\7p\2\2"+
-		"\u0158\u0159\7g\2\2\u0159\u015a\7f\2\2\u015a:\3\2\2\2\u015b\u015c\7w\2"+
-		"\2\u015c\u015d\7p\2\2\u015d\u015e\7u\2\2\u015e\u015f\7k\2\2\u015f\u0160"+
-		"\7i\2\2\u0160\u0161\7p\2\2\u0161\u0162\7g\2\2\u0162\u0163\7f\2\2\u0163"+
-		"<\3\2\2\2\u0164\u0165\7,\2\2\u0165>\3\2\2\2\u0166\u0167\7]\2\2\u0167@"+
-		"\3\2\2\2\u0168\u0169\7_\2\2\u0169B\3\2\2\2\u016a\u016b\7u\2\2\u016b\u016c"+
-		"\7k\2\2\u016c\u016d\7|\2\2\u016d\u016e\7g\2\2\u016e\u016f\7q\2\2\u016f"+
-		"\u0170\7h\2\2\u0170D\3\2\2\2\u0171\u0172\7v\2\2\u0172\u0173\7{\2\2\u0173"+
-		"\u0174\7r\2\2\u0174\u0175\7g\2\2\u0175\u0176\7k\2\2\u0176\u0177\7f\2\2"+
-		"\u0177F\3\2\2\2\u0178\u0179\7/\2\2\u0179\u017a\7/\2\2\u017aH\3\2\2\2\u017b"+
-		"\u017c\7-\2\2\u017c\u017d\7-\2\2\u017dJ\3\2\2\2\u017e\u017f\7-\2\2\u017f"+
-		"L\3\2\2\2\u0180\u0181\7/\2\2\u0181N\3\2\2\2\u0182\u0183\7#\2\2\u0183P"+
-		"\3\2\2\2\u0184\u0185\7(\2\2\u0185R\3\2\2\2\u0186\u0187\7\u0080\2\2\u0187"+
-		"T\3\2\2\2\u0188\u0189\7@\2\2\u0189\u018a\7@\2\2\u018aV\3\2\2\2\u018b\u018c"+
-		"\7>\2\2\u018c\u018d\7>\2\2\u018dX\3\2\2\2\u018e\u018f\7\61\2\2\u018fZ"+
-		"\3\2\2\2\u0190\u0191\7\'\2\2\u0191\\\3\2\2\2\u0192\u0193\7>\2\2\u0193"+
-		"^\3\2\2\2\u0194\u0195\7@\2\2\u0195`\3\2\2\2\u0196\u0197\7?\2\2\u0197\u0198"+
-		"\7?\2\2\u0198b\3\2\2\2\u0199\u019a\7#\2\2\u019a\u019b\7?\2\2\u019bd\3"+
-		"\2\2\2\u019c\u019d\7>\2\2\u019d\u019e\7?\2\2\u019ef\3\2\2\2\u019f\u01a0"+
-		"\7@\2\2\u01a0\u01a1\7?\2\2\u01a1h\3\2\2\2\u01a2\u01a3\7`\2\2\u01a3j\3"+
-		"\2\2\2\u01a4\u01a5\7~\2\2\u01a5l\3\2\2\2\u01a6\u01a7\7(\2\2\u01a7\u01a8"+
-		"\7(\2\2\u01a8n\3\2\2\2\u01a9\u01aa\7~\2\2\u01aa\u01ab\7~\2\2\u01abp\3"+
-		"\2\2\2\u01ac\u01ad\7A\2\2\u01adr\3\2\2\2\u01ae\u01af\7-\2\2\u01af\u01b0"+
-		"\7?\2\2\u01b0t\3\2\2\2\u01b1\u01b2\7/\2\2\u01b2\u01b3\7?\2\2\u01b3v\3"+
-		"\2\2\2\u01b4\u01b5\7,\2\2\u01b5\u01b6\7?\2\2\u01b6x\3\2\2\2\u01b7\u01b8"+
-		"\7\61\2\2\u01b8\u01b9\7?\2\2\u01b9z\3\2\2\2\u01ba\u01bb\7\'\2\2\u01bb"+
-		"\u01bc\7?\2\2\u01bc|\3\2\2\2\u01bd\u01be\7>\2\2\u01be\u01bf\7>\2\2\u01bf"+
-		"\u01c0\7?\2\2\u01c0~\3\2\2\2\u01c1\u01c2\7@\2\2\u01c2\u01c3\7@\2\2\u01c3"+
-		"\u01c4\7?\2\2\u01c4\u0080\3\2\2\2\u01c5\u01c6\7(\2\2\u01c6\u01c7\7?\2"+
-		"\2\u01c7\u0082\3\2\2\2\u01c8\u01c9\7~\2\2\u01c9\u01ca\7?\2\2\u01ca\u0084"+
-		"\3\2\2\2\u01cb\u01cc\7`\2\2\u01cc\u01cd\7?\2\2\u01cd\u0086\3\2\2\2\u01ce"+
-		"\u01cf\7m\2\2\u01cf\u01d0\7k\2\2\u01d0\u01d1\7e\2\2\u01d1\u01d2\7m\2\2"+
-		"\u01d2\u01d3\7c\2\2\u01d3\u01d4\7u\2\2\u01d4\u01d5\7o\2\2\u01d5\u0088"+
-		"\3\2\2\2\u01d6\u01d7\7t\2\2\u01d7\u01d8\7g\2\2\u01d8\u01d9\7u\2\2\u01d9"+
-		"\u01da\7q\2\2\u01da\u01db\7w\2\2\u01db\u01dc\7t\2\2\u01dc\u01dd\7e\2\2"+
-		"\u01dd\u01de\7g\2\2\u01de\u008a\3\2\2\2\u01df\u01e0\7w\2\2\u01e0\u01e1"+
-		"\7u\2\2\u01e1\u01e2\7g\2\2\u01e2\u01e3\7u\2\2\u01e3\u008c\3\2\2\2\u01e4"+
-		"\u01e5\7e\2\2\u01e5\u01e6\7n\2\2\u01e6\u01e7\7q\2\2\u01e7\u01e8\7d\2\2"+
-		"\u01e8\u01e9\7d\2\2\u01e9\u01ea\7g\2\2\u01ea\u01eb\7t\2\2\u01eb\u01ec"+
-		"\7u\2\2\u01ec\u008e\3\2\2\2\u01ed\u01ee\7d\2\2\u01ee\u01ef\7{\2\2\u01ef"+
-		"\u01f0\7v\2\2\u01f0\u01f1\7g\2\2\u01f1\u01f2\7u\2\2\u01f2\u0090\3\2\2"+
-		"\2\u01f3\u01f4\7e\2\2\u01f4\u01f5\7{\2\2\u01f5\u01f6\7e\2\2\u01f6\u01f7"+
-		"\7n\2\2\u01f7\u01f8\7g\2\2\u01f8\u01f9\7u\2\2\u01f9\u0092\3\2\2\2\u01fa"+
-		"\u01fb\7r\2\2\u01fb\u01fc\7e\2\2\u01fc\u0094\3\2\2\2\u01fd\u01fe\7\60"+
-		"\2\2\u01fe\u01ff\7d\2\2\u01ff\u0200\7{\2\2\u0200\u0201\7v\2\2\u0201\u0202"+
-		"\7g\2\2\u0202\u0096\3\2\2\2\u0203\u0204\7%\2\2\u0204\u0098\3\2\2\2\u0205"+
-		"\u0206\7\60\2\2\u0206\u009a\3\2\2\2\u0207\u0208\7d\2\2\u0208\u0209\7t"+
-		"\2\2\u0209\u02e6\7m\2\2\u020a\u020b\7q\2\2\u020b\u020c\7t\2\2\u020c\u02e6"+
-		"\7c\2\2\u020d\u020e\7m\2\2\u020e\u020f\7k\2\2\u020f\u02e6\7n\2\2\u0210"+
-		"\u0211\7u\2\2\u0211\u0212\7n\2\2\u0212\u02e6\7q\2\2\u0213\u0214\7p\2\2"+
-		"\u0214\u0215\7q\2\2\u0215\u02e6\7r\2\2\u0216\u0217\7c\2\2\u0217\u0218"+
-		"\7u\2\2\u0218\u02e6\7n\2\2\u0219\u021a\7r\2\2\u021a\u021b\7j\2\2\u021b"+
-		"\u02e6\7r\2\2\u021c\u021d\7c\2\2\u021d\u021e\7p\2\2\u021e\u02e6\7e\2\2"+
-		"\u021f\u0220\7d\2\2\u0220\u0221\7r\2\2\u0221\u02e6\7n\2\2\u0222\u0223"+
-		"\7e\2\2\u0223\u0224\7n\2\2\u0224\u02e6\7e\2\2\u0225\u0226\7l\2\2\u0226"+
-		"\u0227\7u\2\2\u0227\u02e6\7t\2\2\u0228\u0229\7c\2\2\u0229\u022a\7p\2\2"+
-		"\u022a\u02e6\7f\2\2\u022b\u022c\7t\2\2\u022c\u022d\7n\2\2\u022d\u02e6"+
-		"\7c\2\2\u022e\u022f\7d\2\2\u022f\u0230\7k\2\2\u0230\u02e6\7v\2\2\u0231"+
-		"\u0232\7t\2\2\u0232\u0233\7q\2\2\u0233\u02e6\7n\2\2\u0234\u0235\7r\2\2"+
-		"\u0235\u0236\7n\2\2\u0236\u02e6\7c\2\2\u0237\u0238\7r\2\2\u0238\u0239"+
-		"\7n\2\2\u0239\u02e6\7r\2\2\u023a\u023b\7d\2\2\u023b\u023c\7o\2\2\u023c"+
-		"\u02e6\7k\2\2\u023d\u023e\7u\2\2\u023e\u023f\7g\2\2\u023f\u02e6\7e\2\2"+
-		"\u0240\u0241\7t\2\2\u0241\u0242\7v\2\2\u0242\u02e6\7k\2\2\u0243\u0244"+
-		"\7g\2\2\u0244\u0245\7q\2\2\u0245\u02e6\7t\2\2\u0246\u0247\7u\2\2\u0247"+
-		"\u0248\7t\2\2\u0248\u02e6\7g\2\2\u0249\u024a\7n\2\2\u024a\u024b\7u\2\2"+
-		"\u024b\u02e6\7t\2\2\u024c\u024d\7r\2\2\u024d\u024e\7j\2\2\u024e\u02e6"+
-		"\7c\2\2\u024f\u0250\7c\2\2\u0250\u0251\7n\2\2\u0251\u02e6\7t\2\2\u0252"+
-		"\u0253\7l\2\2\u0253\u0254\7o\2\2\u0254\u02e6\7r\2\2\u0255\u0256\7d\2\2"+
-		"\u0256\u0257\7x\2\2\u0257\u02e6\7e\2\2\u0258\u0259\7e\2\2\u0259\u025a"+
-		"\7n\2\2\u025a\u02e6\7k\2\2\u025b\u025c\7t\2\2\u025c\u025d\7v\2\2\u025d"+
-		"\u02e6\7u\2\2\u025e\u025f\7c\2\2\u025f\u0260\7f\2\2\u0260\u02e6\7e\2\2"+
-		"\u0261\u0262\7t\2\2\u0262\u0263\7t\2\2\u0263\u02e6\7c\2\2\u0264\u0265"+
-		"\7d\2\2\u0265\u0266\7x\2\2\u0266\u02e6\7u\2\2\u0267\u0268\7u\2\2\u0268"+
-		"\u0269\7g\2\2\u0269\u02e6\7k\2\2\u026a\u026b\7u\2\2\u026b\u026c\7c\2\2"+
-		"\u026c\u02e6\7z\2\2\u026d\u026e\7u\2\2\u026e\u026f\7v\2\2\u026f\u02e6"+
-		"\7{\2\2\u0270\u0271\7u\2\2\u0271\u0272\7v\2\2\u0272\u02e6\7c\2\2\u0273"+
-		"\u0274\7u\2\2\u0274\u0275\7v\2\2\u0275\u02e6\7z\2\2\u0276\u0277\7f\2\2"+
-		"\u0277\u0278\7g\2\2\u0278\u02e6\7{\2\2\u0279\u027a\7v\2\2\u027a\u027b"+
-		"\7z\2\2\u027b\u02e6\7c\2\2\u027c\u027d\7z\2\2\u027d\u027e\7c\2\2\u027e"+
-		"\u02e6\7c\2\2\u027f\u0280\7d\2\2\u0280\u0281\7e\2\2\u0281\u02e6\7e\2\2"+
-		"\u0282\u0283\7c\2\2\u0283\u0284\7j\2\2\u0284\u02e6\7z\2\2\u0285\u0286"+
-		"\7v\2\2\u0286\u0287\7{\2\2\u0287\u02e6\7c\2\2\u0288\u0289\7v\2\2\u0289"+
-		"\u028a\7z\2\2\u028a\u02e6\7u\2\2\u028b\u028c\7v\2\2\u028c\u028d\7c\2\2"+
-		"\u028d\u02e6\7u\2\2\u028e\u028f\7u\2\2\u028f\u0290\7j\2\2\u0290\u02e6"+
-		"\7{\2\2\u0291\u0292\7u\2\2\u0292\u0293\7j\2\2\u0293\u02e6\7z\2\2\u0294"+
-		"\u0295\7n\2\2\u0295\u0296\7f\2\2\u0296\u02e6\7{\2\2\u0297\u0298\7n\2\2"+
-		"\u0298\u0299\7f\2\2\u0299\u02e6\7c\2\2\u029a\u029b\7n\2\2\u029b\u029c"+
-		"\7f\2\2\u029c\u02e6\7z\2\2\u029d\u029e\7n\2\2\u029e\u029f\7c\2\2\u029f"+
-		"\u02e6\7z\2\2\u02a0\u02a1\7v\2\2\u02a1\u02a2\7c\2\2\u02a2\u02e6\7{\2\2"+
-		"\u02a3\u02a4\7v\2\2\u02a4\u02a5\7c\2\2\u02a5\u02e6\7z\2\2\u02a6\u02a7"+
-		"\7d\2\2\u02a7\u02a8\7e\2\2\u02a8\u02e6\7u\2\2\u02a9\u02aa\7e\2\2\u02aa"+
-		"\u02ab\7n\2\2\u02ab\u02e6\7x\2\2\u02ac\u02ad\7v\2\2\u02ad\u02ae\7u\2\2"+
-		"\u02ae\u02e6\7z\2\2\u02af\u02b0\7n\2\2\u02b0\u02b1\7c\2\2\u02b1\u02e6"+
-		"\7u\2\2\u02b2\u02b3\7e\2\2\u02b3\u02b4\7r\2\2\u02b4\u02e6\7{\2\2\u02b5"+
-		"\u02b6\7e\2\2\u02b6\u02b7\7o\2\2\u02b7\u02e6\7r\2\2\u02b8\u02b9\7e\2\2"+
-		"\u02b9\u02ba\7r\2\2\u02ba\u02e6\7z\2\2\u02bb\u02bc\7f\2\2\u02bc\u02bd"+
-		"\7e\2\2\u02bd\u02e6\7r\2\2\u02be\u02bf\7f\2\2\u02bf\u02c0\7g\2\2\u02c0"+
-		"\u02e6\7e\2\2\u02c1\u02c2\7k\2\2\u02c2\u02c3\7p\2\2\u02c3\u02e6\7e\2\2"+
-		"\u02c4\u02c5\7c\2\2\u02c5\u02c6\7z\2\2\u02c6\u02e6\7u\2\2\u02c7\u02c8"+
-		"\7d\2\2\u02c8\u02c9\7p\2\2\u02c9\u02e6\7g\2\2\u02ca\u02cb\7e\2\2\u02cb"+
-		"\u02cc\7n\2\2\u02cc\u02e6\7f\2\2\u02cd\u02ce\7u\2\2\u02ce\u02cf\7d\2\2"+
-		"\u02cf\u02e6\7e\2\2\u02d0\u02d1\7k\2\2\u02d1\u02d2\7u\2\2\u02d2\u02e6"+
-		"\7e\2\2\u02d3\u02d4\7k\2\2\u02d4\u02d5\7p\2\2\u02d5\u02e6\7z\2\2\u02d6"+
-		"\u02d7\7d\2\2\u02d7\u02d8\7g\2\2\u02d8\u02e6\7s\2\2\u02d9\u02da\7u\2\2"+
-		"\u02da\u02db\7g\2\2\u02db\u02e6\7f\2\2\u02dc\u02dd\7f\2\2\u02dd\u02de"+
-		"\7g\2\2\u02de\u02e6\7z\2\2\u02df\u02e0\7k\2\2\u02e0\u02e1\7p\2\2\u02e1"+
-		"\u02e6\7{\2\2\u02e2\u02e3\7t\2\2\u02e3\u02e4\7q\2\2\u02e4\u02e6\7t\2\2"+
-		"\u02e5\u0207\3\2\2\2\u02e5\u020a\3\2\2\2\u02e5\u020d\3\2\2\2\u02e5\u0210"+
-		"\3\2\2\2\u02e5\u0213\3\2\2\2\u02e5\u0216\3\2\2\2\u02e5\u0219\3\2\2\2\u02e5"+
-		"\u021c\3\2\2\2\u02e5\u021f\3\2\2\2\u02e5\u0222\3\2\2\2\u02e5\u0225\3\2"+
-		"\2\2\u02e5\u0228\3\2\2\2\u02e5\u022b\3\2\2\2\u02e5\u022e\3\2\2\2\u02e5"+
-		"\u0231\3\2\2\2\u02e5\u0234\3\2\2\2\u02e5\u0237\3\2\2\2\u02e5\u023a\3\2"+
-		"\2\2\u02e5\u023d\3\2\2\2\u02e5\u0240\3\2\2\2\u02e5\u0243\3\2\2\2\u02e5"+
-		"\u0246\3\2\2\2\u02e5\u0249\3\2\2\2\u02e5\u024c\3\2\2\2\u02e5\u024f\3\2"+
-		"\2\2\u02e5\u0252\3\2\2\2\u02e5\u0255\3\2\2\2\u02e5\u0258\3\2\2\2\u02e5"+
-		"\u025b\3\2\2\2\u02e5\u025e\3\2\2\2\u02e5\u0261\3\2\2\2\u02e5\u0264\3\2"+
-		"\2\2\u02e5\u0267\3\2\2\2\u02e5\u026a\3\2\2\2\u02e5\u026d\3\2\2\2\u02e5"+
-		"\u0270\3\2\2\2\u02e5\u0273\3\2\2\2\u02e5\u0276\3\2\2\2\u02e5\u0279\3\2"+
-		"\2\2\u02e5\u027c\3\2\2\2\u02e5\u027f\3\2\2\2\u02e5\u0282\3\2\2\2\u02e5"+
-		"\u0285\3\2\2\2\u02e5\u0288\3\2\2\2\u02e5\u028b\3\2\2\2\u02e5\u028e\3\2"+
-		"\2\2\u02e5\u0291\3\2\2\2\u02e5\u0294\3\2\2\2\u02e5\u0297\3\2\2\2\u02e5"+
-		"\u029a\3\2\2\2\u02e5\u029d\3\2\2\2\u02e5\u02a0\3\2\2\2\u02e5\u02a3\3\2"+
-		"\2\2\u02e5\u02a6\3\2\2\2\u02e5\u02a9\3\2\2\2\u02e5\u02ac\3\2\2\2\u02e5"+
-		"\u02af\3\2\2\2\u02e5\u02b2\3\2\2\2\u02e5\u02b5\3\2\2\2\u02e5\u02b8\3\2"+
-		"\2\2\u02e5\u02bb\3\2\2\2\u02e5\u02be\3\2\2\2\u02e5\u02c1\3\2\2\2\u02e5"+
-		"\u02c4\3\2\2\2\u02e5\u02c7\3\2\2\2\u02e5\u02ca\3\2\2\2\u02e5\u02cd\3\2"+
-		"\2\2\u02e5\u02d0\3\2\2\2\u02e5\u02d3\3\2\2\2\u02e5\u02d6\3\2\2\2\u02e5"+
-		"\u02d9\3\2\2\2\u02e5\u02dc\3\2\2\2\u02e5\u02df\3\2\2\2\u02e5\u02e2\3\2"+
-		"\2\2\u02e6\u009c\3\2\2\2\u02e7\u02e8\7}\2\2\u02e8\u02e9\7}\2\2\u02e9\u02ed"+
-		"\3\2\2\2\u02ea\u02ec\13\2\2\2\u02eb\u02ea\3\2\2\2\u02ec\u02ef\3\2\2\2"+
-		"\u02ed\u02ee\3\2\2\2\u02ed\u02eb\3\2\2\2\u02ee\u02f0\3\2\2\2\u02ef\u02ed"+
-		"\3\2\2\2\u02f0\u02f1\7\177\2\2\u02f1\u02f2\7\177\2\2\u02f2\u009e\3\2\2"+
-		"\2\u02f3\u02f4\7d\2\2\u02f4\u02f5\7{\2\2\u02f5\u02f6\7v\2\2\u02f6\u0319"+
-		"\7g\2\2\u02f7\u02f8\7y\2\2\u02f8\u02f9\7q\2\2\u02f9\u02fa\7t\2\2\u02fa"+
-		"\u0319\7f\2\2\u02fb\u02fc\7f\2\2\u02fc\u02fd\7y\2\2\u02fd\u02fe\7q\2\2"+
-		"\u02fe\u02ff\7t\2\2\u02ff\u0319\7f\2\2\u0300\u0301\7d\2\2\u0301\u0302"+
-		"\7q\2\2\u0302\u0303\7q\2\2\u0303\u0319\7n\2\2\u0304\u0305\7e\2\2\u0305"+
-		"\u0306\7j\2\2\u0306\u0307\7c\2\2\u0307\u0319\7t\2\2\u0308\u0309\7u\2\2"+
-		"\u0309\u030a\7j\2\2\u030a\u030b\7q\2\2\u030b\u030c\7t\2\2\u030c\u0319"+
-		"\7v\2\2\u030d\u030e\7k\2\2\u030e\u030f\7p\2\2\u030f\u0319\7v\2\2\u0310"+
-		"\u0311\7n\2\2\u0311\u0312\7q\2\2\u0312\u0313\7p\2\2\u0313\u0319\7i\2\2"+
-		"\u0314\u0315\7x\2\2\u0315\u0316\7q\2\2\u0316\u0317\7k\2\2\u0317\u0319"+
-		"\7f\2\2\u0318\u02f3\3\2\2\2\u0318\u02f7\3\2\2\2\u0318\u02fb\3\2\2\2\u0318"+
-		"\u0300\3\2\2\2\u0318\u0304\3\2\2\2\u0318\u0308\3\2\2\2\u0318\u030d\3\2"+
-		"\2\2\u0318\u0310\3\2\2\2\u0318\u0314\3\2\2\2\u0319\u00a0\3\2\2\2\u031a"+
-		"\u0320\7$\2\2\u031b\u031c\7^\2\2\u031c\u031f\7$\2\2\u031d\u031f\n\2\2"+
-		"\2\u031e\u031b\3\2\2\2\u031e\u031d\3\2\2\2\u031f\u0322\3\2\2\2\u0320\u031e"+
-		"\3\2\2\2\u0320\u0321\3\2\2\2\u0321\u0323\3\2\2\2\u0322\u0320\3\2\2\2\u0323"+
-		"\u0325\7$\2\2\u0324\u0326\7|\2\2\u0325\u0324\3\2\2\2\u0325\u0326\3\2\2"+
-		"\2\u0326\u00a2\3\2\2\2\u0327\u032b\7)\2\2\u0328\u0329\7^\2\2\u0329\u032c"+
-		"\7)\2\2\u032a\u032c\n\3\2\2\u032b\u0328\3\2\2\2\u032b\u032a\3\2\2\2\u032c"+
-		"\u032d\3\2\2\2\u032d\u032e\7)\2\2\u032e\u00a4\3\2\2\2\u032f\u0330\7v\2"+
-		"\2\u0330\u0331\7t\2\2\u0331\u0332\7w\2\2\u0332\u0339\7g\2\2\u0333\u0334"+
-		"\7h\2\2\u0334\u0335\7c\2\2\u0335\u0336\7n\2\2\u0336\u0337\7u\2\2\u0337"+
-		"\u0339\7g\2\2\u0338\u032f\3\2\2\2\u0338\u0333\3\2\2\2\u0339\u00a6\3\2"+
-		"\2\2\u033a\u033d\5\u00a9U\2\u033b\u033d\5\u00b1Y\2\u033c\u033a\3\2\2\2"+
-		"\u033c\u033b\3\2\2\2\u033d\u00a8\3\2\2\2\u033e\u0342\5\u00abV\2\u033f"+
-		"\u0342\5\u00adW\2\u0340\u0342\5\u00afX\2\u0341\u033e\3\2\2\2\u0341\u033f"+
-		"\3\2\2\2\u0341\u0340\3\2\2\2\u0342\u00aa\3\2\2\2\u0343\u0349\7\'\2\2\u0344"+
-		"\u0345\7\62\2\2\u0345\u0349\7d\2\2\u0346\u0347\7\62\2\2\u0347\u0349\7"+
-		"D\2\2\u0348\u0343\3\2\2\2\u0348\u0344\3\2\2\2\u0348\u0346\3\2\2\2\u0349"+
-		"\u034d\3\2\2\2\u034a\u034c\5\u00b9]\2\u034b\u034a\3\2\2\2\u034c\u034f"+
-		"\3\2\2\2\u034d\u034b\3\2\2\2\u034d\u034e\3\2\2\2\u034e\u0350\3\2\2\2\u034f"+
-		"\u034d\3\2\2\2\u0350\u0352\7\60\2\2\u0351\u0353\5\u00b9]\2\u0352\u0351"+
-		"\3\2\2\2\u0353\u0354\3\2\2\2\u0354\u0352\3\2\2\2\u0354\u0355\3\2\2\2\u0355"+
-		"\u00ac\3\2\2\2\u0356\u0358\5\u00bb^\2\u0357\u0356\3\2\2\2\u0358\u035b"+
-		"\3\2\2\2\u0359\u0357\3\2\2\2\u0359\u035a\3\2\2\2\u035a\u035c\3\2\2\2\u035b"+
-		"\u0359\3\2\2\2\u035c\u035e\7\60\2\2\u035d\u035f\5\u00bb^\2\u035e\u035d"+
-		"\3\2\2\2\u035f\u0360\3\2\2\2\u0360\u035e\3\2\2\2\u0360\u0361\3\2\2\2\u0361"+
-		"\u00ae\3\2\2\2\u0362\u0368\7&\2\2\u0363\u0364\7\62\2\2\u0364\u0368\7z"+
-		"\2\2\u0365\u0366\7\62\2\2\u0366\u0368\7Z\2\2\u0367\u0362\3\2\2\2\u0367"+
-		"\u0363\3\2\2\2\u0367\u0365\3\2\2\2\u0368\u036c\3\2\2\2\u0369\u036b\5\u00bd"+
-		"_\2\u036a\u0369\3\2\2\2\u036b\u036e\3\2\2\2\u036c\u036a\3\2\2\2\u036c"+
-		"\u036d\3\2\2\2\u036d\u036f\3\2\2\2\u036e\u036c\3\2\2\2\u036f\u0371\7\60"+
-		"\2\2\u0370\u0372\5\u00bd_\2\u0371\u0370\3\2\2\2\u0372\u0373\3\2\2\2\u0373"+
-		"\u0371\3\2\2\2\u0373\u0374\3\2\2\2\u0374\u00b0\3\2\2\2\u0375\u0379\5\u00b5"+
-		"[\2\u0376\u0379\5\u00b7\\\2\u0377\u0379\5\u00b3Z\2\u0378\u0375\3\2\2\2"+
-		"\u0378\u0376\3\2\2\2\u0378\u0377\3\2\2\2\u0379\u037d\3\2\2\2\u037a\u037b"+
-		"\t\4\2\2\u037b\u037e\t\5\2\2\u037c\u037e\7n\2\2\u037d\u037a\3\2\2\2\u037d"+
-		"\u037c\3\2\2\2\u037d\u037e\3\2\2\2\u037e\u00b2\3\2\2\2\u037f\u0380\7\62"+
-		"\2\2\u0380\u0382\t\6\2\2\u0381\u0383\5\u00b9]\2\u0382\u0381\3\2\2\2\u0383"+
-		"\u0384\3\2\2\2\u0384\u0382\3\2\2\2\u0384\u0385\3\2\2\2\u0385\u038d\3\2"+
-		"\2\2\u0386\u0388\7\'\2\2\u0387\u0389\5\u00b9]\2\u0388\u0387\3\2\2\2\u0389"+
-		"\u038a\3\2\2\2\u038a\u0388\3\2\2\2\u038a\u038b\3\2\2\2\u038b\u038d\3\2"+
-		"\2\2\u038c\u037f\3\2\2\2\u038c\u0386\3\2\2\2\u038d\u00b4\3\2\2\2\u038e"+
-		"\u0390\5\u00bb^\2\u038f\u038e\3\2\2\2\u0390\u0391\3\2\2\2\u0391\u038f"+
-		"\3\2\2\2\u0391\u0392\3\2\2\2\u0392\u00b6\3\2\2\2\u0393\u0399\7&\2\2\u0394"+
-		"\u0395\7\62\2\2\u0395\u0399\7z\2\2\u0396\u0397\7\62\2\2\u0397\u0399\7"+
-		"Z\2\2\u0398\u0393\3\2\2\2\u0398\u0394\3\2\2\2\u0398\u0396\3\2\2\2\u0399"+
-		"\u039b\3\2\2\2\u039a\u039c\5\u00bd_\2\u039b\u039a\3\2\2\2\u039c\u039d"+
-		"\3\2\2\2\u039d\u039b\3\2\2\2\u039d\u039e\3\2\2\2\u039e\u00b8\3\2\2\2\u039f"+
-		"\u03a0\t\7\2\2\u03a0\u00ba\3\2\2\2\u03a1\u03a2\t\b\2\2\u03a2\u00bc\3\2"+
-		"\2\2\u03a3\u03a4\t\t\2\2\u03a4\u00be\3\2\2\2\u03a5\u03a9\5\u00c1a\2\u03a6"+
-		"\u03a8\5\u00c3b\2\u03a7\u03a6\3\2\2\2\u03a8\u03ab\3\2\2\2\u03a9\u03a7"+
-		"\3\2\2\2\u03a9\u03aa\3\2\2\2\u03aa\u00c0\3\2\2\2\u03ab\u03a9\3\2\2\2\u03ac"+
-		"\u03ad\t\n\2\2\u03ad\u00c2\3\2\2\2\u03ae\u03af\t\13\2\2\u03af\u00c4\3"+
-		"\2\2\2\u03b0\u03b4\7#\2\2\u03b1\u03b3\5\u00c3b\2\u03b2\u03b1\3\2\2\2\u03b3"+
-		"\u03b6\3\2\2\2\u03b4\u03b2\3\2\2\2\u03b4\u03b5\3\2\2\2\u03b5\u03b8\3\2"+
-		"\2\2\u03b6\u03b4\3\2\2\2\u03b7\u03b9\t\f\2\2\u03b8\u03b7\3\2\2\2\u03b9"+
-		"\u03ba\3\2\2\2\u03ba\u03b8\3\2\2\2\u03ba\u03bb\3\2\2\2\u03bb\u00c6\3\2"+
-		"\2\2\u03bc\u03be\t\r\2\2\u03bd\u03bc\3\2\2\2\u03be\u03bf\3\2\2\2\u03bf"+
-		"\u03bd\3\2\2\2\u03bf\u03c0\3\2\2\2\u03c0\u03c1\3\2\2\2\u03c1\u03c2\bd"+
-		"\2\2\u03c2\u00c8\3\2\2\2\u03c3\u03c4\7\61\2\2\u03c4\u03c5\7\61\2\2\u03c5"+
-		"\u03c9\3\2\2\2\u03c6\u03c8\n\16\2\2\u03c7\u03c6\3\2\2\2\u03c8\u03cb\3"+
-		"\2\2\2\u03c9\u03c7\3\2\2\2\u03c9\u03ca\3\2\2\2\u03ca\u03cc\3\2\2\2\u03cb"+
-		"\u03c9\3\2\2\2\u03cc\u03cd\be\3\2\u03cd\u00ca\3\2\2\2\u03ce\u03cf\7\61"+
-		"\2\2\u03cf\u03d0\7,\2\2\u03d0\u03d4\3\2\2\2\u03d1\u03d3\13\2\2\2\u03d2"+
-		"\u03d1\3\2\2\2\u03d3\u03d6\3\2\2\2\u03d4\u03d5\3\2\2\2\u03d4\u03d2\3\2"+
-		"\2\2\u03d5\u03d7\3\2\2\2\u03d6\u03d4\3\2\2\2\u03d7\u03d8\7,\2\2\u03d8"+
-		"\u03d9\7\61\2\2\u03d9\u03da\3\2\2\2\u03da\u03db\bf\3\2\u03db\u00cc\3\2"+
-		"\2\2#\2\u02e5\u02ed\u0318\u031e\u0320\u0325\u032b\u0338\u033c\u0341\u0348"+
-		"\u034d\u0354\u0359\u0360\u0367\u036c\u0373\u0378\u037d\u0384\u038a\u038c"+
-		"\u0391\u0398\u039d\u03a9\u03b4\u03ba\u03bf\u03c9\u03d4\4\2\3\2\2\4\2";
+		"`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\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\21\3\21\3\21\3\21\3\21"+
+		"\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24"+
+		"\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\27\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\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+
+		"\3\31\3\32\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\35"+
+		"\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\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+\3+\3,\3,"+
+		"\3,\3-\3-\3-\3.\3.\3/\3/\3\60\3\60\3\61\3\61\3\62\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\67\3\67\38\38\38\39\3"+
+		"9\39\3:\3:\3;\3;\3;\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3@\3"+
+		"A\3A\3A\3A\3B\3B\3B\3C\3C\3C\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F\3"+
+		"F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3"+
+		"I\3I\3I\3I\3J\3J\3J\3J\3J\3J\3J\3K\3K\3K\3L\3L\3L\3L\3L\3L\3M\3M\3N\3"+
+		"N\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
+		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\5O\u02ef\nO\3P\3P\3P\3"+
+		"P\7P\u02f5\nP\fP\16P\u02f8\13P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q"+
+		"\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q"+
+		"\3Q\3Q\3Q\3Q\5Q\u0322\nQ\3R\3R\3R\3R\7R\u0328\nR\fR\16R\u032b\13R\3R\3"+
+		"R\5R\u032f\nR\3S\3S\3S\3S\5S\u0335\nS\3S\3S\3T\3T\3T\3T\3T\3T\3T\3T\3"+
+		"T\5T\u0342\nT\3U\3U\5U\u0346\nU\3V\3V\3V\5V\u034b\nV\3W\3W\3W\3W\3W\5"+
+		"W\u0352\nW\3W\7W\u0355\nW\fW\16W\u0358\13W\3W\3W\6W\u035c\nW\rW\16W\u035d"+
+		"\3X\7X\u0361\nX\fX\16X\u0364\13X\3X\3X\6X\u0368\nX\rX\16X\u0369\3Y\3Y"+
+		"\3Y\3Y\3Y\5Y\u0371\nY\3Y\7Y\u0374\nY\fY\16Y\u0377\13Y\3Y\3Y\6Y\u037b\n"+
+		"Y\rY\16Y\u037c\3Z\3Z\3Z\5Z\u0382\nZ\3Z\3Z\3Z\5Z\u0387\nZ\3[\3[\3[\6[\u038c"+
+		"\n[\r[\16[\u038d\3[\3[\6[\u0392\n[\r[\16[\u0393\5[\u0396\n[\3\\\6\\\u0399"+
+		"\n\\\r\\\16\\\u039a\3]\3]\3]\3]\3]\5]\u03a2\n]\3]\6]\u03a5\n]\r]\16]\u03a6"+
+		"\3^\3^\3_\3_\3`\3`\3a\3a\7a\u03b1\na\fa\16a\u03b4\13a\3b\3b\3c\3c\3d\3"+
+		"d\7d\u03bc\nd\fd\16d\u03bf\13d\3d\6d\u03c2\nd\rd\16d\u03c3\3e\6e\u03c7"+
+		"\ne\re\16e\u03c8\3e\3e\3f\3f\3f\3f\7f\u03d1\nf\ff\16f\u03d4\13f\3f\3f"+
+		"\3g\3g\3g\3g\7g\u03dc\ng\fg\16g\u03df\13g\3g\3g\3g\3g\3g\4\u02f6\u03dd"+
+		"\2h\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[\u00b5"+
+		"\\\u00b7]\u00b9^\u00bb\2\u00bd\2\u00bf\2\u00c1_\u00c3\2\u00c5\2\u00c7"+
+		"`\u00c9a\u00cbb\u00cdc\3\2\17\3\2$$\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DD"+
+		"dd\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\u0454\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\2U\3\2\2\2\2W\3\2\2\2\2"+
+		"Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3"+
+		"\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2"+
+		"\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2"+
+		"\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3"+
+		"\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2"+
+		"\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099"+
+		"\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2"+
+		"\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab"+
+		"\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2"+
+		"\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00c1\3\2\2\2\2\u00c7"+
+		"\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\3\u00cf\3\2\2"+
+		"\2\5\u00d6\3\2\2\2\7\u00d8\3\2\2\2\t\u00da\3\2\2\2\13\u00dc\3\2\2\2\r"+
+		"\u00de\3\2\2\2\17\u00e0\3\2\2\2\21\u00e2\3\2\2\2\23\u00e4\3\2\2\2\25\u00ea"+
+		"\3\2\2\2\27\u00f1\3\2\2\2\31\u00f7\3\2\2\2\33\u0100\3\2\2\2\35\u0107\3"+
+		"\2\2\2\37\u0110\3\2\2\2!\u011a\3\2\2\2#\u0122\3\2\2\2%\u0125\3\2\2\2\'"+
+		"\u012a\3\2\2\2)\u0130\3\2\2\2+\u0133\3\2\2\2-\u0137\3\2\2\2/\u013e\3\2"+
+		"\2\2\61\u0144\3\2\2\2\63\u014d\3\2\2\2\65\u0151\3\2\2\2\67\u0153\3\2\2"+
+		"\29\u0156\3\2\2\2;\u015d\3\2\2\2=\u0166\3\2\2\2?\u0168\3\2\2\2A\u016a"+
+		"\3\2\2\2C\u016c\3\2\2\2E\u0173\3\2\2\2G\u017a\3\2\2\2I\u0181\3\2\2\2K"+
+		"\u0184\3\2\2\2M\u0187\3\2\2\2O\u0189\3\2\2\2Q\u018b\3\2\2\2S\u018d\3\2"+
+		"\2\2U\u018f\3\2\2\2W\u0191\3\2\2\2Y\u0194\3\2\2\2[\u0197\3\2\2\2]\u0199"+
+		"\3\2\2\2_\u019b\3\2\2\2a\u019d\3\2\2\2c\u019f\3\2\2\2e\u01a2\3\2\2\2g"+
+		"\u01a5\3\2\2\2i\u01a8\3\2\2\2k\u01ab\3\2\2\2m\u01ad\3\2\2\2o\u01af\3\2"+
+		"\2\2q\u01b2\3\2\2\2s\u01b5\3\2\2\2u\u01b7\3\2\2\2w\u01ba\3\2\2\2y\u01bd"+
+		"\3\2\2\2{\u01c0\3\2\2\2}\u01c3\3\2\2\2\177\u01c6\3\2\2\2\u0081\u01ca\3"+
+		"\2\2\2\u0083\u01ce\3\2\2\2\u0085\u01d1\3\2\2\2\u0087\u01d4\3\2\2\2\u0089"+
+		"\u01d7\3\2\2\2\u008b\u01df\3\2\2\2\u008d\u01e8\3\2\2\2\u008f\u01ed\3\2"+
+		"\2\2\u0091\u01f6\3\2\2\2\u0093\u01fc\3\2\2\2\u0095\u0203\3\2\2\2\u0097"+
+		"\u0206\3\2\2\2\u0099\u020c\3\2\2\2\u009b\u020e\3\2\2\2\u009d\u02ee\3\2"+
+		"\2\2\u009f\u02f0\3\2\2\2\u00a1\u0321\3\2\2\2\u00a3\u0323\3\2\2\2\u00a5"+
+		"\u0330\3\2\2\2\u00a7\u0341\3\2\2\2\u00a9\u0345\3\2\2\2\u00ab\u034a\3\2"+
+		"\2\2\u00ad\u0351\3\2\2\2\u00af\u0362\3\2\2\2\u00b1\u0370\3\2\2\2\u00b3"+
+		"\u0381\3\2\2\2\u00b5\u0395\3\2\2\2\u00b7\u0398\3\2\2\2\u00b9\u03a1\3\2"+
+		"\2\2\u00bb\u03a8\3\2\2\2\u00bd\u03aa\3\2\2\2\u00bf\u03ac\3\2\2\2\u00c1"+
+		"\u03ae\3\2\2\2\u00c3\u03b5\3\2\2\2\u00c5\u03b7\3\2\2\2\u00c7\u03b9\3\2"+
+		"\2\2\u00c9\u03c6\3\2\2\2\u00cb\u03cc\3\2\2\2\u00cd\u03d7\3\2\2\2\u00cf"+
+		"\u00d0\7k\2\2\u00d0\u00d1\7o\2\2\u00d1\u00d2\7r\2\2\u00d2\u00d3\7q\2\2"+
+		"\u00d3\u00d4\7t\2\2\u00d4\u00d5\7v\2\2\u00d5\4\3\2\2\2\u00d6\u00d7\7="+
+		"\2\2\u00d7\6\3\2\2\2\u00d8\u00d9\7.\2\2\u00d9\b\3\2\2\2\u00da\u00db\7"+
+		"?\2\2\u00db\n\3\2\2\2\u00dc\u00dd\7*\2\2\u00dd\f\3\2\2\2\u00de\u00df\7"+
+		"+\2\2\u00df\16\3\2\2\2\u00e0\u00e1\7}\2\2\u00e1\20\3\2\2\2\u00e2\u00e3"+
+		"\7\177\2\2\u00e3\22\3\2\2\2\u00e4\u00e5\7e\2\2\u00e5\u00e6\7q\2\2\u00e6"+
+		"\u00e7\7p\2\2\u00e7\u00e8\7u\2\2\u00e8\u00e9\7v\2\2\u00e9\24\3\2\2\2\u00ea"+
+		"\u00eb\7g\2\2\u00eb\u00ec\7z\2\2\u00ec\u00ed\7v\2\2\u00ed\u00ee\7g\2\2"+
+		"\u00ee\u00ef\7t\2\2\u00ef\u00f0\7p\2\2\u00f0\26\3\2\2\2\u00f1\u00f2\7"+
+		"c\2\2\u00f2\u00f3\7n\2\2\u00f3\u00f4\7k\2\2\u00f4\u00f5\7i\2\2\u00f5\u00f6"+
+		"\7p\2\2\u00f6\30\3\2\2\2\u00f7\u00f8\7t\2\2\u00f8\u00f9\7g\2\2\u00f9\u00fa"+
+		"\7i\2\2\u00fa\u00fb\7k\2\2\u00fb\u00fc\7u\2\2\u00fc\u00fd\7v\2\2\u00fd"+
+		"\u00fe\7g\2\2\u00fe\u00ff\7t\2\2\u00ff\32\3\2\2\2\u0100\u0101\7k\2\2\u0101"+
+		"\u0102\7p\2\2\u0102\u0103\7n\2\2\u0103\u0104\7k\2\2\u0104\u0105\7p\2\2"+
+		"\u0105\u0106\7g\2\2\u0106\34\3\2\2\2\u0107\u0108\7x\2\2\u0108\u0109\7"+
+		"q\2\2\u0109\u010a\7n\2\2\u010a\u010b\7c\2\2\u010b\u010c\7v\2\2\u010c\u010d"+
+		"\7k\2\2\u010d\u010e\7n\2\2\u010e\u010f\7g\2\2\u010f\36\3\2\2\2\u0110\u0111"+
+		"\7k\2\2\u0111\u0112\7p\2\2\u0112\u0113\7v\2\2\u0113\u0114\7g\2\2\u0114"+
+		"\u0115\7t\2\2\u0115\u0116\7t\2\2\u0116\u0117\7w\2\2\u0117\u0118\7r\2\2"+
+		"\u0118\u0119\7v\2\2\u0119 \3\2\2\2\u011a\u011b\7t\2\2\u011b\u011c\7g\2"+
+		"\2\u011c\u011d\7u\2\2\u011d\u011e\7g\2\2\u011e\u011f\7t\2\2\u011f\u0120"+
+		"\7x\2\2\u0120\u0121\7g\2\2\u0121\"\3\2\2\2\u0122\u0123\7k\2\2\u0123\u0124"+
+		"\7h\2\2\u0124$\3\2\2\2\u0125\u0126\7g\2\2\u0126\u0127\7n\2\2\u0127\u0128"+
+		"\7u\2\2\u0128\u0129\7g\2\2\u0129&\3\2\2\2\u012a\u012b\7y\2\2\u012b\u012c"+
+		"\7j\2\2\u012c\u012d\7k\2\2\u012d\u012e\7n\2\2\u012e\u012f\7g\2\2\u012f"+
+		"(\3\2\2\2\u0130\u0131\7f\2\2\u0131\u0132\7q\2\2\u0132*\3\2\2\2\u0133\u0134"+
+		"\7h\2\2\u0134\u0135\7q\2\2\u0135\u0136\7t\2\2\u0136,\3\2\2\2\u0137\u0138"+
+		"\7t\2\2\u0138\u0139\7g\2\2\u0139\u013a\7v\2\2\u013a\u013b\7w\2\2\u013b"+
+		"\u013c\7t\2\2\u013c\u013d\7p\2\2\u013d.\3\2\2\2\u013e\u013f\7d\2\2\u013f"+
+		"\u0140\7t\2\2\u0140\u0141\7g\2\2\u0141\u0142\7c\2\2\u0142\u0143\7m\2\2"+
+		"\u0143\60\3\2\2\2\u0144\u0145\7e\2\2\u0145\u0146\7q\2\2\u0146\u0147\7"+
+		"p\2\2\u0147\u0148\7v\2\2\u0148\u0149\7k\2\2\u0149\u014a\7p\2\2\u014a\u014b"+
+		"\7w\2\2\u014b\u014c\7g\2\2\u014c\62\3\2\2\2\u014d\u014e\7c\2\2\u014e\u014f"+
+		"\7u\2\2\u014f\u0150\7o\2\2\u0150\64\3\2\2\2\u0151\u0152\7<\2\2\u0152\66"+
+		"\3\2\2\2\u0153\u0154\7\60\2\2\u0154\u0155\7\60\2\2\u01558\3\2\2\2\u0156"+
+		"\u0157\7u\2\2\u0157\u0158\7k\2\2\u0158\u0159\7i\2\2\u0159\u015a\7p\2\2"+
+		"\u015a\u015b\7g\2\2\u015b\u015c\7f\2\2\u015c:\3\2\2\2\u015d\u015e\7w\2"+
+		"\2\u015e\u015f\7p\2\2\u015f\u0160\7u\2\2\u0160\u0161\7k\2\2\u0161\u0162"+
+		"\7i\2\2\u0162\u0163\7p\2\2\u0163\u0164\7g\2\2\u0164\u0165\7f\2\2\u0165"+
+		"<\3\2\2\2\u0166\u0167\7,\2\2\u0167>\3\2\2\2\u0168\u0169\7]\2\2\u0169@"+
+		"\3\2\2\2\u016a\u016b\7_\2\2\u016bB\3\2\2\2\u016c\u016d\7u\2\2\u016d\u016e"+
+		"\7v\2\2\u016e\u016f\7t\2\2\u016f\u0170\7w\2\2\u0170\u0171\7e\2\2\u0171"+
+		"\u0172\7v\2\2\u0172D\3\2\2\2\u0173\u0174\7u\2\2\u0174\u0175\7k\2\2\u0175"+
+		"\u0176\7|\2\2\u0176\u0177\7g\2\2\u0177\u0178\7q\2\2\u0178\u0179\7h\2\2"+
+		"\u0179F\3\2\2\2\u017a\u017b\7v\2\2\u017b\u017c\7{\2\2\u017c\u017d\7r\2"+
+		"\2\u017d\u017e\7g\2\2\u017e\u017f\7k\2\2\u017f\u0180\7f\2\2\u0180H\3\2"+
+		"\2\2\u0181\u0182\7/\2\2\u0182\u0183\7/\2\2\u0183J\3\2\2\2\u0184\u0185"+
+		"\7-\2\2\u0185\u0186\7-\2\2\u0186L\3\2\2\2\u0187\u0188\7-\2\2\u0188N\3"+
+		"\2\2\2\u0189\u018a\7/\2\2\u018aP\3\2\2\2\u018b\u018c\7#\2\2\u018cR\3\2"+
+		"\2\2\u018d\u018e\7(\2\2\u018eT\3\2\2\2\u018f\u0190\7\u0080\2\2\u0190V"+
+		"\3\2\2\2\u0191\u0192\7@\2\2\u0192\u0193\7@\2\2\u0193X\3\2\2\2\u0194\u0195"+
+		"\7>\2\2\u0195\u0196\7>\2\2\u0196Z\3\2\2\2\u0197\u0198\7\61\2\2\u0198\\"+
+		"\3\2\2\2\u0199\u019a\7\'\2\2\u019a^\3\2\2\2\u019b\u019c\7>\2\2\u019c`"+
+		"\3\2\2\2\u019d\u019e\7@\2\2\u019eb\3\2\2\2\u019f\u01a0\7?\2\2\u01a0\u01a1"+
+		"\7?\2\2\u01a1d\3\2\2\2\u01a2\u01a3\7#\2\2\u01a3\u01a4\7?\2\2\u01a4f\3"+
+		"\2\2\2\u01a5\u01a6\7>\2\2\u01a6\u01a7\7?\2\2\u01a7h\3\2\2\2\u01a8\u01a9"+
+		"\7@\2\2\u01a9\u01aa\7?\2\2\u01aaj\3\2\2\2\u01ab\u01ac\7`\2\2\u01acl\3"+
+		"\2\2\2\u01ad\u01ae\7~\2\2\u01aen\3\2\2\2\u01af\u01b0\7(\2\2\u01b0\u01b1"+
+		"\7(\2\2\u01b1p\3\2\2\2\u01b2\u01b3\7~\2\2\u01b3\u01b4\7~\2\2\u01b4r\3"+
+		"\2\2\2\u01b5\u01b6\7A\2\2\u01b6t\3\2\2\2\u01b7\u01b8\7-\2\2\u01b8\u01b9"+
+		"\7?\2\2\u01b9v\3\2\2\2\u01ba\u01bb\7/\2\2\u01bb\u01bc\7?\2\2\u01bcx\3"+
+		"\2\2\2\u01bd\u01be\7,\2\2\u01be\u01bf\7?\2\2\u01bfz\3\2\2\2\u01c0\u01c1"+
+		"\7\61\2\2\u01c1\u01c2\7?\2\2\u01c2|\3\2\2\2\u01c3\u01c4\7\'\2\2\u01c4"+
+		"\u01c5\7?\2\2\u01c5~\3\2\2\2\u01c6\u01c7\7>\2\2\u01c7\u01c8\7>\2\2\u01c8"+
+		"\u01c9\7?\2\2\u01c9\u0080\3\2\2\2\u01ca\u01cb\7@\2\2\u01cb\u01cc\7@\2"+
+		"\2\u01cc\u01cd\7?\2\2\u01cd\u0082\3\2\2\2\u01ce\u01cf\7(\2\2\u01cf\u01d0"+
+		"\7?\2\2\u01d0\u0084\3\2\2\2\u01d1\u01d2\7~\2\2\u01d2\u01d3\7?\2\2\u01d3"+
+		"\u0086\3\2\2\2\u01d4\u01d5\7`\2\2\u01d5\u01d6\7?\2\2\u01d6\u0088\3\2\2"+
+		"\2\u01d7\u01d8\7m\2\2\u01d8\u01d9\7k\2\2\u01d9\u01da\7e\2\2\u01da\u01db"+
+		"\7m\2\2\u01db\u01dc\7c\2\2\u01dc\u01dd\7u\2\2\u01dd\u01de\7o\2\2\u01de"+
+		"\u008a\3\2\2\2\u01df\u01e0\7t\2\2\u01e0\u01e1\7g\2\2\u01e1\u01e2\7u\2"+
+		"\2\u01e2\u01e3\7q\2\2\u01e3\u01e4\7w\2\2\u01e4\u01e5\7t\2\2\u01e5\u01e6"+
+		"\7e\2\2\u01e6\u01e7\7g\2\2\u01e7\u008c\3\2\2\2\u01e8\u01e9\7w\2\2\u01e9"+
+		"\u01ea\7u\2\2\u01ea\u01eb\7g\2\2\u01eb\u01ec\7u\2\2\u01ec\u008e\3\2\2"+
+		"\2\u01ed\u01ee\7e\2\2\u01ee\u01ef\7n\2\2\u01ef\u01f0\7q\2\2\u01f0\u01f1"+
+		"\7d\2\2\u01f1\u01f2\7d\2\2\u01f2\u01f3\7g\2\2\u01f3\u01f4\7t\2\2\u01f4"+
+		"\u01f5\7u\2\2\u01f5\u0090\3\2\2\2\u01f6\u01f7\7d\2\2\u01f7\u01f8\7{\2"+
+		"\2\u01f8\u01f9\7v\2\2\u01f9\u01fa\7g\2\2\u01fa\u01fb\7u\2\2\u01fb\u0092"+
+		"\3\2\2\2\u01fc\u01fd\7e\2\2\u01fd\u01fe\7{\2\2\u01fe\u01ff\7e\2\2\u01ff"+
+		"\u0200\7n\2\2\u0200\u0201\7g\2\2\u0201\u0202\7u\2\2\u0202\u0094\3\2\2"+
+		"\2\u0203\u0204\7r\2\2\u0204\u0205\7e\2\2\u0205\u0096\3\2\2\2\u0206\u0207"+
+		"\7\60\2\2\u0207\u0208\7d\2\2\u0208\u0209\7{\2\2\u0209\u020a\7v\2\2\u020a"+
+		"\u020b\7g\2\2\u020b\u0098\3\2\2\2\u020c\u020d\7%\2\2\u020d\u009a\3\2\2"+
+		"\2\u020e\u020f\7\60\2\2\u020f\u009c\3\2\2\2\u0210\u0211\7d\2\2\u0211\u0212"+
+		"\7t\2\2\u0212\u02ef\7m\2\2\u0213\u0214\7q\2\2\u0214\u0215\7t\2\2\u0215"+
+		"\u02ef\7c\2\2\u0216\u0217\7m\2\2\u0217\u0218\7k\2\2\u0218\u02ef\7n\2\2"+
+		"\u0219\u021a\7u\2\2\u021a\u021b\7n\2\2\u021b\u02ef\7q\2\2\u021c\u021d"+
+		"\7p\2\2\u021d\u021e\7q\2\2\u021e\u02ef\7r\2\2\u021f\u0220\7c\2\2\u0220"+
+		"\u0221\7u\2\2\u0221\u02ef\7n\2\2\u0222\u0223\7r\2\2\u0223\u0224\7j\2\2"+
+		"\u0224\u02ef\7r\2\2\u0225\u0226\7c\2\2\u0226\u0227\7p\2\2\u0227\u02ef"+
+		"\7e\2\2\u0228\u0229\7d\2\2\u0229\u022a\7r\2\2\u022a\u02ef\7n\2\2\u022b"+
+		"\u022c\7e\2\2\u022c\u022d\7n\2\2\u022d\u02ef\7e\2\2\u022e\u022f\7l\2\2"+
+		"\u022f\u0230\7u\2\2\u0230\u02ef\7t\2\2\u0231\u0232\7c\2\2\u0232\u0233"+
+		"\7p\2\2\u0233\u02ef\7f\2\2\u0234\u0235\7t\2\2\u0235\u0236\7n\2\2\u0236"+
+		"\u02ef\7c\2\2\u0237\u0238\7d\2\2\u0238\u0239\7k\2\2\u0239\u02ef\7v\2\2"+
+		"\u023a\u023b\7t\2\2\u023b\u023c\7q\2\2\u023c\u02ef\7n\2\2\u023d\u023e"+
+		"\7r\2\2\u023e\u023f\7n\2\2\u023f\u02ef\7c\2\2\u0240\u0241\7r\2\2\u0241"+
+		"\u0242\7n\2\2\u0242\u02ef\7r\2\2\u0243\u0244\7d\2\2\u0244\u0245\7o\2\2"+
+		"\u0245\u02ef\7k\2\2\u0246\u0247\7u\2\2\u0247\u0248\7g\2\2\u0248\u02ef"+
+		"\7e\2\2\u0249\u024a\7t\2\2\u024a\u024b\7v\2\2\u024b\u02ef\7k\2\2\u024c"+
+		"\u024d\7g\2\2\u024d\u024e\7q\2\2\u024e\u02ef\7t\2\2\u024f\u0250\7u\2\2"+
+		"\u0250\u0251\7t\2\2\u0251\u02ef\7g\2\2\u0252\u0253\7n\2\2\u0253\u0254"+
+		"\7u\2\2\u0254\u02ef\7t\2\2\u0255\u0256\7r\2\2\u0256\u0257\7j\2\2\u0257"+
+		"\u02ef\7c\2\2\u0258\u0259\7c\2\2\u0259\u025a\7n\2\2\u025a\u02ef\7t\2\2"+
+		"\u025b\u025c\7l\2\2\u025c\u025d\7o\2\2\u025d\u02ef\7r\2\2\u025e\u025f"+
+		"\7d\2\2\u025f\u0260\7x\2\2\u0260\u02ef\7e\2\2\u0261\u0262\7e\2\2\u0262"+
+		"\u0263\7n\2\2\u0263\u02ef\7k\2\2\u0264\u0265\7t\2\2\u0265\u0266\7v\2\2"+
+		"\u0266\u02ef\7u\2\2\u0267\u0268\7c\2\2\u0268\u0269\7f\2\2\u0269\u02ef"+
+		"\7e\2\2\u026a\u026b\7t\2\2\u026b\u026c\7t\2\2\u026c\u02ef\7c\2\2\u026d"+
+		"\u026e\7d\2\2\u026e\u026f\7x\2\2\u026f\u02ef\7u\2\2\u0270\u0271\7u\2\2"+
+		"\u0271\u0272\7g\2\2\u0272\u02ef\7k\2\2\u0273\u0274\7u\2\2\u0274\u0275"+
+		"\7c\2\2\u0275\u02ef\7z\2\2\u0276\u0277\7u\2\2\u0277\u0278\7v\2\2\u0278"+
+		"\u02ef\7{\2\2\u0279\u027a\7u\2\2\u027a\u027b\7v\2\2\u027b\u02ef\7c\2\2"+
+		"\u027c\u027d\7u\2\2\u027d\u027e\7v\2\2\u027e\u02ef\7z\2\2\u027f\u0280"+
+		"\7f\2\2\u0280\u0281\7g\2\2\u0281\u02ef\7{\2\2\u0282\u0283\7v\2\2\u0283"+
+		"\u0284\7z\2\2\u0284\u02ef\7c\2\2\u0285\u0286\7z\2\2\u0286\u0287\7c\2\2"+
+		"\u0287\u02ef\7c\2\2\u0288\u0289\7d\2\2\u0289\u028a\7e\2\2\u028a\u02ef"+
+		"\7e\2\2\u028b\u028c\7c\2\2\u028c\u028d\7j\2\2\u028d\u02ef\7z\2\2\u028e"+
+		"\u028f\7v\2\2\u028f\u0290\7{\2\2\u0290\u02ef\7c\2\2\u0291\u0292\7v\2\2"+
+		"\u0292\u0293\7z\2\2\u0293\u02ef\7u\2\2\u0294\u0295\7v\2\2\u0295\u0296"+
+		"\7c\2\2\u0296\u02ef\7u\2\2\u0297\u0298\7u\2\2\u0298\u0299\7j\2\2\u0299"+
+		"\u02ef\7{\2\2\u029a\u029b\7u\2\2\u029b\u029c\7j\2\2\u029c\u02ef\7z\2\2"+
+		"\u029d\u029e\7n\2\2\u029e\u029f\7f\2\2\u029f\u02ef\7{\2\2\u02a0\u02a1"+
+		"\7n\2\2\u02a1\u02a2\7f\2\2\u02a2\u02ef\7c\2\2\u02a3\u02a4\7n\2\2\u02a4"+
+		"\u02a5\7f\2\2\u02a5\u02ef\7z\2\2\u02a6\u02a7\7n\2\2\u02a7\u02a8\7c\2\2"+
+		"\u02a8\u02ef\7z\2\2\u02a9\u02aa\7v\2\2\u02aa\u02ab\7c\2\2\u02ab\u02ef"+
+		"\7{\2\2\u02ac\u02ad\7v\2\2\u02ad\u02ae\7c\2\2\u02ae\u02ef\7z\2\2\u02af"+
+		"\u02b0\7d\2\2\u02b0\u02b1\7e\2\2\u02b1\u02ef\7u\2\2\u02b2\u02b3\7e\2\2"+
+		"\u02b3\u02b4\7n\2\2\u02b4\u02ef\7x\2\2\u02b5\u02b6\7v\2\2\u02b6\u02b7"+
+		"\7u\2\2\u02b7\u02ef\7z\2\2\u02b8\u02b9\7n\2\2\u02b9\u02ba\7c\2\2\u02ba"+
+		"\u02ef\7u\2\2\u02bb\u02bc\7e\2\2\u02bc\u02bd\7r\2\2\u02bd\u02ef\7{\2\2"+
+		"\u02be\u02bf\7e\2\2\u02bf\u02c0\7o\2\2\u02c0\u02ef\7r\2\2\u02c1\u02c2"+
+		"\7e\2\2\u02c2\u02c3\7r\2\2\u02c3\u02ef\7z\2\2\u02c4\u02c5\7f\2\2\u02c5"+
+		"\u02c6\7e\2\2\u02c6\u02ef\7r\2\2\u02c7\u02c8\7f\2\2\u02c8\u02c9\7g\2\2"+
+		"\u02c9\u02ef\7e\2\2\u02ca\u02cb\7k\2\2\u02cb\u02cc\7p\2\2\u02cc\u02ef"+
+		"\7e\2\2\u02cd\u02ce\7c\2\2\u02ce\u02cf\7z\2\2\u02cf\u02ef\7u\2\2\u02d0"+
+		"\u02d1\7d\2\2\u02d1\u02d2\7p\2\2\u02d2\u02ef\7g\2\2\u02d3\u02d4\7e\2\2"+
+		"\u02d4\u02d5\7n\2\2\u02d5\u02ef\7f\2\2\u02d6\u02d7\7u\2\2\u02d7\u02d8"+
+		"\7d\2\2\u02d8\u02ef\7e\2\2\u02d9\u02da\7k\2\2\u02da\u02db\7u\2\2\u02db"+
+		"\u02ef\7e\2\2\u02dc\u02dd\7k\2\2\u02dd\u02de\7p\2\2\u02de\u02ef\7z\2\2"+
+		"\u02df\u02e0\7d\2\2\u02e0\u02e1\7g\2\2\u02e1\u02ef\7s\2\2\u02e2\u02e3"+
+		"\7u\2\2\u02e3\u02e4\7g\2\2\u02e4\u02ef\7f\2\2\u02e5\u02e6\7f\2\2\u02e6"+
+		"\u02e7\7g\2\2\u02e7\u02ef\7z\2\2\u02e8\u02e9\7k\2\2\u02e9\u02ea\7p\2\2"+
+		"\u02ea\u02ef\7{\2\2\u02eb\u02ec\7t\2\2\u02ec\u02ed\7q\2\2\u02ed\u02ef"+
+		"\7t\2\2\u02ee\u0210\3\2\2\2\u02ee\u0213\3\2\2\2\u02ee\u0216\3\2\2\2\u02ee"+
+		"\u0219\3\2\2\2\u02ee\u021c\3\2\2\2\u02ee\u021f\3\2\2\2\u02ee\u0222\3\2"+
+		"\2\2\u02ee\u0225\3\2\2\2\u02ee\u0228\3\2\2\2\u02ee\u022b\3\2\2\2\u02ee"+
+		"\u022e\3\2\2\2\u02ee\u0231\3\2\2\2\u02ee\u0234\3\2\2\2\u02ee\u0237\3\2"+
+		"\2\2\u02ee\u023a\3\2\2\2\u02ee\u023d\3\2\2\2\u02ee\u0240\3\2\2\2\u02ee"+
+		"\u0243\3\2\2\2\u02ee\u0246\3\2\2\2\u02ee\u0249\3\2\2\2\u02ee\u024c\3\2"+
+		"\2\2\u02ee\u024f\3\2\2\2\u02ee\u0252\3\2\2\2\u02ee\u0255\3\2\2\2\u02ee"+
+		"\u0258\3\2\2\2\u02ee\u025b\3\2\2\2\u02ee\u025e\3\2\2\2\u02ee\u0261\3\2"+
+		"\2\2\u02ee\u0264\3\2\2\2\u02ee\u0267\3\2\2\2\u02ee\u026a\3\2\2\2\u02ee"+
+		"\u026d\3\2\2\2\u02ee\u0270\3\2\2\2\u02ee\u0273\3\2\2\2\u02ee\u0276\3\2"+
+		"\2\2\u02ee\u0279\3\2\2\2\u02ee\u027c\3\2\2\2\u02ee\u027f\3\2\2\2\u02ee"+
+		"\u0282\3\2\2\2\u02ee\u0285\3\2\2\2\u02ee\u0288\3\2\2\2\u02ee\u028b\3\2"+
+		"\2\2\u02ee\u028e\3\2\2\2\u02ee\u0291\3\2\2\2\u02ee\u0294\3\2\2\2\u02ee"+
+		"\u0297\3\2\2\2\u02ee\u029a\3\2\2\2\u02ee\u029d\3\2\2\2\u02ee\u02a0\3\2"+
+		"\2\2\u02ee\u02a3\3\2\2\2\u02ee\u02a6\3\2\2\2\u02ee\u02a9\3\2\2\2\u02ee"+
+		"\u02ac\3\2\2\2\u02ee\u02af\3\2\2\2\u02ee\u02b2\3\2\2\2\u02ee\u02b5\3\2"+
+		"\2\2\u02ee\u02b8\3\2\2\2\u02ee\u02bb\3\2\2\2\u02ee\u02be\3\2\2\2\u02ee"+
+		"\u02c1\3\2\2\2\u02ee\u02c4\3\2\2\2\u02ee\u02c7\3\2\2\2\u02ee\u02ca\3\2"+
+		"\2\2\u02ee\u02cd\3\2\2\2\u02ee\u02d0\3\2\2\2\u02ee\u02d3\3\2\2\2\u02ee"+
+		"\u02d6\3\2\2\2\u02ee\u02d9\3\2\2\2\u02ee\u02dc\3\2\2\2\u02ee\u02df\3\2"+
+		"\2\2\u02ee\u02e2\3\2\2\2\u02ee\u02e5\3\2\2\2\u02ee\u02e8\3\2\2\2\u02ee"+
+		"\u02eb\3\2\2\2\u02ef\u009e\3\2\2\2\u02f0\u02f1\7}\2\2\u02f1\u02f2\7}\2"+
+		"\2\u02f2\u02f6\3\2\2\2\u02f3\u02f5\13\2\2\2\u02f4\u02f3\3\2\2\2\u02f5"+
+		"\u02f8\3\2\2\2\u02f6\u02f7\3\2\2\2\u02f6\u02f4\3\2\2\2\u02f7\u02f9\3\2"+
+		"\2\2\u02f8\u02f6\3\2\2\2\u02f9\u02fa\7\177\2\2\u02fa\u02fb\7\177\2\2\u02fb"+
+		"\u00a0\3\2\2\2\u02fc\u02fd\7d\2\2\u02fd\u02fe\7{\2\2\u02fe\u02ff\7v\2"+
+		"\2\u02ff\u0322\7g\2\2\u0300\u0301\7y\2\2\u0301\u0302\7q\2\2\u0302\u0303"+
+		"\7t\2\2\u0303\u0322\7f\2\2\u0304\u0305\7f\2\2\u0305\u0306\7y\2\2\u0306"+
+		"\u0307\7q\2\2\u0307\u0308\7t\2\2\u0308\u0322\7f\2\2\u0309\u030a\7d\2\2"+
+		"\u030a\u030b\7q\2\2\u030b\u030c\7q\2\2\u030c\u0322\7n\2\2\u030d\u030e"+
+		"\7e\2\2\u030e\u030f\7j\2\2\u030f\u0310\7c\2\2\u0310\u0322\7t\2\2\u0311"+
+		"\u0312\7u\2\2\u0312\u0313\7j\2\2\u0313\u0314\7q\2\2\u0314\u0315\7t\2\2"+
+		"\u0315\u0322\7v\2\2\u0316\u0317\7k\2\2\u0317\u0318\7p\2\2\u0318\u0322"+
+		"\7v\2\2\u0319\u031a\7n\2\2\u031a\u031b\7q\2\2\u031b\u031c\7p\2\2\u031c"+
+		"\u0322\7i\2\2\u031d\u031e\7x\2\2\u031e\u031f\7q\2\2\u031f\u0320\7k\2\2"+
+		"\u0320\u0322\7f\2\2\u0321\u02fc\3\2\2\2\u0321\u0300\3\2\2\2\u0321\u0304"+
+		"\3\2\2\2\u0321\u0309\3\2\2\2\u0321\u030d\3\2\2\2\u0321\u0311\3\2\2\2\u0321"+
+		"\u0316\3\2\2\2\u0321\u0319\3\2\2\2\u0321\u031d\3\2\2\2\u0322\u00a2\3\2"+
+		"\2\2\u0323\u0329\7$\2\2\u0324\u0325\7^\2\2\u0325\u0328\7$\2\2\u0326\u0328"+
+		"\n\2\2\2\u0327\u0324\3\2\2\2\u0327\u0326\3\2\2\2\u0328\u032b\3\2\2\2\u0329"+
+		"\u0327\3\2\2\2\u0329\u032a\3\2\2\2\u032a\u032c\3\2\2\2\u032b\u0329\3\2"+
+		"\2\2\u032c\u032e\7$\2\2\u032d\u032f\7|\2\2\u032e\u032d\3\2\2\2\u032e\u032f"+
+		"\3\2\2\2\u032f\u00a4\3\2\2\2\u0330\u0334\7)\2\2\u0331\u0332\7^\2\2\u0332"+
+		"\u0335\7)\2\2\u0333\u0335\n\3\2\2\u0334\u0331\3\2\2\2\u0334\u0333\3\2"+
+		"\2\2\u0335\u0336\3\2\2\2\u0336\u0337\7)\2\2\u0337\u00a6\3\2\2\2\u0338"+
+		"\u0339\7v\2\2\u0339\u033a\7t\2\2\u033a\u033b\7w\2\2\u033b\u0342\7g\2\2"+
+		"\u033c\u033d\7h\2\2\u033d\u033e\7c\2\2\u033e\u033f\7n\2\2\u033f\u0340"+
+		"\7u\2\2\u0340\u0342\7g\2\2\u0341\u0338\3\2\2\2\u0341\u033c\3\2\2\2\u0342"+
+		"\u00a8\3\2\2\2\u0343\u0346\5\u00abV\2\u0344\u0346\5\u00b3Z\2\u0345\u0343"+
+		"\3\2\2\2\u0345\u0344\3\2\2\2\u0346\u00aa\3\2\2\2\u0347\u034b\5\u00adW"+
+		"\2\u0348\u034b\5\u00afX\2\u0349\u034b\5\u00b1Y\2\u034a\u0347\3\2\2\2\u034a"+
+		"\u0348\3\2\2\2\u034a\u0349\3\2\2\2\u034b\u00ac\3\2\2\2\u034c\u0352\7\'"+
+		"\2\2\u034d\u034e\7\62\2\2\u034e\u0352\7d\2\2\u034f\u0350\7\62\2\2\u0350"+
+		"\u0352\7D\2\2\u0351\u034c\3\2\2\2\u0351\u034d\3\2\2\2\u0351\u034f\3\2"+
+		"\2\2\u0352\u0356\3\2\2\2\u0353\u0355\5\u00bb^\2\u0354\u0353\3\2\2\2\u0355"+
+		"\u0358\3\2\2\2\u0356\u0354\3\2\2\2\u0356\u0357\3\2\2\2\u0357\u0359\3\2"+
+		"\2\2\u0358\u0356\3\2\2\2\u0359\u035b\7\60\2\2\u035a\u035c\5\u00bb^\2\u035b"+
+		"\u035a\3\2\2\2\u035c\u035d\3\2\2\2\u035d\u035b\3\2\2\2\u035d\u035e\3\2"+
+		"\2\2\u035e\u00ae\3\2\2\2\u035f\u0361\5\u00bd_\2\u0360\u035f\3\2\2\2\u0361"+
+		"\u0364\3\2\2\2\u0362\u0360\3\2\2\2\u0362\u0363\3\2\2\2\u0363\u0365\3\2"+
+		"\2\2\u0364\u0362\3\2\2\2\u0365\u0367\7\60\2\2\u0366\u0368\5\u00bd_\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\u00b0\3\2\2\2\u036b\u0371\7&\2\2\u036c\u036d\7\62\2\2\u036d"+
+		"\u0371\7z\2\2\u036e\u036f\7\62\2\2\u036f\u0371\7Z\2\2\u0370\u036b\3\2"+
+		"\2\2\u0370\u036c\3\2\2\2\u0370\u036e\3\2\2\2\u0371\u0375\3\2\2\2\u0372"+
+		"\u0374\5\u00bf`\2\u0373\u0372\3\2\2\2\u0374\u0377\3\2\2\2\u0375\u0373"+
+		"\3\2\2\2\u0375\u0376\3\2\2\2\u0376\u0378\3\2\2\2\u0377\u0375\3\2\2\2\u0378"+
+		"\u037a\7\60\2\2\u0379\u037b\5\u00bf`\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"+
+		"\u0382\5\u00b7\\\2\u037f\u0382\5\u00b9]\2\u0380\u0382\5\u00b5[\2\u0381"+
+		"\u037e\3\2\2\2\u0381\u037f\3\2\2\2\u0381\u0380\3\2\2\2\u0382\u0386\3\2"+
+		"\2\2\u0383\u0384\t\4\2\2\u0384\u0387\t\5\2\2\u0385\u0387\7n\2\2\u0386"+
+		"\u0383\3\2\2\2\u0386\u0385\3\2\2\2\u0386\u0387\3\2\2\2\u0387\u00b4\3\2"+
+		"\2\2\u0388\u0389\7\62\2\2\u0389\u038b\t\6\2\2\u038a\u038c\5\u00bb^\2\u038b"+
+		"\u038a\3\2\2\2\u038c\u038d\3\2\2\2\u038d\u038b\3\2\2\2\u038d\u038e\3\2"+
+		"\2\2\u038e\u0396\3\2\2\2\u038f\u0391\7\'\2\2\u0390\u0392\5\u00bb^\2\u0391"+
+		"\u0390\3\2\2\2\u0392\u0393\3\2\2\2\u0393\u0391\3\2\2\2\u0393\u0394\3\2"+
+		"\2\2\u0394\u0396\3\2\2\2\u0395\u0388\3\2\2\2\u0395\u038f\3\2\2\2\u0396"+
+		"\u00b6\3\2\2\2\u0397\u0399\5\u00bd_\2\u0398\u0397\3\2\2\2\u0399\u039a"+
+		"\3\2\2\2\u039a\u0398\3\2\2\2\u039a\u039b\3\2\2\2\u039b\u00b8\3\2\2\2\u039c"+
+		"\u03a2\7&\2\2\u039d\u039e\7\62\2\2\u039e\u03a2\7z\2\2\u039f\u03a0\7\62"+
+		"\2\2\u03a0\u03a2\7Z\2\2\u03a1\u039c\3\2\2\2\u03a1\u039d\3\2\2\2\u03a1"+
+		"\u039f\3\2\2\2\u03a2\u03a4\3\2\2\2\u03a3\u03a5\5\u00bf`\2\u03a4\u03a3"+
+		"\3\2\2\2\u03a5\u03a6\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a6\u03a7\3\2\2\2\u03a7"+
+		"\u00ba\3\2\2\2\u03a8\u03a9\t\7\2\2\u03a9\u00bc\3\2\2\2\u03aa\u03ab\t\b"+
+		"\2\2\u03ab\u00be\3\2\2\2\u03ac\u03ad\t\t\2\2\u03ad\u00c0\3\2\2\2\u03ae"+
+		"\u03b2\5\u00c3b\2\u03af\u03b1\5\u00c5c\2\u03b0\u03af\3\2\2\2\u03b1\u03b4"+
+		"\3\2\2\2\u03b2\u03b0\3\2\2\2\u03b2\u03b3\3\2\2\2\u03b3\u00c2\3\2\2\2\u03b4"+
+		"\u03b2\3\2\2\2\u03b5\u03b6\t\n\2\2\u03b6\u00c4\3\2\2\2\u03b7\u03b8\t\13"+
+		"\2\2\u03b8\u00c6\3\2\2\2\u03b9\u03bd\7#\2\2\u03ba\u03bc\5\u00c5c\2\u03bb"+
+		"\u03ba\3\2\2\2\u03bc\u03bf\3\2\2\2\u03bd\u03bb\3\2\2\2\u03bd\u03be\3\2"+
+		"\2\2\u03be\u03c1\3\2\2\2\u03bf\u03bd\3\2\2\2\u03c0\u03c2\t\f\2\2\u03c1"+
+		"\u03c0\3\2\2\2\u03c2\u03c3\3\2\2\2\u03c3\u03c1\3\2\2\2\u03c3\u03c4\3\2"+
+		"\2\2\u03c4\u00c8\3\2\2\2\u03c5\u03c7\t\r\2\2\u03c6\u03c5\3\2\2\2\u03c7"+
+		"\u03c8\3\2\2\2\u03c8\u03c6\3\2\2\2\u03c8\u03c9\3\2\2\2\u03c9\u03ca\3\2"+
+		"\2\2\u03ca\u03cb\be\2\2\u03cb\u00ca\3\2\2\2\u03cc\u03cd\7\61\2\2\u03cd"+
+		"\u03ce\7\61\2\2\u03ce\u03d2\3\2\2\2\u03cf\u03d1\n\16\2\2\u03d0\u03cf\3"+
+		"\2\2\2\u03d1\u03d4\3\2\2\2\u03d2\u03d0\3\2\2\2\u03d2\u03d3\3\2\2\2\u03d3"+
+		"\u03d5\3\2\2\2\u03d4\u03d2\3\2\2\2\u03d5\u03d6\bf\3\2\u03d6\u00cc\3\2"+
+		"\2\2\u03d7\u03d8\7\61\2\2\u03d8\u03d9\7,\2\2\u03d9\u03dd\3\2\2\2\u03da"+
+		"\u03dc\13\2\2\2\u03db\u03da\3\2\2\2\u03dc\u03df\3\2\2\2\u03dd\u03de\3"+
+		"\2\2\2\u03dd\u03db\3\2\2\2\u03de\u03e0\3\2\2\2\u03df\u03dd\3\2\2\2\u03e0"+
+		"\u03e1\7,\2\2\u03e1\u03e2\7\61\2\2\u03e2\u03e3\3\2\2\2\u03e3\u03e4\bg"+
+		"\3\2\u03e4\u00ce\3\2\2\2#\2\u02ee\u02f6\u0321\u0327\u0329\u032e\u0334"+
+		"\u0341\u0345\u034a\u0351\u0356\u035d\u0362\u0369\u0370\u0375\u037c\u0381"+
+		"\u0386\u038d\u0393\u0395\u039a\u03a1\u03a6\u03b2\u03bd\u03c3\u03c8\u03d2"+
+		"\u03dd\4\2\3\2\2\4\2";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens
index c69744d23..a303b96fe 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens
@@ -74,26 +74,27 @@ T__72=73
 T__73=74
 T__74=75
 T__75=76
-MNEMONIC=77
-KICKASM=78
-SIMPLETYPE=79
-STRING=80
-CHAR=81
-BOOLEAN=82
-NUMBER=83
-NUMFLOAT=84
-BINFLOAT=85
-DECFLOAT=86
-HEXFLOAT=87
-NUMINT=88
-BININTEGER=89
-DECINTEGER=90
-HEXINTEGER=91
-NAME=92
-ASMREL=93
-WS=94
-COMMENT_LINE=95
-COMMENT_BLOCK=96
+T__76=77
+MNEMONIC=78
+KICKASM=79
+SIMPLETYPE=80
+STRING=81
+CHAR=82
+BOOLEAN=83
+NUMBER=84
+NUMFLOAT=85
+BINFLOAT=86
+DECFLOAT=87
+HEXFLOAT=88
+NUMINT=89
+BININTEGER=90
+DECINTEGER=91
+HEXINTEGER=92
+NAME=93
+ASMREL=94
+WS=95
+COMMENT_LINE=96
+COMMENT_BLOCK=97
 'import'=1
 ';'=2
 ','=3
@@ -126,47 +127,48 @@ COMMENT_BLOCK=96
 '*'=30
 '['=31
 ']'=32
-'sizeof'=33
-'typeid'=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
-'&='=64
-'|='=65
-'^='=66
-'kickasm'=67
-'resource'=68
-'uses'=69
-'clobbers'=70
-'bytes'=71
-'cycles'=72
-'pc'=73
-'.byte'=74
-'#'=75
-'.'=76
+'struct'=33
+'sizeof'=34
+'typeid'=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
+'>>='=64
+'&='=65
+'|='=66
+'^='=67
+'kickasm'=68
+'resource'=69
+'uses'=70
+'clobbers'=71
+'bytes'=72
+'cycles'=73
+'pc'=74
+'.byte'=75
+'#'=76
+'.'=77
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
index 54517c054..950823cc9 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
@@ -517,6 +517,18 @@ public interface KickCListener extends ParseTreeListener {
 	 * @param ctx the parse tree
 	 */
 	void exitTypeArray(KickCParser.TypeArrayContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code typeStructRef}
+	 * labeled alternative in {@link KickCParser#typeDecl}.
+	 * @param ctx the parse tree
+	 */
+	void enterTypeStructRef(KickCParser.TypeStructRefContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code typeStructRef}
+	 * labeled alternative in {@link KickCParser#typeDecl}.
+	 * @param ctx the parse tree
+	 */
+	void exitTypeStructRef(KickCParser.TypeStructRefContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code typeSimple}
 	 * labeled alternative in {@link KickCParser#typeDecl}.
@@ -529,6 +541,18 @@ public interface KickCListener extends ParseTreeListener {
 	 * @param ctx the parse tree
 	 */
 	void exitTypeSimple(KickCParser.TypeSimpleContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code typeStructDef}
+	 * labeled alternative in {@link KickCParser#typeDecl}.
+	 * @param ctx the parse tree
+	 */
+	void enterTypeStructDef(KickCParser.TypeStructDefContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code typeStructDef}
+	 * labeled alternative in {@link KickCParser#typeDecl}.
+	 * @param ctx the parse tree
+	 */
+	void exitTypeStructDef(KickCParser.TypeStructDefContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code typeSignedSimple}
 	 * labeled alternative in {@link KickCParser#typeDecl}.
@@ -541,6 +565,36 @@ public interface KickCListener extends ParseTreeListener {
 	 * @param ctx the parse tree
 	 */
 	void exitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link KickCParser#structRef}.
+	 * @param ctx the parse tree
+	 */
+	void enterStructRef(KickCParser.StructRefContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link KickCParser#structRef}.
+	 * @param ctx the parse tree
+	 */
+	void exitStructRef(KickCParser.StructRefContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link KickCParser#structDef}.
+	 * @param ctx the parse tree
+	 */
+	void enterStructDef(KickCParser.StructDefContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link KickCParser#structDef}.
+	 * @param ctx the parse tree
+	 */
+	void exitStructDef(KickCParser.StructDefContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link KickCParser#structMembers}.
+	 * @param ctx the parse tree
+	 */
+	void enterStructMembers(KickCParser.StructMembersContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link KickCParser#structMembers}.
+	 * @param ctx the parse tree
+	 */
+	void exitStructMembers(KickCParser.StructMembersContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code commaNone}
 	 * labeled alternative in {@link KickCParser#commaExpr}.
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
index 807940f33..02a84e4b0 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
@@ -27,29 +27,30 @@ public class KickCParser extends Parser {
 		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, T__71=72, T__72=73, 
-		T__73=74, T__74=75, T__75=76, MNEMONIC=77, KICKASM=78, SIMPLETYPE=79, 
-		STRING=80, CHAR=81, BOOLEAN=82, NUMBER=83, NUMFLOAT=84, BINFLOAT=85, DECFLOAT=86, 
-		HEXFLOAT=87, NUMINT=88, BININTEGER=89, DECINTEGER=90, HEXINTEGER=91, NAME=92, 
-		ASMREL=93, WS=94, COMMENT_LINE=95, COMMENT_BLOCK=96;
+		T__73=74, T__74=75, T__75=76, T__76=77, MNEMONIC=78, KICKASM=79, SIMPLETYPE=80, 
+		STRING=81, CHAR=82, BOOLEAN=83, NUMBER=84, NUMFLOAT=85, BINFLOAT=86, DECFLOAT=87, 
+		HEXFLOAT=88, NUMINT=89, BININTEGER=90, DECINTEGER=91, HEXINTEGER=92, NAME=93, 
+		ASMREL=94, WS=95, COMMENT_LINE=96, COMMENT_BLOCK=97;
 	public static final int
 		RULE_file = 0, RULE_asmFile = 1, RULE_importSeq = 2, RULE_importDecl = 3, 
 		RULE_declSeq = 4, RULE_decl = 5, RULE_declTypes = 6, RULE_declVariables = 7, 
 		RULE_declVariableList = 8, RULE_declVariableInit = 9, RULE_declFunction = 10, 
 		RULE_parameterListDecl = 11, RULE_parameterDecl = 12, RULE_globalDirective = 13, 
 		RULE_directive = 14, RULE_directiveReserve = 15, RULE_stmtSeq = 16, RULE_stmt = 17, 
-		RULE_forLoop = 18, RULE_forClassicInit = 19, RULE_typeDecl = 20, RULE_commaExpr = 21, 
-		RULE_expr = 22, RULE_parameterList = 23, RULE_declKasm = 24, RULE_asmDirectives = 25, 
-		RULE_asmDirective = 26, RULE_asmLines = 27, RULE_asmLine = 28, RULE_asmLabel = 29, 
-		RULE_asmInstruction = 30, RULE_asmBytes = 31, RULE_asmParamMode = 32, 
-		RULE_asmExpr = 33;
+		RULE_forLoop = 18, RULE_forClassicInit = 19, RULE_typeDecl = 20, RULE_structRef = 21, 
+		RULE_structDef = 22, RULE_structMembers = 23, RULE_commaExpr = 24, RULE_expr = 25, 
+		RULE_parameterList = 26, RULE_declKasm = 27, RULE_asmDirectives = 28, 
+		RULE_asmDirective = 29, RULE_asmLines = 30, RULE_asmLine = 31, RULE_asmLabel = 32, 
+		RULE_asmInstruction = 33, RULE_asmBytes = 34, RULE_asmParamMode = 35, 
+		RULE_asmExpr = 36;
 	public static final String[] ruleNames = {
 		"file", "asmFile", "importSeq", "importDecl", "declSeq", "decl", "declTypes", 
 		"declVariables", "declVariableList", "declVariableInit", "declFunction", 
 		"parameterListDecl", "parameterDecl", "globalDirective", "directive", 
 		"directiveReserve", "stmtSeq", "stmt", "forLoop", "forClassicInit", "typeDecl", 
-		"commaExpr", "expr", "parameterList", "declKasm", "asmDirectives", "asmDirective", 
-		"asmLines", "asmLine", "asmLabel", "asmInstruction", "asmBytes", "asmParamMode", 
-		"asmExpr"
+		"structRef", "structDef", "structMembers", "commaExpr", "expr", "parameterList", 
+		"declKasm", "asmDirectives", "asmDirective", "asmLines", "asmLine", "asmLabel", 
+		"asmInstruction", "asmBytes", "asmParamMode", "asmExpr"
 	};
 
 	private static final String[] _LITERAL_NAMES = {
@@ -57,12 +58,12 @@ public class KickCParser extends Parser {
 		"'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'", 
 		"'reserve'", "'if'", "'else'", "'while'", "'do'", "'for'", "'return'", 
 		"'break'", "'continue'", "'asm'", "':'", "'..'", "'signed'", "'unsigned'", 
-		"'*'", "'['", "']'", "'sizeof'", "'typeid'", "'--'", "'++'", "'+'", "'-'", 
-		"'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", "'>'", "'=='", 
-		"'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", "'+='", "'-='", 
-		"'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", "'^='", "'kickasm'", 
-		"'resource'", "'uses'", "'clobbers'", "'bytes'", "'cycles'", "'pc'", "'.byte'", 
-		"'#'", "'.'"
+		"'*'", "'['", "']'", "'struct'", "'sizeof'", "'typeid'", "'--'", "'++'", 
+		"'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", 
+		"'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", 
+		"'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", 
+		"'^='", "'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, 
@@ -71,10 +72,10 @@ public class KickCParser extends Parser {
 		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, 
-		null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", 
-		"CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", 
-		"NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "ASMREL", 
-		"WS", "COMMENT_LINE", "COMMENT_BLOCK"
+		null, null, null, null, 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);
 
@@ -158,11 +159,11 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(68);
+			setState(74);
 			importSeq();
-			setState(69);
+			setState(75);
 			declSeq();
-			setState(70);
+			setState(76);
 			match(EOF);
 			}
 		}
@@ -207,9 +208,9 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(72);
+			setState(78);
 			asmLines();
-			setState(73);
+			setState(79);
 			match(EOF);
 			}
 		}
@@ -257,17 +258,17 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(78);
+			setState(84);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__0) {
 				{
 				{
-				setState(75);
+				setState(81);
 				importDecl();
 				}
 				}
-				setState(80);
+				setState(86);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -311,9 +312,9 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(81);
+			setState(87);
 			match(T__0);
-			setState(82);
+			setState(88);
 			match(STRING);
 			}
 		}
@@ -361,20 +362,20 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(85); 
+			setState(91); 
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			do {
 				{
 				{
-				setState(84);
+				setState(90);
 				decl();
 				}
 				}
-				setState(87); 
+				setState(93); 
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28))) != 0) || _la==T__66 || _la==SIMPLETYPE );
+			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==T__67 || _la==SIMPLETYPE );
 			}
 		}
 		catch (RecognitionException re) {
@@ -392,6 +393,9 @@ public class KickCParser extends Parser {
 		public DeclVariablesContext declVariables() {
 			return getRuleContext(DeclVariablesContext.class,0);
 		}
+		public StructDefContext structDef() {
+			return getRuleContext(StructDefContext.class,0);
+		}
 		public DeclFunctionContext declFunction() {
 			return getRuleContext(DeclFunctionContext.class,0);
 		}
@@ -424,36 +428,45 @@ public class KickCParser extends Parser {
 		DeclContext _localctx = new DeclContext(_ctx, getState());
 		enterRule(_localctx, 10, RULE_decl);
 		try {
-			setState(95);
+			setState(104);
 			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) {
 			case 1:
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(89);
+				setState(95);
 				declVariables();
-				setState(90);
+				setState(96);
 				match(T__1);
 				}
 				break;
 			case 2:
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(92);
-				declFunction();
+				setState(98);
+				structDef();
+				setState(99);
+				match(T__1);
 				}
 				break;
 			case 3:
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(93);
-				declKasm();
+				setState(101);
+				declFunction();
 				}
 				break;
 			case 4:
 				enterOuterAlt(_localctx, 4);
 				{
-				setState(94);
+				setState(102);
+				declKasm();
+				}
+				break;
+			case 5:
+				enterOuterAlt(_localctx, 5);
+				{
+				setState(103);
 				globalDirective();
 				}
 				break;
@@ -506,33 +519,33 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(100);
+			setState(109);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) {
 				{
 				{
-				setState(97);
+				setState(106);
 				directive();
 				}
 				}
-				setState(102);
+				setState(111);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
-			setState(103);
+			setState(112);
 			typeDecl(0);
-			setState(107);
+			setState(116);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) {
 				{
 				{
-				setState(104);
+				setState(113);
 				directive();
 				}
 				}
-				setState(109);
+				setState(118);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -581,9 +594,9 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(110);
+			setState(119);
 			declTypes();
-			setState(111);
+			setState(120);
 			declVariableList(0);
 			}
 		}
@@ -640,11 +653,11 @@ public class KickCParser extends Parser {
 			enterOuterAlt(_localctx, 1);
 			{
 			{
-			setState(114);
+			setState(123);
 			declVariableInit();
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(121);
+			setState(130);
 			_errHandler.sync(this);
 			_alt = getInterpreter().adaptivePredict(_input,5,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
@@ -655,16 +668,16 @@ public class KickCParser extends Parser {
 					{
 					_localctx = new DeclVariableListContext(_parentctx, _parentState);
 					pushNewRecursionContext(_localctx, _startState, RULE_declVariableList);
-					setState(116);
+					setState(125);
 					if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
-					setState(117);
+					setState(126);
 					match(T__2);
-					setState(118);
+					setState(127);
 					declVariableInit();
 					}
 					} 
 				}
-				setState(123);
+				setState(132);
 				_errHandler.sync(this);
 				_alt = getInterpreter().adaptivePredict(_input,5,_ctx);
 			}
@@ -711,16 +724,16 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(124);
+			setState(133);
 			match(NAME);
-			setState(127);
+			setState(136);
 			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) {
 			case 1:
 				{
-				setState(125);
+				setState(134);
 				match(T__3);
-				setState(126);
+				setState(135);
 				expr(0);
 				}
 				break;
@@ -775,37 +788,37 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(129);
+			setState(138);
 			declTypes();
-			setState(130);
+			setState(139);
 			match(NAME);
-			setState(131);
+			setState(140);
 			match(T__4);
-			setState(133);
+			setState(142);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
-			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28))) != 0) || _la==SIMPLETYPE) {
+			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==SIMPLETYPE) {
 				{
-				setState(132);
+				setState(141);
 				parameterListDecl();
 				}
 			}
 
-			setState(135);
+			setState(144);
 			match(T__5);
-			setState(136);
+			setState(145);
 			match(T__6);
-			setState(138);
+			setState(147);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
-			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & ((1L << (T__66 - 67)) | (1L << (SIMPLETYPE - 67)) | (1L << (STRING - 67)) | (1L << (CHAR - 67)) | (1L << (BOOLEAN - 67)) | (1L << (NUMBER - 67)) | (1L << (NAME - 67)))) != 0)) {
+			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0)) {
 				{
-				setState(137);
+				setState(146);
 				stmtSeq();
 				}
 			}
 
-			setState(140);
+			setState(149);
 			match(T__7);
 			}
 		}
@@ -853,21 +866,21 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(142);
+			setState(151);
 			parameterDecl();
-			setState(147);
+			setState(156);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(143);
+				setState(152);
 				match(T__2);
-				setState(144);
+				setState(153);
 				parameterDecl();
 				}
 				}
-				setState(149);
+				setState(158);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -937,16 +950,16 @@ public class KickCParser extends Parser {
 		ParameterDeclContext _localctx = new ParameterDeclContext(_ctx, getState());
 		enterRule(_localctx, 24, RULE_parameterDecl);
 		try {
-			setState(154);
+			setState(163);
 			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) {
 			case 1:
 				_localctx = new ParameterDeclTypeContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(150);
+				setState(159);
 				declTypes();
-				setState(151);
+				setState(160);
 				match(NAME);
 				}
 				break;
@@ -954,7 +967,7 @@ public class KickCParser extends Parser {
 				_localctx = new ParameterDeclVoidContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(153);
+				setState(162);
 				match(SIMPLETYPE);
 				}
 				break;
@@ -1000,9 +1013,9 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(156);
+			setState(165);
 			directiveReserve();
-			setState(157);
+			setState(166);
 			match(T__1);
 			}
 		}
@@ -1167,14 +1180,14 @@ public class KickCParser extends Parser {
 		DirectiveContext _localctx = new DirectiveContext(_ctx, getState());
 		enterRule(_localctx, 28, RULE_directive);
 		try {
-			setState(178);
+			setState(187);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case T__8:
 				_localctx = new DirectiveConstContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(159);
+				setState(168);
 				match(T__8);
 				}
 				break;
@@ -1182,7 +1195,7 @@ public class KickCParser extends Parser {
 				_localctx = new DirectiveExternContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(160);
+				setState(169);
 				match(T__9);
 				}
 				break;
@@ -1190,13 +1203,13 @@ public class KickCParser extends Parser {
 				_localctx = new DirectiveAlignContext(_localctx);
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(161);
+				setState(170);
 				match(T__10);
-				setState(162);
+				setState(171);
 				match(T__4);
-				setState(163);
+				setState(172);
 				match(NUMBER);
-				setState(164);
+				setState(173);
 				match(T__5);
 				}
 				break;
@@ -1204,13 +1217,13 @@ public class KickCParser extends Parser {
 				_localctx = new DirectiveRegisterContext(_localctx);
 				enterOuterAlt(_localctx, 4);
 				{
-				setState(165);
+				setState(174);
 				match(T__11);
-				setState(166);
+				setState(175);
 				match(T__4);
-				setState(167);
+				setState(176);
 				match(NAME);
-				setState(168);
+				setState(177);
 				match(T__5);
 				}
 				break;
@@ -1218,7 +1231,7 @@ public class KickCParser extends Parser {
 				_localctx = new DirectiveInlineContext(_localctx);
 				enterOuterAlt(_localctx, 5);
 				{
-				setState(169);
+				setState(178);
 				match(T__12);
 				}
 				break;
@@ -1226,7 +1239,7 @@ public class KickCParser extends Parser {
 				_localctx = new DirectiveVolatileContext(_localctx);
 				enterOuterAlt(_localctx, 6);
 				{
-				setState(170);
+				setState(179);
 				match(T__13);
 				}
 				break;
@@ -1234,18 +1247,18 @@ public class KickCParser extends Parser {
 				_localctx = new DirectiveInterruptContext(_localctx);
 				enterOuterAlt(_localctx, 7);
 				{
-				setState(171);
+				setState(180);
 				match(T__14);
-				setState(175);
+				setState(184);
 				_errHandler.sync(this);
 				switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) {
 				case 1:
 					{
-					setState(172);
+					setState(181);
 					match(T__4);
-					setState(173);
+					setState(182);
 					match(NAME);
-					setState(174);
+					setState(183);
 					match(T__5);
 					}
 					break;
@@ -1256,7 +1269,7 @@ public class KickCParser extends Parser {
 				_localctx = new DirectiveReserveZpContext(_localctx);
 				enterOuterAlt(_localctx, 8);
 				{
-				setState(177);
+				setState(186);
 				directiveReserve();
 				}
 				break;
@@ -1306,29 +1319,29 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(180);
+			setState(189);
 			match(T__15);
-			setState(181);
+			setState(190);
 			match(T__4);
-			setState(182);
+			setState(191);
 			match(NUMBER);
-			setState(187);
+			setState(196);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(183);
+				setState(192);
 				match(T__2);
-				setState(184);
+				setState(193);
 				match(NUMBER);
 				}
 				}
-				setState(189);
+				setState(198);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
-			setState(190);
+			setState(199);
 			match(T__5);
 			}
 		}
@@ -1376,20 +1389,20 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(193); 
+			setState(202); 
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			do {
 				{
 				{
-				setState(192);
+				setState(201);
 				stmt();
 				}
 				}
-				setState(195); 
+				setState(204); 
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & ((1L << (T__66 - 67)) | (1L << (SIMPLETYPE - 67)) | (1L << (STRING - 67)) | (1L << (CHAR - 67)) | (1L << (BOOLEAN - 67)) | (1L << (NUMBER - 67)) | (1L << (NAME - 67)))) != 0) );
+			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0) );
 			}
 		}
 		catch (RecognitionException re) {
@@ -1678,16 +1691,16 @@ public class KickCParser extends Parser {
 		enterRule(_localctx, 34, RULE_stmt);
 		int _la;
 		try {
-			setState(273);
+			setState(282);
 			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,22,_ctx) ) {
 			case 1:
 				_localctx = new StmtDeclVarContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(197);
+				setState(206);
 				declVariables();
-				setState(198);
+				setState(207);
 				match(T__1);
 				}
 				break;
@@ -1695,19 +1708,19 @@ public class KickCParser extends Parser {
 				_localctx = new StmtBlockContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(200);
+				setState(209);
 				match(T__6);
-				setState(202);
+				setState(211);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 67)) & ~0x3f) == 0 && ((1L << (_la - 67)) & ((1L << (T__66 - 67)) | (1L << (SIMPLETYPE - 67)) | (1L << (STRING - 67)) | (1L << (CHAR - 67)) | (1L << (BOOLEAN - 67)) | (1L << (NUMBER - 67)) | (1L << (NAME - 67)))) != 0)) {
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0)) {
 					{
-					setState(201);
+					setState(210);
 					stmtSeq();
 					}
 				}
 
-				setState(204);
+				setState(213);
 				match(T__7);
 				}
 				break;
@@ -1715,9 +1728,9 @@ public class KickCParser extends Parser {
 				_localctx = new StmtExprContext(_localctx);
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(205);
+				setState(214);
 				commaExpr(0);
-				setState(206);
+				setState(215);
 				match(T__1);
 				}
 				break;
@@ -1725,24 +1738,24 @@ public class KickCParser extends Parser {
 				_localctx = new StmtIfElseContext(_localctx);
 				enterOuterAlt(_localctx, 4);
 				{
-				setState(208);
+				setState(217);
 				match(T__16);
-				setState(209);
+				setState(218);
 				match(T__4);
-				setState(210);
+				setState(219);
 				commaExpr(0);
-				setState(211);
+				setState(220);
 				match(T__5);
-				setState(212);
+				setState(221);
 				stmt();
-				setState(215);
+				setState(224);
 				_errHandler.sync(this);
 				switch ( getInterpreter().adaptivePredict(_input,16,_ctx) ) {
 				case 1:
 					{
-					setState(213);
+					setState(222);
 					match(T__17);
-					setState(214);
+					setState(223);
 					stmt();
 					}
 					break;
@@ -1753,29 +1766,29 @@ public class KickCParser extends Parser {
 				_localctx = new StmtWhileContext(_localctx);
 				enterOuterAlt(_localctx, 5);
 				{
-				setState(220);
+				setState(229);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) {
 					{
 					{
-					setState(217);
+					setState(226);
 					directive();
 					}
 					}
-					setState(222);
+					setState(231);
 					_errHandler.sync(this);
 					_la = _input.LA(1);
 				}
-				setState(223);
+				setState(232);
 				match(T__18);
-				setState(224);
+				setState(233);
 				match(T__4);
-				setState(225);
+				setState(234);
 				commaExpr(0);
-				setState(226);
+				setState(235);
 				match(T__5);
-				setState(227);
+				setState(236);
 				stmt();
 				}
 				break;
@@ -1783,33 +1796,33 @@ public class KickCParser extends Parser {
 				_localctx = new StmtDoWhileContext(_localctx);
 				enterOuterAlt(_localctx, 6);
 				{
-				setState(232);
+				setState(241);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) {
 					{
 					{
-					setState(229);
+					setState(238);
 					directive();
 					}
 					}
-					setState(234);
+					setState(243);
 					_errHandler.sync(this);
 					_la = _input.LA(1);
 				}
-				setState(235);
+				setState(244);
 				match(T__19);
-				setState(236);
+				setState(245);
 				stmt();
-				setState(237);
+				setState(246);
 				match(T__18);
-				setState(238);
+				setState(247);
 				match(T__4);
-				setState(239);
+				setState(248);
 				commaExpr(0);
-				setState(240);
+				setState(249);
 				match(T__5);
-				setState(241);
+				setState(250);
 				match(T__1);
 				}
 				break;
@@ -1817,29 +1830,29 @@ public class KickCParser extends Parser {
 				_localctx = new StmtForContext(_localctx);
 				enterOuterAlt(_localctx, 7);
 				{
-				setState(246);
+				setState(255);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15))) != 0)) {
 					{
 					{
-					setState(243);
+					setState(252);
 					directive();
 					}
 					}
-					setState(248);
+					setState(257);
 					_errHandler.sync(this);
 					_la = _input.LA(1);
 				}
-				setState(249);
+				setState(258);
 				match(T__20);
-				setState(250);
+				setState(259);
 				match(T__4);
-				setState(251);
+				setState(260);
 				forLoop();
-				setState(252);
+				setState(261);
 				match(T__5);
-				setState(253);
+				setState(262);
 				stmt();
 				}
 				break;
@@ -1847,19 +1860,19 @@ public class KickCParser extends Parser {
 				_localctx = new StmtReturnContext(_localctx);
 				enterOuterAlt(_localctx, 8);
 				{
-				setState(255);
+				setState(264);
 				match(T__21);
-				setState(257);
+				setState(266);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) {
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) {
 					{
-					setState(256);
+					setState(265);
 					commaExpr(0);
 					}
 				}
 
-				setState(259);
+				setState(268);
 				match(T__1);
 				}
 				break;
@@ -1867,9 +1880,9 @@ public class KickCParser extends Parser {
 				_localctx = new StmtBreakContext(_localctx);
 				enterOuterAlt(_localctx, 9);
 				{
-				setState(260);
+				setState(269);
 				match(T__22);
-				setState(261);
+				setState(270);
 				match(T__1);
 				}
 				break;
@@ -1877,9 +1890,9 @@ public class KickCParser extends Parser {
 				_localctx = new StmtContinueContext(_localctx);
 				enterOuterAlt(_localctx, 10);
 				{
-				setState(262);
+				setState(271);
 				match(T__23);
-				setState(263);
+				setState(272);
 				match(T__1);
 				}
 				break;
@@ -1887,23 +1900,23 @@ public class KickCParser extends Parser {
 				_localctx = new StmtAsmContext(_localctx);
 				enterOuterAlt(_localctx, 11);
 				{
-				setState(264);
+				setState(273);
 				match(T__24);
-				setState(266);
+				setState(275);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				if (_la==T__4) {
 					{
-					setState(265);
+					setState(274);
 					asmDirectives();
 					}
 				}
 
-				setState(268);
+				setState(277);
 				match(T__6);
-				setState(269);
+				setState(278);
 				asmLines();
-				setState(270);
+				setState(279);
 				match(T__7);
 				}
 				break;
@@ -1911,7 +1924,7 @@ public class KickCParser extends Parser {
 				_localctx = new StmtDeclKasmContext(_localctx);
 				enterOuterAlt(_localctx, 12);
 				{
-				setState(272);
+				setState(281);
 				declKasm();
 				}
 				break;
@@ -1996,27 +2009,27 @@ public class KickCParser extends Parser {
 		enterRule(_localctx, 36, RULE_forLoop);
 		int _la;
 		try {
-			setState(291);
+			setState(300);
 			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,25,_ctx) ) {
 			case 1:
 				_localctx = new ForClassicContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(275);
+				setState(284);
 				forClassicInit();
-				setState(276);
+				setState(285);
 				match(T__1);
-				setState(277);
+				setState(286);
 				commaExpr(0);
-				setState(278);
+				setState(287);
 				match(T__1);
-				setState(280);
+				setState(289);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) {
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) {
 					{
-					setState(279);
+					setState(288);
 					commaExpr(0);
 					}
 				}
@@ -2027,27 +2040,27 @@ public class KickCParser extends Parser {
 				_localctx = new ForRangeContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(283);
+				setState(292);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28))) != 0) || _la==SIMPLETYPE) {
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==SIMPLETYPE) {
 					{
-					setState(282);
+					setState(291);
 					declTypes();
 					}
 				}
 
-				setState(285);
+				setState(294);
 				match(NAME);
-				setState(286);
+				setState(295);
 				match(T__25);
-				setState(287);
+				setState(296);
 				expr(0);
 				{
-				setState(288);
+				setState(297);
 				match(T__26);
 				}
-				setState(289);
+				setState(298);
 				expr(0);
 				}
 				break;
@@ -2119,19 +2132,19 @@ public class KickCParser extends Parser {
 		enterRule(_localctx, 38, RULE_forClassicInit);
 		int _la;
 		try {
-			setState(297);
+			setState(306);
 			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,27,_ctx) ) {
 			case 1:
 				_localctx = new ForClassicInitDeclContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(294);
+				setState(303);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28))) != 0) || _la==SIMPLETYPE) {
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==SIMPLETYPE) {
 					{
-					setState(293);
+					setState(302);
 					declVariables();
 					}
 				}
@@ -2142,7 +2155,7 @@ public class KickCParser extends Parser {
 				_localctx = new ForClassicInitExprContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(296);
+				setState(305);
 				commaExpr(0);
 				}
 				break;
@@ -2249,6 +2262,25 @@ public class KickCParser extends Parser {
 			else return visitor.visitChildren(this);
 		}
 	}
+	public static class TypeStructRefContext extends TypeDeclContext {
+		public StructRefContext structRef() {
+			return getRuleContext(StructRefContext.class,0);
+		}
+		public TypeStructRefContext(TypeDeclContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).enterTypeStructRef(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).exitTypeStructRef(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitTypeStructRef(this);
+			else return visitor.visitChildren(this);
+		}
+	}
 	public static class TypeSimpleContext extends TypeDeclContext {
 		public TerminalNode SIMPLETYPE() { return getToken(KickCParser.SIMPLETYPE, 0); }
 		public TypeSimpleContext(TypeDeclContext ctx) { copyFrom(ctx); }
@@ -2266,6 +2298,25 @@ public class KickCParser extends Parser {
 			else return visitor.visitChildren(this);
 		}
 	}
+	public static class TypeStructDefContext extends TypeDeclContext {
+		public StructDefContext structDef() {
+			return getRuleContext(StructDefContext.class,0);
+		}
+		public TypeStructDefContext(TypeDeclContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).enterTypeStructDef(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).exitTypeStructDef(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitTypeStructDef(this);
+			else return visitor.visitChildren(this);
+		}
+	}
 	public static class TypeSignedSimpleContext extends TypeDeclContext {
 		public TerminalNode SIMPLETYPE() { return getToken(KickCParser.SIMPLETYPE, 0); }
 		public TypeSignedSimpleContext(TypeDeclContext ctx) { copyFrom(ctx); }
@@ -2300,39 +2351,38 @@ public class KickCParser extends Parser {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(309);
+			setState(320);
 			_errHandler.sync(this);
-			switch (_input.LA(1)) {
-			case T__4:
+			switch ( getInterpreter().adaptivePredict(_input,29,_ctx) ) {
+			case 1:
 				{
 				_localctx = new TypeParContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
 
-				setState(300);
+				setState(309);
 				match(T__4);
-				setState(301);
+				setState(310);
 				typeDecl(0);
-				setState(302);
+				setState(311);
 				match(T__5);
 				}
 				break;
-			case SIMPLETYPE:
+			case 2:
 				{
 				_localctx = new TypeSimpleContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(304);
+				setState(313);
 				match(SIMPLETYPE);
 				}
 				break;
-			case T__27:
-			case T__28:
+			case 3:
 				{
 				_localctx = new TypeSignedSimpleContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(305);
+				setState(314);
 				_la = _input.LA(1);
 				if ( !(_la==T__27 || _la==T__28) ) {
 				_errHandler.recoverInline(this);
@@ -2342,23 +2392,39 @@ public class KickCParser extends Parser {
 					_errHandler.reportMatch(this);
 					consume();
 				}
-				setState(307);
+				setState(316);
 				_errHandler.sync(this);
 				switch ( getInterpreter().adaptivePredict(_input,28,_ctx) ) {
 				case 1:
 					{
-					setState(306);
+					setState(315);
 					match(SIMPLETYPE);
 					}
 					break;
 				}
 				}
 				break;
-			default:
-				throw new NoViableAltException(this);
+			case 4:
+				{
+				_localctx = new TypeStructDefContext(_localctx);
+				_ctx = _localctx;
+				_prevctx = _localctx;
+				setState(318);
+				structDef();
+				}
+				break;
+			case 5:
+				{
+				_localctx = new TypeStructRefContext(_localctx);
+				_ctx = _localctx;
+				_prevctx = _localctx;
+				setState(319);
+				structRef();
+				}
+				break;
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(324);
+			setState(335);
 			_errHandler.sync(this);
 			_alt = getInterpreter().adaptivePredict(_input,32,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
@@ -2366,16 +2432,16 @@ public class KickCParser extends Parser {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
 					_prevctx = _localctx;
 					{
-					setState(322);
+					setState(333);
 					_errHandler.sync(this);
 					switch ( getInterpreter().adaptivePredict(_input,31,_ctx) ) {
 					case 1:
 						{
 						_localctx = new TypePtrContext(new TypeDeclContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_typeDecl);
-						setState(311);
-						if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)");
-						setState(312);
+						setState(322);
+						if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)");
+						setState(323);
 						match(T__29);
 						}
 						break;
@@ -2383,21 +2449,21 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new TypeArrayContext(new TypeDeclContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_typeDecl);
-						setState(313);
-						if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
-						setState(314);
+						setState(324);
+						if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)");
+						setState(325);
 						match(T__30);
-						setState(316);
+						setState(327);
 						_errHandler.sync(this);
 						_la = _input.LA(1);
-						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) {
+						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) {
 							{
-							setState(315);
+							setState(326);
 							expr(0);
 							}
 						}
 
-						setState(318);
+						setState(329);
 						match(T__31);
 						}
 						break;
@@ -2405,18 +2471,18 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new TypeProcedureContext(new TypeDeclContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_typeDecl);
-						setState(319);
-						if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
-						setState(320);
+						setState(330);
+						if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)");
+						setState(331);
 						match(T__4);
-						setState(321);
+						setState(332);
 						match(T__5);
 						}
 						break;
 					}
 					} 
 				}
-				setState(326);
+				setState(337);
 				_errHandler.sync(this);
 				_alt = getInterpreter().adaptivePredict(_input,32,_ctx);
 			}
@@ -2433,6 +2499,173 @@ public class KickCParser extends Parser {
 		return _localctx;
 	}
 
+	public static class StructRefContext extends ParserRuleContext {
+		public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); }
+		public StructRefContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_structRef; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).enterStructRef(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).exitStructRef(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitStructRef(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	public final StructRefContext structRef() throws RecognitionException {
+		StructRefContext _localctx = new StructRefContext(_ctx, getState());
+		enterRule(_localctx, 42, RULE_structRef);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(338);
+			match(T__32);
+			setState(339);
+			match(NAME);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class StructDefContext extends ParserRuleContext {
+		public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); }
+		public List<StructMembersContext> structMembers() {
+			return getRuleContexts(StructMembersContext.class);
+		}
+		public StructMembersContext structMembers(int i) {
+			return getRuleContext(StructMembersContext.class,i);
+		}
+		public StructDefContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_structDef; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).enterStructDef(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).exitStructDef(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitStructDef(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	public final StructDefContext structDef() throws RecognitionException {
+		StructDefContext _localctx = new StructDefContext(_ctx, getState());
+		enterRule(_localctx, 44, RULE_structDef);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(341);
+			match(T__32);
+			setState(343);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			if (_la==NAME) {
+				{
+				setState(342);
+				match(NAME);
+				}
+			}
+
+			setState(345);
+			match(T__6);
+			setState(347); 
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			do {
+				{
+				{
+				setState(346);
+				structMembers();
+				}
+				}
+				setState(349); 
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==SIMPLETYPE );
+			setState(351);
+			match(T__7);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class StructMembersContext extends ParserRuleContext {
+		public DeclVariablesContext declVariables() {
+			return getRuleContext(DeclVariablesContext.class,0);
+		}
+		public StructMembersContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_structMembers; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).enterStructMembers(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).exitStructMembers(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitStructMembers(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	public final StructMembersContext structMembers() throws RecognitionException {
+		StructMembersContext _localctx = new StructMembersContext(_ctx, getState());
+		enterRule(_localctx, 46, RULE_structMembers);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(353);
+			declVariables();
+			setState(354);
+			match(T__1);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
 	public static class CommaExprContext extends ParserRuleContext {
 		public CommaExprContext(ParserRuleContext parent, int invokingState) {
 			super(parent, invokingState);
@@ -2495,8 +2728,8 @@ public class KickCParser extends Parser {
 		int _parentState = getState();
 		CommaExprContext _localctx = new CommaExprContext(_ctx, _parentState);
 		CommaExprContext _prevctx = _localctx;
-		int _startState = 42;
-		enterRecursionRule(_localctx, 42, RULE_commaExpr, _p);
+		int _startState = 48;
+		enterRecursionRule(_localctx, 48, RULE_commaExpr, _p);
 		try {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
@@ -2506,13 +2739,13 @@ public class KickCParser extends Parser {
 			_ctx = _localctx;
 			_prevctx = _localctx;
 
-			setState(328);
+			setState(357);
 			expr(0);
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(335);
+			setState(364);
 			_errHandler.sync(this);
-			_alt = getInterpreter().adaptivePredict(_input,33,_ctx);
+			_alt = getInterpreter().adaptivePredict(_input,35,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 				if ( _alt==1 ) {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
@@ -2521,18 +2754,18 @@ public class KickCParser extends Parser {
 					{
 					_localctx = new CommaSimpleContext(new CommaExprContext(_parentctx, _parentState));
 					pushNewRecursionContext(_localctx, _startState, RULE_commaExpr);
-					setState(330);
+					setState(359);
 					if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
-					setState(331);
+					setState(360);
 					match(T__2);
-					setState(332);
+					setState(361);
 					expr(0);
 					}
 					} 
 				}
-				setState(337);
+				setState(366);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,33,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,35,_ctx);
 			}
 			}
 		}
@@ -2971,27 +3204,27 @@ public class KickCParser extends Parser {
 		int _parentState = getState();
 		ExprContext _localctx = new ExprContext(_ctx, _parentState);
 		ExprContext _prevctx = _localctx;
-		int _startState = 44;
-		enterRecursionRule(_localctx, 44, RULE_expr, _p);
+		int _startState = 50;
+		enterRecursionRule(_localctx, 50, RULE_expr, _p);
 		int _la;
 		try {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(392);
+			setState(421);
 			_errHandler.sync(this);
-			switch ( getInterpreter().adaptivePredict(_input,38,_ctx) ) {
+			switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) {
 			case 1:
 				{
 				_localctx = new ExprParContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
 
-				setState(339);
+				setState(368);
 				match(T__4);
-				setState(340);
+				setState(369);
 				commaExpr(0);
-				setState(341);
+				setState(370);
 				match(T__5);
 				}
 				break;
@@ -3000,27 +3233,27 @@ public class KickCParser extends Parser {
 				_localctx = new ExprSizeOfContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(343);
-				match(T__32);
-				setState(344);
+				setState(372);
+				match(T__33);
+				setState(373);
 				match(T__4);
-				setState(347);
+				setState(376);
 				_errHandler.sync(this);
-				switch ( getInterpreter().adaptivePredict(_input,34,_ctx) ) {
+				switch ( getInterpreter().adaptivePredict(_input,36,_ctx) ) {
 				case 1:
 					{
-					setState(345);
+					setState(374);
 					typeDecl(0);
 					}
 					break;
 				case 2:
 					{
-					setState(346);
+					setState(375);
 					expr(0);
 					}
 					break;
 				}
-				setState(349);
+				setState(378);
 				match(T__5);
 				}
 				break;
@@ -3029,27 +3262,27 @@ public class KickCParser extends Parser {
 				_localctx = new ExprTypeIdContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(351);
-				match(T__33);
-				setState(352);
+				setState(380);
+				match(T__34);
+				setState(381);
 				match(T__4);
-				setState(355);
+				setState(384);
 				_errHandler.sync(this);
-				switch ( getInterpreter().adaptivePredict(_input,35,_ctx) ) {
+				switch ( getInterpreter().adaptivePredict(_input,37,_ctx) ) {
 				case 1:
 					{
-					setState(353);
+					setState(382);
 					typeDecl(0);
 					}
 					break;
 				case 2:
 					{
-					setState(354);
+					setState(383);
 					expr(0);
 					}
 					break;
 				}
-				setState(357);
+				setState(386);
 				match(T__5);
 				}
 				break;
@@ -3058,13 +3291,13 @@ public class KickCParser extends Parser {
 				_localctx = new ExprCastContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(359);
+				setState(388);
 				match(T__4);
-				setState(360);
+				setState(389);
 				typeDecl(0);
-				setState(361);
+				setState(390);
 				match(T__5);
-				setState(362);
+				setState(391);
 				expr(24);
 				}
 				break;
@@ -3073,9 +3306,9 @@ public class KickCParser extends Parser {
 				_localctx = new ExprPreModContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(364);
+				setState(393);
 				_la = _input.LA(1);
-				if ( !(_la==T__34 || _la==T__35) ) {
+				if ( !(_la==T__35 || _la==T__36) ) {
 				_errHandler.recoverInline(this);
 				}
 				else {
@@ -3083,7 +3316,7 @@ public class KickCParser extends Parser {
 					_errHandler.reportMatch(this);
 					consume();
 				}
-				setState(365);
+				setState(394);
 				expr(23);
 				}
 				break;
@@ -3092,9 +3325,9 @@ public class KickCParser extends Parser {
 				_localctx = new ExprPtrContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(366);
+				setState(395);
 				match(T__29);
-				setState(367);
+				setState(396);
 				expr(21);
 				}
 				break;
@@ -3103,9 +3336,9 @@ public class KickCParser extends Parser {
 				_localctx = new ExprUnaryContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(368);
+				setState(397);
 				_la = _input.LA(1);
-				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40))) != 0)) ) {
+				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41))) != 0)) ) {
 				_errHandler.recoverInline(this);
 				}
 				else {
@@ -3113,7 +3346,7 @@ public class KickCParser extends Parser {
 					_errHandler.reportMatch(this);
 					consume();
 				}
-				setState(369);
+				setState(398);
 				expr(20);
 				}
 				break;
@@ -3122,9 +3355,9 @@ public class KickCParser extends Parser {
 				_localctx = new ExprUnaryContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(370);
+				setState(399);
 				_la = _input.LA(1);
-				if ( !(_la==T__45 || _la==T__46) ) {
+				if ( !(_la==T__46 || _la==T__47) ) {
 				_errHandler.recoverInline(this);
 				}
 				else {
@@ -3132,7 +3365,7 @@ public class KickCParser extends Parser {
 					_errHandler.reportMatch(this);
 					consume();
 				}
-				setState(371);
+				setState(400);
 				expr(16);
 				}
 				break;
@@ -3141,27 +3374,27 @@ public class KickCParser extends Parser {
 				_localctx = new InitListContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(372);
+				setState(401);
 				match(T__6);
-				setState(373);
+				setState(402);
 				expr(0);
-				setState(378);
+				setState(407);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				while (_la==T__2) {
 					{
 					{
-					setState(374);
+					setState(403);
 					match(T__2);
-					setState(375);
+					setState(404);
 					expr(0);
 					}
 					}
-					setState(380);
+					setState(409);
 					_errHandler.sync(this);
 					_la = _input.LA(1);
 				}
-				setState(381);
+				setState(410);
 				match(T__7);
 				}
 				break;
@@ -3170,7 +3403,7 @@ public class KickCParser extends Parser {
 				_localctx = new ExprIdContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(383);
+				setState(412);
 				match(NAME);
 				}
 				break;
@@ -3179,7 +3412,7 @@ public class KickCParser extends Parser {
 				_localctx = new ExprNumberContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(384);
+				setState(413);
 				match(NUMBER);
 				}
 				break;
@@ -3188,7 +3421,7 @@ public class KickCParser extends Parser {
 				_localctx = new ExprStringContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(386); 
+				setState(415); 
 				_errHandler.sync(this);
 				_alt = 1;
 				do {
@@ -3196,7 +3429,7 @@ public class KickCParser extends Parser {
 					case 1:
 						{
 						{
-						setState(385);
+						setState(414);
 						match(STRING);
 						}
 						}
@@ -3204,9 +3437,9 @@ public class KickCParser extends Parser {
 					default:
 						throw new NoViableAltException(this);
 					}
-					setState(388); 
+					setState(417); 
 					_errHandler.sync(this);
-					_alt = getInterpreter().adaptivePredict(_input,37,_ctx);
+					_alt = getInterpreter().adaptivePredict(_input,39,_ctx);
 				} while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER );
 				}
 				break;
@@ -3215,7 +3448,7 @@ public class KickCParser extends Parser {
 				_localctx = new ExprCharContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(390);
+				setState(419);
 				match(CHAR);
 				}
 				break;
@@ -3224,32 +3457,32 @@ public class KickCParser extends Parser {
 				_localctx = new ExprBoolContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(391);
+				setState(420);
 				match(BOOLEAN);
 				}
 				break;
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(448);
+			setState(477);
 			_errHandler.sync(this);
-			_alt = getInterpreter().adaptivePredict(_input,41,_ctx);
+			_alt = getInterpreter().adaptivePredict(_input,43,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 				if ( _alt==1 ) {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
 					_prevctx = _localctx;
 					{
-					setState(446);
+					setState(475);
 					_errHandler.sync(this);
-					switch ( getInterpreter().adaptivePredict(_input,40,_ctx) ) {
+					switch ( getInterpreter().adaptivePredict(_input,42,_ctx) ) {
 					case 1:
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(394);
+						setState(423);
 						if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)");
-						setState(395);
+						setState(424);
 						_la = _input.LA(1);
-						if ( !(_la==T__41 || _la==T__42) ) {
+						if ( !(_la==T__42 || _la==T__43) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3257,7 +3490,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(396);
+						setState(425);
 						expr(20);
 						}
 						break;
@@ -3265,11 +3498,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(397);
+						setState(426);
 						if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)");
-						setState(398);
+						setState(427);
 						_la = _input.LA(1);
-						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__43) | (1L << T__44))) != 0)) ) {
+						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__44) | (1L << T__45))) != 0)) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3277,7 +3510,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(399);
+						setState(428);
 						expr(19);
 						}
 						break;
@@ -3285,11 +3518,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(400);
+						setState(429);
 						if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)");
-						setState(401);
+						setState(430);
 						_la = _input.LA(1);
-						if ( !(_la==T__36 || _la==T__37) ) {
+						if ( !(_la==T__37 || _la==T__38) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3297,7 +3530,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(402);
+						setState(431);
 						expr(18);
 						}
 						break;
@@ -3305,11 +3538,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(403);
+						setState(432);
 						if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)");
-						setState(404);
+						setState(433);
 						_la = _input.LA(1);
-						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__45) | (1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50))) != 0)) ) {
+						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50) | (1L << T__51))) != 0)) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3317,7 +3550,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(405);
+						setState(434);
 						expr(16);
 						}
 						break;
@@ -3325,13 +3558,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(406);
+						setState(435);
 						if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)");
 						{
-						setState(407);
-						match(T__39);
+						setState(436);
+						match(T__40);
 						}
-						setState(408);
+						setState(437);
 						expr(15);
 						}
 						break;
@@ -3339,13 +3572,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(409);
+						setState(438);
 						if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)");
 						{
-						setState(410);
-						match(T__51);
+						setState(439);
+						match(T__52);
 						}
-						setState(411);
+						setState(440);
 						expr(14);
 						}
 						break;
@@ -3353,13 +3586,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(412);
+						setState(441);
 						if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
 						{
-						setState(413);
-						match(T__52);
+						setState(442);
+						match(T__53);
 						}
-						setState(414);
+						setState(443);
 						expr(13);
 						}
 						break;
@@ -3367,13 +3600,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(415);
+						setState(444);
 						if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)");
 						{
-						setState(416);
-						match(T__53);
+						setState(445);
+						match(T__54);
 						}
-						setState(417);
+						setState(446);
 						expr(12);
 						}
 						break;
@@ -3381,13 +3614,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(418);
+						setState(447);
 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
 						{
-						setState(419);
-						match(T__54);
+						setState(448);
+						match(T__55);
 						}
-						setState(420);
+						setState(449);
 						expr(11);
 						}
 						break;
@@ -3395,15 +3628,15 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprTernaryContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(421);
+						setState(450);
 						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
-						setState(422);
-						match(T__55);
-						setState(423);
+						setState(451);
+						match(T__56);
+						setState(452);
 						expr(0);
-						setState(424);
+						setState(453);
 						match(T__25);
-						setState(425);
+						setState(454);
 						expr(10);
 						}
 						break;
@@ -3411,11 +3644,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprAssignmentContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(427);
+						setState(456);
 						if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
-						setState(428);
+						setState(457);
 						match(T__3);
-						setState(429);
+						setState(458);
 						expr(8);
 						}
 						break;
@@ -3423,11 +3656,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprAssignmentCompoundContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(430);
+						setState(459);
 						if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
-						setState(431);
+						setState(460);
 						_la = _input.LA(1);
-						if ( !(((((_la - 57)) & ~0x3f) == 0 && ((1L << (_la - 57)) & ((1L << (T__56 - 57)) | (1L << (T__57 - 57)) | (1L << (T__58 - 57)) | (1L << (T__59 - 57)) | (1L << (T__60 - 57)) | (1L << (T__61 - 57)) | (1L << (T__62 - 57)) | (1L << (T__63 - 57)) | (1L << (T__64 - 57)) | (1L << (T__65 - 57)))) != 0)) ) {
+						if ( !(((((_la - 58)) & ~0x3f) == 0 && ((1L << (_la - 58)) & ((1L << (T__57 - 58)) | (1L << (T__58 - 58)) | (1L << (T__59 - 58)) | (1L << (T__60 - 58)) | (1L << (T__61 - 58)) | (1L << (T__62 - 58)) | (1L << (T__63 - 58)) | (1L << (T__64 - 58)) | (1L << (T__65 - 58)) | (1L << (T__66 - 58)))) != 0)) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3435,7 +3668,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(432);
+						setState(461);
 						expr(7);
 						}
 						break;
@@ -3443,21 +3676,21 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(433);
+						setState(462);
 						if (!(precpred(_ctx, 28))) throw new FailedPredicateException(this, "precpred(_ctx, 28)");
-						setState(434);
+						setState(463);
 						match(T__4);
-						setState(436);
+						setState(465);
 						_errHandler.sync(this);
 						_la = _input.LA(1);
-						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__45) | (1L << T__46))) != 0) || ((((_la - 80)) & ~0x3f) == 0 && ((1L << (_la - 80)) & ((1L << (STRING - 80)) | (1L << (CHAR - 80)) | (1L << (BOOLEAN - 80)) | (1L << (NUMBER - 80)) | (1L << (NAME - 80)))) != 0)) {
+						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) {
 							{
-							setState(435);
+							setState(464);
 							parameterList();
 							}
 						}
 
-						setState(438);
+						setState(467);
 						match(T__5);
 						}
 						break;
@@ -3465,13 +3698,13 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(439);
+						setState(468);
 						if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)");
-						setState(440);
+						setState(469);
 						match(T__30);
-						setState(441);
+						setState(470);
 						commaExpr(0);
-						setState(442);
+						setState(471);
 						match(T__31);
 						}
 						break;
@@ -3479,11 +3712,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(444);
+						setState(473);
 						if (!(precpred(_ctx, 22))) throw new FailedPredicateException(this, "precpred(_ctx, 22)");
-						setState(445);
+						setState(474);
 						_la = _input.LA(1);
-						if ( !(_la==T__34 || _la==T__35) ) {
+						if ( !(_la==T__35 || _la==T__36) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3496,9 +3729,9 @@ public class KickCParser extends Parser {
 					}
 					} 
 				}
-				setState(450);
+				setState(479);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,41,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,43,_ctx);
 			}
 			}
 		}
@@ -3541,26 +3774,26 @@ public class KickCParser extends Parser {
 
 	public final ParameterListContext parameterList() throws RecognitionException {
 		ParameterListContext _localctx = new ParameterListContext(_ctx, getState());
-		enterRule(_localctx, 46, RULE_parameterList);
+		enterRule(_localctx, 52, RULE_parameterList);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(451);
+			setState(480);
 			expr(0);
-			setState(456);
+			setState(485);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(452);
+				setState(481);
 				match(T__2);
-				setState(453);
+				setState(482);
 				expr(0);
 				}
 				}
-				setState(458);
+				setState(487);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -3603,24 +3836,24 @@ public class KickCParser extends Parser {
 
 	public final DeclKasmContext declKasm() throws RecognitionException {
 		DeclKasmContext _localctx = new DeclKasmContext(_ctx, getState());
-		enterRule(_localctx, 48, RULE_declKasm);
+		enterRule(_localctx, 54, RULE_declKasm);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(459);
-			match(T__66);
-			setState(461);
+			setState(488);
+			match(T__67);
+			setState(490);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			if (_la==T__4) {
 				{
-				setState(460);
+				setState(489);
 				asmDirectives();
 				}
 			}
 
-			setState(463);
+			setState(492);
 			match(KICKASM);
 			}
 		}
@@ -3663,32 +3896,32 @@ public class KickCParser extends Parser {
 
 	public final AsmDirectivesContext asmDirectives() throws RecognitionException {
 		AsmDirectivesContext _localctx = new AsmDirectivesContext(_ctx, getState());
-		enterRule(_localctx, 50, RULE_asmDirectives);
+		enterRule(_localctx, 56, RULE_asmDirectives);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(465);
+			setState(494);
 			match(T__4);
-			setState(466);
+			setState(495);
 			asmDirective();
-			setState(471);
+			setState(500);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(467);
+				setState(496);
 				match(T__2);
-				setState(468);
+				setState(497);
 				asmDirective();
 				}
 				}
-				setState(473);
+				setState(502);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
-			setState(474);
+			setState(503);
 			match(T__5);
 			}
 		}
@@ -3825,80 +4058,79 @@ public class KickCParser extends Parser {
 
 	public final AsmDirectiveContext asmDirective() throws RecognitionException {
 		AsmDirectiveContext _localctx = new AsmDirectiveContext(_ctx, getState());
-		enterRule(_localctx, 52, RULE_asmDirective);
+		enterRule(_localctx, 58, RULE_asmDirective);
 		try {
-			setState(491);
+			setState(520);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
-			case T__67:
+			case T__68:
 				_localctx = new AsmDirectiveResourceContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(476);
-				match(T__67);
-				setState(477);
-				match(STRING);
-				}
-				break;
-			case T__68:
-				_localctx = new AsmDirectiveUsesContext(_localctx);
-				enterOuterAlt(_localctx, 2);
-				{
-				setState(478);
+				setState(505);
 				match(T__68);
-				setState(479);
-				match(NAME);
+				setState(506);
+				match(STRING);
 				}
 				break;
 			case T__69:
-				_localctx = new AsmDirectiveClobberContext(_localctx);
-				enterOuterAlt(_localctx, 3);
+				_localctx = new AsmDirectiveUsesContext(_localctx);
+				enterOuterAlt(_localctx, 2);
 				{
-				setState(480);
+				setState(507);
 				match(T__69);
-				setState(481);
-				match(STRING);
+				setState(508);
+				match(NAME);
 				}
 				break;
 			case T__70:
-				_localctx = new AsmDirectiveBytesContext(_localctx);
-				enterOuterAlt(_localctx, 4);
+				_localctx = new AsmDirectiveClobberContext(_localctx);
+				enterOuterAlt(_localctx, 3);
 				{
-				setState(482);
+				setState(509);
 				match(T__70);
-				setState(483);
-				expr(0);
+				setState(510);
+				match(STRING);
 				}
 				break;
 			case T__71:
-				_localctx = new AsmDirectiveCyclesContext(_localctx);
-				enterOuterAlt(_localctx, 5);
+				_localctx = new AsmDirectiveBytesContext(_localctx);
+				enterOuterAlt(_localctx, 4);
 				{
-				setState(484);
+				setState(511);
 				match(T__71);
-				setState(485);
+				setState(512);
 				expr(0);
 				}
 				break;
 			case T__72:
+				_localctx = new AsmDirectiveCyclesContext(_localctx);
+				enterOuterAlt(_localctx, 5);
+				{
+				setState(513);
+				match(T__72);
+				setState(514);
+				expr(0);
+				}
+				break;
+			case T__73:
 				_localctx = new AsmDirectiveAddressContext(_localctx);
 				enterOuterAlt(_localctx, 6);
 				{
-				setState(486);
-				match(T__72);
-				setState(489);
+				setState(515);
+				match(T__73);
+				setState(518);
 				_errHandler.sync(this);
 				switch (_input.LA(1)) {
 				case T__12:
 					{
-					setState(487);
+					setState(516);
 					match(T__12);
 					}
 					break;
 				case T__4:
 				case T__6:
 				case T__29:
-				case T__32:
 				case T__33:
 				case T__34:
 				case T__35:
@@ -3907,15 +4139,16 @@ public class KickCParser extends Parser {
 				case T__38:
 				case T__39:
 				case T__40:
-				case T__45:
+				case T__41:
 				case T__46:
+				case T__47:
 				case STRING:
 				case CHAR:
 				case BOOLEAN:
 				case NUMBER:
 				case NAME:
 					{
-					setState(488);
+					setState(517);
 					expr(0);
 					}
 					break;
@@ -3967,22 +4200,22 @@ public class KickCParser extends Parser {
 
 	public final AsmLinesContext asmLines() throws RecognitionException {
 		AsmLinesContext _localctx = new AsmLinesContext(_ctx, getState());
-		enterRule(_localctx, 54, RULE_asmLines);
+		enterRule(_localctx, 60, RULE_asmLines);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(496);
+			setState(525);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
-			while (((((_la - 39)) & ~0x3f) == 0 && ((1L << (_la - 39)) & ((1L << (T__38 - 39)) | (1L << (T__73 - 39)) | (1L << (MNEMONIC - 39)) | (1L << (NAME - 39)))) != 0)) {
+			while (((((_la - 40)) & ~0x3f) == 0 && ((1L << (_la - 40)) & ((1L << (T__39 - 40)) | (1L << (T__74 - 40)) | (1L << (MNEMONIC - 40)) | (1L << (NAME - 40)))) != 0)) {
 				{
 				{
-				setState(493);
+				setState(522);
 				asmLine();
 				}
 				}
-				setState(498);
+				setState(527);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -4030,30 +4263,30 @@ public class KickCParser extends Parser {
 
 	public final AsmLineContext asmLine() throws RecognitionException {
 		AsmLineContext _localctx = new AsmLineContext(_ctx, getState());
-		enterRule(_localctx, 56, RULE_asmLine);
+		enterRule(_localctx, 62, RULE_asmLine);
 		try {
-			setState(502);
+			setState(531);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
-			case T__38:
+			case T__39:
 			case NAME:
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(499);
+				setState(528);
 				asmLabel();
 				}
 				break;
 			case MNEMONIC:
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(500);
+				setState(529);
 				asmInstruction();
 				}
 				break;
-			case T__73:
+			case T__74:
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(501);
+				setState(530);
 				asmBytes();
 				}
 				break;
@@ -4120,39 +4353,39 @@ public class KickCParser extends Parser {
 
 	public final AsmLabelContext asmLabel() throws RecognitionException {
 		AsmLabelContext _localctx = new AsmLabelContext(_ctx, getState());
-		enterRule(_localctx, 58, RULE_asmLabel);
+		enterRule(_localctx, 64, RULE_asmLabel);
 		int _la;
 		try {
-			setState(511);
+			setState(540);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case NAME:
 				_localctx = new AsmLabelNameContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(504);
+				setState(533);
 				match(NAME);
-				setState(505);
+				setState(534);
 				match(T__25);
 				}
 				break;
-			case T__38:
+			case T__39:
 				_localctx = new AsmLabelMultiContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(506);
-				match(T__38);
-				setState(508);
+				setState(535);
+				match(T__39);
+				setState(537);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				if (_la==NAME) {
 					{
-					setState(507);
+					setState(536);
 					match(NAME);
 					}
 				}
 
-				setState(510);
+				setState(539);
 				match(T__25);
 				}
 				break;
@@ -4197,18 +4430,18 @@ public class KickCParser extends Parser {
 
 	public final AsmInstructionContext asmInstruction() throws RecognitionException {
 		AsmInstructionContext _localctx = new AsmInstructionContext(_ctx, getState());
-		enterRule(_localctx, 60, RULE_asmInstruction);
+		enterRule(_localctx, 66, RULE_asmInstruction);
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(513);
+			setState(542);
 			match(MNEMONIC);
-			setState(515);
+			setState(544);
 			_errHandler.sync(this);
-			switch ( getInterpreter().adaptivePredict(_input,51,_ctx) ) {
+			switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) {
 			case 1:
 				{
-				setState(514);
+				setState(543);
 				asmParamMode();
 				}
 				break;
@@ -4254,28 +4487,28 @@ public class KickCParser extends Parser {
 
 	public final AsmBytesContext asmBytes() throws RecognitionException {
 		AsmBytesContext _localctx = new AsmBytesContext(_ctx, getState());
-		enterRule(_localctx, 62, RULE_asmBytes);
+		enterRule(_localctx, 68, RULE_asmBytes);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(517);
-			match(T__73);
-			setState(518);
+			setState(546);
+			match(T__74);
+			setState(547);
 			asmExpr(0);
-			setState(523);
+			setState(552);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(519);
+				setState(548);
 				match(T__2);
-				setState(520);
+				setState(549);
 				asmExpr(0);
 				}
 				}
-				setState(525);
+				setState(554);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -4423,16 +4656,16 @@ public class KickCParser extends Parser {
 
 	public final AsmParamModeContext asmParamMode() throws RecognitionException {
 		AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState());
-		enterRule(_localctx, 64, RULE_asmParamMode);
+		enterRule(_localctx, 70, RULE_asmParamMode);
 		try {
-			setState(549);
+			setState(578);
 			_errHandler.sync(this);
-			switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) {
+			switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) {
 			case 1:
 				_localctx = new AsmModeAbsContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(526);
+				setState(555);
 				asmExpr(0);
 				}
 				break;
@@ -4440,9 +4673,9 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeImmContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(527);
-				match(T__74);
-				setState(528);
+				setState(556);
+				match(T__75);
+				setState(557);
 				asmExpr(0);
 				}
 				break;
@@ -4450,11 +4683,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeAbsXYContext(_localctx);
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(529);
+				setState(558);
 				asmExpr(0);
-				setState(530);
+				setState(559);
 				match(T__2);
-				setState(531);
+				setState(560);
 				match(NAME);
 				}
 				break;
@@ -4462,15 +4695,15 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIndIdxXYContext(_localctx);
 				enterOuterAlt(_localctx, 4);
 				{
-				setState(533);
+				setState(562);
 				match(T__4);
-				setState(534);
+				setState(563);
 				asmExpr(0);
-				setState(535);
+				setState(564);
 				match(T__5);
-				setState(536);
+				setState(565);
 				match(T__2);
-				setState(537);
+				setState(566);
 				match(NAME);
 				}
 				break;
@@ -4478,15 +4711,15 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIdxIndXYContext(_localctx);
 				enterOuterAlt(_localctx, 5);
 				{
-				setState(539);
+				setState(568);
 				match(T__4);
-				setState(540);
+				setState(569);
 				asmExpr(0);
-				setState(541);
+				setState(570);
 				match(T__2);
-				setState(542);
+				setState(571);
 				match(NAME);
-				setState(543);
+				setState(572);
 				match(T__5);
 				}
 				break;
@@ -4494,11 +4727,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIndContext(_localctx);
 				enterOuterAlt(_localctx, 6);
 				{
-				setState(545);
+				setState(574);
 				match(T__4);
-				setState(546);
+				setState(575);
 				asmExpr(0);
-				setState(547);
+				setState(576);
 				match(T__5);
 				}
 				break;
@@ -4681,14 +4914,14 @@ public class KickCParser extends Parser {
 		int _parentState = getState();
 		AsmExprContext _localctx = new AsmExprContext(_ctx, _parentState);
 		AsmExprContext _prevctx = _localctx;
-		int _startState = 66;
-		enterRecursionRule(_localctx, 66, RULE_asmExpr, _p);
+		int _startState = 72;
+		enterRecursionRule(_localctx, 72, RULE_asmExpr, _p);
 		int _la;
 		try {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(565);
+			setState(594);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case T__30:
@@ -4697,25 +4930,25 @@ public class KickCParser extends Parser {
 				_ctx = _localctx;
 				_prevctx = _localctx;
 
-				setState(552);
+				setState(581);
 				match(T__30);
-				setState(553);
+				setState(582);
 				asmExpr(0);
-				setState(554);
+				setState(583);
 				match(T__31);
 				}
 				break;
-			case T__36:
 			case T__37:
-			case T__45:
+			case T__38:
 			case T__46:
+			case T__47:
 				{
 				_localctx = new AsmExprUnaryContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(556);
+				setState(585);
 				_la = _input.LA(1);
-				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__36) | (1L << T__37) | (1L << T__45) | (1L << T__46))) != 0)) ) {
+				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__46) | (1L << T__47))) != 0)) ) {
 				_errHandler.recoverInline(this);
 				}
 				else {
@@ -4723,7 +4956,7 @@ public class KickCParser extends Parser {
 					_errHandler.reportMatch(this);
 					consume();
 				}
-				setState(557);
+				setState(586);
 				asmExpr(8);
 				}
 				break;
@@ -4732,7 +4965,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprLabelContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(558);
+				setState(587);
 				match(NAME);
 				}
 				break;
@@ -4741,7 +4974,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprLabelRelContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(559);
+				setState(588);
 				match(ASMREL);
 				}
 				break;
@@ -4750,11 +4983,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprReplaceContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(560);
+				setState(589);
 				match(T__6);
-				setState(561);
+				setState(590);
 				match(NAME);
-				setState(562);
+				setState(591);
 				match(T__7);
 				}
 				break;
@@ -4763,7 +4996,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprIntContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(563);
+				setState(592);
 				match(NUMBER);
 				}
 				break;
@@ -4772,7 +5005,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprCharContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(564);
+				setState(593);
 				match(CHAR);
 				}
 				break;
@@ -4780,28 +5013,28 @@ public class KickCParser extends Parser {
 				throw new NoViableAltException(this);
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(581);
+			setState(610);
 			_errHandler.sync(this);
-			_alt = getInterpreter().adaptivePredict(_input,56,_ctx);
+			_alt = getInterpreter().adaptivePredict(_input,58,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 				if ( _alt==1 ) {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
 					_prevctx = _localctx;
 					{
-					setState(579);
+					setState(608);
 					_errHandler.sync(this);
-					switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) {
+					switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) {
 					case 1:
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(567);
+						setState(596);
 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
 						{
-						setState(568);
-						match(T__75);
+						setState(597);
+						match(T__76);
 						}
-						setState(569);
+						setState(598);
 						asmExpr(11);
 						}
 						break;
@@ -4809,11 +5042,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(570);
+						setState(599);
 						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
-						setState(571);
+						setState(600);
 						_la = _input.LA(1);
-						if ( !(_la==T__41 || _la==T__42) ) {
+						if ( !(_la==T__42 || _la==T__43) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -4821,7 +5054,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(572);
+						setState(601);
 						asmExpr(10);
 						}
 						break;
@@ -4829,11 +5062,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(573);
+						setState(602);
 						if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
-						setState(574);
+						setState(603);
 						_la = _input.LA(1);
-						if ( !(_la==T__29 || _la==T__43) ) {
+						if ( !(_la==T__29 || _la==T__44) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -4841,7 +5074,7 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(575);
+						setState(604);
 						asmExpr(8);
 						}
 						break;
@@ -4849,11 +5082,11 @@ public class KickCParser extends Parser {
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(576);
+						setState(605);
 						if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
-						setState(577);
+						setState(606);
 						_la = _input.LA(1);
-						if ( !(_la==T__36 || _la==T__37) ) {
+						if ( !(_la==T__37 || _la==T__38) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -4861,16 +5094,16 @@ public class KickCParser extends Parser {
 							_errHandler.reportMatch(this);
 							consume();
 						}
-						setState(578);
+						setState(607);
 						asmExpr(7);
 						}
 						break;
 					}
 					} 
 				}
-				setState(583);
+				setState(612);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,56,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,58,_ctx);
 			}
 			}
 		}
@@ -4891,11 +5124,11 @@ public class KickCParser extends Parser {
 			return declVariableList_sempred((DeclVariableListContext)_localctx, predIndex);
 		case 20:
 			return typeDecl_sempred((TypeDeclContext)_localctx, predIndex);
-		case 21:
+		case 24:
 			return commaExpr_sempred((CommaExprContext)_localctx, predIndex);
-		case 22:
+		case 25:
 			return expr_sempred((ExprContext)_localctx, predIndex);
-		case 33:
+		case 36:
 			return asmExpr_sempred((AsmExprContext)_localctx, predIndex);
 		}
 		return true;
@@ -4910,11 +5143,11 @@ public class KickCParser extends Parser {
 	private boolean typeDecl_sempred(TypeDeclContext _localctx, int predIndex) {
 		switch (predIndex) {
 		case 1:
-			return precpred(_ctx, 3);
+			return precpred(_ctx, 5);
 		case 2:
-			return precpred(_ctx, 2);
+			return precpred(_ctx, 4);
 		case 3:
-			return precpred(_ctx, 1);
+			return precpred(_ctx, 3);
 		}
 		return true;
 	}
@@ -4975,235 +5208,246 @@ public class KickCParser extends Parser {
 	}
 
 	public static final String _serializedATN =
-		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3b\u024b\4\2\t\2\4"+
+		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3c\u0268\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"+
 		"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
-		"\t!\4\"\t\"\4#\t#\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\4\7\4O\n\4\f\4\16\4R\13"+
-		"\4\3\5\3\5\3\5\3\6\6\6X\n\6\r\6\16\6Y\3\7\3\7\3\7\3\7\3\7\3\7\5\7b\n\7"+
-		"\3\b\7\be\n\b\f\b\16\bh\13\b\3\b\3\b\7\bl\n\b\f\b\16\bo\13\b\3\t\3\t\3"+
-		"\t\3\n\3\n\3\n\3\n\3\n\3\n\7\nz\n\n\f\n\16\n}\13\n\3\13\3\13\3\13\5\13"+
-		"\u0082\n\13\3\f\3\f\3\f\3\f\5\f\u0088\n\f\3\f\3\f\3\f\5\f\u008d\n\f\3"+
-		"\f\3\f\3\r\3\r\3\r\7\r\u0094\n\r\f\r\16\r\u0097\13\r\3\16\3\16\3\16\3"+
-		"\16\5\16\u009d\n\16\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\20\3\20\3\20\3\20\3\20\3\20\5\20\u00b2\n\20\3\20\5\20"+
-		"\u00b5\n\20\3\21\3\21\3\21\3\21\3\21\7\21\u00bc\n\21\f\21\16\21\u00bf"+
-		"\13\21\3\21\3\21\3\22\6\22\u00c4\n\22\r\22\16\22\u00c5\3\23\3\23\3\23"+
-		"\3\23\3\23\5\23\u00cd\n\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23"+
-		"\3\23\3\23\5\23\u00da\n\23\3\23\7\23\u00dd\n\23\f\23\16\23\u00e0\13\23"+
-		"\3\23\3\23\3\23\3\23\3\23\3\23\3\23\7\23\u00e9\n\23\f\23\16\23\u00ec\13"+
-		"\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\7\23\u00f7\n\23\f\23"+
-		"\16\23\u00fa\13\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u0104"+
-		"\n\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u010d\n\23\3\23\3\23\3\23"+
-		"\3\23\3\23\5\23\u0114\n\23\3\24\3\24\3\24\3\24\3\24\5\24\u011b\n\24\3"+
-		"\24\5\24\u011e\n\24\3\24\3\24\3\24\3\24\3\24\3\24\5\24\u0126\n\24\3\25"+
-		"\5\25\u0129\n\25\3\25\5\25\u012c\n\25\3\26\3\26\3\26\3\26\3\26\3\26\3"+
-		"\26\3\26\5\26\u0136\n\26\5\26\u0138\n\26\3\26\3\26\3\26\3\26\3\26\5\26"+
-		"\u013f\n\26\3\26\3\26\3\26\3\26\7\26\u0145\n\26\f\26\16\26\u0148\13\26"+
-		"\3\27\3\27\3\27\3\27\3\27\3\27\7\27\u0150\n\27\f\27\16\27\u0153\13\27"+
-		"\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u015e\n\30\3\30\3\30"+
-		"\3\30\3\30\3\30\3\30\5\30\u0166\n\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
-		"\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u017b"+
-		"\n\30\f\30\16\30\u017e\13\30\3\30\3\30\3\30\3\30\3\30\6\30\u0185\n\30"+
-		"\r\30\16\30\u0186\3\30\3\30\5\30\u018b\n\30\3\30\3\30\3\30\3\30\3\30\3"+
-		"\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3"+
-		"\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3"+
-		"\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\5\30\u01b7\n\30\3\30\3\30"+
-		"\3\30\3\30\3\30\3\30\3\30\3\30\7\30\u01c1\n\30\f\30\16\30\u01c4\13\30"+
-		"\3\31\3\31\3\31\7\31\u01c9\n\31\f\31\16\31\u01cc\13\31\3\32\3\32\5\32"+
-		"\u01d0\n\32\3\32\3\32\3\33\3\33\3\33\3\33\7\33\u01d8\n\33\f\33\16\33\u01db"+
-		"\13\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34"+
-		"\3\34\3\34\5\34\u01ec\n\34\5\34\u01ee\n\34\3\35\7\35\u01f1\n\35\f\35\16"+
-		"\35\u01f4\13\35\3\36\3\36\3\36\5\36\u01f9\n\36\3\37\3\37\3\37\3\37\5\37"+
-		"\u01ff\n\37\3\37\5\37\u0202\n\37\3 \3 \5 \u0206\n \3!\3!\3!\3!\7!\u020c"+
-		"\n!\f!\16!\u020f\13!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3"+
-		"\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\5\"\u0228\n\"\3#\3#\3#\3#\3"+
-		"#\3#\3#\3#\3#\3#\3#\3#\3#\3#\5#\u0238\n#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3"+
-		"#\3#\3#\7#\u0246\n#\f#\16#\u0249\13#\3#\2\7\22*,.D$\2\4\6\b\n\f\16\20"+
-		"\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BD\2\r\3\2\36\37\3\2%&"+
-		"\3\2\'+\3\2\60\61\3\2,-\4\2  ./\3\2\'(\3\2\60\65\3\2;D\4\2\'(\60\61\4"+
-		"\2  ..\2\u029e\2F\3\2\2\2\4J\3\2\2\2\6P\3\2\2\2\bS\3\2\2\2\nW\3\2\2\2"+
-		"\fa\3\2\2\2\16f\3\2\2\2\20p\3\2\2\2\22s\3\2\2\2\24~\3\2\2\2\26\u0083\3"+
-		"\2\2\2\30\u0090\3\2\2\2\32\u009c\3\2\2\2\34\u009e\3\2\2\2\36\u00b4\3\2"+
-		"\2\2 \u00b6\3\2\2\2\"\u00c3\3\2\2\2$\u0113\3\2\2\2&\u0125\3\2\2\2(\u012b"+
-		"\3\2\2\2*\u0137\3\2\2\2,\u0149\3\2\2\2.\u018a\3\2\2\2\60\u01c5\3\2\2\2"+
-		"\62\u01cd\3\2\2\2\64\u01d3\3\2\2\2\66\u01ed\3\2\2\28\u01f2\3\2\2\2:\u01f8"+
-		"\3\2\2\2<\u0201\3\2\2\2>\u0203\3\2\2\2@\u0207\3\2\2\2B\u0227\3\2\2\2D"+
-		"\u0237\3\2\2\2FG\5\6\4\2GH\5\n\6\2HI\7\2\2\3I\3\3\2\2\2JK\58\35\2KL\7"+
-		"\2\2\3L\5\3\2\2\2MO\5\b\5\2NM\3\2\2\2OR\3\2\2\2PN\3\2\2\2PQ\3\2\2\2Q\7"+
-		"\3\2\2\2RP\3\2\2\2ST\7\3\2\2TU\7R\2\2U\t\3\2\2\2VX\5\f\7\2WV\3\2\2\2X"+
-		"Y\3\2\2\2YW\3\2\2\2YZ\3\2\2\2Z\13\3\2\2\2[\\\5\20\t\2\\]\7\4\2\2]b\3\2"+
-		"\2\2^b\5\26\f\2_b\5\62\32\2`b\5\34\17\2a[\3\2\2\2a^\3\2\2\2a_\3\2\2\2"+
-		"a`\3\2\2\2b\r\3\2\2\2ce\5\36\20\2dc\3\2\2\2eh\3\2\2\2fd\3\2\2\2fg\3\2"+
-		"\2\2gi\3\2\2\2hf\3\2\2\2im\5*\26\2jl\5\36\20\2kj\3\2\2\2lo\3\2\2\2mk\3"+
-		"\2\2\2mn\3\2\2\2n\17\3\2\2\2om\3\2\2\2pq\5\16\b\2qr\5\22\n\2r\21\3\2\2"+
-		"\2st\b\n\1\2tu\5\24\13\2u{\3\2\2\2vw\f\3\2\2wx\7\5\2\2xz\5\24\13\2yv\3"+
-		"\2\2\2z}\3\2\2\2{y\3\2\2\2{|\3\2\2\2|\23\3\2\2\2}{\3\2\2\2~\u0081\7^\2"+
-		"\2\177\u0080\7\6\2\2\u0080\u0082\5.\30\2\u0081\177\3\2\2\2\u0081\u0082"+
-		"\3\2\2\2\u0082\25\3\2\2\2\u0083\u0084\5\16\b\2\u0084\u0085\7^\2\2\u0085"+
-		"\u0087\7\7\2\2\u0086\u0088\5\30\r\2\u0087\u0086\3\2\2\2\u0087\u0088\3"+
-		"\2\2\2\u0088\u0089\3\2\2\2\u0089\u008a\7\b\2\2\u008a\u008c\7\t\2\2\u008b"+
-		"\u008d\5\"\22\2\u008c\u008b\3\2\2\2\u008c\u008d\3\2\2\2\u008d\u008e\3"+
-		"\2\2\2\u008e\u008f\7\n\2\2\u008f\27\3\2\2\2\u0090\u0095\5\32\16\2\u0091"+
-		"\u0092\7\5\2\2\u0092\u0094\5\32\16\2\u0093\u0091\3\2\2\2\u0094\u0097\3"+
-		"\2\2\2\u0095\u0093\3\2\2\2\u0095\u0096\3\2\2\2\u0096\31\3\2\2\2\u0097"+
-		"\u0095\3\2\2\2\u0098\u0099\5\16\b\2\u0099\u009a\7^\2\2\u009a\u009d\3\2"+
-		"\2\2\u009b\u009d\7Q\2\2\u009c\u0098\3\2\2\2\u009c\u009b\3\2\2\2\u009d"+
-		"\33\3\2\2\2\u009e\u009f\5 \21\2\u009f\u00a0\7\4\2\2\u00a0\35\3\2\2\2\u00a1"+
-		"\u00b5\7\13\2\2\u00a2\u00b5\7\f\2\2\u00a3\u00a4\7\r\2\2\u00a4\u00a5\7"+
-		"\7\2\2\u00a5\u00a6\7U\2\2\u00a6\u00b5\7\b\2\2\u00a7\u00a8\7\16\2\2\u00a8"+
-		"\u00a9\7\7\2\2\u00a9\u00aa\7^\2\2\u00aa\u00b5\7\b\2\2\u00ab\u00b5\7\17"+
-		"\2\2\u00ac\u00b5\7\20\2\2\u00ad\u00b1\7\21\2\2\u00ae\u00af\7\7\2\2\u00af"+
-		"\u00b0\7^\2\2\u00b0\u00b2\7\b\2\2\u00b1\u00ae\3\2\2\2\u00b1\u00b2\3\2"+
-		"\2\2\u00b2\u00b5\3\2\2\2\u00b3\u00b5\5 \21\2\u00b4\u00a1\3\2\2\2\u00b4"+
-		"\u00a2\3\2\2\2\u00b4\u00a3\3\2\2\2\u00b4\u00a7\3\2\2\2\u00b4\u00ab\3\2"+
-		"\2\2\u00b4\u00ac\3\2\2\2\u00b4\u00ad\3\2\2\2\u00b4\u00b3\3\2\2\2\u00b5"+
-		"\37\3\2\2\2\u00b6\u00b7\7\22\2\2\u00b7\u00b8\7\7\2\2\u00b8\u00bd\7U\2"+
-		"\2\u00b9\u00ba\7\5\2\2\u00ba\u00bc\7U\2\2\u00bb\u00b9\3\2\2\2\u00bc\u00bf"+
-		"\3\2\2\2\u00bd\u00bb\3\2\2\2\u00bd\u00be\3\2\2\2\u00be\u00c0\3\2\2\2\u00bf"+
-		"\u00bd\3\2\2\2\u00c0\u00c1\7\b\2\2\u00c1!\3\2\2\2\u00c2\u00c4\5$\23\2"+
-		"\u00c3\u00c2\3\2\2\2\u00c4\u00c5\3\2\2\2\u00c5\u00c3\3\2\2\2\u00c5\u00c6"+
-		"\3\2\2\2\u00c6#\3\2\2\2\u00c7\u00c8\5\20\t\2\u00c8\u00c9\7\4\2\2\u00c9"+
-		"\u0114\3\2\2\2\u00ca\u00cc\7\t\2\2\u00cb\u00cd\5\"\22\2\u00cc\u00cb\3"+
-		"\2\2\2\u00cc\u00cd\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u0114\7\n\2\2\u00cf"+
-		"\u00d0\5,\27\2\u00d0\u00d1\7\4\2\2\u00d1\u0114\3\2\2\2\u00d2\u00d3\7\23"+
-		"\2\2\u00d3\u00d4\7\7\2\2\u00d4\u00d5\5,\27\2\u00d5\u00d6\7\b\2\2\u00d6"+
-		"\u00d9\5$\23\2\u00d7\u00d8\7\24\2\2\u00d8\u00da\5$\23\2\u00d9\u00d7\3"+
-		"\2\2\2\u00d9\u00da\3\2\2\2\u00da\u0114\3\2\2\2\u00db\u00dd\5\36\20\2\u00dc"+
-		"\u00db\3\2\2\2\u00dd\u00e0\3\2\2\2\u00de\u00dc\3\2\2\2\u00de\u00df\3\2"+
-		"\2\2\u00df\u00e1\3\2\2\2\u00e0\u00de\3\2\2\2\u00e1\u00e2\7\25\2\2\u00e2"+
-		"\u00e3\7\7\2\2\u00e3\u00e4\5,\27\2\u00e4\u00e5\7\b\2\2\u00e5\u00e6\5$"+
-		"\23\2\u00e6\u0114\3\2\2\2\u00e7\u00e9\5\36\20\2\u00e8\u00e7\3\2\2\2\u00e9"+
-		"\u00ec\3\2\2\2\u00ea\u00e8\3\2\2\2\u00ea\u00eb\3\2\2\2\u00eb\u00ed\3\2"+
-		"\2\2\u00ec\u00ea\3\2\2\2\u00ed\u00ee\7\26\2\2\u00ee\u00ef\5$\23\2\u00ef"+
-		"\u00f0\7\25\2\2\u00f0\u00f1\7\7\2\2\u00f1\u00f2\5,\27\2\u00f2\u00f3\7"+
-		"\b\2\2\u00f3\u00f4\7\4\2\2\u00f4\u0114\3\2\2\2\u00f5\u00f7\5\36\20\2\u00f6"+
-		"\u00f5\3\2\2\2\u00f7\u00fa\3\2\2\2\u00f8\u00f6\3\2\2\2\u00f8\u00f9\3\2"+
-		"\2\2\u00f9\u00fb\3\2\2\2\u00fa\u00f8\3\2\2\2\u00fb\u00fc\7\27\2\2\u00fc"+
-		"\u00fd\7\7\2\2\u00fd\u00fe\5&\24\2\u00fe\u00ff\7\b\2\2\u00ff\u0100\5$"+
-		"\23\2\u0100\u0114\3\2\2\2\u0101\u0103\7\30\2\2\u0102\u0104\5,\27\2\u0103"+
-		"\u0102\3\2\2\2\u0103\u0104\3\2\2\2\u0104\u0105\3\2\2\2\u0105\u0114\7\4"+
-		"\2\2\u0106\u0107\7\31\2\2\u0107\u0114\7\4\2\2\u0108\u0109\7\32\2\2\u0109"+
-		"\u0114\7\4\2\2\u010a\u010c\7\33\2\2\u010b\u010d\5\64\33\2\u010c\u010b"+
-		"\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2\2\2\u010e\u010f\7\t\2\2\u010f"+
-		"\u0110\58\35\2\u0110\u0111\7\n\2\2\u0111\u0114\3\2\2\2\u0112\u0114\5\62"+
-		"\32\2\u0113\u00c7\3\2\2\2\u0113\u00ca\3\2\2\2\u0113\u00cf\3\2\2\2\u0113"+
-		"\u00d2\3\2\2\2\u0113\u00de\3\2\2\2\u0113\u00ea\3\2\2\2\u0113\u00f8\3\2"+
-		"\2\2\u0113\u0101\3\2\2\2\u0113\u0106\3\2\2\2\u0113\u0108\3\2\2\2\u0113"+
-		"\u010a\3\2\2\2\u0113\u0112\3\2\2\2\u0114%\3\2\2\2\u0115\u0116\5(\25\2"+
-		"\u0116\u0117\7\4\2\2\u0117\u0118\5,\27\2\u0118\u011a\7\4\2\2\u0119\u011b"+
-		"\5,\27\2\u011a\u0119\3\2\2\2\u011a\u011b\3\2\2\2\u011b\u0126\3\2\2\2\u011c"+
-		"\u011e\5\16\b\2\u011d\u011c\3\2\2\2\u011d\u011e\3\2\2\2\u011e\u011f\3"+
-		"\2\2\2\u011f\u0120\7^\2\2\u0120\u0121\7\34\2\2\u0121\u0122\5.\30\2\u0122"+
-		"\u0123\7\35\2\2\u0123\u0124\5.\30\2\u0124\u0126\3\2\2\2\u0125\u0115\3"+
-		"\2\2\2\u0125\u011d\3\2\2\2\u0126\'\3\2\2\2\u0127\u0129\5\20\t\2\u0128"+
-		"\u0127\3\2\2\2\u0128\u0129\3\2\2\2\u0129\u012c\3\2\2\2\u012a\u012c\5,"+
-		"\27\2\u012b\u0128\3\2\2\2\u012b\u012a\3\2\2\2\u012c)\3\2\2\2\u012d\u012e"+
-		"\b\26\1\2\u012e\u012f\7\7\2\2\u012f\u0130\5*\26\2\u0130\u0131\7\b\2\2"+
-		"\u0131\u0138\3\2\2\2\u0132\u0138\7Q\2\2\u0133\u0135\t\2\2\2\u0134\u0136"+
-		"\7Q\2\2\u0135\u0134\3\2\2\2\u0135\u0136\3\2\2\2\u0136\u0138\3\2\2\2\u0137"+
-		"\u012d\3\2\2\2\u0137\u0132\3\2\2\2\u0137\u0133\3\2\2\2\u0138\u0146\3\2"+
-		"\2\2\u0139\u013a\f\5\2\2\u013a\u0145\7 \2\2\u013b\u013c\f\4\2\2\u013c"+
-		"\u013e\7!\2\2\u013d\u013f\5.\30\2\u013e\u013d\3\2\2\2\u013e\u013f\3\2"+
-		"\2\2\u013f\u0140\3\2\2\2\u0140\u0145\7\"\2\2\u0141\u0142\f\3\2\2\u0142"+
-		"\u0143\7\7\2\2\u0143\u0145\7\b\2\2\u0144\u0139\3\2\2\2\u0144\u013b\3\2"+
-		"\2\2\u0144\u0141\3\2\2\2\u0145\u0148\3\2\2\2\u0146\u0144\3\2\2\2\u0146"+
-		"\u0147\3\2\2\2\u0147+\3\2\2\2\u0148\u0146\3\2\2\2\u0149\u014a\b\27\1\2"+
-		"\u014a\u014b\5.\30\2\u014b\u0151\3\2\2\2\u014c\u014d\f\3\2\2\u014d\u014e"+
-		"\7\5\2\2\u014e\u0150\5.\30\2\u014f\u014c\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+
-		"\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152-\3\2\2\2\u0153\u0151\3\2\2\2"+
-		"\u0154\u0155\b\30\1\2\u0155\u0156\7\7\2\2\u0156\u0157\5,\27\2\u0157\u0158"+
-		"\7\b\2\2\u0158\u018b\3\2\2\2\u0159\u015a\7#\2\2\u015a\u015d\7\7\2\2\u015b"+
-		"\u015e\5*\26\2\u015c\u015e\5.\30\2\u015d\u015b\3\2\2\2\u015d\u015c\3\2"+
-		"\2\2\u015e\u015f\3\2\2\2\u015f\u0160\7\b\2\2\u0160\u018b\3\2\2\2\u0161"+
-		"\u0162\7$\2\2\u0162\u0165\7\7\2\2\u0163\u0166\5*\26\2\u0164\u0166\5.\30"+
-		"\2\u0165\u0163\3\2\2\2\u0165\u0164\3\2\2\2\u0166\u0167\3\2\2\2\u0167\u0168"+
-		"\7\b\2\2\u0168\u018b\3\2\2\2\u0169\u016a\7\7\2\2\u016a\u016b\5*\26\2\u016b"+
-		"\u016c\7\b\2\2\u016c\u016d\5.\30\32\u016d\u018b\3\2\2\2\u016e\u016f\t"+
-		"\3\2\2\u016f\u018b\5.\30\31\u0170\u0171\7 \2\2\u0171\u018b\5.\30\27\u0172"+
-		"\u0173\t\4\2\2\u0173\u018b\5.\30\26\u0174\u0175\t\5\2\2\u0175\u018b\5"+
-		".\30\22\u0176\u0177\7\t\2\2\u0177\u017c\5.\30\2\u0178\u0179\7\5\2\2\u0179"+
-		"\u017b\5.\30\2\u017a\u0178\3\2\2\2\u017b\u017e\3\2\2\2\u017c\u017a\3\2"+
-		"\2\2\u017c\u017d\3\2\2\2\u017d\u017f\3\2\2\2\u017e\u017c\3\2\2\2\u017f"+
-		"\u0180\7\n\2\2\u0180\u018b\3\2\2\2\u0181\u018b\7^\2\2\u0182\u018b\7U\2"+
-		"\2\u0183\u0185\7R\2\2\u0184\u0183\3\2\2\2\u0185\u0186\3\2\2\2\u0186\u0184"+
-		"\3\2\2\2\u0186\u0187\3\2\2\2\u0187\u018b\3\2\2\2\u0188\u018b\7S\2\2\u0189"+
-		"\u018b\7T\2\2\u018a\u0154\3\2\2\2\u018a\u0159\3\2\2\2\u018a\u0161\3\2"+
-		"\2\2\u018a\u0169\3\2\2\2\u018a\u016e\3\2\2\2\u018a\u0170\3\2\2\2\u018a"+
-		"\u0172\3\2\2\2\u018a\u0174\3\2\2\2\u018a\u0176\3\2\2\2\u018a\u0181\3\2"+
-		"\2\2\u018a\u0182\3\2\2\2\u018a\u0184\3\2\2\2\u018a\u0188\3\2\2\2\u018a"+
-		"\u0189\3\2\2\2\u018b\u01c2\3\2\2\2\u018c\u018d\f\25\2\2\u018d\u018e\t"+
-		"\6\2\2\u018e\u01c1\5.\30\26\u018f\u0190\f\24\2\2\u0190\u0191\t\7\2\2\u0191"+
-		"\u01c1\5.\30\25\u0192\u0193\f\23\2\2\u0193\u0194\t\b\2\2\u0194\u01c1\5"+
-		".\30\24\u0195\u0196\f\21\2\2\u0196\u0197\t\t\2\2\u0197\u01c1\5.\30\22"+
-		"\u0198\u0199\f\20\2\2\u0199\u019a\7*\2\2\u019a\u01c1\5.\30\21\u019b\u019c"+
-		"\f\17\2\2\u019c\u019d\7\66\2\2\u019d\u01c1\5.\30\20\u019e\u019f\f\16\2"+
-		"\2\u019f\u01a0\7\67\2\2\u01a0\u01c1\5.\30\17\u01a1\u01a2\f\r\2\2\u01a2"+
-		"\u01a3\78\2\2\u01a3\u01c1\5.\30\16\u01a4\u01a5\f\f\2\2\u01a5\u01a6\79"+
-		"\2\2\u01a6\u01c1\5.\30\r\u01a7\u01a8\f\13\2\2\u01a8\u01a9\7:\2\2\u01a9"+
-		"\u01aa\5.\30\2\u01aa\u01ab\7\34\2\2\u01ab\u01ac\5.\30\f\u01ac\u01c1\3"+
-		"\2\2\2\u01ad\u01ae\f\n\2\2\u01ae\u01af\7\6\2\2\u01af\u01c1\5.\30\n\u01b0"+
-		"\u01b1\f\t\2\2\u01b1\u01b2\t\n\2\2\u01b2\u01c1\5.\30\t\u01b3\u01b4\f\36"+
-		"\2\2\u01b4\u01b6\7\7\2\2\u01b5\u01b7\5\60\31\2\u01b6\u01b5\3\2\2\2\u01b6"+
-		"\u01b7\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8\u01c1\7\b\2\2\u01b9\u01ba\f\33"+
-		"\2\2\u01ba\u01bb\7!\2\2\u01bb\u01bc\5,\27\2\u01bc\u01bd\7\"\2\2\u01bd"+
-		"\u01c1\3\2\2\2\u01be\u01bf\f\30\2\2\u01bf\u01c1\t\3\2\2\u01c0\u018c\3"+
-		"\2\2\2\u01c0\u018f\3\2\2\2\u01c0\u0192\3\2\2\2\u01c0\u0195\3\2\2\2\u01c0"+
-		"\u0198\3\2\2\2\u01c0\u019b\3\2\2\2\u01c0\u019e\3\2\2\2\u01c0\u01a1\3\2"+
-		"\2\2\u01c0\u01a4\3\2\2\2\u01c0\u01a7\3\2\2\2\u01c0\u01ad\3\2\2\2\u01c0"+
-		"\u01b0\3\2\2\2\u01c0\u01b3\3\2\2\2\u01c0\u01b9\3\2\2\2\u01c0\u01be\3\2"+
-		"\2\2\u01c1\u01c4\3\2\2\2\u01c2\u01c0\3\2\2\2\u01c2\u01c3\3\2\2\2\u01c3"+
-		"/\3\2\2\2\u01c4\u01c2\3\2\2\2\u01c5\u01ca\5.\30\2\u01c6\u01c7\7\5\2\2"+
-		"\u01c7\u01c9\5.\30\2\u01c8\u01c6\3\2\2\2\u01c9\u01cc\3\2\2\2\u01ca\u01c8"+
-		"\3\2\2\2\u01ca\u01cb\3\2\2\2\u01cb\61\3\2\2\2\u01cc\u01ca\3\2\2\2\u01cd"+
-		"\u01cf\7E\2\2\u01ce\u01d0\5\64\33\2\u01cf\u01ce\3\2\2\2\u01cf\u01d0\3"+
-		"\2\2\2\u01d0\u01d1\3\2\2\2\u01d1\u01d2\7P\2\2\u01d2\63\3\2\2\2\u01d3\u01d4"+
-		"\7\7\2\2\u01d4\u01d9\5\66\34\2\u01d5\u01d6\7\5\2\2\u01d6\u01d8\5\66\34"+
-		"\2\u01d7\u01d5\3\2\2\2\u01d8\u01db\3\2\2\2\u01d9\u01d7\3\2\2\2\u01d9\u01da"+
-		"\3\2\2\2\u01da\u01dc\3\2\2\2\u01db\u01d9\3\2\2\2\u01dc\u01dd\7\b\2\2\u01dd"+
-		"\65\3\2\2\2\u01de\u01df\7F\2\2\u01df\u01ee\7R\2\2\u01e0\u01e1\7G\2\2\u01e1"+
-		"\u01ee\7^\2\2\u01e2\u01e3\7H\2\2\u01e3\u01ee\7R\2\2\u01e4\u01e5\7I\2\2"+
-		"\u01e5\u01ee\5.\30\2\u01e6\u01e7\7J\2\2\u01e7\u01ee\5.\30\2\u01e8\u01eb"+
-		"\7K\2\2\u01e9\u01ec\7\17\2\2\u01ea\u01ec\5.\30\2\u01eb\u01e9\3\2\2\2\u01eb"+
-		"\u01ea\3\2\2\2\u01ec\u01ee\3\2\2\2\u01ed\u01de\3\2\2\2\u01ed\u01e0\3\2"+
-		"\2\2\u01ed\u01e2\3\2\2\2\u01ed\u01e4\3\2\2\2\u01ed\u01e6\3\2\2\2\u01ed"+
-		"\u01e8\3\2\2\2\u01ee\67\3\2\2\2\u01ef\u01f1\5:\36\2\u01f0\u01ef\3\2\2"+
-		"\2\u01f1\u01f4\3\2\2\2\u01f2\u01f0\3\2\2\2\u01f2\u01f3\3\2\2\2\u01f39"+
-		"\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f5\u01f9\5<\37\2\u01f6\u01f9\5> \2\u01f7"+
-		"\u01f9\5@!\2\u01f8\u01f5\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f8\u01f7\3\2\2"+
-		"\2\u01f9;\3\2\2\2\u01fa\u01fb\7^\2\2\u01fb\u0202\7\34\2\2\u01fc\u01fe"+
-		"\7)\2\2\u01fd\u01ff\7^\2\2\u01fe\u01fd\3\2\2\2\u01fe\u01ff\3\2\2\2\u01ff"+
-		"\u0200\3\2\2\2\u0200\u0202\7\34\2\2\u0201\u01fa\3\2\2\2\u0201\u01fc\3"+
-		"\2\2\2\u0202=\3\2\2\2\u0203\u0205\7O\2\2\u0204\u0206\5B\"\2\u0205\u0204"+
-		"\3\2\2\2\u0205\u0206\3\2\2\2\u0206?\3\2\2\2\u0207\u0208\7L\2\2\u0208\u020d"+
-		"\5D#\2\u0209\u020a\7\5\2\2\u020a\u020c\5D#\2\u020b\u0209\3\2\2\2\u020c"+
-		"\u020f\3\2\2\2\u020d\u020b\3\2\2\2\u020d\u020e\3\2\2\2\u020eA\3\2\2\2"+
-		"\u020f\u020d\3\2\2\2\u0210\u0228\5D#\2\u0211\u0212\7M\2\2\u0212\u0228"+
-		"\5D#\2\u0213\u0214\5D#\2\u0214\u0215\7\5\2\2\u0215\u0216\7^\2\2\u0216"+
-		"\u0228\3\2\2\2\u0217\u0218\7\7\2\2\u0218\u0219\5D#\2\u0219\u021a\7\b\2"+
-		"\2\u021a\u021b\7\5\2\2\u021b\u021c\7^\2\2\u021c\u0228\3\2\2\2\u021d\u021e"+
-		"\7\7\2\2\u021e\u021f\5D#\2\u021f\u0220\7\5\2\2\u0220\u0221\7^\2\2\u0221"+
-		"\u0222\7\b\2\2\u0222\u0228\3\2\2\2\u0223\u0224\7\7\2\2\u0224\u0225\5D"+
-		"#\2\u0225\u0226\7\b\2\2\u0226\u0228\3\2\2\2\u0227\u0210\3\2\2\2\u0227"+
-		"\u0211\3\2\2\2\u0227\u0213\3\2\2\2\u0227\u0217\3\2\2\2\u0227\u021d\3\2"+
-		"\2\2\u0227\u0223\3\2\2\2\u0228C\3\2\2\2\u0229\u022a\b#\1\2\u022a\u022b"+
-		"\7!\2\2\u022b\u022c\5D#\2\u022c\u022d\7\"\2\2\u022d\u0238\3\2\2\2\u022e"+
-		"\u022f\t\13\2\2\u022f\u0238\5D#\n\u0230\u0238\7^\2\2\u0231\u0238\7_\2"+
-		"\2\u0232\u0233\7\t\2\2\u0233\u0234\7^\2\2\u0234\u0238\7\n\2\2\u0235\u0238"+
-		"\7U\2\2\u0236\u0238\7S\2\2\u0237\u0229\3\2\2\2\u0237\u022e\3\2\2\2\u0237"+
-		"\u0230\3\2\2\2\u0237\u0231\3\2\2\2\u0237\u0232\3\2\2\2\u0237\u0235\3\2"+
-		"\2\2\u0237\u0236\3\2\2\2\u0238\u0247\3\2\2\2\u0239\u023a\f\f\2\2\u023a"+
-		"\u023b\7N\2\2\u023b\u0246\5D#\r\u023c\u023d\f\13\2\2\u023d\u023e\t\6\2"+
-		"\2\u023e\u0246\5D#\f\u023f\u0240\f\t\2\2\u0240\u0241\t\f\2\2\u0241\u0246"+
-		"\5D#\n\u0242\u0243\f\b\2\2\u0243\u0244\t\b\2\2\u0244\u0246\5D#\t\u0245"+
-		"\u0239\3\2\2\2\u0245\u023c\3\2\2\2\u0245\u023f\3\2\2\2\u0245\u0242\3\2"+
-		"\2\2\u0246\u0249\3\2\2\2\u0247\u0245\3\2\2\2\u0247\u0248\3\2\2\2\u0248"+
-		"E\3\2\2\2\u0249\u0247\3\2\2\2;PYafm{\u0081\u0087\u008c\u0095\u009c\u00b1"+
-		"\u00b4\u00bd\u00c5\u00cc\u00d9\u00de\u00ea\u00f8\u0103\u010c\u0113\u011a"+
-		"\u011d\u0125\u0128\u012b\u0135\u0137\u013e\u0144\u0146\u0151\u015d\u0165"+
-		"\u017c\u0186\u018a\u01b6\u01c0\u01c2\u01ca\u01cf\u01d9\u01eb\u01ed\u01f2"+
-		"\u01f8\u01fe\u0201\u0205\u020d\u0227\u0237\u0245\u0247";
+		"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\4\7"+
+		"\4U\n\4\f\4\16\4X\13\4\3\5\3\5\3\5\3\6\6\6^\n\6\r\6\16\6_\3\7\3\7\3\7"+
+		"\3\7\3\7\3\7\3\7\3\7\3\7\5\7k\n\7\3\b\7\bn\n\b\f\b\16\bq\13\b\3\b\3\b"+
+		"\7\bu\n\b\f\b\16\bx\13\b\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u0083"+
+		"\n\n\f\n\16\n\u0086\13\n\3\13\3\13\3\13\5\13\u008b\n\13\3\f\3\f\3\f\3"+
+		"\f\5\f\u0091\n\f\3\f\3\f\3\f\5\f\u0096\n\f\3\f\3\f\3\r\3\r\3\r\7\r\u009d"+
+		"\n\r\f\r\16\r\u00a0\13\r\3\16\3\16\3\16\3\16\5\16\u00a6\n\16\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\20\3\20\3\20"+
+		"\3\20\3\20\3\20\5\20\u00bb\n\20\3\20\5\20\u00be\n\20\3\21\3\21\3\21\3"+
+		"\21\3\21\7\21\u00c5\n\21\f\21\16\21\u00c8\13\21\3\21\3\21\3\22\6\22\u00cd"+
+		"\n\22\r\22\16\22\u00ce\3\23\3\23\3\23\3\23\3\23\5\23\u00d6\n\23\3\23\3"+
+		"\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u00e3\n\23\3\23"+
+		"\7\23\u00e6\n\23\f\23\16\23\u00e9\13\23\3\23\3\23\3\23\3\23\3\23\3\23"+
+		"\3\23\7\23\u00f2\n\23\f\23\16\23\u00f5\13\23\3\23\3\23\3\23\3\23\3\23"+
+		"\3\23\3\23\3\23\3\23\7\23\u0100\n\23\f\23\16\23\u0103\13\23\3\23\3\23"+
+		"\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u010d\n\23\3\23\3\23\3\23\3\23\3\23"+
+		"\3\23\3\23\5\23\u0116\n\23\3\23\3\23\3\23\3\23\3\23\5\23\u011d\n\23\3"+
+		"\24\3\24\3\24\3\24\3\24\5\24\u0124\n\24\3\24\5\24\u0127\n\24\3\24\3\24"+
+		"\3\24\3\24\3\24\3\24\5\24\u012f\n\24\3\25\5\25\u0132\n\25\3\25\5\25\u0135"+
+		"\n\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\26\5\26\u013f\n\26\3\26\3\26"+
+		"\5\26\u0143\n\26\3\26\3\26\3\26\3\26\3\26\5\26\u014a\n\26\3\26\3\26\3"+
+		"\26\3\26\7\26\u0150\n\26\f\26\16\26\u0153\13\26\3\27\3\27\3\27\3\30\3"+
+		"\30\5\30\u015a\n\30\3\30\3\30\6\30\u015e\n\30\r\30\16\30\u015f\3\30\3"+
+		"\30\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\7\32\u016d\n\32\f\32"+
+		"\16\32\u0170\13\32\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u017b"+
+		"\n\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u0183\n\33\3\33\3\33\3\33\3\33"+
+		"\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
+		"\3\33\7\33\u0198\n\33\f\33\16\33\u019b\13\33\3\33\3\33\3\33\3\33\3\33"+
+		"\6\33\u01a2\n\33\r\33\16\33\u01a3\3\33\3\33\5\33\u01a8\n\33\3\33\3\33"+
+		"\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
+		"\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
+		"\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01d4"+
+		"\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\7\33\u01de\n\33\f\33\16"+
+		"\33\u01e1\13\33\3\34\3\34\3\34\7\34\u01e6\n\34\f\34\16\34\u01e9\13\34"+
+		"\3\35\3\35\5\35\u01ed\n\35\3\35\3\35\3\36\3\36\3\36\3\36\7\36\u01f5\n"+
+		"\36\f\36\16\36\u01f8\13\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37"+
+		"\3\37\3\37\3\37\3\37\3\37\3\37\5\37\u0209\n\37\5\37\u020b\n\37\3 \7 \u020e"+
+		"\n \f \16 \u0211\13 \3!\3!\3!\5!\u0216\n!\3\"\3\"\3\"\3\"\5\"\u021c\n"+
+		"\"\3\"\5\"\u021f\n\"\3#\3#\5#\u0223\n#\3$\3$\3$\3$\7$\u0229\n$\f$\16$"+
+		"\u022c\13$\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3"+
+		"%\3%\3%\3%\5%\u0245\n%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\5&\u0255"+
+		"\n&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\7&\u0263\n&\f&\16&\u0266\13&\3"+
+		"&\2\7\22*\62\64J\'\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+
+		"\62\64\668:<>@BDFHJ\2\r\3\2\36\37\3\2&\'\3\2(,\3\2\61\62\3\2-.\4\2  /"+
+		"\60\3\2()\3\2\61\66\3\2<E\4\2()\61\62\4\2  //\2\u02bd\2L\3\2\2\2\4P\3"+
+		"\2\2\2\6V\3\2\2\2\bY\3\2\2\2\n]\3\2\2\2\fj\3\2\2\2\16o\3\2\2\2\20y\3\2"+
+		"\2\2\22|\3\2\2\2\24\u0087\3\2\2\2\26\u008c\3\2\2\2\30\u0099\3\2\2\2\32"+
+		"\u00a5\3\2\2\2\34\u00a7\3\2\2\2\36\u00bd\3\2\2\2 \u00bf\3\2\2\2\"\u00cc"+
+		"\3\2\2\2$\u011c\3\2\2\2&\u012e\3\2\2\2(\u0134\3\2\2\2*\u0142\3\2\2\2,"+
+		"\u0154\3\2\2\2.\u0157\3\2\2\2\60\u0163\3\2\2\2\62\u0166\3\2\2\2\64\u01a7"+
+		"\3\2\2\2\66\u01e2\3\2\2\28\u01ea\3\2\2\2:\u01f0\3\2\2\2<\u020a\3\2\2\2"+
+		">\u020f\3\2\2\2@\u0215\3\2\2\2B\u021e\3\2\2\2D\u0220\3\2\2\2F\u0224\3"+
+		"\2\2\2H\u0244\3\2\2\2J\u0254\3\2\2\2LM\5\6\4\2MN\5\n\6\2NO\7\2\2\3O\3"+
+		"\3\2\2\2PQ\5> \2QR\7\2\2\3R\5\3\2\2\2SU\5\b\5\2TS\3\2\2\2UX\3\2\2\2VT"+
+		"\3\2\2\2VW\3\2\2\2W\7\3\2\2\2XV\3\2\2\2YZ\7\3\2\2Z[\7S\2\2[\t\3\2\2\2"+
+		"\\^\5\f\7\2]\\\3\2\2\2^_\3\2\2\2_]\3\2\2\2_`\3\2\2\2`\13\3\2\2\2ab\5\20"+
+		"\t\2bc\7\4\2\2ck\3\2\2\2de\5.\30\2ef\7\4\2\2fk\3\2\2\2gk\5\26\f\2hk\5"+
+		"8\35\2ik\5\34\17\2ja\3\2\2\2jd\3\2\2\2jg\3\2\2\2jh\3\2\2\2ji\3\2\2\2k"+
+		"\r\3\2\2\2ln\5\36\20\2ml\3\2\2\2nq\3\2\2\2om\3\2\2\2op\3\2\2\2pr\3\2\2"+
+		"\2qo\3\2\2\2rv\5*\26\2su\5\36\20\2ts\3\2\2\2ux\3\2\2\2vt\3\2\2\2vw\3\2"+
+		"\2\2w\17\3\2\2\2xv\3\2\2\2yz\5\16\b\2z{\5\22\n\2{\21\3\2\2\2|}\b\n\1\2"+
+		"}~\5\24\13\2~\u0084\3\2\2\2\177\u0080\f\3\2\2\u0080\u0081\7\5\2\2\u0081"+
+		"\u0083\5\24\13\2\u0082\177\3\2\2\2\u0083\u0086\3\2\2\2\u0084\u0082\3\2"+
+		"\2\2\u0084\u0085\3\2\2\2\u0085\23\3\2\2\2\u0086\u0084\3\2\2\2\u0087\u008a"+
+		"\7_\2\2\u0088\u0089\7\6\2\2\u0089\u008b\5\64\33\2\u008a\u0088\3\2\2\2"+
+		"\u008a\u008b\3\2\2\2\u008b\25\3\2\2\2\u008c\u008d\5\16\b\2\u008d\u008e"+
+		"\7_\2\2\u008e\u0090\7\7\2\2\u008f\u0091\5\30\r\2\u0090\u008f\3\2\2\2\u0090"+
+		"\u0091\3\2\2\2\u0091\u0092\3\2\2\2\u0092\u0093\7\b\2\2\u0093\u0095\7\t"+
+		"\2\2\u0094\u0096\5\"\22\2\u0095\u0094\3\2\2\2\u0095\u0096\3\2\2\2\u0096"+
+		"\u0097\3\2\2\2\u0097\u0098\7\n\2\2\u0098\27\3\2\2\2\u0099\u009e\5\32\16"+
+		"\2\u009a\u009b\7\5\2\2\u009b\u009d\5\32\16\2\u009c\u009a\3\2\2\2\u009d"+
+		"\u00a0\3\2\2\2\u009e\u009c\3\2\2\2\u009e\u009f\3\2\2\2\u009f\31\3\2\2"+
+		"\2\u00a0\u009e\3\2\2\2\u00a1\u00a2\5\16\b\2\u00a2\u00a3\7_\2\2\u00a3\u00a6"+
+		"\3\2\2\2\u00a4\u00a6\7R\2\2\u00a5\u00a1\3\2\2\2\u00a5\u00a4\3\2\2\2\u00a6"+
+		"\33\3\2\2\2\u00a7\u00a8\5 \21\2\u00a8\u00a9\7\4\2\2\u00a9\35\3\2\2\2\u00aa"+
+		"\u00be\7\13\2\2\u00ab\u00be\7\f\2\2\u00ac\u00ad\7\r\2\2\u00ad\u00ae\7"+
+		"\7\2\2\u00ae\u00af\7V\2\2\u00af\u00be\7\b\2\2\u00b0\u00b1\7\16\2\2\u00b1"+
+		"\u00b2\7\7\2\2\u00b2\u00b3\7_\2\2\u00b3\u00be\7\b\2\2\u00b4\u00be\7\17"+
+		"\2\2\u00b5\u00be\7\20\2\2\u00b6\u00ba\7\21\2\2\u00b7\u00b8\7\7\2\2\u00b8"+
+		"\u00b9\7_\2\2\u00b9\u00bb\7\b\2\2\u00ba\u00b7\3\2\2\2\u00ba\u00bb\3\2"+
+		"\2\2\u00bb\u00be\3\2\2\2\u00bc\u00be\5 \21\2\u00bd\u00aa\3\2\2\2\u00bd"+
+		"\u00ab\3\2\2\2\u00bd\u00ac\3\2\2\2\u00bd\u00b0\3\2\2\2\u00bd\u00b4\3\2"+
+		"\2\2\u00bd\u00b5\3\2\2\2\u00bd\u00b6\3\2\2\2\u00bd\u00bc\3\2\2\2\u00be"+
+		"\37\3\2\2\2\u00bf\u00c0\7\22\2\2\u00c0\u00c1\7\7\2\2\u00c1\u00c6\7V\2"+
+		"\2\u00c2\u00c3\7\5\2\2\u00c3\u00c5\7V\2\2\u00c4\u00c2\3\2\2\2\u00c5\u00c8"+
+		"\3\2\2\2\u00c6\u00c4\3\2\2\2\u00c6\u00c7\3\2\2\2\u00c7\u00c9\3\2\2\2\u00c8"+
+		"\u00c6\3\2\2\2\u00c9\u00ca\7\b\2\2\u00ca!\3\2\2\2\u00cb\u00cd\5$\23\2"+
+		"\u00cc\u00cb\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u00cc\3\2\2\2\u00ce\u00cf"+
+		"\3\2\2\2\u00cf#\3\2\2\2\u00d0\u00d1\5\20\t\2\u00d1\u00d2\7\4\2\2\u00d2"+
+		"\u011d\3\2\2\2\u00d3\u00d5\7\t\2\2\u00d4\u00d6\5\"\22\2\u00d5\u00d4\3"+
+		"\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u011d\7\n\2\2\u00d8"+
+		"\u00d9\5\62\32\2\u00d9\u00da\7\4\2\2\u00da\u011d\3\2\2\2\u00db\u00dc\7"+
+		"\23\2\2\u00dc\u00dd\7\7\2\2\u00dd\u00de\5\62\32\2\u00de\u00df\7\b\2\2"+
+		"\u00df\u00e2\5$\23\2\u00e0\u00e1\7\24\2\2\u00e1\u00e3\5$\23\2\u00e2\u00e0"+
+		"\3\2\2\2\u00e2\u00e3\3\2\2\2\u00e3\u011d\3\2\2\2\u00e4\u00e6\5\36\20\2"+
+		"\u00e5\u00e4\3\2\2\2\u00e6\u00e9\3\2\2\2\u00e7\u00e5\3\2\2\2\u00e7\u00e8"+
+		"\3\2\2\2\u00e8\u00ea\3\2\2\2\u00e9\u00e7\3\2\2\2\u00ea\u00eb\7\25\2\2"+
+		"\u00eb\u00ec\7\7\2\2\u00ec\u00ed\5\62\32\2\u00ed\u00ee\7\b\2\2\u00ee\u00ef"+
+		"\5$\23\2\u00ef\u011d\3\2\2\2\u00f0\u00f2\5\36\20\2\u00f1\u00f0\3\2\2\2"+
+		"\u00f2\u00f5\3\2\2\2\u00f3\u00f1\3\2\2\2\u00f3\u00f4\3\2\2\2\u00f4\u00f6"+
+		"\3\2\2\2\u00f5\u00f3\3\2\2\2\u00f6\u00f7\7\26\2\2\u00f7\u00f8\5$\23\2"+
+		"\u00f8\u00f9\7\25\2\2\u00f9\u00fa\7\7\2\2\u00fa\u00fb\5\62\32\2\u00fb"+
+		"\u00fc\7\b\2\2\u00fc\u00fd\7\4\2\2\u00fd\u011d\3\2\2\2\u00fe\u0100\5\36"+
+		"\20\2\u00ff\u00fe\3\2\2\2\u0100\u0103\3\2\2\2\u0101\u00ff\3\2\2\2\u0101"+
+		"\u0102\3\2\2\2\u0102\u0104\3\2\2\2\u0103\u0101\3\2\2\2\u0104\u0105\7\27"+
+		"\2\2\u0105\u0106\7\7\2\2\u0106\u0107\5&\24\2\u0107\u0108\7\b\2\2\u0108"+
+		"\u0109\5$\23\2\u0109\u011d\3\2\2\2\u010a\u010c\7\30\2\2\u010b\u010d\5"+
+		"\62\32\2\u010c\u010b\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2\2\2\u010e"+
+		"\u011d\7\4\2\2\u010f\u0110\7\31\2\2\u0110\u011d\7\4\2\2\u0111\u0112\7"+
+		"\32\2\2\u0112\u011d\7\4\2\2\u0113\u0115\7\33\2\2\u0114\u0116\5:\36\2\u0115"+
+		"\u0114\3\2\2\2\u0115\u0116\3\2\2\2\u0116\u0117\3\2\2\2\u0117\u0118\7\t"+
+		"\2\2\u0118\u0119\5> \2\u0119\u011a\7\n\2\2\u011a\u011d\3\2\2\2\u011b\u011d"+
+		"\58\35\2\u011c\u00d0\3\2\2\2\u011c\u00d3\3\2\2\2\u011c\u00d8\3\2\2\2\u011c"+
+		"\u00db\3\2\2\2\u011c\u00e7\3\2\2\2\u011c\u00f3\3\2\2\2\u011c\u0101\3\2"+
+		"\2\2\u011c\u010a\3\2\2\2\u011c\u010f\3\2\2\2\u011c\u0111\3\2\2\2\u011c"+
+		"\u0113\3\2\2\2\u011c\u011b\3\2\2\2\u011d%\3\2\2\2\u011e\u011f\5(\25\2"+
+		"\u011f\u0120\7\4\2\2\u0120\u0121\5\62\32\2\u0121\u0123\7\4\2\2\u0122\u0124"+
+		"\5\62\32\2\u0123\u0122\3\2\2\2\u0123\u0124\3\2\2\2\u0124\u012f\3\2\2\2"+
+		"\u0125\u0127\5\16\b\2\u0126\u0125\3\2\2\2\u0126\u0127\3\2\2\2\u0127\u0128"+
+		"\3\2\2\2\u0128\u0129\7_\2\2\u0129\u012a\7\34\2\2\u012a\u012b\5\64\33\2"+
+		"\u012b\u012c\7\35\2\2\u012c\u012d\5\64\33\2\u012d\u012f\3\2\2\2\u012e"+
+		"\u011e\3\2\2\2\u012e\u0126\3\2\2\2\u012f\'\3\2\2\2\u0130\u0132\5\20\t"+
+		"\2\u0131\u0130\3\2\2\2\u0131\u0132\3\2\2\2\u0132\u0135\3\2\2\2\u0133\u0135"+
+		"\5\62\32\2\u0134\u0131\3\2\2\2\u0134\u0133\3\2\2\2\u0135)\3\2\2\2\u0136"+
+		"\u0137\b\26\1\2\u0137\u0138\7\7\2\2\u0138\u0139\5*\26\2\u0139\u013a\7"+
+		"\b\2\2\u013a\u0143\3\2\2\2\u013b\u0143\7R\2\2\u013c\u013e\t\2\2\2\u013d"+
+		"\u013f\7R\2\2\u013e\u013d\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u0143\3\2"+
+		"\2\2\u0140\u0143\5.\30\2\u0141\u0143\5,\27\2\u0142\u0136\3\2\2\2\u0142"+
+		"\u013b\3\2\2\2\u0142\u013c\3\2\2\2\u0142\u0140\3\2\2\2\u0142\u0141\3\2"+
+		"\2\2\u0143\u0151\3\2\2\2\u0144\u0145\f\7\2\2\u0145\u0150\7 \2\2\u0146"+
+		"\u0147\f\6\2\2\u0147\u0149\7!\2\2\u0148\u014a\5\64\33\2\u0149\u0148\3"+
+		"\2\2\2\u0149\u014a\3\2\2\2\u014a\u014b\3\2\2\2\u014b\u0150\7\"\2\2\u014c"+
+		"\u014d\f\5\2\2\u014d\u014e\7\7\2\2\u014e\u0150\7\b\2\2\u014f\u0144\3\2"+
+		"\2\2\u014f\u0146\3\2\2\2\u014f\u014c\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+
+		"\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152+\3\2\2\2\u0153\u0151\3\2\2\2"+
+		"\u0154\u0155\7#\2\2\u0155\u0156\7_\2\2\u0156-\3\2\2\2\u0157\u0159\7#\2"+
+		"\2\u0158\u015a\7_\2\2\u0159\u0158\3\2\2\2\u0159\u015a\3\2\2\2\u015a\u015b"+
+		"\3\2\2\2\u015b\u015d\7\t\2\2\u015c\u015e\5\60\31\2\u015d\u015c\3\2\2\2"+
+		"\u015e\u015f\3\2\2\2\u015f\u015d\3\2\2\2\u015f\u0160\3\2\2\2\u0160\u0161"+
+		"\3\2\2\2\u0161\u0162\7\n\2\2\u0162/\3\2\2\2\u0163\u0164\5\20\t\2\u0164"+
+		"\u0165\7\4\2\2\u0165\61\3\2\2\2\u0166\u0167\b\32\1\2\u0167\u0168\5\64"+
+		"\33\2\u0168\u016e\3\2\2\2\u0169\u016a\f\3\2\2\u016a\u016b\7\5\2\2\u016b"+
+		"\u016d\5\64\33\2\u016c\u0169\3\2\2\2\u016d\u0170\3\2\2\2\u016e\u016c\3"+
+		"\2\2\2\u016e\u016f\3\2\2\2\u016f\63\3\2\2\2\u0170\u016e\3\2\2\2\u0171"+
+		"\u0172\b\33\1\2\u0172\u0173\7\7\2\2\u0173\u0174\5\62\32\2\u0174\u0175"+
+		"\7\b\2\2\u0175\u01a8\3\2\2\2\u0176\u0177\7$\2\2\u0177\u017a\7\7\2\2\u0178"+
+		"\u017b\5*\26\2\u0179\u017b\5\64\33\2\u017a\u0178\3\2\2\2\u017a\u0179\3"+
+		"\2\2\2\u017b\u017c\3\2\2\2\u017c\u017d\7\b\2\2\u017d\u01a8\3\2\2\2\u017e"+
+		"\u017f\7%\2\2\u017f\u0182\7\7\2\2\u0180\u0183\5*\26\2\u0181\u0183\5\64"+
+		"\33\2\u0182\u0180\3\2\2\2\u0182\u0181\3\2\2\2\u0183\u0184\3\2\2\2\u0184"+
+		"\u0185\7\b\2\2\u0185\u01a8\3\2\2\2\u0186\u0187\7\7\2\2\u0187\u0188\5*"+
+		"\26\2\u0188\u0189\7\b\2\2\u0189\u018a\5\64\33\32\u018a\u01a8\3\2\2\2\u018b"+
+		"\u018c\t\3\2\2\u018c\u01a8\5\64\33\31\u018d\u018e\7 \2\2\u018e\u01a8\5"+
+		"\64\33\27\u018f\u0190\t\4\2\2\u0190\u01a8\5\64\33\26\u0191\u0192\t\5\2"+
+		"\2\u0192\u01a8\5\64\33\22\u0193\u0194\7\t\2\2\u0194\u0199\5\64\33\2\u0195"+
+		"\u0196\7\5\2\2\u0196\u0198\5\64\33\2\u0197\u0195\3\2\2\2\u0198\u019b\3"+
+		"\2\2\2\u0199\u0197\3\2\2\2\u0199\u019a\3\2\2\2\u019a\u019c\3\2\2\2\u019b"+
+		"\u0199\3\2\2\2\u019c\u019d\7\n\2\2\u019d\u01a8\3\2\2\2\u019e\u01a8\7_"+
+		"\2\2\u019f\u01a8\7V\2\2\u01a0\u01a2\7S\2\2\u01a1\u01a0\3\2\2\2\u01a2\u01a3"+
+		"\3\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4\u01a8\3\2\2\2\u01a5"+
+		"\u01a8\7T\2\2\u01a6\u01a8\7U\2\2\u01a7\u0171\3\2\2\2\u01a7\u0176\3\2\2"+
+		"\2\u01a7\u017e\3\2\2\2\u01a7\u0186\3\2\2\2\u01a7\u018b\3\2\2\2\u01a7\u018d"+
+		"\3\2\2\2\u01a7\u018f\3\2\2\2\u01a7\u0191\3\2\2\2\u01a7\u0193\3\2\2\2\u01a7"+
+		"\u019e\3\2\2\2\u01a7\u019f\3\2\2\2\u01a7\u01a1\3\2\2\2\u01a7\u01a5\3\2"+
+		"\2\2\u01a7\u01a6\3\2\2\2\u01a8\u01df\3\2\2\2\u01a9\u01aa\f\25\2\2\u01aa"+
+		"\u01ab\t\6\2\2\u01ab\u01de\5\64\33\26\u01ac\u01ad\f\24\2\2\u01ad\u01ae"+
+		"\t\7\2\2\u01ae\u01de\5\64\33\25\u01af\u01b0\f\23\2\2\u01b0\u01b1\t\b\2"+
+		"\2\u01b1\u01de\5\64\33\24\u01b2\u01b3\f\21\2\2\u01b3\u01b4\t\t\2\2\u01b4"+
+		"\u01de\5\64\33\22\u01b5\u01b6\f\20\2\2\u01b6\u01b7\7+\2\2\u01b7\u01de"+
+		"\5\64\33\21\u01b8\u01b9\f\17\2\2\u01b9\u01ba\7\67\2\2\u01ba\u01de\5\64"+
+		"\33\20\u01bb\u01bc\f\16\2\2\u01bc\u01bd\78\2\2\u01bd\u01de\5\64\33\17"+
+		"\u01be\u01bf\f\r\2\2\u01bf\u01c0\79\2\2\u01c0\u01de\5\64\33\16\u01c1\u01c2"+
+		"\f\f\2\2\u01c2\u01c3\7:\2\2\u01c3\u01de\5\64\33\r\u01c4\u01c5\f\13\2\2"+
+		"\u01c5\u01c6\7;\2\2\u01c6\u01c7\5\64\33\2\u01c7\u01c8\7\34\2\2\u01c8\u01c9"+
+		"\5\64\33\f\u01c9\u01de\3\2\2\2\u01ca\u01cb\f\n\2\2\u01cb\u01cc\7\6\2\2"+
+		"\u01cc\u01de\5\64\33\n\u01cd\u01ce\f\t\2\2\u01ce\u01cf\t\n\2\2\u01cf\u01de"+
+		"\5\64\33\t\u01d0\u01d1\f\36\2\2\u01d1\u01d3\7\7\2\2\u01d2\u01d4\5\66\34"+
+		"\2\u01d3\u01d2\3\2\2\2\u01d3\u01d4\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5\u01de"+
+		"\7\b\2\2\u01d6\u01d7\f\33\2\2\u01d7\u01d8\7!\2\2\u01d8\u01d9\5\62\32\2"+
+		"\u01d9\u01da\7\"\2\2\u01da\u01de\3\2\2\2\u01db\u01dc\f\30\2\2\u01dc\u01de"+
+		"\t\3\2\2\u01dd\u01a9\3\2\2\2\u01dd\u01ac\3\2\2\2\u01dd\u01af\3\2\2\2\u01dd"+
+		"\u01b2\3\2\2\2\u01dd\u01b5\3\2\2\2\u01dd\u01b8\3\2\2\2\u01dd\u01bb\3\2"+
+		"\2\2\u01dd\u01be\3\2\2\2\u01dd\u01c1\3\2\2\2\u01dd\u01c4\3\2\2\2\u01dd"+
+		"\u01ca\3\2\2\2\u01dd\u01cd\3\2\2\2\u01dd\u01d0\3\2\2\2\u01dd\u01d6\3\2"+
+		"\2\2\u01dd\u01db\3\2\2\2\u01de\u01e1\3\2\2\2\u01df\u01dd\3\2\2\2\u01df"+
+		"\u01e0\3\2\2\2\u01e0\65\3\2\2\2\u01e1\u01df\3\2\2\2\u01e2\u01e7\5\64\33"+
+		"\2\u01e3\u01e4\7\5\2\2\u01e4\u01e6\5\64\33\2\u01e5\u01e3\3\2\2\2\u01e6"+
+		"\u01e9\3\2\2\2\u01e7\u01e5\3\2\2\2\u01e7\u01e8\3\2\2\2\u01e8\67\3\2\2"+
+		"\2\u01e9\u01e7\3\2\2\2\u01ea\u01ec\7F\2\2\u01eb\u01ed\5:\36\2\u01ec\u01eb"+
+		"\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed\u01ee\3\2\2\2\u01ee\u01ef\7Q\2\2\u01ef"+
+		"9\3\2\2\2\u01f0\u01f1\7\7\2\2\u01f1\u01f6\5<\37\2\u01f2\u01f3\7\5\2\2"+
+		"\u01f3\u01f5\5<\37\2\u01f4\u01f2\3\2\2\2\u01f5\u01f8\3\2\2\2\u01f6\u01f4"+
+		"\3\2\2\2\u01f6\u01f7\3\2\2\2\u01f7\u01f9\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f9"+
+		"\u01fa\7\b\2\2\u01fa;\3\2\2\2\u01fb\u01fc\7G\2\2\u01fc\u020b\7S\2\2\u01fd"+
+		"\u01fe\7H\2\2\u01fe\u020b\7_\2\2\u01ff\u0200\7I\2\2\u0200\u020b\7S\2\2"+
+		"\u0201\u0202\7J\2\2\u0202\u020b\5\64\33\2\u0203\u0204\7K\2\2\u0204\u020b"+
+		"\5\64\33\2\u0205\u0208\7L\2\2\u0206\u0209\7\17\2\2\u0207\u0209\5\64\33"+
+		"\2\u0208\u0206\3\2\2\2\u0208\u0207\3\2\2\2\u0209\u020b\3\2\2\2\u020a\u01fb"+
+		"\3\2\2\2\u020a\u01fd\3\2\2\2\u020a\u01ff\3\2\2\2\u020a\u0201\3\2\2\2\u020a"+
+		"\u0203\3\2\2\2\u020a\u0205\3\2\2\2\u020b=\3\2\2\2\u020c\u020e\5@!\2\u020d"+
+		"\u020c\3\2\2\2\u020e\u0211\3\2\2\2\u020f\u020d\3\2\2\2\u020f\u0210\3\2"+
+		"\2\2\u0210?\3\2\2\2\u0211\u020f\3\2\2\2\u0212\u0216\5B\"\2\u0213\u0216"+
+		"\5D#\2\u0214\u0216\5F$\2\u0215\u0212\3\2\2\2\u0215\u0213\3\2\2\2\u0215"+
+		"\u0214\3\2\2\2\u0216A\3\2\2\2\u0217\u0218\7_\2\2\u0218\u021f\7\34\2\2"+
+		"\u0219\u021b\7*\2\2\u021a\u021c\7_\2\2\u021b\u021a\3\2\2\2\u021b\u021c"+
+		"\3\2\2\2\u021c\u021d\3\2\2\2\u021d\u021f\7\34\2\2\u021e\u0217\3\2\2\2"+
+		"\u021e\u0219\3\2\2\2\u021fC\3\2\2\2\u0220\u0222\7P\2\2\u0221\u0223\5H"+
+		"%\2\u0222\u0221\3\2\2\2\u0222\u0223\3\2\2\2\u0223E\3\2\2\2\u0224\u0225"+
+		"\7M\2\2\u0225\u022a\5J&\2\u0226\u0227\7\5\2\2\u0227\u0229\5J&\2\u0228"+
+		"\u0226\3\2\2\2\u0229\u022c\3\2\2\2\u022a\u0228\3\2\2\2\u022a\u022b\3\2"+
+		"\2\2\u022bG\3\2\2\2\u022c\u022a\3\2\2\2\u022d\u0245\5J&\2\u022e\u022f"+
+		"\7N\2\2\u022f\u0245\5J&\2\u0230\u0231\5J&\2\u0231\u0232\7\5\2\2\u0232"+
+		"\u0233\7_\2\2\u0233\u0245\3\2\2\2\u0234\u0235\7\7\2\2\u0235\u0236\5J&"+
+		"\2\u0236\u0237\7\b\2\2\u0237\u0238\7\5\2\2\u0238\u0239\7_\2\2\u0239\u0245"+
+		"\3\2\2\2\u023a\u023b\7\7\2\2\u023b\u023c\5J&\2\u023c\u023d\7\5\2\2\u023d"+
+		"\u023e\7_\2\2\u023e\u023f\7\b\2\2\u023f\u0245\3\2\2\2\u0240\u0241\7\7"+
+		"\2\2\u0241\u0242\5J&\2\u0242\u0243\7\b\2\2\u0243\u0245\3\2\2\2\u0244\u022d"+
+		"\3\2\2\2\u0244\u022e\3\2\2\2\u0244\u0230\3\2\2\2\u0244\u0234\3\2\2\2\u0244"+
+		"\u023a\3\2\2\2\u0244\u0240\3\2\2\2\u0245I\3\2\2\2\u0246\u0247\b&\1\2\u0247"+
+		"\u0248\7!\2\2\u0248\u0249\5J&\2\u0249\u024a\7\"\2\2\u024a\u0255\3\2\2"+
+		"\2\u024b\u024c\t\13\2\2\u024c\u0255\5J&\n\u024d\u0255\7_\2\2\u024e\u0255"+
+		"\7`\2\2\u024f\u0250\7\t\2\2\u0250\u0251\7_\2\2\u0251\u0255\7\n\2\2\u0252"+
+		"\u0255\7V\2\2\u0253\u0255\7T\2\2\u0254\u0246\3\2\2\2\u0254\u024b\3\2\2"+
+		"\2\u0254\u024d\3\2\2\2\u0254\u024e\3\2\2\2\u0254\u024f\3\2\2\2\u0254\u0252"+
+		"\3\2\2\2\u0254\u0253\3\2\2\2\u0255\u0264\3\2\2\2\u0256\u0257\f\f\2\2\u0257"+
+		"\u0258\7O\2\2\u0258\u0263\5J&\r\u0259\u025a\f\13\2\2\u025a\u025b\t\6\2"+
+		"\2\u025b\u0263\5J&\f\u025c\u025d\f\t\2\2\u025d\u025e\t\f\2\2\u025e\u0263"+
+		"\5J&\n\u025f\u0260\f\b\2\2\u0260\u0261\t\b\2\2\u0261\u0263\5J&\t\u0262"+
+		"\u0256\3\2\2\2\u0262\u0259\3\2\2\2\u0262\u025c\3\2\2\2\u0262\u025f\3\2"+
+		"\2\2\u0263\u0266\3\2\2\2\u0264\u0262\3\2\2\2\u0264\u0265\3\2\2\2\u0265"+
+		"K\3\2\2\2\u0266\u0264\3\2\2\2=V_jov\u0084\u008a\u0090\u0095\u009e\u00a5"+
+		"\u00ba\u00bd\u00c6\u00ce\u00d5\u00e2\u00e7\u00f3\u0101\u010c\u0115\u011c"+
+		"\u0123\u0126\u012e\u0131\u0134\u013e\u0142\u0149\u014f\u0151\u0159\u015f"+
+		"\u016e\u017a\u0182\u0199\u01a3\u01a7\u01d3\u01dd\u01df\u01e7\u01ec\u01f6"+
+		"\u0208\u020a\u020f\u0215\u021b\u021e\u0222\u022a\u0244\u0254\u0262\u0264";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
index 98035b89e..edb044629 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
@@ -310,6 +310,13 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
 	 * @return the visitor result
 	 */
 	T visitTypeArray(KickCParser.TypeArrayContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code typeStructRef}
+	 * labeled alternative in {@link KickCParser#typeDecl}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitTypeStructRef(KickCParser.TypeStructRefContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code typeSimple}
 	 * labeled alternative in {@link KickCParser#typeDecl}.
@@ -317,6 +324,13 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
 	 * @return the visitor result
 	 */
 	T visitTypeSimple(KickCParser.TypeSimpleContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code typeStructDef}
+	 * labeled alternative in {@link KickCParser#typeDecl}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitTypeStructDef(KickCParser.TypeStructDefContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code typeSignedSimple}
 	 * labeled alternative in {@link KickCParser#typeDecl}.
@@ -324,6 +338,24 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
 	 * @return the visitor result
 	 */
 	T visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link KickCParser#structRef}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitStructRef(KickCParser.StructRefContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link KickCParser#structDef}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitStructDef(KickCParser.StructDefContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link KickCParser#structMembers}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitStructMembers(KickCParser.StructMembersContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code commaNone}
 	 * labeled alternative in {@link KickCParser#commaExpr}.

From 30d6878ade5d5739ec9fd150b9a1c66c52b414a1 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Mon, 27 May 2019 08:39:59 +0200
Subject: [PATCH 89/93] Minimalistic struct example working with several
 shortcuts in the code.

---
 .../fragment/_deref_pbuc1=vssz1_mbr_0.asm     |   2 +
 .../fragment/_deref_pbuc1=vssz1_mbr_1.asm     |   2 +
 src/main/fragment/vssz1=vssf2.asm             |   3 +
 src/main/fragment/vssz1_mbr_0=vbuc1.asm       |   2 +
 src/main/fragment/vssz1_mbr_1=vbuc1.asm       |   2 +
 .../AsmFragmentInstanceSpecFactory.java       |  30 +-
 .../dk/camelot64/kickc/model/Registers.java   |  14 +
 .../kickc/model/iterator/ProgramValue.java    |  22 +
 .../model/iterator/ProgramValueIterator.java  |   3 +
 .../camelot64/kickc/model/symbols/Scope.java  |  43 +-
 .../kickc/model/symbols/StructDefinition.java |  25 +
 .../model/types/SymbolTypeInference.java      |  17 +
 .../kickc/model/types/SymbolTypePointer.java  |   4 +-
 .../kickc/model/types/SymbolTypeStruct.java   |  60 ++
 .../kickc/model/values/StructMemberRef.java   |  45 +
 .../kickc/model/values/StructZero.java        |  25 +
 .../java/dk/camelot64/kickc/parser/KickC.g4   |   2 +
 .../dk/camelot64/kickc/parser/KickC.tokens    | 130 +--
 .../kickc/parser/KickCBaseListener.java       |  24 +
 .../kickc/parser/KickCBaseVisitor.java        |  14 +
 .../dk/camelot64/kickc/parser/KickCLexer.java | 723 ++++++-------
 .../camelot64/kickc/parser/KickCLexer.tokens  | 130 +--
 .../camelot64/kickc/parser/KickCListener.java |  24 +
 .../camelot64/kickc/parser/KickCParser.java   | 975 ++++++++++--------
 .../camelot64/kickc/parser/KickCVisitor.java  |  14 +
 .../Pass0GenerateStatementSequence.java       |  42 +
 .../kickc/passes/Pass2AssertSymbols.java      |   2 +
 .../kickc/passes/Pass4RegistersFinalize.java  |   5 +
 .../dk/camelot64/kickc/test/TestPrograms.java |   5 +
 src/test/kc/struct-0.kc                       |  14 +
 src/test/ref/struct-0.asm                     |  23 +
 31 files changed, 1455 insertions(+), 971 deletions(-)
 create mode 100644 src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm
 create mode 100644 src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm
 create mode 100644 src/main/fragment/vssz1=vssf2.asm
 create mode 100644 src/main/fragment/vssz1_mbr_0=vbuc1.asm
 create mode 100644 src/main/fragment/vssz1_mbr_1=vbuc1.asm
 create mode 100644 src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/values/StructMemberRef.java
 create mode 100644 src/main/java/dk/camelot64/kickc/model/values/StructZero.java
 create mode 100644 src/test/kc/struct-0.kc
 create mode 100644 src/test/ref/struct-0.asm

diff --git a/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm b/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm
new file mode 100644
index 000000000..f235c1aee
--- /dev/null
+++ b/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm
@@ -0,0 +1,2 @@
+lda {z1}+0
+sta {c1}
\ No newline at end of file
diff --git a/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm b/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm
new file mode 100644
index 000000000..59a255b43
--- /dev/null
+++ b/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm
@@ -0,0 +1,2 @@
+lda {z1}+1
+sta {c1}
\ No newline at end of file
diff --git a/src/main/fragment/vssz1=vssf2.asm b/src/main/fragment/vssz1=vssf2.asm
new file mode 100644
index 000000000..5a5c14b91
--- /dev/null
+++ b/src/main/fragment/vssz1=vssf2.asm
@@ -0,0 +1,3 @@
+lda #0
+sta {z1}
+sta {z1}+1
\ No newline at end of file
diff --git a/src/main/fragment/vssz1_mbr_0=vbuc1.asm b/src/main/fragment/vssz1_mbr_0=vbuc1.asm
new file mode 100644
index 000000000..cdbf628d1
--- /dev/null
+++ b/src/main/fragment/vssz1_mbr_0=vbuc1.asm
@@ -0,0 +1,2 @@
+lda #{c1}
+sta {z1}+0
\ No newline at end of file
diff --git a/src/main/fragment/vssz1_mbr_1=vbuc1.asm b/src/main/fragment/vssz1_mbr_1=vbuc1.asm
new file mode 100644
index 000000000..540828c77
--- /dev/null
+++ b/src/main/fragment/vssz1_mbr_1=vbuc1.asm
@@ -0,0 +1,2 @@
+lda #{c1}
+sta {z1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
index f3e3624c4..760674038 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
@@ -7,10 +7,7 @@ import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.Statement;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
 import dk.camelot64.kickc.model.statements.StatementConditionalJump;
-import dk.camelot64.kickc.model.symbols.ConstantVar;
-import dk.camelot64.kickc.model.symbols.Label;
-import dk.camelot64.kickc.model.symbols.Symbol;
-import dk.camelot64.kickc.model.symbols.Variable;
+import dk.camelot64.kickc.model.symbols.*;
 import dk.camelot64.kickc.model.types.*;
 import dk.camelot64.kickc.model.values.*;
 
@@ -306,6 +303,26 @@ public class AsmFragmentInstanceSpecFactory {
          String name = "la" + nextLabelIdx++;
          bind(name, value);
          return name;
+      } else if(value instanceof StructZero) {
+         return "vssf"+((StructZero) value).getTypeStruct().getSizeBytes();
+      } else if(value instanceof StructMemberRef) {
+         StructMemberRef structMemberRef = (StructMemberRef) value;
+         RValue struct = structMemberRef.getStruct();
+         String memberName = structMemberRef.getMemberName();
+         SymbolType symbolType = SymbolTypeInference.inferType(program.getScope(), struct);
+         byte idx = 0;
+         if(symbolType instanceof SymbolTypeStruct) {
+            String structTypeName = ((SymbolTypeStruct) symbolType).getStructTypeName();
+            StructDefinition structDefinition = program.getScope().getStructDefinition(structTypeName);
+            for(Variable structMember : structDefinition.getAllVariables(false)) {
+               if(structMember.getLocalName().equals(memberName)) {
+                  break;
+               } else {
+                  idx += structMember.getType().getSizeBytes();
+               }
+            }
+         }
+         return bind(struct)+"_mbr_"+ idx;
       }
       throw new RuntimeException("Binding of value type not supported " + value);
    }
@@ -343,6 +360,8 @@ public class AsmFragmentInstanceSpecFactory {
          return "pbu";
       } else if(SymbolType.BOOLEAN.equals(type)) {
          return "vbo";
+      } else if(type instanceof SymbolTypeStruct) {
+         return "vss";
       } else if(type instanceof SymbolTypePointer) {
          SymbolType elementType = ((SymbolTypePointer) type).getElementType();
          if(SymbolType.BYTE.equals(elementType)) {
@@ -383,7 +402,8 @@ public class AsmFragmentInstanceSpecFactory {
             Registers.RegisterType.ZP_BOOL.equals(register.getType()) ||
                   Registers.RegisterType.ZP_BYTE.equals(register.getType()) ||
                   Registers.RegisterType.ZP_WORD.equals(register.getType()) ||
-                  Registers.RegisterType.ZP_DWORD.equals(register.getType())
+                  Registers.RegisterType.ZP_DWORD.equals(register.getType()) ||
+                  Registers.RegisterType.ZP_STRUCT.equals(register.getType())
       ) {
          // Examine if the ZP register is already bound
          Registers.RegisterZp registerZp = (Registers.RegisterZp) register;
diff --git a/src/main/java/dk/camelot64/kickc/model/Registers.java b/src/main/java/dk/camelot64/kickc/model/Registers.java
index b889d62bd..7e2075931 100644
--- a/src/main/java/dk/camelot64/kickc/model/Registers.java
+++ b/src/main/java/dk/camelot64/kickc/model/Registers.java
@@ -45,6 +45,7 @@ public class Registers {
       ZP_BYTE,
       ZP_WORD,
       ZP_DWORD,
+      ZP_STRUCT,
       ZP_BOOL,
       CONSTANT
    }
@@ -150,6 +151,19 @@ public class Registers {
 
    }
 
+   /** Zero page addresses used as a register for a struct variable. */
+   public static class RegisterZpStruct extends RegisterZp {
+
+      public RegisterZpStruct(int zp) {
+         super(zp);
+      }
+
+      @Override
+      public RegisterType getType() {
+         return RegisterType.ZP_STRUCT;
+      }
+
+   }
 
    /** 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/iterator/ProgramValue.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
index 0477f39ef..c6d75927a 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java
@@ -748,6 +748,28 @@ public interface ProgramValue {
 
    }
 
+   /**
+    * Struct expression inside a struct member reference.
+    */
+   class ProgramValueStruct implements ProgramValue {
+      private final StructMemberRef structMemberRef;
+
+      public ProgramValueStruct(StructMemberRef structMemberRef) {
+         this.structMemberRef = structMemberRef;
+      }
+
+      @Override
+      public Value get() {
+         return structMemberRef.getStruct();
+      }
+
+      @Override
+      public void set(Value val) {
+         structMemberRef.setStruct((RValue) val);
+      }
+
+   }
+
    /**
     * Pointer index inside a indexed pointer dererence value.
     */
diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java
index 6fe274204..a1984c1a8 100644
--- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java
@@ -186,6 +186,8 @@ public class ProgramValueIterator {
          subValues.add(new ProgramValue.ProgramValuePointerIndex((PointerDereferenceIndexed) value));
       } else if(value instanceof PointerDereferenceSimple) {
          subValues.add(new ProgramValue.ProgramValuePointer((PointerDereference) value));
+      } else if(value instanceof StructMemberRef) {
+         subValues.add(new ProgramValue.ProgramValueStruct((StructMemberRef) value));
       } else if(value instanceof ValueList) {
          ValueList valueList = (ValueList) value;
          int size = valueList.getList().size();
@@ -223,6 +225,7 @@ public class ProgramValueIterator {
             value instanceof ProcedureRef ||
             value instanceof ConstantLiteral ||
             value instanceof ConstantRef ||
+            value instanceof StructZero ||
             value instanceof LabelRef
             ) {
          // No sub values
diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java
index 3070e188f..d7d55166b 100644
--- a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java
+++ b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java
@@ -82,7 +82,7 @@ public abstract class Scope implements Symbol {
       }
    }
 
-   public Symbol add(Symbol symbol) {
+   public <T extends Symbol> T add(T symbol) {
       if(symbols.get(symbol.getLocalName()) != null) {
          throw new CompileError("Symbol already declared " + symbol.getLocalName());
       }
@@ -95,16 +95,12 @@ public abstract class Scope implements Symbol {
    }
 
    public VariableUnversioned addVariable(String name, SymbolType type) {
-      VariableUnversioned symbol = new VariableUnversioned(name, this, type);
-      add(symbol);
-      return symbol;
+      return add(new VariableUnversioned(name, this, type));
    }
 
    public VariableIntermediate addVariableIntermediate() {
       String name = allocateIntermediateVariableName();
-      VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolType.VAR);
-      add(symbol);
-      return symbol;
+      return add(new VariableIntermediate(name, this, SymbolType.VAR));
    }
 
    /**
@@ -254,16 +250,12 @@ public abstract class Scope implements Symbol {
 
 
    public Label addLabel(String name) {
-      Label symbol = new Label(name, this, false);
-      add(symbol);
-      return symbol;
+      return add(new Label(name, this, false));
    }
 
    public Label addLabelIntermediate() {
       String name = "@" + intermediateLabelCount++;
-      Label symbol = new Label(name, this, true);
-      add(symbol);
-      return symbol;
+      return add(new Label(name, this, true));
    }
 
    public Label getLabel(String name) {
@@ -276,9 +268,7 @@ public abstract class Scope implements Symbol {
 
    public BlockScope addBlockScope() {
       String name = ":" + blockCount++;
-      BlockScope blockScope = new BlockScope(name, this);
-      add(blockScope);
-      return blockScope;
+      return add(new BlockScope(name, this));
    }
 
    public BlockScope getBlockScope(String name) {
@@ -286,13 +276,7 @@ public abstract class Scope implements Symbol {
    }
 
    public Procedure addProcedure(String name, SymbolType type) {
-      Symbol symbol = symbols.get(name);
-      if(symbol != null) {
-         throw new RuntimeException("Error! Symbol already defined " + symbol);
-      }
-      Procedure procedure = new Procedure(name, type, this);
-      add(procedure);
-      return procedure;
+      return add(new Procedure(name, type, this));
    }
 
    public Procedure getProcedure(String name) {
@@ -304,6 +288,19 @@ public abstract class Scope implements Symbol {
       }
    }
 
+   /**
+    * Add a struct definition.
+    * The name can be either defined in the program or an intermediate name.
+    * @param name
+    */
+   public StructDefinition addStructDefinition(String name) {
+      return add(new StructDefinition(name, this));
+   }
+
+   public StructDefinition getStructDefinition(String name) {
+      return (StructDefinition) getSymbol(name);
+   }
+
    public Scope getScope(ScopeRef scopeRef) {
       if(scopeRef.getFullName().equals("") && this instanceof ProgramScope) {
          // Special case for the outer program scope
diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java
new file mode 100644
index 000000000..165980096
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java
@@ -0,0 +1,25 @@
+package dk.camelot64.kickc.model.symbols;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeStruct;
+
+/**
+ * A struct definition containing a set of variables.
+ */
+public class StructDefinition extends Scope {
+
+   public StructDefinition(String name, Scope parentScope) {
+      super(name, parentScope);
+   }
+
+   @Override
+   public SymbolType getType() {
+      return new SymbolTypeStruct(this);
+   }
+
+   @Override
+   public String toString(Program program) {
+      return "block-"+getFullName();
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
index c2875ef15..3506dfadd 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java
@@ -1,6 +1,8 @@
 package dk.camelot64.kickc.model.types;
 
+import dk.camelot64.kickc.fragment.AsmFragmentInstanceSpec;
 import dk.camelot64.kickc.model.CompileError;
+import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.operators.OperatorBinary;
 import dk.camelot64.kickc.model.operators.OperatorUnary;
 import dk.camelot64.kickc.model.statements.StatementAssignment;
@@ -98,6 +100,21 @@ public class SymbolTypeInference {
             throw new CompileError("Cannot infer type of " + assignment.toString());
          }
          return rValueType;
+      } else if(rValue instanceof StructMemberRef) {
+         StructMemberRef structMemberRef = (StructMemberRef) rValue;
+         SymbolType structType = inferType(symbols, structMemberRef.getStruct());
+         if(structType instanceof SymbolTypeStruct) {
+            String typeName = ((SymbolTypeStruct) structType).getStructTypeName();
+            StructDefinition structDefinition = symbols.getStructDefinition(typeName);
+            Variable structMember = structDefinition.getVariable(structMemberRef.getMemberName());
+            return structMember.getType();
+         } else {
+            AsmFragmentInstanceSpec asmFragmentInstanceSpec = null;
+            Program program = asmFragmentInstanceSpec.getProgram();
+            throw new CompileError("Dot applied to non-struct "+ structMemberRef.getStruct().toString(program));
+         }
+      } else if(rValue instanceof StructZero) {
+         return ((StructZero)rValue).getTypeStruct();
       }
       if(type == null) {
          throw new RuntimeException("Cannot infer type for " + rValue.toString());
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java
index 451b04e87..b9bedcb87 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypePointer.java
@@ -4,7 +4,7 @@ package dk.camelot64.kickc.model.types;
 public class SymbolTypePointer implements SymbolType {
 
    /** The number of bytes needed to represent a pointer in memory. */
-   public static final int SIZE_BYTES = 2;
+   public static final int SIZE_POINTER_BYTES = 2;
 
    private SymbolType elementType;
 
@@ -28,7 +28,7 @@ public class SymbolTypePointer implements SymbolType {
 
    @Override
    public int getSizeBytes() {
-      return SIZE_BYTES;
+      return SIZE_POINTER_BYTES;
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java
new file mode 100644
index 000000000..558f73708
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java
@@ -0,0 +1,60 @@
+package dk.camelot64.kickc.model.types;
+
+import dk.camelot64.kickc.model.symbols.StructDefinition;
+import dk.camelot64.kickc.model.symbols.Variable;
+
+import java.util.Objects;
+
+/** A struct */
+public class SymbolTypeStruct implements SymbolType {
+
+   /** Name of the struct type. */
+   private String name;
+
+   /** Size of the struct in bytes. */
+   private int sizeBytes;
+
+   public SymbolTypeStruct(StructDefinition structDefinition) {
+      this.name = structDefinition.getLocalName();
+      int sizeBytes = 0;
+      for(Variable member : structDefinition.getAllVariables(false)) {
+         sizeBytes += member.getType().getSizeBytes();
+      }
+      this.sizeBytes = sizeBytes;
+   }
+
+   @Override
+   public String getTypeName() {
+      return "struct " + name;
+   }
+
+   public String getStructTypeName() {
+      return name;
+   }
+
+   @Override
+   public int getSizeBytes() {
+      return sizeBytes;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if(this == o) return true;
+      if(o == null || getClass() != o.getClass()) return false;
+      SymbolTypeStruct that = (SymbolTypeStruct) o;
+      return sizeBytes == that.sizeBytes &&
+            Objects.equals(name, that.name);
+   }
+
+   @Override
+   public int hashCode() {
+
+      return Objects.hash(name, sizeBytes);
+   }
+
+   @Override
+   public String toString() {
+      return getTypeName();
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/values/StructMemberRef.java b/src/main/java/dk/camelot64/kickc/model/values/StructMemberRef.java
new file mode 100644
index 000000000..a171bf582
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/values/StructMemberRef.java
@@ -0,0 +1,45 @@
+package dk.camelot64.kickc.model.values;
+
+import dk.camelot64.kickc.model.Program;
+
+/** A reference to a struct member */
+public class StructMemberRef implements LValue {
+
+   /** Expression evaluating to a struct. */
+   private RValue struct;
+
+   /** Name of the referenced member. */
+   private String memberName;
+
+   public StructMemberRef(RValue struct, String memberName) {
+      this.struct = struct;
+      this.memberName = memberName;
+   }
+
+   public RValue getStruct() {
+      return struct;
+   }
+
+   public void setStruct(RValue struct) {
+      this.struct = struct;
+   }
+
+   public String getMemberName() {
+      return memberName;
+   }
+
+   public void setMemberName(String memberName) {
+      this.memberName = memberName;
+   }
+
+   @Override
+   public String toString() {
+      return toString(null);
+   }
+
+   @Override
+   public String toString(Program program) {
+      return struct.toString(program) + "." + memberName ;
+   }
+
+}
diff --git a/src/main/java/dk/camelot64/kickc/model/values/StructZero.java b/src/main/java/dk/camelot64/kickc/model/values/StructZero.java
new file mode 100644
index 000000000..9d6798d6e
--- /dev/null
+++ b/src/main/java/dk/camelot64/kickc/model/values/StructZero.java
@@ -0,0 +1,25 @@
+package dk.camelot64.kickc.model.values;
+
+import dk.camelot64.kickc.model.Program;
+import dk.camelot64.kickc.model.types.SymbolTypeStruct;
+
+/**
+ * An zero-filled struct.
+ */
+public class StructZero implements RValue {
+
+   private SymbolTypeStruct typeStruct;
+
+   public StructZero(SymbolTypeStruct typeStruct) {
+      this.typeStruct = typeStruct;
+   }
+
+   public SymbolTypeStruct getTypeStruct() {
+      return typeStruct;
+   }
+
+   @Override
+   public String toString(Program program) {
+      return "{}";
+   }
+}
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.g4 b/src/main/java/dk/camelot64/kickc/parser/KickC.g4
index 117fd6732..a604ccb24 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickC.g4
+++ b/src/main/java/dk/camelot64/kickc/parser/KickC.g4
@@ -136,6 +136,8 @@ commaExpr
 
 expr
     : '(' commaExpr ')' #exprPar
+    | expr '.' NAME #exprDot
+    | expr '->' NAME  #exprArrow
     | expr '(' parameterList? ')' #exprCall
     | 'sizeof' '(' ( typeDecl | expr ) ')' #exprSizeOf
     | 'typeid' '(' ( typeDecl | expr ) ')' #exprTypeId
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickC.tokens b/src/main/java/dk/camelot64/kickc/parser/KickC.tokens
index a303b96fe..42dfa728a 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickC.tokens
+++ b/src/main/java/dk/camelot64/kickc/parser/KickC.tokens
@@ -75,26 +75,27 @@ T__73=74
 T__74=75
 T__75=76
 T__76=77
-MNEMONIC=78
-KICKASM=79
-SIMPLETYPE=80
-STRING=81
-CHAR=82
-BOOLEAN=83
-NUMBER=84
-NUMFLOAT=85
-BINFLOAT=86
-DECFLOAT=87
-HEXFLOAT=88
-NUMINT=89
-BININTEGER=90
-DECINTEGER=91
-HEXINTEGER=92
-NAME=93
-ASMREL=94
-WS=95
-COMMENT_LINE=96
-COMMENT_BLOCK=97
+T__77=78
+MNEMONIC=79
+KICKASM=80
+SIMPLETYPE=81
+STRING=82
+CHAR=83
+BOOLEAN=84
+NUMBER=85
+NUMFLOAT=86
+BINFLOAT=87
+DECFLOAT=88
+HEXFLOAT=89
+NUMINT=90
+BININTEGER=91
+DECINTEGER=92
+HEXINTEGER=93
+NAME=94
+ASMREL=95
+WS=96
+COMMENT_LINE=97
+COMMENT_BLOCK=98
 'import'=1
 ';'=2
 ','=3
@@ -128,47 +129,48 @@ COMMENT_BLOCK=97
 '['=31
 ']'=32
 'struct'=33
-'sizeof'=34
-'typeid'=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
-'>>='=64
-'&='=65
-'|='=66
-'^='=67
-'kickasm'=68
-'resource'=69
-'uses'=70
-'clobbers'=71
-'bytes'=72
-'cycles'=73
-'pc'=74
-'.byte'=75
-'#'=76
-'.'=77
+'.'=34
+'->'=35
+'sizeof'=36
+'typeid'=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
+'%='=64
+'<<='=65
+'>>='=66
+'&='=67
+'|='=68
+'^='=69
+'kickasm'=70
+'resource'=71
+'uses'=72
+'clobbers'=73
+'bytes'=74
+'cycles'=75
+'pc'=76
+'.byte'=77
+'#'=78
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
index b8a02352a..ba4d3501e 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseListener.java
@@ -755,6 +755,30 @@ public class KickCBaseListener implements KickCListener {
 	 * <p>The default implementation does nothing.</p>
 	 */
 	@Override public void exitExprChar(KickCParser.ExprCharContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterExprArrow(KickCParser.ExprArrowContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitExprArrow(KickCParser.ExprArrowContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterExprDot(KickCParser.ExprDotContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitExprDot(KickCParser.ExprDotContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
index 2cba0e61e..111fc9a36 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCBaseVisitor.java
@@ -445,6 +445,20 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
 	@Override public T visitExprChar(KickCParser.ExprCharContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitExprArrow(KickCParser.ExprArrowContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitExprDot(KickCParser.ExprDotContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
index 594b24209..c8c2c2b66 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.java
@@ -27,10 +27,10 @@ public class KickCLexer extends Lexer {
 		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, T__71=72, T__72=73, 
-		T__73=74, T__74=75, T__75=76, T__76=77, MNEMONIC=78, KICKASM=79, SIMPLETYPE=80, 
-		STRING=81, CHAR=82, BOOLEAN=83, NUMBER=84, NUMFLOAT=85, BINFLOAT=86, DECFLOAT=87, 
-		HEXFLOAT=88, NUMINT=89, BININTEGER=90, DECINTEGER=91, HEXINTEGER=92, NAME=93, 
-		ASMREL=94, WS=95, COMMENT_LINE=96, COMMENT_BLOCK=97;
+		T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, MNEMONIC=79, KICKASM=80, 
+		SIMPLETYPE=81, STRING=82, CHAR=83, BOOLEAN=84, NUMBER=85, NUMFLOAT=86, 
+		BINFLOAT=87, DECFLOAT=88, HEXFLOAT=89, NUMINT=90, BININTEGER=91, DECINTEGER=92, 
+		HEXINTEGER=93, NAME=94, ASMREL=95, WS=96, COMMENT_LINE=97, COMMENT_BLOCK=98;
 	public static String[] channelNames = {
 		"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
 	};
@@ -49,7 +49,7 @@ public class KickCLexer extends Lexer {
 		"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", "T__71", "T__72", 
-		"T__73", "T__74", "T__75", "T__76", "MNEMONIC", "KICKASM", "SIMPLETYPE", 
+		"T__73", "T__74", "T__75", "T__76", "T__77", "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", 
@@ -61,12 +61,12 @@ public class KickCLexer extends Lexer {
 		"'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'", 
 		"'reserve'", "'if'", "'else'", "'while'", "'do'", "'for'", "'return'", 
 		"'break'", "'continue'", "'asm'", "':'", "'..'", "'signed'", "'unsigned'", 
-		"'*'", "'['", "']'", "'struct'", "'sizeof'", "'typeid'", "'--'", "'++'", 
-		"'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", 
-		"'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", 
-		"'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", 
-		"'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'", 
-		"'cycles'", "'pc'", "'.byte'", "'#'", "'.'"
+		"'*'", "'['", "']'", "'struct'", "'.'", "'->'", "'sizeof'", "'typeid'", 
+		"'--'", "'++'", "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", 
+		"'%'", "'<'", "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", 
+		"'||'", "'?'", "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", 
+		"'&='", "'|='", "'^='", "'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, 
@@ -75,7 +75,7 @@ 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, 
-		null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", 
+		null, null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", 
 		"STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", 
 		"HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", 
 		"ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK"
@@ -138,7 +138,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\2c\u03e5\b\1\4\2\t"+
+		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2d\u03ea\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"+
@@ -149,354 +149,355 @@ 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\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\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\21\3\21\3\21\3\21\3\21"+
-		"\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24"+
-		"\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\27\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\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31"+
-		"\3\31\3\32\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\35"+
-		"\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\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+\3+\3,\3,"+
-		"\3,\3-\3-\3-\3.\3.\3/\3/\3\60\3\60\3\61\3\61\3\62\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\67\3\67\38\38\38\39\3"+
-		"9\39\3:\3:\3;\3;\3;\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3@\3"+
-		"A\3A\3A\3A\3B\3B\3B\3C\3C\3C\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F\3"+
-		"F\3F\3F\3F\3F\3F\3F\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3"+
-		"I\3I\3I\3I\3J\3J\3J\3J\3J\3J\3J\3K\3K\3K\3L\3L\3L\3L\3L\3L\3M\3M\3N\3"+
-		"N\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3"+
-		"O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\5O\u02ef\nO\3P\3P\3P\3"+
-		"P\7P\u02f5\nP\fP\16P\u02f8\13P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q"+
-		"\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q"+
-		"\3Q\3Q\3Q\3Q\5Q\u0322\nQ\3R\3R\3R\3R\7R\u0328\nR\fR\16R\u032b\13R\3R\3"+
-		"R\5R\u032f\nR\3S\3S\3S\3S\5S\u0335\nS\3S\3S\3T\3T\3T\3T\3T\3T\3T\3T\3"+
-		"T\5T\u0342\nT\3U\3U\5U\u0346\nU\3V\3V\3V\5V\u034b\nV\3W\3W\3W\3W\3W\5"+
-		"W\u0352\nW\3W\7W\u0355\nW\fW\16W\u0358\13W\3W\3W\6W\u035c\nW\rW\16W\u035d"+
-		"\3X\7X\u0361\nX\fX\16X\u0364\13X\3X\3X\6X\u0368\nX\rX\16X\u0369\3Y\3Y"+
-		"\3Y\3Y\3Y\5Y\u0371\nY\3Y\7Y\u0374\nY\fY\16Y\u0377\13Y\3Y\3Y\6Y\u037b\n"+
-		"Y\rY\16Y\u037c\3Z\3Z\3Z\5Z\u0382\nZ\3Z\3Z\3Z\5Z\u0387\nZ\3[\3[\3[\6[\u038c"+
-		"\n[\r[\16[\u038d\3[\3[\6[\u0392\n[\r[\16[\u0393\5[\u0396\n[\3\\\6\\\u0399"+
-		"\n\\\r\\\16\\\u039a\3]\3]\3]\3]\3]\5]\u03a2\n]\3]\6]\u03a5\n]\r]\16]\u03a6"+
-		"\3^\3^\3_\3_\3`\3`\3a\3a\7a\u03b1\na\fa\16a\u03b4\13a\3b\3b\3c\3c\3d\3"+
-		"d\7d\u03bc\nd\fd\16d\u03bf\13d\3d\6d\u03c2\nd\rd\16d\u03c3\3e\6e\u03c7"+
-		"\ne\re\16e\u03c8\3e\3e\3f\3f\3f\3f\7f\u03d1\nf\ff\16f\u03d4\13f\3f\3f"+
-		"\3g\3g\3g\3g\7g\u03dc\ng\fg\16g\u03df\13g\3g\3g\3g\3g\3g\4\u02f6\u03dd"+
-		"\2h\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[\u00b5"+
-		"\\\u00b7]\u00b9^\u00bb\2\u00bd\2\u00bf\2\u00c1_\u00c3\2\u00c5\2\u00c7"+
-		"`\u00c9a\u00cbb\u00cdc\3\2\17\3\2$$\3\2))\4\2uuww\7\2dfkknnuuyy\4\2DD"+
-		"dd\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\u0454\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\2U\3\2\2\2\2W\3\2\2\2\2"+
-		"Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3"+
-		"\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2"+
-		"\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2"+
-		"\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3"+
-		"\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2"+
-		"\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099"+
-		"\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2"+
-		"\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab"+
-		"\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2"+
-		"\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00c1\3\2\2\2\2\u00c7"+
-		"\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2\2\3\u00cf\3\2\2"+
-		"\2\5\u00d6\3\2\2\2\7\u00d8\3\2\2\2\t\u00da\3\2\2\2\13\u00dc\3\2\2\2\r"+
-		"\u00de\3\2\2\2\17\u00e0\3\2\2\2\21\u00e2\3\2\2\2\23\u00e4\3\2\2\2\25\u00ea"+
-		"\3\2\2\2\27\u00f1\3\2\2\2\31\u00f7\3\2\2\2\33\u0100\3\2\2\2\35\u0107\3"+
-		"\2\2\2\37\u0110\3\2\2\2!\u011a\3\2\2\2#\u0122\3\2\2\2%\u0125\3\2\2\2\'"+
-		"\u012a\3\2\2\2)\u0130\3\2\2\2+\u0133\3\2\2\2-\u0137\3\2\2\2/\u013e\3\2"+
-		"\2\2\61\u0144\3\2\2\2\63\u014d\3\2\2\2\65\u0151\3\2\2\2\67\u0153\3\2\2"+
-		"\29\u0156\3\2\2\2;\u015d\3\2\2\2=\u0166\3\2\2\2?\u0168\3\2\2\2A\u016a"+
-		"\3\2\2\2C\u016c\3\2\2\2E\u0173\3\2\2\2G\u017a\3\2\2\2I\u0181\3\2\2\2K"+
-		"\u0184\3\2\2\2M\u0187\3\2\2\2O\u0189\3\2\2\2Q\u018b\3\2\2\2S\u018d\3\2"+
-		"\2\2U\u018f\3\2\2\2W\u0191\3\2\2\2Y\u0194\3\2\2\2[\u0197\3\2\2\2]\u0199"+
-		"\3\2\2\2_\u019b\3\2\2\2a\u019d\3\2\2\2c\u019f\3\2\2\2e\u01a2\3\2\2\2g"+
-		"\u01a5\3\2\2\2i\u01a8\3\2\2\2k\u01ab\3\2\2\2m\u01ad\3\2\2\2o\u01af\3\2"+
-		"\2\2q\u01b2\3\2\2\2s\u01b5\3\2\2\2u\u01b7\3\2\2\2w\u01ba\3\2\2\2y\u01bd"+
-		"\3\2\2\2{\u01c0\3\2\2\2}\u01c3\3\2\2\2\177\u01c6\3\2\2\2\u0081\u01ca\3"+
-		"\2\2\2\u0083\u01ce\3\2\2\2\u0085\u01d1\3\2\2\2\u0087\u01d4\3\2\2\2\u0089"+
-		"\u01d7\3\2\2\2\u008b\u01df\3\2\2\2\u008d\u01e8\3\2\2\2\u008f\u01ed\3\2"+
-		"\2\2\u0091\u01f6\3\2\2\2\u0093\u01fc\3\2\2\2\u0095\u0203\3\2\2\2\u0097"+
-		"\u0206\3\2\2\2\u0099\u020c\3\2\2\2\u009b\u020e\3\2\2\2\u009d\u02ee\3\2"+
-		"\2\2\u009f\u02f0\3\2\2\2\u00a1\u0321\3\2\2\2\u00a3\u0323\3\2\2\2\u00a5"+
-		"\u0330\3\2\2\2\u00a7\u0341\3\2\2\2\u00a9\u0345\3\2\2\2\u00ab\u034a\3\2"+
-		"\2\2\u00ad\u0351\3\2\2\2\u00af\u0362\3\2\2\2\u00b1\u0370\3\2\2\2\u00b3"+
-		"\u0381\3\2\2\2\u00b5\u0395\3\2\2\2\u00b7\u0398\3\2\2\2\u00b9\u03a1\3\2"+
-		"\2\2\u00bb\u03a8\3\2\2\2\u00bd\u03aa\3\2\2\2\u00bf\u03ac\3\2\2\2\u00c1"+
-		"\u03ae\3\2\2\2\u00c3\u03b5\3\2\2\2\u00c5\u03b7\3\2\2\2\u00c7\u03b9\3\2"+
-		"\2\2\u00c9\u03c6\3\2\2\2\u00cb\u03cc\3\2\2\2\u00cd\u03d7\3\2\2\2\u00cf"+
-		"\u00d0\7k\2\2\u00d0\u00d1\7o\2\2\u00d1\u00d2\7r\2\2\u00d2\u00d3\7q\2\2"+
-		"\u00d3\u00d4\7t\2\2\u00d4\u00d5\7v\2\2\u00d5\4\3\2\2\2\u00d6\u00d7\7="+
-		"\2\2\u00d7\6\3\2\2\2\u00d8\u00d9\7.\2\2\u00d9\b\3\2\2\2\u00da\u00db\7"+
-		"?\2\2\u00db\n\3\2\2\2\u00dc\u00dd\7*\2\2\u00dd\f\3\2\2\2\u00de\u00df\7"+
-		"+\2\2\u00df\16\3\2\2\2\u00e0\u00e1\7}\2\2\u00e1\20\3\2\2\2\u00e2\u00e3"+
-		"\7\177\2\2\u00e3\22\3\2\2\2\u00e4\u00e5\7e\2\2\u00e5\u00e6\7q\2\2\u00e6"+
-		"\u00e7\7p\2\2\u00e7\u00e8\7u\2\2\u00e8\u00e9\7v\2\2\u00e9\24\3\2\2\2\u00ea"+
-		"\u00eb\7g\2\2\u00eb\u00ec\7z\2\2\u00ec\u00ed\7v\2\2\u00ed\u00ee\7g\2\2"+
-		"\u00ee\u00ef\7t\2\2\u00ef\u00f0\7p\2\2\u00f0\26\3\2\2\2\u00f1\u00f2\7"+
-		"c\2\2\u00f2\u00f3\7n\2\2\u00f3\u00f4\7k\2\2\u00f4\u00f5\7i\2\2\u00f5\u00f6"+
-		"\7p\2\2\u00f6\30\3\2\2\2\u00f7\u00f8\7t\2\2\u00f8\u00f9\7g\2\2\u00f9\u00fa"+
-		"\7i\2\2\u00fa\u00fb\7k\2\2\u00fb\u00fc\7u\2\2\u00fc\u00fd\7v\2\2\u00fd"+
-		"\u00fe\7g\2\2\u00fe\u00ff\7t\2\2\u00ff\32\3\2\2\2\u0100\u0101\7k\2\2\u0101"+
-		"\u0102\7p\2\2\u0102\u0103\7n\2\2\u0103\u0104\7k\2\2\u0104\u0105\7p\2\2"+
-		"\u0105\u0106\7g\2\2\u0106\34\3\2\2\2\u0107\u0108\7x\2\2\u0108\u0109\7"+
-		"q\2\2\u0109\u010a\7n\2\2\u010a\u010b\7c\2\2\u010b\u010c\7v\2\2\u010c\u010d"+
-		"\7k\2\2\u010d\u010e\7n\2\2\u010e\u010f\7g\2\2\u010f\36\3\2\2\2\u0110\u0111"+
-		"\7k\2\2\u0111\u0112\7p\2\2\u0112\u0113\7v\2\2\u0113\u0114\7g\2\2\u0114"+
-		"\u0115\7t\2\2\u0115\u0116\7t\2\2\u0116\u0117\7w\2\2\u0117\u0118\7r\2\2"+
-		"\u0118\u0119\7v\2\2\u0119 \3\2\2\2\u011a\u011b\7t\2\2\u011b\u011c\7g\2"+
-		"\2\u011c\u011d\7u\2\2\u011d\u011e\7g\2\2\u011e\u011f\7t\2\2\u011f\u0120"+
-		"\7x\2\2\u0120\u0121\7g\2\2\u0121\"\3\2\2\2\u0122\u0123\7k\2\2\u0123\u0124"+
-		"\7h\2\2\u0124$\3\2\2\2\u0125\u0126\7g\2\2\u0126\u0127\7n\2\2\u0127\u0128"+
-		"\7u\2\2\u0128\u0129\7g\2\2\u0129&\3\2\2\2\u012a\u012b\7y\2\2\u012b\u012c"+
-		"\7j\2\2\u012c\u012d\7k\2\2\u012d\u012e\7n\2\2\u012e\u012f\7g\2\2\u012f"+
-		"(\3\2\2\2\u0130\u0131\7f\2\2\u0131\u0132\7q\2\2\u0132*\3\2\2\2\u0133\u0134"+
-		"\7h\2\2\u0134\u0135\7q\2\2\u0135\u0136\7t\2\2\u0136,\3\2\2\2\u0137\u0138"+
-		"\7t\2\2\u0138\u0139\7g\2\2\u0139\u013a\7v\2\2\u013a\u013b\7w\2\2\u013b"+
-		"\u013c\7t\2\2\u013c\u013d\7p\2\2\u013d.\3\2\2\2\u013e\u013f\7d\2\2\u013f"+
-		"\u0140\7t\2\2\u0140\u0141\7g\2\2\u0141\u0142\7c\2\2\u0142\u0143\7m\2\2"+
-		"\u0143\60\3\2\2\2\u0144\u0145\7e\2\2\u0145\u0146\7q\2\2\u0146\u0147\7"+
-		"p\2\2\u0147\u0148\7v\2\2\u0148\u0149\7k\2\2\u0149\u014a\7p\2\2\u014a\u014b"+
-		"\7w\2\2\u014b\u014c\7g\2\2\u014c\62\3\2\2\2\u014d\u014e\7c\2\2\u014e\u014f"+
-		"\7u\2\2\u014f\u0150\7o\2\2\u0150\64\3\2\2\2\u0151\u0152\7<\2\2\u0152\66"+
-		"\3\2\2\2\u0153\u0154\7\60\2\2\u0154\u0155\7\60\2\2\u01558\3\2\2\2\u0156"+
-		"\u0157\7u\2\2\u0157\u0158\7k\2\2\u0158\u0159\7i\2\2\u0159\u015a\7p\2\2"+
-		"\u015a\u015b\7g\2\2\u015b\u015c\7f\2\2\u015c:\3\2\2\2\u015d\u015e\7w\2"+
-		"\2\u015e\u015f\7p\2\2\u015f\u0160\7u\2\2\u0160\u0161\7k\2\2\u0161\u0162"+
-		"\7i\2\2\u0162\u0163\7p\2\2\u0163\u0164\7g\2\2\u0164\u0165\7f\2\2\u0165"+
-		"<\3\2\2\2\u0166\u0167\7,\2\2\u0167>\3\2\2\2\u0168\u0169\7]\2\2\u0169@"+
-		"\3\2\2\2\u016a\u016b\7_\2\2\u016bB\3\2\2\2\u016c\u016d\7u\2\2\u016d\u016e"+
-		"\7v\2\2\u016e\u016f\7t\2\2\u016f\u0170\7w\2\2\u0170\u0171\7e\2\2\u0171"+
-		"\u0172\7v\2\2\u0172D\3\2\2\2\u0173\u0174\7u\2\2\u0174\u0175\7k\2\2\u0175"+
-		"\u0176\7|\2\2\u0176\u0177\7g\2\2\u0177\u0178\7q\2\2\u0178\u0179\7h\2\2"+
-		"\u0179F\3\2\2\2\u017a\u017b\7v\2\2\u017b\u017c\7{\2\2\u017c\u017d\7r\2"+
-		"\2\u017d\u017e\7g\2\2\u017e\u017f\7k\2\2\u017f\u0180\7f\2\2\u0180H\3\2"+
-		"\2\2\u0181\u0182\7/\2\2\u0182\u0183\7/\2\2\u0183J\3\2\2\2\u0184\u0185"+
-		"\7-\2\2\u0185\u0186\7-\2\2\u0186L\3\2\2\2\u0187\u0188\7-\2\2\u0188N\3"+
-		"\2\2\2\u0189\u018a\7/\2\2\u018aP\3\2\2\2\u018b\u018c\7#\2\2\u018cR\3\2"+
-		"\2\2\u018d\u018e\7(\2\2\u018eT\3\2\2\2\u018f\u0190\7\u0080\2\2\u0190V"+
-		"\3\2\2\2\u0191\u0192\7@\2\2\u0192\u0193\7@\2\2\u0193X\3\2\2\2\u0194\u0195"+
-		"\7>\2\2\u0195\u0196\7>\2\2\u0196Z\3\2\2\2\u0197\u0198\7\61\2\2\u0198\\"+
-		"\3\2\2\2\u0199\u019a\7\'\2\2\u019a^\3\2\2\2\u019b\u019c\7>\2\2\u019c`"+
-		"\3\2\2\2\u019d\u019e\7@\2\2\u019eb\3\2\2\2\u019f\u01a0\7?\2\2\u01a0\u01a1"+
-		"\7?\2\2\u01a1d\3\2\2\2\u01a2\u01a3\7#\2\2\u01a3\u01a4\7?\2\2\u01a4f\3"+
-		"\2\2\2\u01a5\u01a6\7>\2\2\u01a6\u01a7\7?\2\2\u01a7h\3\2\2\2\u01a8\u01a9"+
-		"\7@\2\2\u01a9\u01aa\7?\2\2\u01aaj\3\2\2\2\u01ab\u01ac\7`\2\2\u01acl\3"+
-		"\2\2\2\u01ad\u01ae\7~\2\2\u01aen\3\2\2\2\u01af\u01b0\7(\2\2\u01b0\u01b1"+
-		"\7(\2\2\u01b1p\3\2\2\2\u01b2\u01b3\7~\2\2\u01b3\u01b4\7~\2\2\u01b4r\3"+
-		"\2\2\2\u01b5\u01b6\7A\2\2\u01b6t\3\2\2\2\u01b7\u01b8\7-\2\2\u01b8\u01b9"+
-		"\7?\2\2\u01b9v\3\2\2\2\u01ba\u01bb\7/\2\2\u01bb\u01bc\7?\2\2\u01bcx\3"+
-		"\2\2\2\u01bd\u01be\7,\2\2\u01be\u01bf\7?\2\2\u01bfz\3\2\2\2\u01c0\u01c1"+
-		"\7\61\2\2\u01c1\u01c2\7?\2\2\u01c2|\3\2\2\2\u01c3\u01c4\7\'\2\2\u01c4"+
-		"\u01c5\7?\2\2\u01c5~\3\2\2\2\u01c6\u01c7\7>\2\2\u01c7\u01c8\7>\2\2\u01c8"+
-		"\u01c9\7?\2\2\u01c9\u0080\3\2\2\2\u01ca\u01cb\7@\2\2\u01cb\u01cc\7@\2"+
-		"\2\u01cc\u01cd\7?\2\2\u01cd\u0082\3\2\2\2\u01ce\u01cf\7(\2\2\u01cf\u01d0"+
-		"\7?\2\2\u01d0\u0084\3\2\2\2\u01d1\u01d2\7~\2\2\u01d2\u01d3\7?\2\2\u01d3"+
-		"\u0086\3\2\2\2\u01d4\u01d5\7`\2\2\u01d5\u01d6\7?\2\2\u01d6\u0088\3\2\2"+
-		"\2\u01d7\u01d8\7m\2\2\u01d8\u01d9\7k\2\2\u01d9\u01da\7e\2\2\u01da\u01db"+
-		"\7m\2\2\u01db\u01dc\7c\2\2\u01dc\u01dd\7u\2\2\u01dd\u01de\7o\2\2\u01de"+
-		"\u008a\3\2\2\2\u01df\u01e0\7t\2\2\u01e0\u01e1\7g\2\2\u01e1\u01e2\7u\2"+
-		"\2\u01e2\u01e3\7q\2\2\u01e3\u01e4\7w\2\2\u01e4\u01e5\7t\2\2\u01e5\u01e6"+
-		"\7e\2\2\u01e6\u01e7\7g\2\2\u01e7\u008c\3\2\2\2\u01e8\u01e9\7w\2\2\u01e9"+
-		"\u01ea\7u\2\2\u01ea\u01eb\7g\2\2\u01eb\u01ec\7u\2\2\u01ec\u008e\3\2\2"+
-		"\2\u01ed\u01ee\7e\2\2\u01ee\u01ef\7n\2\2\u01ef\u01f0\7q\2\2\u01f0\u01f1"+
-		"\7d\2\2\u01f1\u01f2\7d\2\2\u01f2\u01f3\7g\2\2\u01f3\u01f4\7t\2\2\u01f4"+
-		"\u01f5\7u\2\2\u01f5\u0090\3\2\2\2\u01f6\u01f7\7d\2\2\u01f7\u01f8\7{\2"+
-		"\2\u01f8\u01f9\7v\2\2\u01f9\u01fa\7g\2\2\u01fa\u01fb\7u\2\2\u01fb\u0092"+
-		"\3\2\2\2\u01fc\u01fd\7e\2\2\u01fd\u01fe\7{\2\2\u01fe\u01ff\7e\2\2\u01ff"+
-		"\u0200\7n\2\2\u0200\u0201\7g\2\2\u0201\u0202\7u\2\2\u0202\u0094\3\2\2"+
-		"\2\u0203\u0204\7r\2\2\u0204\u0205\7e\2\2\u0205\u0096\3\2\2\2\u0206\u0207"+
-		"\7\60\2\2\u0207\u0208\7d\2\2\u0208\u0209\7{\2\2\u0209\u020a\7v\2\2\u020a"+
-		"\u020b\7g\2\2\u020b\u0098\3\2\2\2\u020c\u020d\7%\2\2\u020d\u009a\3\2\2"+
-		"\2\u020e\u020f\7\60\2\2\u020f\u009c\3\2\2\2\u0210\u0211\7d\2\2\u0211\u0212"+
-		"\7t\2\2\u0212\u02ef\7m\2\2\u0213\u0214\7q\2\2\u0214\u0215\7t\2\2\u0215"+
-		"\u02ef\7c\2\2\u0216\u0217\7m\2\2\u0217\u0218\7k\2\2\u0218\u02ef\7n\2\2"+
-		"\u0219\u021a\7u\2\2\u021a\u021b\7n\2\2\u021b\u02ef\7q\2\2\u021c\u021d"+
-		"\7p\2\2\u021d\u021e\7q\2\2\u021e\u02ef\7r\2\2\u021f\u0220\7c\2\2\u0220"+
-		"\u0221\7u\2\2\u0221\u02ef\7n\2\2\u0222\u0223\7r\2\2\u0223\u0224\7j\2\2"+
-		"\u0224\u02ef\7r\2\2\u0225\u0226\7c\2\2\u0226\u0227\7p\2\2\u0227\u02ef"+
-		"\7e\2\2\u0228\u0229\7d\2\2\u0229\u022a\7r\2\2\u022a\u02ef\7n\2\2\u022b"+
-		"\u022c\7e\2\2\u022c\u022d\7n\2\2\u022d\u02ef\7e\2\2\u022e\u022f\7l\2\2"+
-		"\u022f\u0230\7u\2\2\u0230\u02ef\7t\2\2\u0231\u0232\7c\2\2\u0232\u0233"+
-		"\7p\2\2\u0233\u02ef\7f\2\2\u0234\u0235\7t\2\2\u0235\u0236\7n\2\2\u0236"+
-		"\u02ef\7c\2\2\u0237\u0238\7d\2\2\u0238\u0239\7k\2\2\u0239\u02ef\7v\2\2"+
-		"\u023a\u023b\7t\2\2\u023b\u023c\7q\2\2\u023c\u02ef\7n\2\2\u023d\u023e"+
-		"\7r\2\2\u023e\u023f\7n\2\2\u023f\u02ef\7c\2\2\u0240\u0241\7r\2\2\u0241"+
-		"\u0242\7n\2\2\u0242\u02ef\7r\2\2\u0243\u0244\7d\2\2\u0244\u0245\7o\2\2"+
-		"\u0245\u02ef\7k\2\2\u0246\u0247\7u\2\2\u0247\u0248\7g\2\2\u0248\u02ef"+
-		"\7e\2\2\u0249\u024a\7t\2\2\u024a\u024b\7v\2\2\u024b\u02ef\7k\2\2\u024c"+
-		"\u024d\7g\2\2\u024d\u024e\7q\2\2\u024e\u02ef\7t\2\2\u024f\u0250\7u\2\2"+
-		"\u0250\u0251\7t\2\2\u0251\u02ef\7g\2\2\u0252\u0253\7n\2\2\u0253\u0254"+
-		"\7u\2\2\u0254\u02ef\7t\2\2\u0255\u0256\7r\2\2\u0256\u0257\7j\2\2\u0257"+
-		"\u02ef\7c\2\2\u0258\u0259\7c\2\2\u0259\u025a\7n\2\2\u025a\u02ef\7t\2\2"+
-		"\u025b\u025c\7l\2\2\u025c\u025d\7o\2\2\u025d\u02ef\7r\2\2\u025e\u025f"+
-		"\7d\2\2\u025f\u0260\7x\2\2\u0260\u02ef\7e\2\2\u0261\u0262\7e\2\2\u0262"+
-		"\u0263\7n\2\2\u0263\u02ef\7k\2\2\u0264\u0265\7t\2\2\u0265\u0266\7v\2\2"+
-		"\u0266\u02ef\7u\2\2\u0267\u0268\7c\2\2\u0268\u0269\7f\2\2\u0269\u02ef"+
-		"\7e\2\2\u026a\u026b\7t\2\2\u026b\u026c\7t\2\2\u026c\u02ef\7c\2\2\u026d"+
-		"\u026e\7d\2\2\u026e\u026f\7x\2\2\u026f\u02ef\7u\2\2\u0270\u0271\7u\2\2"+
-		"\u0271\u0272\7g\2\2\u0272\u02ef\7k\2\2\u0273\u0274\7u\2\2\u0274\u0275"+
-		"\7c\2\2\u0275\u02ef\7z\2\2\u0276\u0277\7u\2\2\u0277\u0278\7v\2\2\u0278"+
-		"\u02ef\7{\2\2\u0279\u027a\7u\2\2\u027a\u027b\7v\2\2\u027b\u02ef\7c\2\2"+
-		"\u027c\u027d\7u\2\2\u027d\u027e\7v\2\2\u027e\u02ef\7z\2\2\u027f\u0280"+
-		"\7f\2\2\u0280\u0281\7g\2\2\u0281\u02ef\7{\2\2\u0282\u0283\7v\2\2\u0283"+
-		"\u0284\7z\2\2\u0284\u02ef\7c\2\2\u0285\u0286\7z\2\2\u0286\u0287\7c\2\2"+
-		"\u0287\u02ef\7c\2\2\u0288\u0289\7d\2\2\u0289\u028a\7e\2\2\u028a\u02ef"+
-		"\7e\2\2\u028b\u028c\7c\2\2\u028c\u028d\7j\2\2\u028d\u02ef\7z\2\2\u028e"+
-		"\u028f\7v\2\2\u028f\u0290\7{\2\2\u0290\u02ef\7c\2\2\u0291\u0292\7v\2\2"+
-		"\u0292\u0293\7z\2\2\u0293\u02ef\7u\2\2\u0294\u0295\7v\2\2\u0295\u0296"+
-		"\7c\2\2\u0296\u02ef\7u\2\2\u0297\u0298\7u\2\2\u0298\u0299\7j\2\2\u0299"+
-		"\u02ef\7{\2\2\u029a\u029b\7u\2\2\u029b\u029c\7j\2\2\u029c\u02ef\7z\2\2"+
-		"\u029d\u029e\7n\2\2\u029e\u029f\7f\2\2\u029f\u02ef\7{\2\2\u02a0\u02a1"+
-		"\7n\2\2\u02a1\u02a2\7f\2\2\u02a2\u02ef\7c\2\2\u02a3\u02a4\7n\2\2\u02a4"+
-		"\u02a5\7f\2\2\u02a5\u02ef\7z\2\2\u02a6\u02a7\7n\2\2\u02a7\u02a8\7c\2\2"+
-		"\u02a8\u02ef\7z\2\2\u02a9\u02aa\7v\2\2\u02aa\u02ab\7c\2\2\u02ab\u02ef"+
-		"\7{\2\2\u02ac\u02ad\7v\2\2\u02ad\u02ae\7c\2\2\u02ae\u02ef\7z\2\2\u02af"+
-		"\u02b0\7d\2\2\u02b0\u02b1\7e\2\2\u02b1\u02ef\7u\2\2\u02b2\u02b3\7e\2\2"+
-		"\u02b3\u02b4\7n\2\2\u02b4\u02ef\7x\2\2\u02b5\u02b6\7v\2\2\u02b6\u02b7"+
-		"\7u\2\2\u02b7\u02ef\7z\2\2\u02b8\u02b9\7n\2\2\u02b9\u02ba\7c\2\2\u02ba"+
-		"\u02ef\7u\2\2\u02bb\u02bc\7e\2\2\u02bc\u02bd\7r\2\2\u02bd\u02ef\7{\2\2"+
-		"\u02be\u02bf\7e\2\2\u02bf\u02c0\7o\2\2\u02c0\u02ef\7r\2\2\u02c1\u02c2"+
-		"\7e\2\2\u02c2\u02c3\7r\2\2\u02c3\u02ef\7z\2\2\u02c4\u02c5\7f\2\2\u02c5"+
-		"\u02c6\7e\2\2\u02c6\u02ef\7r\2\2\u02c7\u02c8\7f\2\2\u02c8\u02c9\7g\2\2"+
-		"\u02c9\u02ef\7e\2\2\u02ca\u02cb\7k\2\2\u02cb\u02cc\7p\2\2\u02cc\u02ef"+
-		"\7e\2\2\u02cd\u02ce\7c\2\2\u02ce\u02cf\7z\2\2\u02cf\u02ef\7u\2\2\u02d0"+
-		"\u02d1\7d\2\2\u02d1\u02d2\7p\2\2\u02d2\u02ef\7g\2\2\u02d3\u02d4\7e\2\2"+
-		"\u02d4\u02d5\7n\2\2\u02d5\u02ef\7f\2\2\u02d6\u02d7\7u\2\2\u02d7\u02d8"+
-		"\7d\2\2\u02d8\u02ef\7e\2\2\u02d9\u02da\7k\2\2\u02da\u02db\7u\2\2\u02db"+
-		"\u02ef\7e\2\2\u02dc\u02dd\7k\2\2\u02dd\u02de\7p\2\2\u02de\u02ef\7z\2\2"+
-		"\u02df\u02e0\7d\2\2\u02e0\u02e1\7g\2\2\u02e1\u02ef\7s\2\2\u02e2\u02e3"+
-		"\7u\2\2\u02e3\u02e4\7g\2\2\u02e4\u02ef\7f\2\2\u02e5\u02e6\7f\2\2\u02e6"+
-		"\u02e7\7g\2\2\u02e7\u02ef\7z\2\2\u02e8\u02e9\7k\2\2\u02e9\u02ea\7p\2\2"+
-		"\u02ea\u02ef\7{\2\2\u02eb\u02ec\7t\2\2\u02ec\u02ed\7q\2\2\u02ed\u02ef"+
-		"\7t\2\2\u02ee\u0210\3\2\2\2\u02ee\u0213\3\2\2\2\u02ee\u0216\3\2\2\2\u02ee"+
-		"\u0219\3\2\2\2\u02ee\u021c\3\2\2\2\u02ee\u021f\3\2\2\2\u02ee\u0222\3\2"+
-		"\2\2\u02ee\u0225\3\2\2\2\u02ee\u0228\3\2\2\2\u02ee\u022b\3\2\2\2\u02ee"+
-		"\u022e\3\2\2\2\u02ee\u0231\3\2\2\2\u02ee\u0234\3\2\2\2\u02ee\u0237\3\2"+
-		"\2\2\u02ee\u023a\3\2\2\2\u02ee\u023d\3\2\2\2\u02ee\u0240\3\2\2\2\u02ee"+
-		"\u0243\3\2\2\2\u02ee\u0246\3\2\2\2\u02ee\u0249\3\2\2\2\u02ee\u024c\3\2"+
-		"\2\2\u02ee\u024f\3\2\2\2\u02ee\u0252\3\2\2\2\u02ee\u0255\3\2\2\2\u02ee"+
-		"\u0258\3\2\2\2\u02ee\u025b\3\2\2\2\u02ee\u025e\3\2\2\2\u02ee\u0261\3\2"+
-		"\2\2\u02ee\u0264\3\2\2\2\u02ee\u0267\3\2\2\2\u02ee\u026a\3\2\2\2\u02ee"+
-		"\u026d\3\2\2\2\u02ee\u0270\3\2\2\2\u02ee\u0273\3\2\2\2\u02ee\u0276\3\2"+
-		"\2\2\u02ee\u0279\3\2\2\2\u02ee\u027c\3\2\2\2\u02ee\u027f\3\2\2\2\u02ee"+
-		"\u0282\3\2\2\2\u02ee\u0285\3\2\2\2\u02ee\u0288\3\2\2\2\u02ee\u028b\3\2"+
-		"\2\2\u02ee\u028e\3\2\2\2\u02ee\u0291\3\2\2\2\u02ee\u0294\3\2\2\2\u02ee"+
-		"\u0297\3\2\2\2\u02ee\u029a\3\2\2\2\u02ee\u029d\3\2\2\2\u02ee\u02a0\3\2"+
-		"\2\2\u02ee\u02a3\3\2\2\2\u02ee\u02a6\3\2\2\2\u02ee\u02a9\3\2\2\2\u02ee"+
-		"\u02ac\3\2\2\2\u02ee\u02af\3\2\2\2\u02ee\u02b2\3\2\2\2\u02ee\u02b5\3\2"+
-		"\2\2\u02ee\u02b8\3\2\2\2\u02ee\u02bb\3\2\2\2\u02ee\u02be\3\2\2\2\u02ee"+
-		"\u02c1\3\2\2\2\u02ee\u02c4\3\2\2\2\u02ee\u02c7\3\2\2\2\u02ee\u02ca\3\2"+
-		"\2\2\u02ee\u02cd\3\2\2\2\u02ee\u02d0\3\2\2\2\u02ee\u02d3\3\2\2\2\u02ee"+
-		"\u02d6\3\2\2\2\u02ee\u02d9\3\2\2\2\u02ee\u02dc\3\2\2\2\u02ee\u02df\3\2"+
-		"\2\2\u02ee\u02e2\3\2\2\2\u02ee\u02e5\3\2\2\2\u02ee\u02e8\3\2\2\2\u02ee"+
-		"\u02eb\3\2\2\2\u02ef\u009e\3\2\2\2\u02f0\u02f1\7}\2\2\u02f1\u02f2\7}\2"+
-		"\2\u02f2\u02f6\3\2\2\2\u02f3\u02f5\13\2\2\2\u02f4\u02f3\3\2\2\2\u02f5"+
-		"\u02f8\3\2\2\2\u02f6\u02f7\3\2\2\2\u02f6\u02f4\3\2\2\2\u02f7\u02f9\3\2"+
-		"\2\2\u02f8\u02f6\3\2\2\2\u02f9\u02fa\7\177\2\2\u02fa\u02fb\7\177\2\2\u02fb"+
-		"\u00a0\3\2\2\2\u02fc\u02fd\7d\2\2\u02fd\u02fe\7{\2\2\u02fe\u02ff\7v\2"+
-		"\2\u02ff\u0322\7g\2\2\u0300\u0301\7y\2\2\u0301\u0302\7q\2\2\u0302\u0303"+
-		"\7t\2\2\u0303\u0322\7f\2\2\u0304\u0305\7f\2\2\u0305\u0306\7y\2\2\u0306"+
-		"\u0307\7q\2\2\u0307\u0308\7t\2\2\u0308\u0322\7f\2\2\u0309\u030a\7d\2\2"+
-		"\u030a\u030b\7q\2\2\u030b\u030c\7q\2\2\u030c\u0322\7n\2\2\u030d\u030e"+
-		"\7e\2\2\u030e\u030f\7j\2\2\u030f\u0310\7c\2\2\u0310\u0322\7t\2\2\u0311"+
-		"\u0312\7u\2\2\u0312\u0313\7j\2\2\u0313\u0314\7q\2\2\u0314\u0315\7t\2\2"+
-		"\u0315\u0322\7v\2\2\u0316\u0317\7k\2\2\u0317\u0318\7p\2\2\u0318\u0322"+
-		"\7v\2\2\u0319\u031a\7n\2\2\u031a\u031b\7q\2\2\u031b\u031c\7p\2\2\u031c"+
-		"\u0322\7i\2\2\u031d\u031e\7x\2\2\u031e\u031f\7q\2\2\u031f\u0320\7k\2\2"+
-		"\u0320\u0322\7f\2\2\u0321\u02fc\3\2\2\2\u0321\u0300\3\2\2\2\u0321\u0304"+
-		"\3\2\2\2\u0321\u0309\3\2\2\2\u0321\u030d\3\2\2\2\u0321\u0311\3\2\2\2\u0321"+
-		"\u0316\3\2\2\2\u0321\u0319\3\2\2\2\u0321\u031d\3\2\2\2\u0322\u00a2\3\2"+
-		"\2\2\u0323\u0329\7$\2\2\u0324\u0325\7^\2\2\u0325\u0328\7$\2\2\u0326\u0328"+
-		"\n\2\2\2\u0327\u0324\3\2\2\2\u0327\u0326\3\2\2\2\u0328\u032b\3\2\2\2\u0329"+
-		"\u0327\3\2\2\2\u0329\u032a\3\2\2\2\u032a\u032c\3\2\2\2\u032b\u0329\3\2"+
-		"\2\2\u032c\u032e\7$\2\2\u032d\u032f\7|\2\2\u032e\u032d\3\2\2\2\u032e\u032f"+
-		"\3\2\2\2\u032f\u00a4\3\2\2\2\u0330\u0334\7)\2\2\u0331\u0332\7^\2\2\u0332"+
-		"\u0335\7)\2\2\u0333\u0335\n\3\2\2\u0334\u0331\3\2\2\2\u0334\u0333\3\2"+
-		"\2\2\u0335\u0336\3\2\2\2\u0336\u0337\7)\2\2\u0337\u00a6\3\2\2\2\u0338"+
-		"\u0339\7v\2\2\u0339\u033a\7t\2\2\u033a\u033b\7w\2\2\u033b\u0342\7g\2\2"+
-		"\u033c\u033d\7h\2\2\u033d\u033e\7c\2\2\u033e\u033f\7n\2\2\u033f\u0340"+
-		"\7u\2\2\u0340\u0342\7g\2\2\u0341\u0338\3\2\2\2\u0341\u033c\3\2\2\2\u0342"+
-		"\u00a8\3\2\2\2\u0343\u0346\5\u00abV\2\u0344\u0346\5\u00b3Z\2\u0345\u0343"+
-		"\3\2\2\2\u0345\u0344\3\2\2\2\u0346\u00aa\3\2\2\2\u0347\u034b\5\u00adW"+
-		"\2\u0348\u034b\5\u00afX\2\u0349\u034b\5\u00b1Y\2\u034a\u0347\3\2\2\2\u034a"+
-		"\u0348\3\2\2\2\u034a\u0349\3\2\2\2\u034b\u00ac\3\2\2\2\u034c\u0352\7\'"+
-		"\2\2\u034d\u034e\7\62\2\2\u034e\u0352\7d\2\2\u034f\u0350\7\62\2\2\u0350"+
-		"\u0352\7D\2\2\u0351\u034c\3\2\2\2\u0351\u034d\3\2\2\2\u0351\u034f\3\2"+
-		"\2\2\u0352\u0356\3\2\2\2\u0353\u0355\5\u00bb^\2\u0354\u0353\3\2\2\2\u0355"+
-		"\u0358\3\2\2\2\u0356\u0354\3\2\2\2\u0356\u0357\3\2\2\2\u0357\u0359\3\2"+
-		"\2\2\u0358\u0356\3\2\2\2\u0359\u035b\7\60\2\2\u035a\u035c\5\u00bb^\2\u035b"+
-		"\u035a\3\2\2\2\u035c\u035d\3\2\2\2\u035d\u035b\3\2\2\2\u035d\u035e\3\2"+
-		"\2\2\u035e\u00ae\3\2\2\2\u035f\u0361\5\u00bd_\2\u0360\u035f\3\2\2\2\u0361"+
-		"\u0364\3\2\2\2\u0362\u0360\3\2\2\2\u0362\u0363\3\2\2\2\u0363\u0365\3\2"+
-		"\2\2\u0364\u0362\3\2\2\2\u0365\u0367\7\60\2\2\u0366\u0368\5\u00bd_\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\u00b0\3\2\2\2\u036b\u0371\7&\2\2\u036c\u036d\7\62\2\2\u036d"+
-		"\u0371\7z\2\2\u036e\u036f\7\62\2\2\u036f\u0371\7Z\2\2\u0370\u036b\3\2"+
-		"\2\2\u0370\u036c\3\2\2\2\u0370\u036e\3\2\2\2\u0371\u0375\3\2\2\2\u0372"+
-		"\u0374\5\u00bf`\2\u0373\u0372\3\2\2\2\u0374\u0377\3\2\2\2\u0375\u0373"+
-		"\3\2\2\2\u0375\u0376\3\2\2\2\u0376\u0378\3\2\2\2\u0377\u0375\3\2\2\2\u0378"+
-		"\u037a\7\60\2\2\u0379\u037b\5\u00bf`\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"+
-		"\u0382\5\u00b7\\\2\u037f\u0382\5\u00b9]\2\u0380\u0382\5\u00b5[\2\u0381"+
-		"\u037e\3\2\2\2\u0381\u037f\3\2\2\2\u0381\u0380\3\2\2\2\u0382\u0386\3\2"+
-		"\2\2\u0383\u0384\t\4\2\2\u0384\u0387\t\5\2\2\u0385\u0387\7n\2\2\u0386"+
-		"\u0383\3\2\2\2\u0386\u0385\3\2\2\2\u0386\u0387\3\2\2\2\u0387\u00b4\3\2"+
-		"\2\2\u0388\u0389\7\62\2\2\u0389\u038b\t\6\2\2\u038a\u038c\5\u00bb^\2\u038b"+
-		"\u038a\3\2\2\2\u038c\u038d\3\2\2\2\u038d\u038b\3\2\2\2\u038d\u038e\3\2"+
-		"\2\2\u038e\u0396\3\2\2\2\u038f\u0391\7\'\2\2\u0390\u0392\5\u00bb^\2\u0391"+
-		"\u0390\3\2\2\2\u0392\u0393\3\2\2\2\u0393\u0391\3\2\2\2\u0393\u0394\3\2"+
-		"\2\2\u0394\u0396\3\2\2\2\u0395\u0388\3\2\2\2\u0395\u038f\3\2\2\2\u0396"+
-		"\u00b6\3\2\2\2\u0397\u0399\5\u00bd_\2\u0398\u0397\3\2\2\2\u0399\u039a"+
-		"\3\2\2\2\u039a\u0398\3\2\2\2\u039a\u039b\3\2\2\2\u039b\u00b8\3\2\2\2\u039c"+
-		"\u03a2\7&\2\2\u039d\u039e\7\62\2\2\u039e\u03a2\7z\2\2\u039f\u03a0\7\62"+
-		"\2\2\u03a0\u03a2\7Z\2\2\u03a1\u039c\3\2\2\2\u03a1\u039d\3\2\2\2\u03a1"+
-		"\u039f\3\2\2\2\u03a2\u03a4\3\2\2\2\u03a3\u03a5\5\u00bf`\2\u03a4\u03a3"+
-		"\3\2\2\2\u03a5\u03a6\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a6\u03a7\3\2\2\2\u03a7"+
-		"\u00ba\3\2\2\2\u03a8\u03a9\t\7\2\2\u03a9\u00bc\3\2\2\2\u03aa\u03ab\t\b"+
-		"\2\2\u03ab\u00be\3\2\2\2\u03ac\u03ad\t\t\2\2\u03ad\u00c0\3\2\2\2\u03ae"+
-		"\u03b2\5\u00c3b\2\u03af\u03b1\5\u00c5c\2\u03b0\u03af\3\2\2\2\u03b1\u03b4"+
-		"\3\2\2\2\u03b2\u03b0\3\2\2\2\u03b2\u03b3\3\2\2\2\u03b3\u00c2\3\2\2\2\u03b4"+
-		"\u03b2\3\2\2\2\u03b5\u03b6\t\n\2\2\u03b6\u00c4\3\2\2\2\u03b7\u03b8\t\13"+
-		"\2\2\u03b8\u00c6\3\2\2\2\u03b9\u03bd\7#\2\2\u03ba\u03bc\5\u00c5c\2\u03bb"+
-		"\u03ba\3\2\2\2\u03bc\u03bf\3\2\2\2\u03bd\u03bb\3\2\2\2\u03bd\u03be\3\2"+
-		"\2\2\u03be\u03c1\3\2\2\2\u03bf\u03bd\3\2\2\2\u03c0\u03c2\t\f\2\2\u03c1"+
-		"\u03c0\3\2\2\2\u03c2\u03c3\3\2\2\2\u03c3\u03c1\3\2\2\2\u03c3\u03c4\3\2"+
-		"\2\2\u03c4\u00c8\3\2\2\2\u03c5\u03c7\t\r\2\2\u03c6\u03c5\3\2\2\2\u03c7"+
-		"\u03c8\3\2\2\2\u03c8\u03c6\3\2\2\2\u03c8\u03c9\3\2\2\2\u03c9\u03ca\3\2"+
-		"\2\2\u03ca\u03cb\be\2\2\u03cb\u00ca\3\2\2\2\u03cc\u03cd\7\61\2\2\u03cd"+
-		"\u03ce\7\61\2\2\u03ce\u03d2\3\2\2\2\u03cf\u03d1\n\16\2\2\u03d0\u03cf\3"+
-		"\2\2\2\u03d1\u03d4\3\2\2\2\u03d2\u03d0\3\2\2\2\u03d2\u03d3\3\2\2\2\u03d3"+
-		"\u03d5\3\2\2\2\u03d4\u03d2\3\2\2\2\u03d5\u03d6\bf\3\2\u03d6\u00cc\3\2"+
-		"\2\2\u03d7\u03d8\7\61\2\2\u03d8\u03d9\7,\2\2\u03d9\u03dd\3\2\2\2\u03da"+
-		"\u03dc\13\2\2\2\u03db\u03da\3\2\2\2\u03dc\u03df\3\2\2\2\u03dd\u03de\3"+
-		"\2\2\2\u03dd\u03db\3\2\2\2\u03de\u03e0\3\2\2\2\u03df\u03dd\3\2\2\2\u03e0"+
-		"\u03e1\7,\2\2\u03e1\u03e2\7\61\2\2\u03e2\u03e3\3\2\2\2\u03e3\u03e4\bg"+
-		"\3\2\u03e4\u00ce\3\2\2\2#\2\u02ee\u02f6\u0321\u0327\u0329\u032e\u0334"+
-		"\u0341\u0345\u034a\u0351\u0356\u035d\u0362\u0369\u0370\u0375\u037c\u0381"+
-		"\u0386\u038d\u0393\u0395\u039a\u03a1\u03a6\u03b2\u03bd\u03c3\u03c8\u03d2"+
-		"\u03dd\4\2\3\2\2\4\2";
+		"`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\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\21\3\21\3\21\3\21"+
+		"\3\21\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24"+
+		"\3\24\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\27\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\31\3\31\3\31\3\31\3\31\3\31\3\31"+
+		"\3\31\3\31\3\32\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35"+
+		"\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3\36\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*\3+"+
+		"\3+\3,\3,\3-\3-\3.\3.\3.\3/\3/\3/\3\60\3\60\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\66\3\67\3\67\3\67\38\38"+
+		"\39\39\3:\3:\3:\3;\3;\3;\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?\3?\3@\3@\3@\3A"+
+		"\3A\3A\3B\3B\3B\3B\3C\3C\3C\3C\3D\3D\3D\3E\3E\3E\3F\3F\3F\3G\3G\3G\3G"+
+		"\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3J\3J\3J\3J\3J"+
+		"\3J\3J\3J\3J\3K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3L\3L\3M\3M\3M\3N\3N\3N"+
+		"\3N\3N\3N\3O\3O\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P"+
+		"\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\3P\5P\u02f4"+
+		"\nP\3Q\3Q\3Q\3Q\7Q\u02fa\nQ\fQ\16Q\u02fd\13Q\3Q\3Q\3Q\3R\3R\3R\3R\3R\3"+
+		"R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3R\3"+
+		"R\3R\3R\3R\3R\3R\3R\3R\3R\5R\u0327\nR\3S\3S\3S\3S\7S\u032d\nS\fS\16S\u0330"+
+		"\13S\3S\3S\5S\u0334\nS\3T\3T\3T\3T\5T\u033a\nT\3T\3T\3U\3U\3U\3U\3U\3"+
+		"U\3U\3U\3U\5U\u0347\nU\3V\3V\5V\u034b\nV\3W\3W\3W\5W\u0350\nW\3X\3X\3"+
+		"X\3X\3X\5X\u0357\nX\3X\7X\u035a\nX\fX\16X\u035d\13X\3X\3X\6X\u0361\nX"+
+		"\rX\16X\u0362\3Y\7Y\u0366\nY\fY\16Y\u0369\13Y\3Y\3Y\6Y\u036d\nY\rY\16"+
+		"Y\u036e\3Z\3Z\3Z\3Z\3Z\5Z\u0376\nZ\3Z\7Z\u0379\nZ\fZ\16Z\u037c\13Z\3Z"+
+		"\3Z\6Z\u0380\nZ\rZ\16Z\u0381\3[\3[\3[\5[\u0387\n[\3[\3[\3[\5[\u038c\n"+
+		"[\3\\\3\\\3\\\6\\\u0391\n\\\r\\\16\\\u0392\3\\\3\\\6\\\u0397\n\\\r\\\16"+
+		"\\\u0398\5\\\u039b\n\\\3]\6]\u039e\n]\r]\16]\u039f\3^\3^\3^\3^\3^\5^\u03a7"+
+		"\n^\3^\6^\u03aa\n^\r^\16^\u03ab\3_\3_\3`\3`\3a\3a\3b\3b\7b\u03b6\nb\f"+
+		"b\16b\u03b9\13b\3c\3c\3d\3d\3e\3e\7e\u03c1\ne\fe\16e\u03c4\13e\3e\6e\u03c7"+
+		"\ne\re\16e\u03c8\3f\6f\u03cc\nf\rf\16f\u03cd\3f\3f\3g\3g\3g\3g\7g\u03d6"+
+		"\ng\fg\16g\u03d9\13g\3g\3g\3h\3h\3h\3h\7h\u03e1\nh\fh\16h\u03e4\13h\3"+
+		"h\3h\3h\3h\3h\4\u02fb\u03e2\2i\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_\61"+
+		"a\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"+
+		"Y\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd\2\u00bf\2\u00c1\2\u00c3"+
+		"`\u00c5\2\u00c7\2\u00c9a\u00cbb\u00cdc\u00cfd\3\2\17\3\2$$\3\2))\4\2u"+
+		"uww\7\2dfkknnuuyy\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\u0459"+
+		"\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2"+
+		"\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2"+
+		"\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2"+
+		"\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2"+
+		"\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3"+
+		"\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2"+
+		"\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2"+
+		"U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3"+
+		"\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2"+
+		"\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2"+
+		"{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085"+
+		"\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2"+
+		"\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097"+
+		"\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2"+
+		"\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9"+
+		"\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2"+
+		"\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb"+
+		"\3\2\2\2\2\u00c3\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2"+
+		"\2\2\u00cf\3\2\2\2\3\u00d1\3\2\2\2\5\u00d8\3\2\2\2\7\u00da\3\2\2\2\t\u00dc"+
+		"\3\2\2\2\13\u00de\3\2\2\2\r\u00e0\3\2\2\2\17\u00e2\3\2\2\2\21\u00e4\3"+
+		"\2\2\2\23\u00e6\3\2\2\2\25\u00ec\3\2\2\2\27\u00f3\3\2\2\2\31\u00f9\3\2"+
+		"\2\2\33\u0102\3\2\2\2\35\u0109\3\2\2\2\37\u0112\3\2\2\2!\u011c\3\2\2\2"+
+		"#\u0124\3\2\2\2%\u0127\3\2\2\2\'\u012c\3\2\2\2)\u0132\3\2\2\2+\u0135\3"+
+		"\2\2\2-\u0139\3\2\2\2/\u0140\3\2\2\2\61\u0146\3\2\2\2\63\u014f\3\2\2\2"+
+		"\65\u0153\3\2\2\2\67\u0155\3\2\2\29\u0158\3\2\2\2;\u015f\3\2\2\2=\u0168"+
+		"\3\2\2\2?\u016a\3\2\2\2A\u016c\3\2\2\2C\u016e\3\2\2\2E\u0175\3\2\2\2G"+
+		"\u0177\3\2\2\2I\u017a\3\2\2\2K\u0181\3\2\2\2M\u0188\3\2\2\2O\u018b\3\2"+
+		"\2\2Q\u018e\3\2\2\2S\u0190\3\2\2\2U\u0192\3\2\2\2W\u0194\3\2\2\2Y\u0196"+
+		"\3\2\2\2[\u0198\3\2\2\2]\u019b\3\2\2\2_\u019e\3\2\2\2a\u01a0\3\2\2\2c"+
+		"\u01a2\3\2\2\2e\u01a4\3\2\2\2g\u01a6\3\2\2\2i\u01a9\3\2\2\2k\u01ac\3\2"+
+		"\2\2m\u01af\3\2\2\2o\u01b2\3\2\2\2q\u01b4\3\2\2\2s\u01b6\3\2\2\2u\u01b9"+
+		"\3\2\2\2w\u01bc\3\2\2\2y\u01be\3\2\2\2{\u01c1\3\2\2\2}\u01c4\3\2\2\2\177"+
+		"\u01c7\3\2\2\2\u0081\u01ca\3\2\2\2\u0083\u01cd\3\2\2\2\u0085\u01d1\3\2"+
+		"\2\2\u0087\u01d5\3\2\2\2\u0089\u01d8\3\2\2\2\u008b\u01db\3\2\2\2\u008d"+
+		"\u01de\3\2\2\2\u008f\u01e6\3\2\2\2\u0091\u01ef\3\2\2\2\u0093\u01f4\3\2"+
+		"\2\2\u0095\u01fd\3\2\2\2\u0097\u0203\3\2\2\2\u0099\u020a\3\2\2\2\u009b"+
+		"\u020d\3\2\2\2\u009d\u0213\3\2\2\2\u009f\u02f3\3\2\2\2\u00a1\u02f5\3\2"+
+		"\2\2\u00a3\u0326\3\2\2\2\u00a5\u0328\3\2\2\2\u00a7\u0335\3\2\2\2\u00a9"+
+		"\u0346\3\2\2\2\u00ab\u034a\3\2\2\2\u00ad\u034f\3\2\2\2\u00af\u0356\3\2"+
+		"\2\2\u00b1\u0367\3\2\2\2\u00b3\u0375\3\2\2\2\u00b5\u0386\3\2\2\2\u00b7"+
+		"\u039a\3\2\2\2\u00b9\u039d\3\2\2\2\u00bb\u03a6\3\2\2\2\u00bd\u03ad\3\2"+
+		"\2\2\u00bf\u03af\3\2\2\2\u00c1\u03b1\3\2\2\2\u00c3\u03b3\3\2\2\2\u00c5"+
+		"\u03ba\3\2\2\2\u00c7\u03bc\3\2\2\2\u00c9\u03be\3\2\2\2\u00cb\u03cb\3\2"+
+		"\2\2\u00cd\u03d1\3\2\2\2\u00cf\u03dc\3\2\2\2\u00d1\u00d2\7k\2\2\u00d2"+
+		"\u00d3\7o\2\2\u00d3\u00d4\7r\2\2\u00d4\u00d5\7q\2\2\u00d5\u00d6\7t\2\2"+
+		"\u00d6\u00d7\7v\2\2\u00d7\4\3\2\2\2\u00d8\u00d9\7=\2\2\u00d9\6\3\2\2\2"+
+		"\u00da\u00db\7.\2\2\u00db\b\3\2\2\2\u00dc\u00dd\7?\2\2\u00dd\n\3\2\2\2"+
+		"\u00de\u00df\7*\2\2\u00df\f\3\2\2\2\u00e0\u00e1\7+\2\2\u00e1\16\3\2\2"+
+		"\2\u00e2\u00e3\7}\2\2\u00e3\20\3\2\2\2\u00e4\u00e5\7\177\2\2\u00e5\22"+
+		"\3\2\2\2\u00e6\u00e7\7e\2\2\u00e7\u00e8\7q\2\2\u00e8\u00e9\7p\2\2\u00e9"+
+		"\u00ea\7u\2\2\u00ea\u00eb\7v\2\2\u00eb\24\3\2\2\2\u00ec\u00ed\7g\2\2\u00ed"+
+		"\u00ee\7z\2\2\u00ee\u00ef\7v\2\2\u00ef\u00f0\7g\2\2\u00f0\u00f1\7t\2\2"+
+		"\u00f1\u00f2\7p\2\2\u00f2\26\3\2\2\2\u00f3\u00f4\7c\2\2\u00f4\u00f5\7"+
+		"n\2\2\u00f5\u00f6\7k\2\2\u00f6\u00f7\7i\2\2\u00f7\u00f8\7p\2\2\u00f8\30"+
+		"\3\2\2\2\u00f9\u00fa\7t\2\2\u00fa\u00fb\7g\2\2\u00fb\u00fc\7i\2\2\u00fc"+
+		"\u00fd\7k\2\2\u00fd\u00fe\7u\2\2\u00fe\u00ff\7v\2\2\u00ff\u0100\7g\2\2"+
+		"\u0100\u0101\7t\2\2\u0101\32\3\2\2\2\u0102\u0103\7k\2\2\u0103\u0104\7"+
+		"p\2\2\u0104\u0105\7n\2\2\u0105\u0106\7k\2\2\u0106\u0107\7p\2\2\u0107\u0108"+
+		"\7g\2\2\u0108\34\3\2\2\2\u0109\u010a\7x\2\2\u010a\u010b\7q\2\2\u010b\u010c"+
+		"\7n\2\2\u010c\u010d\7c\2\2\u010d\u010e\7v\2\2\u010e\u010f\7k\2\2\u010f"+
+		"\u0110\7n\2\2\u0110\u0111\7g\2\2\u0111\36\3\2\2\2\u0112\u0113\7k\2\2\u0113"+
+		"\u0114\7p\2\2\u0114\u0115\7v\2\2\u0115\u0116\7g\2\2\u0116\u0117\7t\2\2"+
+		"\u0117\u0118\7t\2\2\u0118\u0119\7w\2\2\u0119\u011a\7r\2\2\u011a\u011b"+
+		"\7v\2\2\u011b \3\2\2\2\u011c\u011d\7t\2\2\u011d\u011e\7g\2\2\u011e\u011f"+
+		"\7u\2\2\u011f\u0120\7g\2\2\u0120\u0121\7t\2\2\u0121\u0122\7x\2\2\u0122"+
+		"\u0123\7g\2\2\u0123\"\3\2\2\2\u0124\u0125\7k\2\2\u0125\u0126\7h\2\2\u0126"+
+		"$\3\2\2\2\u0127\u0128\7g\2\2\u0128\u0129\7n\2\2\u0129\u012a\7u\2\2\u012a"+
+		"\u012b\7g\2\2\u012b&\3\2\2\2\u012c\u012d\7y\2\2\u012d\u012e\7j\2\2\u012e"+
+		"\u012f\7k\2\2\u012f\u0130\7n\2\2\u0130\u0131\7g\2\2\u0131(\3\2\2\2\u0132"+
+		"\u0133\7f\2\2\u0133\u0134\7q\2\2\u0134*\3\2\2\2\u0135\u0136\7h\2\2\u0136"+
+		"\u0137\7q\2\2\u0137\u0138\7t\2\2\u0138,\3\2\2\2\u0139\u013a\7t\2\2\u013a"+
+		"\u013b\7g\2\2\u013b\u013c\7v\2\2\u013c\u013d\7w\2\2\u013d\u013e\7t\2\2"+
+		"\u013e\u013f\7p\2\2\u013f.\3\2\2\2\u0140\u0141\7d\2\2\u0141\u0142\7t\2"+
+		"\2\u0142\u0143\7g\2\2\u0143\u0144\7c\2\2\u0144\u0145\7m\2\2\u0145\60\3"+
+		"\2\2\2\u0146\u0147\7e\2\2\u0147\u0148\7q\2\2\u0148\u0149\7p\2\2\u0149"+
+		"\u014a\7v\2\2\u014a\u014b\7k\2\2\u014b\u014c\7p\2\2\u014c\u014d\7w\2\2"+
+		"\u014d\u014e\7g\2\2\u014e\62\3\2\2\2\u014f\u0150\7c\2\2\u0150\u0151\7"+
+		"u\2\2\u0151\u0152\7o\2\2\u0152\64\3\2\2\2\u0153\u0154\7<\2\2\u0154\66"+
+		"\3\2\2\2\u0155\u0156\7\60\2\2\u0156\u0157\7\60\2\2\u01578\3\2\2\2\u0158"+
+		"\u0159\7u\2\2\u0159\u015a\7k\2\2\u015a\u015b\7i\2\2\u015b\u015c\7p\2\2"+
+		"\u015c\u015d\7g\2\2\u015d\u015e\7f\2\2\u015e:\3\2\2\2\u015f\u0160\7w\2"+
+		"\2\u0160\u0161\7p\2\2\u0161\u0162\7u\2\2\u0162\u0163\7k\2\2\u0163\u0164"+
+		"\7i\2\2\u0164\u0165\7p\2\2\u0165\u0166\7g\2\2\u0166\u0167\7f\2\2\u0167"+
+		"<\3\2\2\2\u0168\u0169\7,\2\2\u0169>\3\2\2\2\u016a\u016b\7]\2\2\u016b@"+
+		"\3\2\2\2\u016c\u016d\7_\2\2\u016dB\3\2\2\2\u016e\u016f\7u\2\2\u016f\u0170"+
+		"\7v\2\2\u0170\u0171\7t\2\2\u0171\u0172\7w\2\2\u0172\u0173\7e\2\2\u0173"+
+		"\u0174\7v\2\2\u0174D\3\2\2\2\u0175\u0176\7\60\2\2\u0176F\3\2\2\2\u0177"+
+		"\u0178\7/\2\2\u0178\u0179\7@\2\2\u0179H\3\2\2\2\u017a\u017b\7u\2\2\u017b"+
+		"\u017c\7k\2\2\u017c\u017d\7|\2\2\u017d\u017e\7g\2\2\u017e\u017f\7q\2\2"+
+		"\u017f\u0180\7h\2\2\u0180J\3\2\2\2\u0181\u0182\7v\2\2\u0182\u0183\7{\2"+
+		"\2\u0183\u0184\7r\2\2\u0184\u0185\7g\2\2\u0185\u0186\7k\2\2\u0186\u0187"+
+		"\7f\2\2\u0187L\3\2\2\2\u0188\u0189\7/\2\2\u0189\u018a\7/\2\2\u018aN\3"+
+		"\2\2\2\u018b\u018c\7-\2\2\u018c\u018d\7-\2\2\u018dP\3\2\2\2\u018e\u018f"+
+		"\7-\2\2\u018fR\3\2\2\2\u0190\u0191\7/\2\2\u0191T\3\2\2\2\u0192\u0193\7"+
+		"#\2\2\u0193V\3\2\2\2\u0194\u0195\7(\2\2\u0195X\3\2\2\2\u0196\u0197\7\u0080"+
+		"\2\2\u0197Z\3\2\2\2\u0198\u0199\7@\2\2\u0199\u019a\7@\2\2\u019a\\\3\2"+
+		"\2\2\u019b\u019c\7>\2\2\u019c\u019d\7>\2\2\u019d^\3\2\2\2\u019e\u019f"+
+		"\7\61\2\2\u019f`\3\2\2\2\u01a0\u01a1\7\'\2\2\u01a1b\3\2\2\2\u01a2\u01a3"+
+		"\7>\2\2\u01a3d\3\2\2\2\u01a4\u01a5\7@\2\2\u01a5f\3\2\2\2\u01a6\u01a7\7"+
+		"?\2\2\u01a7\u01a8\7?\2\2\u01a8h\3\2\2\2\u01a9\u01aa\7#\2\2\u01aa\u01ab"+
+		"\7?\2\2\u01abj\3\2\2\2\u01ac\u01ad\7>\2\2\u01ad\u01ae\7?\2\2\u01ael\3"+
+		"\2\2\2\u01af\u01b0\7@\2\2\u01b0\u01b1\7?\2\2\u01b1n\3\2\2\2\u01b2\u01b3"+
+		"\7`\2\2\u01b3p\3\2\2\2\u01b4\u01b5\7~\2\2\u01b5r\3\2\2\2\u01b6\u01b7\7"+
+		"(\2\2\u01b7\u01b8\7(\2\2\u01b8t\3\2\2\2\u01b9\u01ba\7~\2\2\u01ba\u01bb"+
+		"\7~\2\2\u01bbv\3\2\2\2\u01bc\u01bd\7A\2\2\u01bdx\3\2\2\2\u01be\u01bf\7"+
+		"-\2\2\u01bf\u01c0\7?\2\2\u01c0z\3\2\2\2\u01c1\u01c2\7/\2\2\u01c2\u01c3"+
+		"\7?\2\2\u01c3|\3\2\2\2\u01c4\u01c5\7,\2\2\u01c5\u01c6\7?\2\2\u01c6~\3"+
+		"\2\2\2\u01c7\u01c8\7\61\2\2\u01c8\u01c9\7?\2\2\u01c9\u0080\3\2\2\2\u01ca"+
+		"\u01cb\7\'\2\2\u01cb\u01cc\7?\2\2\u01cc\u0082\3\2\2\2\u01cd\u01ce\7>\2"+
+		"\2\u01ce\u01cf\7>\2\2\u01cf\u01d0\7?\2\2\u01d0\u0084\3\2\2\2\u01d1\u01d2"+
+		"\7@\2\2\u01d2\u01d3\7@\2\2\u01d3\u01d4\7?\2\2\u01d4\u0086\3\2\2\2\u01d5"+
+		"\u01d6\7(\2\2\u01d6\u01d7\7?\2\2\u01d7\u0088\3\2\2\2\u01d8\u01d9\7~\2"+
+		"\2\u01d9\u01da\7?\2\2\u01da\u008a\3\2\2\2\u01db\u01dc\7`\2\2\u01dc\u01dd"+
+		"\7?\2\2\u01dd\u008c\3\2\2\2\u01de\u01df\7m\2\2\u01df\u01e0\7k\2\2\u01e0"+
+		"\u01e1\7e\2\2\u01e1\u01e2\7m\2\2\u01e2\u01e3\7c\2\2\u01e3\u01e4\7u\2\2"+
+		"\u01e4\u01e5\7o\2\2\u01e5\u008e\3\2\2\2\u01e6\u01e7\7t\2\2\u01e7\u01e8"+
+		"\7g\2\2\u01e8\u01e9\7u\2\2\u01e9\u01ea\7q\2\2\u01ea\u01eb\7w\2\2\u01eb"+
+		"\u01ec\7t\2\2\u01ec\u01ed\7e\2\2\u01ed\u01ee\7g\2\2\u01ee\u0090\3\2\2"+
+		"\2\u01ef\u01f0\7w\2\2\u01f0\u01f1\7u\2\2\u01f1\u01f2\7g\2\2\u01f2\u01f3"+
+		"\7u\2\2\u01f3\u0092\3\2\2\2\u01f4\u01f5\7e\2\2\u01f5\u01f6\7n\2\2\u01f6"+
+		"\u01f7\7q\2\2\u01f7\u01f8\7d\2\2\u01f8\u01f9\7d\2\2\u01f9\u01fa\7g\2\2"+
+		"\u01fa\u01fb\7t\2\2\u01fb\u01fc\7u\2\2\u01fc\u0094\3\2\2\2\u01fd\u01fe"+
+		"\7d\2\2\u01fe\u01ff\7{\2\2\u01ff\u0200\7v\2\2\u0200\u0201\7g\2\2\u0201"+
+		"\u0202\7u\2\2\u0202\u0096\3\2\2\2\u0203\u0204\7e\2\2\u0204\u0205\7{\2"+
+		"\2\u0205\u0206\7e\2\2\u0206\u0207\7n\2\2\u0207\u0208\7g\2\2\u0208\u0209"+
+		"\7u\2\2\u0209\u0098\3\2\2\2\u020a\u020b\7r\2\2\u020b\u020c\7e\2\2\u020c"+
+		"\u009a\3\2\2\2\u020d\u020e\7\60\2\2\u020e\u020f\7d\2\2\u020f\u0210\7{"+
+		"\2\2\u0210\u0211\7v\2\2\u0211\u0212\7g\2\2\u0212\u009c\3\2\2\2\u0213\u0214"+
+		"\7%\2\2\u0214\u009e\3\2\2\2\u0215\u0216\7d\2\2\u0216\u0217\7t\2\2\u0217"+
+		"\u02f4\7m\2\2\u0218\u0219\7q\2\2\u0219\u021a\7t\2\2\u021a\u02f4\7c\2\2"+
+		"\u021b\u021c\7m\2\2\u021c\u021d\7k\2\2\u021d\u02f4\7n\2\2\u021e\u021f"+
+		"\7u\2\2\u021f\u0220\7n\2\2\u0220\u02f4\7q\2\2\u0221\u0222\7p\2\2\u0222"+
+		"\u0223\7q\2\2\u0223\u02f4\7r\2\2\u0224\u0225\7c\2\2\u0225\u0226\7u\2\2"+
+		"\u0226\u02f4\7n\2\2\u0227\u0228\7r\2\2\u0228\u0229\7j\2\2\u0229\u02f4"+
+		"\7r\2\2\u022a\u022b\7c\2\2\u022b\u022c\7p\2\2\u022c\u02f4\7e\2\2\u022d"+
+		"\u022e\7d\2\2\u022e\u022f\7r\2\2\u022f\u02f4\7n\2\2\u0230\u0231\7e\2\2"+
+		"\u0231\u0232\7n\2\2\u0232\u02f4\7e\2\2\u0233\u0234\7l\2\2\u0234\u0235"+
+		"\7u\2\2\u0235\u02f4\7t\2\2\u0236\u0237\7c\2\2\u0237\u0238\7p\2\2\u0238"+
+		"\u02f4\7f\2\2\u0239\u023a\7t\2\2\u023a\u023b\7n\2\2\u023b\u02f4\7c\2\2"+
+		"\u023c\u023d\7d\2\2\u023d\u023e\7k\2\2\u023e\u02f4\7v\2\2\u023f\u0240"+
+		"\7t\2\2\u0240\u0241\7q\2\2\u0241\u02f4\7n\2\2\u0242\u0243\7r\2\2\u0243"+
+		"\u0244\7n\2\2\u0244\u02f4\7c\2\2\u0245\u0246\7r\2\2\u0246\u0247\7n\2\2"+
+		"\u0247\u02f4\7r\2\2\u0248\u0249\7d\2\2\u0249\u024a\7o\2\2\u024a\u02f4"+
+		"\7k\2\2\u024b\u024c\7u\2\2\u024c\u024d\7g\2\2\u024d\u02f4\7e\2\2\u024e"+
+		"\u024f\7t\2\2\u024f\u0250\7v\2\2\u0250\u02f4\7k\2\2\u0251\u0252\7g\2\2"+
+		"\u0252\u0253\7q\2\2\u0253\u02f4\7t\2\2\u0254\u0255\7u\2\2\u0255\u0256"+
+		"\7t\2\2\u0256\u02f4\7g\2\2\u0257\u0258\7n\2\2\u0258\u0259\7u\2\2\u0259"+
+		"\u02f4\7t\2\2\u025a\u025b\7r\2\2\u025b\u025c\7j\2\2\u025c\u02f4\7c\2\2"+
+		"\u025d\u025e\7c\2\2\u025e\u025f\7n\2\2\u025f\u02f4\7t\2\2\u0260\u0261"+
+		"\7l\2\2\u0261\u0262\7o\2\2\u0262\u02f4\7r\2\2\u0263\u0264\7d\2\2\u0264"+
+		"\u0265\7x\2\2\u0265\u02f4\7e\2\2\u0266\u0267\7e\2\2\u0267\u0268\7n\2\2"+
+		"\u0268\u02f4\7k\2\2\u0269\u026a\7t\2\2\u026a\u026b\7v\2\2\u026b\u02f4"+
+		"\7u\2\2\u026c\u026d\7c\2\2\u026d\u026e\7f\2\2\u026e\u02f4\7e\2\2\u026f"+
+		"\u0270\7t\2\2\u0270\u0271\7t\2\2\u0271\u02f4\7c\2\2\u0272\u0273\7d\2\2"+
+		"\u0273\u0274\7x\2\2\u0274\u02f4\7u\2\2\u0275\u0276\7u\2\2\u0276\u0277"+
+		"\7g\2\2\u0277\u02f4\7k\2\2\u0278\u0279\7u\2\2\u0279\u027a\7c\2\2\u027a"+
+		"\u02f4\7z\2\2\u027b\u027c\7u\2\2\u027c\u027d\7v\2\2\u027d\u02f4\7{\2\2"+
+		"\u027e\u027f\7u\2\2\u027f\u0280\7v\2\2\u0280\u02f4\7c\2\2\u0281\u0282"+
+		"\7u\2\2\u0282\u0283\7v\2\2\u0283\u02f4\7z\2\2\u0284\u0285\7f\2\2\u0285"+
+		"\u0286\7g\2\2\u0286\u02f4\7{\2\2\u0287\u0288\7v\2\2\u0288\u0289\7z\2\2"+
+		"\u0289\u02f4\7c\2\2\u028a\u028b\7z\2\2\u028b\u028c\7c\2\2\u028c\u02f4"+
+		"\7c\2\2\u028d\u028e\7d\2\2\u028e\u028f\7e\2\2\u028f\u02f4\7e\2\2\u0290"+
+		"\u0291\7c\2\2\u0291\u0292\7j\2\2\u0292\u02f4\7z\2\2\u0293\u0294\7v\2\2"+
+		"\u0294\u0295\7{\2\2\u0295\u02f4\7c\2\2\u0296\u0297\7v\2\2\u0297\u0298"+
+		"\7z\2\2\u0298\u02f4\7u\2\2\u0299\u029a\7v\2\2\u029a\u029b\7c\2\2\u029b"+
+		"\u02f4\7u\2\2\u029c\u029d\7u\2\2\u029d\u029e\7j\2\2\u029e\u02f4\7{\2\2"+
+		"\u029f\u02a0\7u\2\2\u02a0\u02a1\7j\2\2\u02a1\u02f4\7z\2\2\u02a2\u02a3"+
+		"\7n\2\2\u02a3\u02a4\7f\2\2\u02a4\u02f4\7{\2\2\u02a5\u02a6\7n\2\2\u02a6"+
+		"\u02a7\7f\2\2\u02a7\u02f4\7c\2\2\u02a8\u02a9\7n\2\2\u02a9\u02aa\7f\2\2"+
+		"\u02aa\u02f4\7z\2\2\u02ab\u02ac\7n\2\2\u02ac\u02ad\7c\2\2\u02ad\u02f4"+
+		"\7z\2\2\u02ae\u02af\7v\2\2\u02af\u02b0\7c\2\2\u02b0\u02f4\7{\2\2\u02b1"+
+		"\u02b2\7v\2\2\u02b2\u02b3\7c\2\2\u02b3\u02f4\7z\2\2\u02b4\u02b5\7d\2\2"+
+		"\u02b5\u02b6\7e\2\2\u02b6\u02f4\7u\2\2\u02b7\u02b8\7e\2\2\u02b8\u02b9"+
+		"\7n\2\2\u02b9\u02f4\7x\2\2\u02ba\u02bb\7v\2\2\u02bb\u02bc\7u\2\2\u02bc"+
+		"\u02f4\7z\2\2\u02bd\u02be\7n\2\2\u02be\u02bf\7c\2\2\u02bf\u02f4\7u\2\2"+
+		"\u02c0\u02c1\7e\2\2\u02c1\u02c2\7r\2\2\u02c2\u02f4\7{\2\2\u02c3\u02c4"+
+		"\7e\2\2\u02c4\u02c5\7o\2\2\u02c5\u02f4\7r\2\2\u02c6\u02c7\7e\2\2\u02c7"+
+		"\u02c8\7r\2\2\u02c8\u02f4\7z\2\2\u02c9\u02ca\7f\2\2\u02ca\u02cb\7e\2\2"+
+		"\u02cb\u02f4\7r\2\2\u02cc\u02cd\7f\2\2\u02cd\u02ce\7g\2\2\u02ce\u02f4"+
+		"\7e\2\2\u02cf\u02d0\7k\2\2\u02d0\u02d1\7p\2\2\u02d1\u02f4\7e\2\2\u02d2"+
+		"\u02d3\7c\2\2\u02d3\u02d4\7z\2\2\u02d4\u02f4\7u\2\2\u02d5\u02d6\7d\2\2"+
+		"\u02d6\u02d7\7p\2\2\u02d7\u02f4\7g\2\2\u02d8\u02d9\7e\2\2\u02d9\u02da"+
+		"\7n\2\2\u02da\u02f4\7f\2\2\u02db\u02dc\7u\2\2\u02dc\u02dd\7d\2\2\u02dd"+
+		"\u02f4\7e\2\2\u02de\u02df\7k\2\2\u02df\u02e0\7u\2\2\u02e0\u02f4\7e\2\2"+
+		"\u02e1\u02e2\7k\2\2\u02e2\u02e3\7p\2\2\u02e3\u02f4\7z\2\2\u02e4\u02e5"+
+		"\7d\2\2\u02e5\u02e6\7g\2\2\u02e6\u02f4\7s\2\2\u02e7\u02e8\7u\2\2\u02e8"+
+		"\u02e9\7g\2\2\u02e9\u02f4\7f\2\2\u02ea\u02eb\7f\2\2\u02eb\u02ec\7g\2\2"+
+		"\u02ec\u02f4\7z\2\2\u02ed\u02ee\7k\2\2\u02ee\u02ef\7p\2\2\u02ef\u02f4"+
+		"\7{\2\2\u02f0\u02f1\7t\2\2\u02f1\u02f2\7q\2\2\u02f2\u02f4\7t\2\2\u02f3"+
+		"\u0215\3\2\2\2\u02f3\u0218\3\2\2\2\u02f3\u021b\3\2\2\2\u02f3\u021e\3\2"+
+		"\2\2\u02f3\u0221\3\2\2\2\u02f3\u0224\3\2\2\2\u02f3\u0227\3\2\2\2\u02f3"+
+		"\u022a\3\2\2\2\u02f3\u022d\3\2\2\2\u02f3\u0230\3\2\2\2\u02f3\u0233\3\2"+
+		"\2\2\u02f3\u0236\3\2\2\2\u02f3\u0239\3\2\2\2\u02f3\u023c\3\2\2\2\u02f3"+
+		"\u023f\3\2\2\2\u02f3\u0242\3\2\2\2\u02f3\u0245\3\2\2\2\u02f3\u0248\3\2"+
+		"\2\2\u02f3\u024b\3\2\2\2\u02f3\u024e\3\2\2\2\u02f3\u0251\3\2\2\2\u02f3"+
+		"\u0254\3\2\2\2\u02f3\u0257\3\2\2\2\u02f3\u025a\3\2\2\2\u02f3\u025d\3\2"+
+		"\2\2\u02f3\u0260\3\2\2\2\u02f3\u0263\3\2\2\2\u02f3\u0266\3\2\2\2\u02f3"+
+		"\u0269\3\2\2\2\u02f3\u026c\3\2\2\2\u02f3\u026f\3\2\2\2\u02f3\u0272\3\2"+
+		"\2\2\u02f3\u0275\3\2\2\2\u02f3\u0278\3\2\2\2\u02f3\u027b\3\2\2\2\u02f3"+
+		"\u027e\3\2\2\2\u02f3\u0281\3\2\2\2\u02f3\u0284\3\2\2\2\u02f3\u0287\3\2"+
+		"\2\2\u02f3\u028a\3\2\2\2\u02f3\u028d\3\2\2\2\u02f3\u0290\3\2\2\2\u02f3"+
+		"\u0293\3\2\2\2\u02f3\u0296\3\2\2\2\u02f3\u0299\3\2\2\2\u02f3\u029c\3\2"+
+		"\2\2\u02f3\u029f\3\2\2\2\u02f3\u02a2\3\2\2\2\u02f3\u02a5\3\2\2\2\u02f3"+
+		"\u02a8\3\2\2\2\u02f3\u02ab\3\2\2\2\u02f3\u02ae\3\2\2\2\u02f3\u02b1\3\2"+
+		"\2\2\u02f3\u02b4\3\2\2\2\u02f3\u02b7\3\2\2\2\u02f3\u02ba\3\2\2\2\u02f3"+
+		"\u02bd\3\2\2\2\u02f3\u02c0\3\2\2\2\u02f3\u02c3\3\2\2\2\u02f3\u02c6\3\2"+
+		"\2\2\u02f3\u02c9\3\2\2\2\u02f3\u02cc\3\2\2\2\u02f3\u02cf\3\2\2\2\u02f3"+
+		"\u02d2\3\2\2\2\u02f3\u02d5\3\2\2\2\u02f3\u02d8\3\2\2\2\u02f3\u02db\3\2"+
+		"\2\2\u02f3\u02de\3\2\2\2\u02f3\u02e1\3\2\2\2\u02f3\u02e4\3\2\2\2\u02f3"+
+		"\u02e7\3\2\2\2\u02f3\u02ea\3\2\2\2\u02f3\u02ed\3\2\2\2\u02f3\u02f0\3\2"+
+		"\2\2\u02f4\u00a0\3\2\2\2\u02f5\u02f6\7}\2\2\u02f6\u02f7\7}\2\2\u02f7\u02fb"+
+		"\3\2\2\2\u02f8\u02fa\13\2\2\2\u02f9\u02f8\3\2\2\2\u02fa\u02fd\3\2\2\2"+
+		"\u02fb\u02fc\3\2\2\2\u02fb\u02f9\3\2\2\2\u02fc\u02fe\3\2\2\2\u02fd\u02fb"+
+		"\3\2\2\2\u02fe\u02ff\7\177\2\2\u02ff\u0300\7\177\2\2\u0300\u00a2\3\2\2"+
+		"\2\u0301\u0302\7d\2\2\u0302\u0303\7{\2\2\u0303\u0304\7v\2\2\u0304\u0327"+
+		"\7g\2\2\u0305\u0306\7y\2\2\u0306\u0307\7q\2\2\u0307\u0308\7t\2\2\u0308"+
+		"\u0327\7f\2\2\u0309\u030a\7f\2\2\u030a\u030b\7y\2\2\u030b\u030c\7q\2\2"+
+		"\u030c\u030d\7t\2\2\u030d\u0327\7f\2\2\u030e\u030f\7d\2\2\u030f\u0310"+
+		"\7q\2\2\u0310\u0311\7q\2\2\u0311\u0327\7n\2\2\u0312\u0313\7e\2\2\u0313"+
+		"\u0314\7j\2\2\u0314\u0315\7c\2\2\u0315\u0327\7t\2\2\u0316\u0317\7u\2\2"+
+		"\u0317\u0318\7j\2\2\u0318\u0319\7q\2\2\u0319\u031a\7t\2\2\u031a\u0327"+
+		"\7v\2\2\u031b\u031c\7k\2\2\u031c\u031d\7p\2\2\u031d\u0327\7v\2\2\u031e"+
+		"\u031f\7n\2\2\u031f\u0320\7q\2\2\u0320\u0321\7p\2\2\u0321\u0327\7i\2\2"+
+		"\u0322\u0323\7x\2\2\u0323\u0324\7q\2\2\u0324\u0325\7k\2\2\u0325\u0327"+
+		"\7f\2\2\u0326\u0301\3\2\2\2\u0326\u0305\3\2\2\2\u0326\u0309\3\2\2\2\u0326"+
+		"\u030e\3\2\2\2\u0326\u0312\3\2\2\2\u0326\u0316\3\2\2\2\u0326\u031b\3\2"+
+		"\2\2\u0326\u031e\3\2\2\2\u0326\u0322\3\2\2\2\u0327\u00a4\3\2\2\2\u0328"+
+		"\u032e\7$\2\2\u0329\u032a\7^\2\2\u032a\u032d\7$\2\2\u032b\u032d\n\2\2"+
+		"\2\u032c\u0329\3\2\2\2\u032c\u032b\3\2\2\2\u032d\u0330\3\2\2\2\u032e\u032c"+
+		"\3\2\2\2\u032e\u032f\3\2\2\2\u032f\u0331\3\2\2\2\u0330\u032e\3\2\2\2\u0331"+
+		"\u0333\7$\2\2\u0332\u0334\7|\2\2\u0333\u0332\3\2\2\2\u0333\u0334\3\2\2"+
+		"\2\u0334\u00a6\3\2\2\2\u0335\u0339\7)\2\2\u0336\u0337\7^\2\2\u0337\u033a"+
+		"\7)\2\2\u0338\u033a\n\3\2\2\u0339\u0336\3\2\2\2\u0339\u0338\3\2\2\2\u033a"+
+		"\u033b\3\2\2\2\u033b\u033c\7)\2\2\u033c\u00a8\3\2\2\2\u033d\u033e\7v\2"+
+		"\2\u033e\u033f\7t\2\2\u033f\u0340\7w\2\2\u0340\u0347\7g\2\2\u0341\u0342"+
+		"\7h\2\2\u0342\u0343\7c\2\2\u0343\u0344\7n\2\2\u0344\u0345\7u\2\2\u0345"+
+		"\u0347\7g\2\2\u0346\u033d\3\2\2\2\u0346\u0341\3\2\2\2\u0347\u00aa\3\2"+
+		"\2\2\u0348\u034b\5\u00adW\2\u0349\u034b\5\u00b5[\2\u034a\u0348\3\2\2\2"+
+		"\u034a\u0349\3\2\2\2\u034b\u00ac\3\2\2\2\u034c\u0350\5\u00afX\2\u034d"+
+		"\u0350\5\u00b1Y\2\u034e\u0350\5\u00b3Z\2\u034f\u034c\3\2\2\2\u034f\u034d"+
+		"\3\2\2\2\u034f\u034e\3\2\2\2\u0350\u00ae\3\2\2\2\u0351\u0357\7\'\2\2\u0352"+
+		"\u0353\7\62\2\2\u0353\u0357\7d\2\2\u0354\u0355\7\62\2\2\u0355\u0357\7"+
+		"D\2\2\u0356\u0351\3\2\2\2\u0356\u0352\3\2\2\2\u0356\u0354\3\2\2\2\u0357"+
+		"\u035b\3\2\2\2\u0358\u035a\5\u00bd_\2\u0359\u0358\3\2\2\2\u035a\u035d"+
+		"\3\2\2\2\u035b\u0359\3\2\2\2\u035b\u035c\3\2\2\2\u035c\u035e\3\2\2\2\u035d"+
+		"\u035b\3\2\2\2\u035e\u0360\7\60\2\2\u035f\u0361\5\u00bd_\2\u0360\u035f"+
+		"\3\2\2\2\u0361\u0362\3\2\2\2\u0362\u0360\3\2\2\2\u0362\u0363\3\2\2\2\u0363"+
+		"\u00b0\3\2\2\2\u0364\u0366\5\u00bf`\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\u036a\3\2\2\2\u0369"+
+		"\u0367\3\2\2\2\u036a\u036c\7\60\2\2\u036b\u036d\5\u00bf`\2\u036c\u036b"+
+		"\3\2\2\2\u036d\u036e\3\2\2\2\u036e\u036c\3\2\2\2\u036e\u036f\3\2\2\2\u036f"+
+		"\u00b2\3\2\2\2\u0370\u0376\7&\2\2\u0371\u0372\7\62\2\2\u0372\u0376\7z"+
+		"\2\2\u0373\u0374\7\62\2\2\u0374\u0376\7Z\2\2\u0375\u0370\3\2\2\2\u0375"+
+		"\u0371\3\2\2\2\u0375\u0373\3\2\2\2\u0376\u037a\3\2\2\2\u0377\u0379\5\u00c1"+
+		"a\2\u0378\u0377\3\2\2\2\u0379\u037c\3\2\2\2\u037a\u0378\3\2\2\2\u037a"+
+		"\u037b\3\2\2\2\u037b\u037d\3\2\2\2\u037c\u037a\3\2\2\2\u037d\u037f\7\60"+
+		"\2\2\u037e\u0380\5\u00c1a\2\u037f\u037e\3\2\2\2\u0380\u0381\3\2\2\2\u0381"+
+		"\u037f\3\2\2\2\u0381\u0382\3\2\2\2\u0382\u00b4\3\2\2\2\u0383\u0387\5\u00b9"+
+		"]\2\u0384\u0387\5\u00bb^\2\u0385\u0387\5\u00b7\\\2\u0386\u0383\3\2\2\2"+
+		"\u0386\u0384\3\2\2\2\u0386\u0385\3\2\2\2\u0387\u038b\3\2\2\2\u0388\u0389"+
+		"\t\4\2\2\u0389\u038c\t\5\2\2\u038a\u038c\7n\2\2\u038b\u0388\3\2\2\2\u038b"+
+		"\u038a\3\2\2\2\u038b\u038c\3\2\2\2\u038c\u00b6\3\2\2\2\u038d\u038e\7\62"+
+		"\2\2\u038e\u0390\t\6\2\2\u038f\u0391\5\u00bd_\2\u0390\u038f\3\2\2\2\u0391"+
+		"\u0392\3\2\2\2\u0392\u0390\3\2\2\2\u0392\u0393\3\2\2\2\u0393\u039b\3\2"+
+		"\2\2\u0394\u0396\7\'\2\2\u0395\u0397\5\u00bd_\2\u0396\u0395\3\2\2\2\u0397"+
+		"\u0398\3\2\2\2\u0398\u0396\3\2\2\2\u0398\u0399\3\2\2\2\u0399\u039b\3\2"+
+		"\2\2\u039a\u038d\3\2\2\2\u039a\u0394\3\2\2\2\u039b\u00b8\3\2\2\2\u039c"+
+		"\u039e\5\u00bf`\2\u039d\u039c\3\2\2\2\u039e\u039f\3\2\2\2\u039f\u039d"+
+		"\3\2\2\2\u039f\u03a0\3\2\2\2\u03a0\u00ba\3\2\2\2\u03a1\u03a7\7&\2\2\u03a2"+
+		"\u03a3\7\62\2\2\u03a3\u03a7\7z\2\2\u03a4\u03a5\7\62\2\2\u03a5\u03a7\7"+
+		"Z\2\2\u03a6\u03a1\3\2\2\2\u03a6\u03a2\3\2\2\2\u03a6\u03a4\3\2\2\2\u03a7"+
+		"\u03a9\3\2\2\2\u03a8\u03aa\5\u00c1a\2\u03a9\u03a8\3\2\2\2\u03aa\u03ab"+
+		"\3\2\2\2\u03ab\u03a9\3\2\2\2\u03ab\u03ac\3\2\2\2\u03ac\u00bc\3\2\2\2\u03ad"+
+		"\u03ae\t\7\2\2\u03ae\u00be\3\2\2\2\u03af\u03b0\t\b\2\2\u03b0\u00c0\3\2"+
+		"\2\2\u03b1\u03b2\t\t\2\2\u03b2\u00c2\3\2\2\2\u03b3\u03b7\5\u00c5c\2\u03b4"+
+		"\u03b6\5\u00c7d\2\u03b5\u03b4\3\2\2\2\u03b6\u03b9\3\2\2\2\u03b7\u03b5"+
+		"\3\2\2\2\u03b7\u03b8\3\2\2\2\u03b8\u00c4\3\2\2\2\u03b9\u03b7\3\2\2\2\u03ba"+
+		"\u03bb\t\n\2\2\u03bb\u00c6\3\2\2\2\u03bc\u03bd\t\13\2\2\u03bd\u00c8\3"+
+		"\2\2\2\u03be\u03c2\7#\2\2\u03bf\u03c1\5\u00c7d\2\u03c0\u03bf\3\2\2\2\u03c1"+
+		"\u03c4\3\2\2\2\u03c2\u03c0\3\2\2\2\u03c2\u03c3\3\2\2\2\u03c3\u03c6\3\2"+
+		"\2\2\u03c4\u03c2\3\2\2\2\u03c5\u03c7\t\f\2\2\u03c6\u03c5\3\2\2\2\u03c7"+
+		"\u03c8\3\2\2\2\u03c8\u03c6\3\2\2\2\u03c8\u03c9\3\2\2\2\u03c9\u00ca\3\2"+
+		"\2\2\u03ca\u03cc\t\r\2\2\u03cb\u03ca\3\2\2\2\u03cc\u03cd\3\2\2\2\u03cd"+
+		"\u03cb\3\2\2\2\u03cd\u03ce\3\2\2\2\u03ce\u03cf\3\2\2\2\u03cf\u03d0\bf"+
+		"\2\2\u03d0\u00cc\3\2\2\2\u03d1\u03d2\7\61\2\2\u03d2\u03d3\7\61\2\2\u03d3"+
+		"\u03d7\3\2\2\2\u03d4\u03d6\n\16\2\2\u03d5\u03d4\3\2\2\2\u03d6\u03d9\3"+
+		"\2\2\2\u03d7\u03d5\3\2\2\2\u03d7\u03d8\3\2\2\2\u03d8\u03da\3\2\2\2\u03d9"+
+		"\u03d7\3\2\2\2\u03da\u03db\bg\3\2\u03db\u00ce\3\2\2\2\u03dc\u03dd\7\61"+
+		"\2\2\u03dd\u03de\7,\2\2\u03de\u03e2\3\2\2\2\u03df\u03e1\13\2\2\2\u03e0"+
+		"\u03df\3\2\2\2\u03e1\u03e4\3\2\2\2\u03e2\u03e3\3\2\2\2\u03e2\u03e0\3\2"+
+		"\2\2\u03e3\u03e5\3\2\2\2\u03e4\u03e2\3\2\2\2\u03e5\u03e6\7,\2\2\u03e6"+
+		"\u03e7\7\61\2\2\u03e7\u03e8\3\2\2\2\u03e8\u03e9\bh\3\2\u03e9\u00d0\3\2"+
+		"\2\2#\2\u02f3\u02fb\u0326\u032c\u032e\u0333\u0339\u0346\u034a\u034f\u0356"+
+		"\u035b\u0362\u0367\u036e\u0375\u037a\u0381\u0386\u038b\u0392\u0398\u039a"+
+		"\u039f\u03a6\u03ab\u03b7\u03c2\u03c8\u03cd\u03d7\u03e2\4\2\3\2\2\4\2";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens
index a303b96fe..42dfa728a 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCLexer.tokens
@@ -75,26 +75,27 @@ T__73=74
 T__74=75
 T__75=76
 T__76=77
-MNEMONIC=78
-KICKASM=79
-SIMPLETYPE=80
-STRING=81
-CHAR=82
-BOOLEAN=83
-NUMBER=84
-NUMFLOAT=85
-BINFLOAT=86
-DECFLOAT=87
-HEXFLOAT=88
-NUMINT=89
-BININTEGER=90
-DECINTEGER=91
-HEXINTEGER=92
-NAME=93
-ASMREL=94
-WS=95
-COMMENT_LINE=96
-COMMENT_BLOCK=97
+T__77=78
+MNEMONIC=79
+KICKASM=80
+SIMPLETYPE=81
+STRING=82
+CHAR=83
+BOOLEAN=84
+NUMBER=85
+NUMFLOAT=86
+BINFLOAT=87
+DECFLOAT=88
+HEXFLOAT=89
+NUMINT=90
+BININTEGER=91
+DECINTEGER=92
+HEXINTEGER=93
+NAME=94
+ASMREL=95
+WS=96
+COMMENT_LINE=97
+COMMENT_BLOCK=98
 'import'=1
 ';'=2
 ','=3
@@ -128,47 +129,48 @@ COMMENT_BLOCK=97
 '['=31
 ']'=32
 'struct'=33
-'sizeof'=34
-'typeid'=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
-'>>='=64
-'&='=65
-'|='=66
-'^='=67
-'kickasm'=68
-'resource'=69
-'uses'=70
-'clobbers'=71
-'bytes'=72
-'cycles'=73
-'pc'=74
-'.byte'=75
-'#'=76
-'.'=77
+'.'=34
+'->'=35
+'sizeof'=36
+'typeid'=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
+'%='=64
+'<<='=65
+'>>='=66
+'&='=67
+'|='=68
+'^='=69
+'kickasm'=70
+'resource'=71
+'uses'=72
+'clobbers'=73
+'bytes'=74
+'cycles'=75
+'pc'=76
+'.byte'=77
+'#'=78
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
index 950823cc9..24069cabb 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCListener.java
@@ -715,6 +715,30 @@ public interface KickCListener extends ParseTreeListener {
 	 * @param ctx the parse tree
 	 */
 	void exitExprChar(KickCParser.ExprCharContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code exprArrow}
+	 * labeled alternative in {@link KickCParser#expr}.
+	 * @param ctx the parse tree
+	 */
+	void enterExprArrow(KickCParser.ExprArrowContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code exprArrow}
+	 * labeled alternative in {@link KickCParser#expr}.
+	 * @param ctx the parse tree
+	 */
+	void exitExprArrow(KickCParser.ExprArrowContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code exprDot}
+	 * labeled alternative in {@link KickCParser#expr}.
+	 * @param ctx the parse tree
+	 */
+	void enterExprDot(KickCParser.ExprDotContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code exprDot}
+	 * labeled alternative in {@link KickCParser#expr}.
+	 * @param ctx the parse tree
+	 */
+	void exitExprDot(KickCParser.ExprDotContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code initList}
 	 * labeled alternative in {@link KickCParser#expr}.
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
index 02a84e4b0..57be1778b 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCParser.java
@@ -27,10 +27,10 @@ public class KickCParser extends Parser {
 		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, T__71=72, T__72=73, 
-		T__73=74, T__74=75, T__75=76, T__76=77, MNEMONIC=78, KICKASM=79, SIMPLETYPE=80, 
-		STRING=81, CHAR=82, BOOLEAN=83, NUMBER=84, NUMFLOAT=85, BINFLOAT=86, DECFLOAT=87, 
-		HEXFLOAT=88, NUMINT=89, BININTEGER=90, DECINTEGER=91, HEXINTEGER=92, NAME=93, 
-		ASMREL=94, WS=95, COMMENT_LINE=96, COMMENT_BLOCK=97;
+		T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, MNEMONIC=79, KICKASM=80, 
+		SIMPLETYPE=81, STRING=82, CHAR=83, BOOLEAN=84, NUMBER=85, NUMFLOAT=86, 
+		BINFLOAT=87, DECFLOAT=88, HEXFLOAT=89, NUMINT=90, BININTEGER=91, DECINTEGER=92, 
+		HEXINTEGER=93, NAME=94, ASMREL=95, WS=96, COMMENT_LINE=97, COMMENT_BLOCK=98;
 	public static final int
 		RULE_file = 0, RULE_asmFile = 1, RULE_importSeq = 2, RULE_importDecl = 3, 
 		RULE_declSeq = 4, RULE_decl = 5, RULE_declTypes = 6, RULE_declVariables = 7, 
@@ -58,12 +58,12 @@ public class KickCParser extends Parser {
 		"'extern'", "'align'", "'register'", "'inline'", "'volatile'", "'interrupt'", 
 		"'reserve'", "'if'", "'else'", "'while'", "'do'", "'for'", "'return'", 
 		"'break'", "'continue'", "'asm'", "':'", "'..'", "'signed'", "'unsigned'", 
-		"'*'", "'['", "']'", "'struct'", "'sizeof'", "'typeid'", "'--'", "'++'", 
-		"'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'", 
-		"'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'", 
-		"'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", 
-		"'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'", 
-		"'cycles'", "'pc'", "'.byte'", "'#'", "'.'"
+		"'*'", "'['", "']'", "'struct'", "'.'", "'->'", "'sizeof'", "'typeid'", 
+		"'--'", "'++'", "'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", 
+		"'%'", "'<'", "'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", 
+		"'||'", "'?'", "'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", 
+		"'&='", "'|='", "'^='", "'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,7 +72,7 @@ public class KickCParser extends Parser {
 		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, 
-		null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", 
+		null, null, null, null, null, null, null, "MNEMONIC", "KICKASM", "SIMPLETYPE", 
 		"STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", 
 		"HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", 
 		"ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK"
@@ -375,7 +375,7 @@ public class KickCParser extends Parser {
 				setState(93); 
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==T__67 || _la==SIMPLETYPE );
+			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__27) | (1L << T__28) | (1L << T__32))) != 0) || _la==T__69 || _la==SIMPLETYPE );
 			}
 		}
 		catch (RecognitionException re) {
@@ -811,7 +811,7 @@ public class KickCParser extends Parser {
 			setState(147);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
-			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0)) {
+			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (T__69 - 70)) | (1L << (SIMPLETYPE - 70)) | (1L << (STRING - 70)) | (1L << (CHAR - 70)) | (1L << (BOOLEAN - 70)) | (1L << (NUMBER - 70)) | (1L << (NAME - 70)))) != 0)) {
 				{
 				setState(146);
 				stmtSeq();
@@ -1402,7 +1402,7 @@ public class KickCParser extends Parser {
 				setState(204); 
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0) );
+			} while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (T__69 - 70)) | (1L << (SIMPLETYPE - 70)) | (1L << (STRING - 70)) | (1L << (CHAR - 70)) | (1L << (BOOLEAN - 70)) | (1L << (NUMBER - 70)) | (1L << (NAME - 70)))) != 0) );
 			}
 		}
 		catch (RecognitionException re) {
@@ -1713,7 +1713,7 @@ public class KickCParser extends Parser {
 				setState(211);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 68)) & ~0x3f) == 0 && ((1L << (_la - 68)) & ((1L << (T__67 - 68)) | (1L << (SIMPLETYPE - 68)) | (1L << (STRING - 68)) | (1L << (CHAR - 68)) | (1L << (BOOLEAN - 68)) | (1L << (NUMBER - 68)) | (1L << (NAME - 68)))) != 0)) {
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__32) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 70)) & ~0x3f) == 0 && ((1L << (_la - 70)) & ((1L << (T__69 - 70)) | (1L << (SIMPLETYPE - 70)) | (1L << (STRING - 70)) | (1L << (CHAR - 70)) | (1L << (BOOLEAN - 70)) | (1L << (NUMBER - 70)) | (1L << (NAME - 70)))) != 0)) {
 					{
 					setState(210);
 					stmtSeq();
@@ -1865,7 +1865,7 @@ public class KickCParser extends Parser {
 				setState(266);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) {
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 82)) & ~0x3f) == 0 && ((1L << (_la - 82)) & ((1L << (STRING - 82)) | (1L << (CHAR - 82)) | (1L << (BOOLEAN - 82)) | (1L << (NUMBER - 82)) | (1L << (NAME - 82)))) != 0)) {
 					{
 					setState(265);
 					commaExpr(0);
@@ -2027,7 +2027,7 @@ public class KickCParser extends Parser {
 				setState(289);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
-				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) {
+				if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 82)) & ~0x3f) == 0 && ((1L << (_la - 82)) & ((1L << (STRING - 82)) | (1L << (CHAR - 82)) | (1L << (BOOLEAN - 82)) | (1L << (NUMBER - 82)) | (1L << (NAME - 82)))) != 0)) {
 					{
 					setState(288);
 					commaExpr(0);
@@ -2456,7 +2456,7 @@ public class KickCParser extends Parser {
 						setState(327);
 						_errHandler.sync(this);
 						_la = _input.LA(1);
-						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) {
+						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 82)) & ~0x3f) == 0 && ((1L << (_la - 82)) & ((1L << (STRING - 82)) | (1L << (CHAR - 82)) | (1L << (BOOLEAN - 82)) | (1L << (NUMBER - 82)) | (1L << (NAME - 82)))) != 0)) {
 							{
 							setState(326);
 							expr(0);
@@ -2945,6 +2945,46 @@ public class KickCParser extends Parser {
 			else return visitor.visitChildren(this);
 		}
 	}
+	public static class ExprArrowContext extends ExprContext {
+		public ExprContext expr() {
+			return getRuleContext(ExprContext.class,0);
+		}
+		public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); }
+		public ExprArrowContext(ExprContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).enterExprArrow(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).exitExprArrow(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitExprArrow(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class ExprDotContext extends ExprContext {
+		public ExprContext expr() {
+			return getRuleContext(ExprContext.class,0);
+		}
+		public TerminalNode NAME() { return getToken(KickCParser.NAME, 0); }
+		public ExprDotContext(ExprContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).enterExprDot(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof KickCListener ) ((KickCListener)listener).exitExprDot(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof KickCVisitor ) return ((KickCVisitor<? extends T>)visitor).visitExprDot(this);
+			else return visitor.visitChildren(this);
+		}
+	}
 	public static class InitListContext extends ExprContext {
 		public List<ExprContext> expr() {
 			return getRuleContexts(ExprContext.class);
@@ -3234,7 +3274,7 @@ public class KickCParser extends Parser {
 				_ctx = _localctx;
 				_prevctx = _localctx;
 				setState(372);
-				match(T__33);
+				match(T__35);
 				setState(373);
 				match(T__4);
 				setState(376);
@@ -3263,7 +3303,7 @@ public class KickCParser extends Parser {
 				_ctx = _localctx;
 				_prevctx = _localctx;
 				setState(380);
-				match(T__34);
+				match(T__36);
 				setState(381);
 				match(T__4);
 				setState(384);
@@ -3308,7 +3348,7 @@ public class KickCParser extends Parser {
 				_prevctx = _localctx;
 				setState(393);
 				_la = _input.LA(1);
-				if ( !(_la==T__35 || _la==T__36) ) {
+				if ( !(_la==T__37 || _la==T__38) ) {
 				_errHandler.recoverInline(this);
 				}
 				else {
@@ -3338,7 +3378,7 @@ public class KickCParser extends Parser {
 				_prevctx = _localctx;
 				setState(397);
 				_la = _input.LA(1);
-				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41))) != 0)) ) {
+				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43))) != 0)) ) {
 				_errHandler.recoverInline(this);
 				}
 				else {
@@ -3357,7 +3397,7 @@ public class KickCParser extends Parser {
 				_prevctx = _localctx;
 				setState(399);
 				_la = _input.LA(1);
-				if ( !(_la==T__46 || _la==T__47) ) {
+				if ( !(_la==T__48 || _la==T__49) ) {
 				_errHandler.recoverInline(this);
 				}
 				else {
@@ -3463,7 +3503,7 @@ public class KickCParser extends Parser {
 				break;
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(477);
+			setState(483);
 			_errHandler.sync(this);
 			_alt = getInterpreter().adaptivePredict(_input,43,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
@@ -3471,7 +3511,7 @@ public class KickCParser extends Parser {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
 					_prevctx = _localctx;
 					{
-					setState(475);
+					setState(481);
 					_errHandler.sync(this);
 					switch ( getInterpreter().adaptivePredict(_input,42,_ctx) ) {
 					case 1:
@@ -3482,7 +3522,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)");
 						setState(424);
 						_la = _input.LA(1);
-						if ( !(_la==T__42 || _la==T__43) ) {
+						if ( !(_la==T__44 || _la==T__45) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3502,7 +3542,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)");
 						setState(427);
 						_la = _input.LA(1);
-						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__44) | (1L << T__45))) != 0)) ) {
+						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__29) | (1L << T__46) | (1L << T__47))) != 0)) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3522,7 +3562,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)");
 						setState(430);
 						_la = _input.LA(1);
-						if ( !(_la==T__37 || _la==T__38) ) {
+						if ( !(_la==T__39 || _la==T__40) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3542,7 +3582,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 15))) throw new FailedPredicateException(this, "precpred(_ctx, 15)");
 						setState(433);
 						_la = _input.LA(1);
-						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50) | (1L << T__51))) != 0)) ) {
+						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__48) | (1L << T__49) | (1L << T__50) | (1L << T__51) | (1L << T__52) | (1L << T__53))) != 0)) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3562,7 +3602,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 14))) throw new FailedPredicateException(this, "precpred(_ctx, 14)");
 						{
 						setState(436);
-						match(T__40);
+						match(T__42);
 						}
 						setState(437);
 						expr(15);
@@ -3576,7 +3616,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)");
 						{
 						setState(439);
-						match(T__52);
+						match(T__54);
 						}
 						setState(440);
 						expr(14);
@@ -3590,7 +3630,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
 						{
 						setState(442);
-						match(T__53);
+						match(T__55);
 						}
 						setState(443);
 						expr(13);
@@ -3604,7 +3644,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)");
 						{
 						setState(445);
-						match(T__54);
+						match(T__56);
 						}
 						setState(446);
 						expr(12);
@@ -3618,7 +3658,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
 						{
 						setState(448);
-						match(T__55);
+						match(T__57);
 						}
 						setState(449);
 						expr(11);
@@ -3631,7 +3671,7 @@ public class KickCParser extends Parser {
 						setState(450);
 						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
 						setState(451);
-						match(T__56);
+						match(T__58);
 						setState(452);
 						expr(0);
 						setState(453);
@@ -3660,7 +3700,7 @@ public class KickCParser extends Parser {
 						if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
 						setState(460);
 						_la = _input.LA(1);
-						if ( !(((((_la - 58)) & ~0x3f) == 0 && ((1L << (_la - 58)) & ((1L << (T__57 - 58)) | (1L << (T__58 - 58)) | (1L << (T__59 - 58)) | (1L << (T__60 - 58)) | (1L << (T__61 - 58)) | (1L << (T__62 - 58)) | (1L << (T__63 - 58)) | (1L << (T__64 - 58)) | (1L << (T__65 - 58)) | (1L << (T__66 - 58)))) != 0)) ) {
+						if ( !(((((_la - 60)) & ~0x3f) == 0 && ((1L << (_la - 60)) & ((1L << (T__59 - 60)) | (1L << (T__60 - 60)) | (1L << (T__61 - 60)) | (1L << (T__62 - 60)) | (1L << (T__63 - 60)) | (1L << (T__64 - 60)) | (1L << (T__65 - 60)) | (1L << (T__66 - 60)) | (1L << (T__67 - 60)) | (1L << (T__68 - 60)))) != 0)) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3674,49 +3714,73 @@ public class KickCParser extends Parser {
 						break;
 					case 13:
 						{
-						_localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState));
+						_localctx = new ExprDotContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
 						setState(462);
-						if (!(precpred(_ctx, 28))) throw new FailedPredicateException(this, "precpred(_ctx, 28)");
+						if (!(precpred(_ctx, 30))) throw new FailedPredicateException(this, "precpred(_ctx, 30)");
 						setState(463);
-						match(T__4);
-						setState(465);
-						_errHandler.sync(this);
-						_la = _input.LA(1);
-						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__46) | (1L << T__47))) != 0) || ((((_la - 81)) & ~0x3f) == 0 && ((1L << (_la - 81)) & ((1L << (STRING - 81)) | (1L << (CHAR - 81)) | (1L << (BOOLEAN - 81)) | (1L << (NUMBER - 81)) | (1L << (NAME - 81)))) != 0)) {
-							{
-							setState(464);
-							parameterList();
-							}
-						}
-
-						setState(467);
-						match(T__5);
+						match(T__33);
+						setState(464);
+						match(NAME);
 						}
 						break;
 					case 14:
 						{
-						_localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState));
+						_localctx = new ExprArrowContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(468);
-						if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)");
-						setState(469);
-						match(T__30);
-						setState(470);
-						commaExpr(0);
-						setState(471);
-						match(T__31);
+						setState(465);
+						if (!(precpred(_ctx, 29))) throw new FailedPredicateException(this, "precpred(_ctx, 29)");
+						setState(466);
+						match(T__34);
+						setState(467);
+						match(NAME);
 						}
 						break;
 					case 15:
+						{
+						_localctx = new ExprCallContext(new ExprContext(_parentctx, _parentState));
+						pushNewRecursionContext(_localctx, _startState, RULE_expr);
+						setState(468);
+						if (!(precpred(_ctx, 28))) throw new FailedPredicateException(this, "precpred(_ctx, 28)");
+						setState(469);
+						match(T__4);
+						setState(471);
+						_errHandler.sync(this);
+						_la = _input.LA(1);
+						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__6) | (1L << T__29) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__48) | (1L << T__49))) != 0) || ((((_la - 82)) & ~0x3f) == 0 && ((1L << (_la - 82)) & ((1L << (STRING - 82)) | (1L << (CHAR - 82)) | (1L << (BOOLEAN - 82)) | (1L << (NUMBER - 82)) | (1L << (NAME - 82)))) != 0)) {
+							{
+							setState(470);
+							parameterList();
+							}
+						}
+
+						setState(473);
+						match(T__5);
+						}
+						break;
+					case 16:
+						{
+						_localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState));
+						pushNewRecursionContext(_localctx, _startState, RULE_expr);
+						setState(474);
+						if (!(precpred(_ctx, 25))) throw new FailedPredicateException(this, "precpred(_ctx, 25)");
+						setState(475);
+						match(T__30);
+						setState(476);
+						commaExpr(0);
+						setState(477);
+						match(T__31);
+						}
+						break;
+					case 17:
 						{
 						_localctx = new ExprPostModContext(new ExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expr);
-						setState(473);
+						setState(479);
 						if (!(precpred(_ctx, 22))) throw new FailedPredicateException(this, "precpred(_ctx, 22)");
-						setState(474);
+						setState(480);
 						_la = _input.LA(1);
-						if ( !(_la==T__35 || _la==T__36) ) {
+						if ( !(_la==T__37 || _la==T__38) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -3729,7 +3793,7 @@ public class KickCParser extends Parser {
 					}
 					} 
 				}
-				setState(479);
+				setState(485);
 				_errHandler.sync(this);
 				_alt = getInterpreter().adaptivePredict(_input,43,_ctx);
 			}
@@ -3779,21 +3843,21 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(480);
+			setState(486);
 			expr(0);
-			setState(485);
+			setState(491);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(481);
+				setState(487);
 				match(T__2);
-				setState(482);
+				setState(488);
 				expr(0);
 				}
 				}
-				setState(487);
+				setState(493);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -3841,19 +3905,19 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(488);
-			match(T__67);
-			setState(490);
+			setState(494);
+			match(T__69);
+			setState(496);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			if (_la==T__4) {
 				{
-				setState(489);
+				setState(495);
 				asmDirectives();
 				}
 			}
 
-			setState(492);
+			setState(498);
 			match(KICKASM);
 			}
 		}
@@ -3901,27 +3965,27 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(494);
-			match(T__4);
-			setState(495);
-			asmDirective();
 			setState(500);
+			match(T__4);
+			setState(501);
+			asmDirective();
+			setState(506);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(496);
+				setState(502);
 				match(T__2);
-				setState(497);
+				setState(503);
 				asmDirective();
 				}
 				}
-				setState(502);
+				setState(508);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
-			setState(503);
+			setState(509);
 			match(T__5);
 			}
 		}
@@ -4060,79 +4124,77 @@ public class KickCParser extends Parser {
 		AsmDirectiveContext _localctx = new AsmDirectiveContext(_ctx, getState());
 		enterRule(_localctx, 58, RULE_asmDirective);
 		try {
-			setState(520);
+			setState(526);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
-			case T__68:
+			case T__70:
 				_localctx = new AsmDirectiveResourceContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(505);
-				match(T__68);
-				setState(506);
-				match(STRING);
-				}
-				break;
-			case T__69:
-				_localctx = new AsmDirectiveUsesContext(_localctx);
-				enterOuterAlt(_localctx, 2);
-				{
-				setState(507);
-				match(T__69);
-				setState(508);
-				match(NAME);
-				}
-				break;
-			case T__70:
-				_localctx = new AsmDirectiveClobberContext(_localctx);
-				enterOuterAlt(_localctx, 3);
-				{
-				setState(509);
+				setState(511);
 				match(T__70);
-				setState(510);
+				setState(512);
 				match(STRING);
 				}
 				break;
 			case T__71:
-				_localctx = new AsmDirectiveBytesContext(_localctx);
-				enterOuterAlt(_localctx, 4);
+				_localctx = new AsmDirectiveUsesContext(_localctx);
+				enterOuterAlt(_localctx, 2);
 				{
-				setState(511);
+				setState(513);
 				match(T__71);
-				setState(512);
-				expr(0);
+				setState(514);
+				match(NAME);
 				}
 				break;
 			case T__72:
-				_localctx = new AsmDirectiveCyclesContext(_localctx);
-				enterOuterAlt(_localctx, 5);
+				_localctx = new AsmDirectiveClobberContext(_localctx);
+				enterOuterAlt(_localctx, 3);
 				{
-				setState(513);
+				setState(515);
 				match(T__72);
-				setState(514);
-				expr(0);
+				setState(516);
+				match(STRING);
 				}
 				break;
 			case T__73:
+				_localctx = new AsmDirectiveBytesContext(_localctx);
+				enterOuterAlt(_localctx, 4);
+				{
+				setState(517);
+				match(T__73);
+				setState(518);
+				expr(0);
+				}
+				break;
+			case T__74:
+				_localctx = new AsmDirectiveCyclesContext(_localctx);
+				enterOuterAlt(_localctx, 5);
+				{
+				setState(519);
+				match(T__74);
+				setState(520);
+				expr(0);
+				}
+				break;
+			case T__75:
 				_localctx = new AsmDirectiveAddressContext(_localctx);
 				enterOuterAlt(_localctx, 6);
 				{
-				setState(515);
-				match(T__73);
-				setState(518);
+				setState(521);
+				match(T__75);
+				setState(524);
 				_errHandler.sync(this);
 				switch (_input.LA(1)) {
 				case T__12:
 					{
-					setState(516);
+					setState(522);
 					match(T__12);
 					}
 					break;
 				case T__4:
 				case T__6:
 				case T__29:
-				case T__33:
-				case T__34:
 				case T__35:
 				case T__36:
 				case T__37:
@@ -4140,15 +4202,17 @@ public class KickCParser extends Parser {
 				case T__39:
 				case T__40:
 				case T__41:
-				case T__46:
-				case T__47:
+				case T__42:
+				case T__43:
+				case T__48:
+				case T__49:
 				case STRING:
 				case CHAR:
 				case BOOLEAN:
 				case NUMBER:
 				case NAME:
 					{
-					setState(517);
+					setState(523);
 					expr(0);
 					}
 					break;
@@ -4205,17 +4269,17 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(525);
+			setState(531);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
-			while (((((_la - 40)) & ~0x3f) == 0 && ((1L << (_la - 40)) & ((1L << (T__39 - 40)) | (1L << (T__74 - 40)) | (1L << (MNEMONIC - 40)) | (1L << (NAME - 40)))) != 0)) {
+			while (((((_la - 42)) & ~0x3f) == 0 && ((1L << (_la - 42)) & ((1L << (T__41 - 42)) | (1L << (T__76 - 42)) | (1L << (MNEMONIC - 42)) | (1L << (NAME - 42)))) != 0)) {
 				{
 				{
-				setState(522);
+				setState(528);
 				asmLine();
 				}
 				}
-				setState(527);
+				setState(533);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -4265,28 +4329,28 @@ public class KickCParser extends Parser {
 		AsmLineContext _localctx = new AsmLineContext(_ctx, getState());
 		enterRule(_localctx, 62, RULE_asmLine);
 		try {
-			setState(531);
+			setState(537);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
-			case T__39:
+			case T__41:
 			case NAME:
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(528);
+				setState(534);
 				asmLabel();
 				}
 				break;
 			case MNEMONIC:
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(529);
+				setState(535);
 				asmInstruction();
 				}
 				break;
-			case T__74:
+			case T__76:
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(530);
+				setState(536);
 				asmBytes();
 				}
 				break;
@@ -4356,36 +4420,36 @@ public class KickCParser extends Parser {
 		enterRule(_localctx, 64, RULE_asmLabel);
 		int _la;
 		try {
-			setState(540);
+			setState(546);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case NAME:
 				_localctx = new AsmLabelNameContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(533);
+				setState(539);
 				match(NAME);
-				setState(534);
+				setState(540);
 				match(T__25);
 				}
 				break;
-			case T__39:
+			case T__41:
 				_localctx = new AsmLabelMultiContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(535);
-				match(T__39);
-				setState(537);
+				setState(541);
+				match(T__41);
+				setState(543);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				if (_la==NAME) {
 					{
-					setState(536);
+					setState(542);
 					match(NAME);
 					}
 				}
 
-				setState(539);
+				setState(545);
 				match(T__25);
 				}
 				break;
@@ -4434,14 +4498,14 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(542);
+			setState(548);
 			match(MNEMONIC);
-			setState(544);
+			setState(550);
 			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,53,_ctx) ) {
 			case 1:
 				{
-				setState(543);
+				setState(549);
 				asmParamMode();
 				}
 				break;
@@ -4492,23 +4556,23 @@ public class KickCParser extends Parser {
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(546);
-			match(T__74);
-			setState(547);
-			asmExpr(0);
 			setState(552);
+			match(T__76);
+			setState(553);
+			asmExpr(0);
+			setState(558);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__2) {
 				{
 				{
-				setState(548);
+				setState(554);
 				match(T__2);
-				setState(549);
+				setState(555);
 				asmExpr(0);
 				}
 				}
-				setState(554);
+				setState(560);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -4658,14 +4722,14 @@ public class KickCParser extends Parser {
 		AsmParamModeContext _localctx = new AsmParamModeContext(_ctx, getState());
 		enterRule(_localctx, 70, RULE_asmParamMode);
 		try {
-			setState(578);
+			setState(584);
 			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,55,_ctx) ) {
 			case 1:
 				_localctx = new AsmModeAbsContext(_localctx);
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(555);
+				setState(561);
 				asmExpr(0);
 				}
 				break;
@@ -4673,9 +4737,9 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeImmContext(_localctx);
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(556);
-				match(T__75);
-				setState(557);
+				setState(562);
+				match(T__77);
+				setState(563);
 				asmExpr(0);
 				}
 				break;
@@ -4683,11 +4747,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeAbsXYContext(_localctx);
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(558);
+				setState(564);
 				asmExpr(0);
-				setState(559);
+				setState(565);
 				match(T__2);
-				setState(560);
+				setState(566);
 				match(NAME);
 				}
 				break;
@@ -4695,15 +4759,15 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIndIdxXYContext(_localctx);
 				enterOuterAlt(_localctx, 4);
 				{
-				setState(562);
+				setState(568);
 				match(T__4);
-				setState(563);
+				setState(569);
 				asmExpr(0);
-				setState(564);
+				setState(570);
 				match(T__5);
-				setState(565);
+				setState(571);
 				match(T__2);
-				setState(566);
+				setState(572);
 				match(NAME);
 				}
 				break;
@@ -4711,15 +4775,15 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIdxIndXYContext(_localctx);
 				enterOuterAlt(_localctx, 5);
 				{
-				setState(568);
+				setState(574);
 				match(T__4);
-				setState(569);
+				setState(575);
 				asmExpr(0);
-				setState(570);
+				setState(576);
 				match(T__2);
-				setState(571);
+				setState(577);
 				match(NAME);
-				setState(572);
+				setState(578);
 				match(T__5);
 				}
 				break;
@@ -4727,11 +4791,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmModeIndContext(_localctx);
 				enterOuterAlt(_localctx, 6);
 				{
-				setState(574);
+				setState(580);
 				match(T__4);
-				setState(575);
+				setState(581);
 				asmExpr(0);
-				setState(576);
+				setState(582);
 				match(T__5);
 				}
 				break;
@@ -4921,7 +4985,7 @@ public class KickCParser extends Parser {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(594);
+			setState(600);
 			_errHandler.sync(this);
 			switch (_input.LA(1)) {
 			case T__30:
@@ -4930,25 +4994,25 @@ public class KickCParser extends Parser {
 				_ctx = _localctx;
 				_prevctx = _localctx;
 
-				setState(581);
+				setState(587);
 				match(T__30);
-				setState(582);
+				setState(588);
 				asmExpr(0);
-				setState(583);
+				setState(589);
 				match(T__31);
 				}
 				break;
-			case T__37:
-			case T__38:
-			case T__46:
-			case T__47:
+			case T__39:
+			case T__40:
+			case T__48:
+			case T__49:
 				{
 				_localctx = new AsmExprUnaryContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(585);
+				setState(591);
 				_la = _input.LA(1);
-				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__37) | (1L << T__38) | (1L << T__46) | (1L << T__47))) != 0)) ) {
+				if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__39) | (1L << T__40) | (1L << T__48) | (1L << T__49))) != 0)) ) {
 				_errHandler.recoverInline(this);
 				}
 				else {
@@ -4956,7 +5020,7 @@ public class KickCParser extends Parser {
 					_errHandler.reportMatch(this);
 					consume();
 				}
-				setState(586);
+				setState(592);
 				asmExpr(8);
 				}
 				break;
@@ -4965,7 +5029,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprLabelContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(587);
+				setState(593);
 				match(NAME);
 				}
 				break;
@@ -4974,7 +5038,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprLabelRelContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(588);
+				setState(594);
 				match(ASMREL);
 				}
 				break;
@@ -4983,11 +5047,11 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprReplaceContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(589);
+				setState(595);
 				match(T__6);
-				setState(590);
+				setState(596);
 				match(NAME);
-				setState(591);
+				setState(597);
 				match(T__7);
 				}
 				break;
@@ -4996,7 +5060,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprIntContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(592);
+				setState(598);
 				match(NUMBER);
 				}
 				break;
@@ -5005,7 +5069,7 @@ public class KickCParser extends Parser {
 				_localctx = new AsmExprCharContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(593);
+				setState(599);
 				match(CHAR);
 				}
 				break;
@@ -5013,7 +5077,7 @@ public class KickCParser extends Parser {
 				throw new NoViableAltException(this);
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(610);
+			setState(616);
 			_errHandler.sync(this);
 			_alt = getInterpreter().adaptivePredict(_input,58,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
@@ -5021,72 +5085,32 @@ public class KickCParser extends Parser {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
 					_prevctx = _localctx;
 					{
-					setState(608);
+					setState(614);
 					_errHandler.sync(this);
 					switch ( getInterpreter().adaptivePredict(_input,57,_ctx) ) {
 					case 1:
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(596);
+						setState(602);
 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
 						{
-						setState(597);
-						match(T__76);
+						setState(603);
+						match(T__33);
 						}
-						setState(598);
+						setState(604);
 						asmExpr(11);
 						}
 						break;
 					case 2:
-						{
-						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
-						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(599);
-						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
-						setState(600);
-						_la = _input.LA(1);
-						if ( !(_la==T__42 || _la==T__43) ) {
-						_errHandler.recoverInline(this);
-						}
-						else {
-							if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
-							_errHandler.reportMatch(this);
-							consume();
-						}
-						setState(601);
-						asmExpr(10);
-						}
-						break;
-					case 3:
-						{
-						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
-						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
-						setState(602);
-						if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
-						setState(603);
-						_la = _input.LA(1);
-						if ( !(_la==T__29 || _la==T__44) ) {
-						_errHandler.recoverInline(this);
-						}
-						else {
-							if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
-							_errHandler.reportMatch(this);
-							consume();
-						}
-						setState(604);
-						asmExpr(8);
-						}
-						break;
-					case 4:
 						{
 						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
 						setState(605);
-						if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
+						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
 						setState(606);
 						_la = _input.LA(1);
-						if ( !(_la==T__37 || _la==T__38) ) {
+						if ( !(_la==T__44 || _la==T__45) ) {
 						_errHandler.recoverInline(this);
 						}
 						else {
@@ -5095,13 +5119,53 @@ public class KickCParser extends Parser {
 							consume();
 						}
 						setState(607);
+						asmExpr(10);
+						}
+						break;
+					case 3:
+						{
+						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
+						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
+						setState(608);
+						if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
+						setState(609);
+						_la = _input.LA(1);
+						if ( !(_la==T__29 || _la==T__46) ) {
+						_errHandler.recoverInline(this);
+						}
+						else {
+							if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
+							_errHandler.reportMatch(this);
+							consume();
+						}
+						setState(610);
+						asmExpr(8);
+						}
+						break;
+					case 4:
+						{
+						_localctx = new AsmExprBinaryContext(new AsmExprContext(_parentctx, _parentState));
+						pushNewRecursionContext(_localctx, _startState, RULE_asmExpr);
+						setState(611);
+						if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
+						setState(612);
+						_la = _input.LA(1);
+						if ( !(_la==T__39 || _la==T__40) ) {
+						_errHandler.recoverInline(this);
+						}
+						else {
+							if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
+							_errHandler.reportMatch(this);
+							consume();
+						}
+						setState(613);
 						asmExpr(7);
 						}
 						break;
 					}
 					} 
 				}
-				setState(612);
+				setState(618);
 				_errHandler.sync(this);
 				_alt = getInterpreter().adaptivePredict(_input,58,_ctx);
 			}
@@ -5185,30 +5249,34 @@ public class KickCParser extends Parser {
 		case 16:
 			return precpred(_ctx, 7);
 		case 17:
-			return precpred(_ctx, 28);
+			return precpred(_ctx, 30);
 		case 18:
-			return precpred(_ctx, 25);
+			return precpred(_ctx, 29);
 		case 19:
+			return precpred(_ctx, 28);
+		case 20:
+			return precpred(_ctx, 25);
+		case 21:
 			return precpred(_ctx, 22);
 		}
 		return true;
 	}
 	private boolean asmExpr_sempred(AsmExprContext _localctx, int predIndex) {
 		switch (predIndex) {
-		case 20:
-			return precpred(_ctx, 10);
-		case 21:
-			return precpred(_ctx, 9);
 		case 22:
-			return precpred(_ctx, 7);
+			return precpred(_ctx, 10);
 		case 23:
+			return precpred(_ctx, 9);
+		case 24:
+			return precpred(_ctx, 7);
+		case 25:
 			return precpred(_ctx, 6);
 		}
 		return true;
 	}
 
 	public static final String _serializedATN =
-		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3c\u0268\4\2\t\2\4"+
+		"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3d\u026e\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"+
@@ -5244,210 +5312,213 @@ public class KickCParser extends Parser {
 		"\6\33\u01a2\n\33\r\33\16\33\u01a3\3\33\3\33\5\33\u01a8\n\33\3\33\3\33"+
 		"\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
 		"\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
-		"\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\5\33\u01d4"+
-		"\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\7\33\u01de\n\33\f\33\16"+
-		"\33\u01e1\13\33\3\34\3\34\3\34\7\34\u01e6\n\34\f\34\16\34\u01e9\13\34"+
-		"\3\35\3\35\5\35\u01ed\n\35\3\35\3\35\3\36\3\36\3\36\3\36\7\36\u01f5\n"+
-		"\36\f\36\16\36\u01f8\13\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37"+
-		"\3\37\3\37\3\37\3\37\3\37\3\37\5\37\u0209\n\37\5\37\u020b\n\37\3 \7 \u020e"+
-		"\n \f \16 \u0211\13 \3!\3!\3!\5!\u0216\n!\3\"\3\"\3\"\3\"\5\"\u021c\n"+
-		"\"\3\"\5\"\u021f\n\"\3#\3#\5#\u0223\n#\3$\3$\3$\3$\7$\u0229\n$\f$\16$"+
-		"\u022c\13$\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3"+
-		"%\3%\3%\3%\5%\u0245\n%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\5&\u0255"+
-		"\n&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\7&\u0263\n&\f&\16&\u0266\13&\3"+
-		"&\2\7\22*\62\64J\'\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60"+
-		"\62\64\668:<>@BDFHJ\2\r\3\2\36\37\3\2&\'\3\2(,\3\2\61\62\3\2-.\4\2  /"+
-		"\60\3\2()\3\2\61\66\3\2<E\4\2()\61\62\4\2  //\2\u02bd\2L\3\2\2\2\4P\3"+
-		"\2\2\2\6V\3\2\2\2\bY\3\2\2\2\n]\3\2\2\2\fj\3\2\2\2\16o\3\2\2\2\20y\3\2"+
-		"\2\2\22|\3\2\2\2\24\u0087\3\2\2\2\26\u008c\3\2\2\2\30\u0099\3\2\2\2\32"+
-		"\u00a5\3\2\2\2\34\u00a7\3\2\2\2\36\u00bd\3\2\2\2 \u00bf\3\2\2\2\"\u00cc"+
-		"\3\2\2\2$\u011c\3\2\2\2&\u012e\3\2\2\2(\u0134\3\2\2\2*\u0142\3\2\2\2,"+
-		"\u0154\3\2\2\2.\u0157\3\2\2\2\60\u0163\3\2\2\2\62\u0166\3\2\2\2\64\u01a7"+
-		"\3\2\2\2\66\u01e2\3\2\2\28\u01ea\3\2\2\2:\u01f0\3\2\2\2<\u020a\3\2\2\2"+
-		">\u020f\3\2\2\2@\u0215\3\2\2\2B\u021e\3\2\2\2D\u0220\3\2\2\2F\u0224\3"+
-		"\2\2\2H\u0244\3\2\2\2J\u0254\3\2\2\2LM\5\6\4\2MN\5\n\6\2NO\7\2\2\3O\3"+
-		"\3\2\2\2PQ\5> \2QR\7\2\2\3R\5\3\2\2\2SU\5\b\5\2TS\3\2\2\2UX\3\2\2\2VT"+
-		"\3\2\2\2VW\3\2\2\2W\7\3\2\2\2XV\3\2\2\2YZ\7\3\2\2Z[\7S\2\2[\t\3\2\2\2"+
-		"\\^\5\f\7\2]\\\3\2\2\2^_\3\2\2\2_]\3\2\2\2_`\3\2\2\2`\13\3\2\2\2ab\5\20"+
-		"\t\2bc\7\4\2\2ck\3\2\2\2de\5.\30\2ef\7\4\2\2fk\3\2\2\2gk\5\26\f\2hk\5"+
-		"8\35\2ik\5\34\17\2ja\3\2\2\2jd\3\2\2\2jg\3\2\2\2jh\3\2\2\2ji\3\2\2\2k"+
-		"\r\3\2\2\2ln\5\36\20\2ml\3\2\2\2nq\3\2\2\2om\3\2\2\2op\3\2\2\2pr\3\2\2"+
-		"\2qo\3\2\2\2rv\5*\26\2su\5\36\20\2ts\3\2\2\2ux\3\2\2\2vt\3\2\2\2vw\3\2"+
-		"\2\2w\17\3\2\2\2xv\3\2\2\2yz\5\16\b\2z{\5\22\n\2{\21\3\2\2\2|}\b\n\1\2"+
-		"}~\5\24\13\2~\u0084\3\2\2\2\177\u0080\f\3\2\2\u0080\u0081\7\5\2\2\u0081"+
-		"\u0083\5\24\13\2\u0082\177\3\2\2\2\u0083\u0086\3\2\2\2\u0084\u0082\3\2"+
-		"\2\2\u0084\u0085\3\2\2\2\u0085\23\3\2\2\2\u0086\u0084\3\2\2\2\u0087\u008a"+
-		"\7_\2\2\u0088\u0089\7\6\2\2\u0089\u008b\5\64\33\2\u008a\u0088\3\2\2\2"+
-		"\u008a\u008b\3\2\2\2\u008b\25\3\2\2\2\u008c\u008d\5\16\b\2\u008d\u008e"+
-		"\7_\2\2\u008e\u0090\7\7\2\2\u008f\u0091\5\30\r\2\u0090\u008f\3\2\2\2\u0090"+
-		"\u0091\3\2\2\2\u0091\u0092\3\2\2\2\u0092\u0093\7\b\2\2\u0093\u0095\7\t"+
-		"\2\2\u0094\u0096\5\"\22\2\u0095\u0094\3\2\2\2\u0095\u0096\3\2\2\2\u0096"+
-		"\u0097\3\2\2\2\u0097\u0098\7\n\2\2\u0098\27\3\2\2\2\u0099\u009e\5\32\16"+
-		"\2\u009a\u009b\7\5\2\2\u009b\u009d\5\32\16\2\u009c\u009a\3\2\2\2\u009d"+
-		"\u00a0\3\2\2\2\u009e\u009c\3\2\2\2\u009e\u009f\3\2\2\2\u009f\31\3\2\2"+
-		"\2\u00a0\u009e\3\2\2\2\u00a1\u00a2\5\16\b\2\u00a2\u00a3\7_\2\2\u00a3\u00a6"+
-		"\3\2\2\2\u00a4\u00a6\7R\2\2\u00a5\u00a1\3\2\2\2\u00a5\u00a4\3\2\2\2\u00a6"+
-		"\33\3\2\2\2\u00a7\u00a8\5 \21\2\u00a8\u00a9\7\4\2\2\u00a9\35\3\2\2\2\u00aa"+
-		"\u00be\7\13\2\2\u00ab\u00be\7\f\2\2\u00ac\u00ad\7\r\2\2\u00ad\u00ae\7"+
-		"\7\2\2\u00ae\u00af\7V\2\2\u00af\u00be\7\b\2\2\u00b0\u00b1\7\16\2\2\u00b1"+
-		"\u00b2\7\7\2\2\u00b2\u00b3\7_\2\2\u00b3\u00be\7\b\2\2\u00b4\u00be\7\17"+
-		"\2\2\u00b5\u00be\7\20\2\2\u00b6\u00ba\7\21\2\2\u00b7\u00b8\7\7\2\2\u00b8"+
-		"\u00b9\7_\2\2\u00b9\u00bb\7\b\2\2\u00ba\u00b7\3\2\2\2\u00ba\u00bb\3\2"+
-		"\2\2\u00bb\u00be\3\2\2\2\u00bc\u00be\5 \21\2\u00bd\u00aa\3\2\2\2\u00bd"+
-		"\u00ab\3\2\2\2\u00bd\u00ac\3\2\2\2\u00bd\u00b0\3\2\2\2\u00bd\u00b4\3\2"+
-		"\2\2\u00bd\u00b5\3\2\2\2\u00bd\u00b6\3\2\2\2\u00bd\u00bc\3\2\2\2\u00be"+
-		"\37\3\2\2\2\u00bf\u00c0\7\22\2\2\u00c0\u00c1\7\7\2\2\u00c1\u00c6\7V\2"+
-		"\2\u00c2\u00c3\7\5\2\2\u00c3\u00c5\7V\2\2\u00c4\u00c2\3\2\2\2\u00c5\u00c8"+
-		"\3\2\2\2\u00c6\u00c4\3\2\2\2\u00c6\u00c7\3\2\2\2\u00c7\u00c9\3\2\2\2\u00c8"+
-		"\u00c6\3\2\2\2\u00c9\u00ca\7\b\2\2\u00ca!\3\2\2\2\u00cb\u00cd\5$\23\2"+
-		"\u00cc\u00cb\3\2\2\2\u00cd\u00ce\3\2\2\2\u00ce\u00cc\3\2\2\2\u00ce\u00cf"+
-		"\3\2\2\2\u00cf#\3\2\2\2\u00d0\u00d1\5\20\t\2\u00d1\u00d2\7\4\2\2\u00d2"+
-		"\u011d\3\2\2\2\u00d3\u00d5\7\t\2\2\u00d4\u00d6\5\"\22\2\u00d5\u00d4\3"+
-		"\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\u00d7\3\2\2\2\u00d7\u011d\7\n\2\2\u00d8"+
-		"\u00d9\5\62\32\2\u00d9\u00da\7\4\2\2\u00da\u011d\3\2\2\2\u00db\u00dc\7"+
-		"\23\2\2\u00dc\u00dd\7\7\2\2\u00dd\u00de\5\62\32\2\u00de\u00df\7\b\2\2"+
-		"\u00df\u00e2\5$\23\2\u00e0\u00e1\7\24\2\2\u00e1\u00e3\5$\23\2\u00e2\u00e0"+
-		"\3\2\2\2\u00e2\u00e3\3\2\2\2\u00e3\u011d\3\2\2\2\u00e4\u00e6\5\36\20\2"+
-		"\u00e5\u00e4\3\2\2\2\u00e6\u00e9\3\2\2\2\u00e7\u00e5\3\2\2\2\u00e7\u00e8"+
-		"\3\2\2\2\u00e8\u00ea\3\2\2\2\u00e9\u00e7\3\2\2\2\u00ea\u00eb\7\25\2\2"+
-		"\u00eb\u00ec\7\7\2\2\u00ec\u00ed\5\62\32\2\u00ed\u00ee\7\b\2\2\u00ee\u00ef"+
-		"\5$\23\2\u00ef\u011d\3\2\2\2\u00f0\u00f2\5\36\20\2\u00f1\u00f0\3\2\2\2"+
-		"\u00f2\u00f5\3\2\2\2\u00f3\u00f1\3\2\2\2\u00f3\u00f4\3\2\2\2\u00f4\u00f6"+
-		"\3\2\2\2\u00f5\u00f3\3\2\2\2\u00f6\u00f7\7\26\2\2\u00f7\u00f8\5$\23\2"+
-		"\u00f8\u00f9\7\25\2\2\u00f9\u00fa\7\7\2\2\u00fa\u00fb\5\62\32\2\u00fb"+
-		"\u00fc\7\b\2\2\u00fc\u00fd\7\4\2\2\u00fd\u011d\3\2\2\2\u00fe\u0100\5\36"+
-		"\20\2\u00ff\u00fe\3\2\2\2\u0100\u0103\3\2\2\2\u0101\u00ff\3\2\2\2\u0101"+
-		"\u0102\3\2\2\2\u0102\u0104\3\2\2\2\u0103\u0101\3\2\2\2\u0104\u0105\7\27"+
-		"\2\2\u0105\u0106\7\7\2\2\u0106\u0107\5&\24\2\u0107\u0108\7\b\2\2\u0108"+
-		"\u0109\5$\23\2\u0109\u011d\3\2\2\2\u010a\u010c\7\30\2\2\u010b\u010d\5"+
-		"\62\32\2\u010c\u010b\3\2\2\2\u010c\u010d\3\2\2\2\u010d\u010e\3\2\2\2\u010e"+
-		"\u011d\7\4\2\2\u010f\u0110\7\31\2\2\u0110\u011d\7\4\2\2\u0111\u0112\7"+
-		"\32\2\2\u0112\u011d\7\4\2\2\u0113\u0115\7\33\2\2\u0114\u0116\5:\36\2\u0115"+
-		"\u0114\3\2\2\2\u0115\u0116\3\2\2\2\u0116\u0117\3\2\2\2\u0117\u0118\7\t"+
-		"\2\2\u0118\u0119\5> \2\u0119\u011a\7\n\2\2\u011a\u011d\3\2\2\2\u011b\u011d"+
-		"\58\35\2\u011c\u00d0\3\2\2\2\u011c\u00d3\3\2\2\2\u011c\u00d8\3\2\2\2\u011c"+
-		"\u00db\3\2\2\2\u011c\u00e7\3\2\2\2\u011c\u00f3\3\2\2\2\u011c\u0101\3\2"+
-		"\2\2\u011c\u010a\3\2\2\2\u011c\u010f\3\2\2\2\u011c\u0111\3\2\2\2\u011c"+
-		"\u0113\3\2\2\2\u011c\u011b\3\2\2\2\u011d%\3\2\2\2\u011e\u011f\5(\25\2"+
-		"\u011f\u0120\7\4\2\2\u0120\u0121\5\62\32\2\u0121\u0123\7\4\2\2\u0122\u0124"+
-		"\5\62\32\2\u0123\u0122\3\2\2\2\u0123\u0124\3\2\2\2\u0124\u012f\3\2\2\2"+
-		"\u0125\u0127\5\16\b\2\u0126\u0125\3\2\2\2\u0126\u0127\3\2\2\2\u0127\u0128"+
-		"\3\2\2\2\u0128\u0129\7_\2\2\u0129\u012a\7\34\2\2\u012a\u012b\5\64\33\2"+
-		"\u012b\u012c\7\35\2\2\u012c\u012d\5\64\33\2\u012d\u012f\3\2\2\2\u012e"+
-		"\u011e\3\2\2\2\u012e\u0126\3\2\2\2\u012f\'\3\2\2\2\u0130\u0132\5\20\t"+
-		"\2\u0131\u0130\3\2\2\2\u0131\u0132\3\2\2\2\u0132\u0135\3\2\2\2\u0133\u0135"+
-		"\5\62\32\2\u0134\u0131\3\2\2\2\u0134\u0133\3\2\2\2\u0135)\3\2\2\2\u0136"+
-		"\u0137\b\26\1\2\u0137\u0138\7\7\2\2\u0138\u0139\5*\26\2\u0139\u013a\7"+
-		"\b\2\2\u013a\u0143\3\2\2\2\u013b\u0143\7R\2\2\u013c\u013e\t\2\2\2\u013d"+
-		"\u013f\7R\2\2\u013e\u013d\3\2\2\2\u013e\u013f\3\2\2\2\u013f\u0143\3\2"+
-		"\2\2\u0140\u0143\5.\30\2\u0141\u0143\5,\27\2\u0142\u0136\3\2\2\2\u0142"+
-		"\u013b\3\2\2\2\u0142\u013c\3\2\2\2\u0142\u0140\3\2\2\2\u0142\u0141\3\2"+
-		"\2\2\u0143\u0151\3\2\2\2\u0144\u0145\f\7\2\2\u0145\u0150\7 \2\2\u0146"+
-		"\u0147\f\6\2\2\u0147\u0149\7!\2\2\u0148\u014a\5\64\33\2\u0149\u0148\3"+
-		"\2\2\2\u0149\u014a\3\2\2\2\u014a\u014b\3\2\2\2\u014b\u0150\7\"\2\2\u014c"+
-		"\u014d\f\5\2\2\u014d\u014e\7\7\2\2\u014e\u0150\7\b\2\2\u014f\u0144\3\2"+
-		"\2\2\u014f\u0146\3\2\2\2\u014f\u014c\3\2\2\2\u0150\u0153\3\2\2\2\u0151"+
-		"\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152+\3\2\2\2\u0153\u0151\3\2\2\2"+
-		"\u0154\u0155\7#\2\2\u0155\u0156\7_\2\2\u0156-\3\2\2\2\u0157\u0159\7#\2"+
-		"\2\u0158\u015a\7_\2\2\u0159\u0158\3\2\2\2\u0159\u015a\3\2\2\2\u015a\u015b"+
-		"\3\2\2\2\u015b\u015d\7\t\2\2\u015c\u015e\5\60\31\2\u015d\u015c\3\2\2\2"+
-		"\u015e\u015f\3\2\2\2\u015f\u015d\3\2\2\2\u015f\u0160\3\2\2\2\u0160\u0161"+
-		"\3\2\2\2\u0161\u0162\7\n\2\2\u0162/\3\2\2\2\u0163\u0164\5\20\t\2\u0164"+
-		"\u0165\7\4\2\2\u0165\61\3\2\2\2\u0166\u0167\b\32\1\2\u0167\u0168\5\64"+
-		"\33\2\u0168\u016e\3\2\2\2\u0169\u016a\f\3\2\2\u016a\u016b\7\5\2\2\u016b"+
-		"\u016d\5\64\33\2\u016c\u0169\3\2\2\2\u016d\u0170\3\2\2\2\u016e\u016c\3"+
-		"\2\2\2\u016e\u016f\3\2\2\2\u016f\63\3\2\2\2\u0170\u016e\3\2\2\2\u0171"+
-		"\u0172\b\33\1\2\u0172\u0173\7\7\2\2\u0173\u0174\5\62\32\2\u0174\u0175"+
-		"\7\b\2\2\u0175\u01a8\3\2\2\2\u0176\u0177\7$\2\2\u0177\u017a\7\7\2\2\u0178"+
-		"\u017b\5*\26\2\u0179\u017b\5\64\33\2\u017a\u0178\3\2\2\2\u017a\u0179\3"+
-		"\2\2\2\u017b\u017c\3\2\2\2\u017c\u017d\7\b\2\2\u017d\u01a8\3\2\2\2\u017e"+
-		"\u017f\7%\2\2\u017f\u0182\7\7\2\2\u0180\u0183\5*\26\2\u0181\u0183\5\64"+
-		"\33\2\u0182\u0180\3\2\2\2\u0182\u0181\3\2\2\2\u0183\u0184\3\2\2\2\u0184"+
-		"\u0185\7\b\2\2\u0185\u01a8\3\2\2\2\u0186\u0187\7\7\2\2\u0187\u0188\5*"+
-		"\26\2\u0188\u0189\7\b\2\2\u0189\u018a\5\64\33\32\u018a\u01a8\3\2\2\2\u018b"+
-		"\u018c\t\3\2\2\u018c\u01a8\5\64\33\31\u018d\u018e\7 \2\2\u018e\u01a8\5"+
-		"\64\33\27\u018f\u0190\t\4\2\2\u0190\u01a8\5\64\33\26\u0191\u0192\t\5\2"+
-		"\2\u0192\u01a8\5\64\33\22\u0193\u0194\7\t\2\2\u0194\u0199\5\64\33\2\u0195"+
-		"\u0196\7\5\2\2\u0196\u0198\5\64\33\2\u0197\u0195\3\2\2\2\u0198\u019b\3"+
-		"\2\2\2\u0199\u0197\3\2\2\2\u0199\u019a\3\2\2\2\u019a\u019c\3\2\2\2\u019b"+
-		"\u0199\3\2\2\2\u019c\u019d\7\n\2\2\u019d\u01a8\3\2\2\2\u019e\u01a8\7_"+
-		"\2\2\u019f\u01a8\7V\2\2\u01a0\u01a2\7S\2\2\u01a1\u01a0\3\2\2\2\u01a2\u01a3"+
-		"\3\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4\u01a8\3\2\2\2\u01a5"+
-		"\u01a8\7T\2\2\u01a6\u01a8\7U\2\2\u01a7\u0171\3\2\2\2\u01a7\u0176\3\2\2"+
-		"\2\u01a7\u017e\3\2\2\2\u01a7\u0186\3\2\2\2\u01a7\u018b\3\2\2\2\u01a7\u018d"+
-		"\3\2\2\2\u01a7\u018f\3\2\2\2\u01a7\u0191\3\2\2\2\u01a7\u0193\3\2\2\2\u01a7"+
-		"\u019e\3\2\2\2\u01a7\u019f\3\2\2\2\u01a7\u01a1\3\2\2\2\u01a7\u01a5\3\2"+
-		"\2\2\u01a7\u01a6\3\2\2\2\u01a8\u01df\3\2\2\2\u01a9\u01aa\f\25\2\2\u01aa"+
-		"\u01ab\t\6\2\2\u01ab\u01de\5\64\33\26\u01ac\u01ad\f\24\2\2\u01ad\u01ae"+
-		"\t\7\2\2\u01ae\u01de\5\64\33\25\u01af\u01b0\f\23\2\2\u01b0\u01b1\t\b\2"+
-		"\2\u01b1\u01de\5\64\33\24\u01b2\u01b3\f\21\2\2\u01b3\u01b4\t\t\2\2\u01b4"+
-		"\u01de\5\64\33\22\u01b5\u01b6\f\20\2\2\u01b6\u01b7\7+\2\2\u01b7\u01de"+
-		"\5\64\33\21\u01b8\u01b9\f\17\2\2\u01b9\u01ba\7\67\2\2\u01ba\u01de\5\64"+
-		"\33\20\u01bb\u01bc\f\16\2\2\u01bc\u01bd\78\2\2\u01bd\u01de\5\64\33\17"+
-		"\u01be\u01bf\f\r\2\2\u01bf\u01c0\79\2\2\u01c0\u01de\5\64\33\16\u01c1\u01c2"+
-		"\f\f\2\2\u01c2\u01c3\7:\2\2\u01c3\u01de\5\64\33\r\u01c4\u01c5\f\13\2\2"+
-		"\u01c5\u01c6\7;\2\2\u01c6\u01c7\5\64\33\2\u01c7\u01c8\7\34\2\2\u01c8\u01c9"+
-		"\5\64\33\f\u01c9\u01de\3\2\2\2\u01ca\u01cb\f\n\2\2\u01cb\u01cc\7\6\2\2"+
-		"\u01cc\u01de\5\64\33\n\u01cd\u01ce\f\t\2\2\u01ce\u01cf\t\n\2\2\u01cf\u01de"+
-		"\5\64\33\t\u01d0\u01d1\f\36\2\2\u01d1\u01d3\7\7\2\2\u01d2\u01d4\5\66\34"+
-		"\2\u01d3\u01d2\3\2\2\2\u01d3\u01d4\3\2\2\2\u01d4\u01d5\3\2\2\2\u01d5\u01de"+
-		"\7\b\2\2\u01d6\u01d7\f\33\2\2\u01d7\u01d8\7!\2\2\u01d8\u01d9\5\62\32\2"+
-		"\u01d9\u01da\7\"\2\2\u01da\u01de\3\2\2\2\u01db\u01dc\f\30\2\2\u01dc\u01de"+
-		"\t\3\2\2\u01dd\u01a9\3\2\2\2\u01dd\u01ac\3\2\2\2\u01dd\u01af\3\2\2\2\u01dd"+
-		"\u01b2\3\2\2\2\u01dd\u01b5\3\2\2\2\u01dd\u01b8\3\2\2\2\u01dd\u01bb\3\2"+
-		"\2\2\u01dd\u01be\3\2\2\2\u01dd\u01c1\3\2\2\2\u01dd\u01c4\3\2\2\2\u01dd"+
-		"\u01ca\3\2\2\2\u01dd\u01cd\3\2\2\2\u01dd\u01d0\3\2\2\2\u01dd\u01d6\3\2"+
-		"\2\2\u01dd\u01db\3\2\2\2\u01de\u01e1\3\2\2\2\u01df\u01dd\3\2\2\2\u01df"+
-		"\u01e0\3\2\2\2\u01e0\65\3\2\2\2\u01e1\u01df\3\2\2\2\u01e2\u01e7\5\64\33"+
-		"\2\u01e3\u01e4\7\5\2\2\u01e4\u01e6\5\64\33\2\u01e5\u01e3\3\2\2\2\u01e6"+
-		"\u01e9\3\2\2\2\u01e7\u01e5\3\2\2\2\u01e7\u01e8\3\2\2\2\u01e8\67\3\2\2"+
-		"\2\u01e9\u01e7\3\2\2\2\u01ea\u01ec\7F\2\2\u01eb\u01ed\5:\36\2\u01ec\u01eb"+
-		"\3\2\2\2\u01ec\u01ed\3\2\2\2\u01ed\u01ee\3\2\2\2\u01ee\u01ef\7Q\2\2\u01ef"+
-		"9\3\2\2\2\u01f0\u01f1\7\7\2\2\u01f1\u01f6\5<\37\2\u01f2\u01f3\7\5\2\2"+
-		"\u01f3\u01f5\5<\37\2\u01f4\u01f2\3\2\2\2\u01f5\u01f8\3\2\2\2\u01f6\u01f4"+
-		"\3\2\2\2\u01f6\u01f7\3\2\2\2\u01f7\u01f9\3\2\2\2\u01f8\u01f6\3\2\2\2\u01f9"+
-		"\u01fa\7\b\2\2\u01fa;\3\2\2\2\u01fb\u01fc\7G\2\2\u01fc\u020b\7S\2\2\u01fd"+
-		"\u01fe\7H\2\2\u01fe\u020b\7_\2\2\u01ff\u0200\7I\2\2\u0200\u020b\7S\2\2"+
-		"\u0201\u0202\7J\2\2\u0202\u020b\5\64\33\2\u0203\u0204\7K\2\2\u0204\u020b"+
-		"\5\64\33\2\u0205\u0208\7L\2\2\u0206\u0209\7\17\2\2\u0207\u0209\5\64\33"+
-		"\2\u0208\u0206\3\2\2\2\u0208\u0207\3\2\2\2\u0209\u020b\3\2\2\2\u020a\u01fb"+
-		"\3\2\2\2\u020a\u01fd\3\2\2\2\u020a\u01ff\3\2\2\2\u020a\u0201\3\2\2\2\u020a"+
-		"\u0203\3\2\2\2\u020a\u0205\3\2\2\2\u020b=\3\2\2\2\u020c\u020e\5@!\2\u020d"+
-		"\u020c\3\2\2\2\u020e\u0211\3\2\2\2\u020f\u020d\3\2\2\2\u020f\u0210\3\2"+
-		"\2\2\u0210?\3\2\2\2\u0211\u020f\3\2\2\2\u0212\u0216\5B\"\2\u0213\u0216"+
-		"\5D#\2\u0214\u0216\5F$\2\u0215\u0212\3\2\2\2\u0215\u0213\3\2\2\2\u0215"+
-		"\u0214\3\2\2\2\u0216A\3\2\2\2\u0217\u0218\7_\2\2\u0218\u021f\7\34\2\2"+
-		"\u0219\u021b\7*\2\2\u021a\u021c\7_\2\2\u021b\u021a\3\2\2\2\u021b\u021c"+
-		"\3\2\2\2\u021c\u021d\3\2\2\2\u021d\u021f\7\34\2\2\u021e\u0217\3\2\2\2"+
-		"\u021e\u0219\3\2\2\2\u021fC\3\2\2\2\u0220\u0222\7P\2\2\u0221\u0223\5H"+
-		"%\2\u0222\u0221\3\2\2\2\u0222\u0223\3\2\2\2\u0223E\3\2\2\2\u0224\u0225"+
-		"\7M\2\2\u0225\u022a\5J&\2\u0226\u0227\7\5\2\2\u0227\u0229\5J&\2\u0228"+
-		"\u0226\3\2\2\2\u0229\u022c\3\2\2\2\u022a\u0228\3\2\2\2\u022a\u022b\3\2"+
-		"\2\2\u022bG\3\2\2\2\u022c\u022a\3\2\2\2\u022d\u0245\5J&\2\u022e\u022f"+
-		"\7N\2\2\u022f\u0245\5J&\2\u0230\u0231\5J&\2\u0231\u0232\7\5\2\2\u0232"+
-		"\u0233\7_\2\2\u0233\u0245\3\2\2\2\u0234\u0235\7\7\2\2\u0235\u0236\5J&"+
-		"\2\u0236\u0237\7\b\2\2\u0237\u0238\7\5\2\2\u0238\u0239\7_\2\2\u0239\u0245"+
-		"\3\2\2\2\u023a\u023b\7\7\2\2\u023b\u023c\5J&\2\u023c\u023d\7\5\2\2\u023d"+
-		"\u023e\7_\2\2\u023e\u023f\7\b\2\2\u023f\u0245\3\2\2\2\u0240\u0241\7\7"+
-		"\2\2\u0241\u0242\5J&\2\u0242\u0243\7\b\2\2\u0243\u0245\3\2\2\2\u0244\u022d"+
-		"\3\2\2\2\u0244\u022e\3\2\2\2\u0244\u0230\3\2\2\2\u0244\u0234\3\2\2\2\u0244"+
-		"\u023a\3\2\2\2\u0244\u0240\3\2\2\2\u0245I\3\2\2\2\u0246\u0247\b&\1\2\u0247"+
-		"\u0248\7!\2\2\u0248\u0249\5J&\2\u0249\u024a\7\"\2\2\u024a\u0255\3\2\2"+
-		"\2\u024b\u024c\t\13\2\2\u024c\u0255\5J&\n\u024d\u0255\7_\2\2\u024e\u0255"+
-		"\7`\2\2\u024f\u0250\7\t\2\2\u0250\u0251\7_\2\2\u0251\u0255\7\n\2\2\u0252"+
-		"\u0255\7V\2\2\u0253\u0255\7T\2\2\u0254\u0246\3\2\2\2\u0254\u024b\3\2\2"+
-		"\2\u0254\u024d\3\2\2\2\u0254\u024e\3\2\2\2\u0254\u024f\3\2\2\2\u0254\u0252"+
-		"\3\2\2\2\u0254\u0253\3\2\2\2\u0255\u0264\3\2\2\2\u0256\u0257\f\f\2\2\u0257"+
-		"\u0258\7O\2\2\u0258\u0263\5J&\r\u0259\u025a\f\13\2\2\u025a\u025b\t\6\2"+
-		"\2\u025b\u0263\5J&\f\u025c\u025d\f\t\2\2\u025d\u025e\t\f\2\2\u025e\u0263"+
-		"\5J&\n\u025f\u0260\f\b\2\2\u0260\u0261\t\b\2\2\u0261\u0263\5J&\t\u0262"+
-		"\u0256\3\2\2\2\u0262\u0259\3\2\2\2\u0262\u025c\3\2\2\2\u0262\u025f\3\2"+
-		"\2\2\u0263\u0266\3\2\2\2\u0264\u0262\3\2\2\2\u0264\u0265\3\2\2\2\u0265"+
-		"K\3\2\2\2\u0266\u0264\3\2\2\2=V_jov\u0084\u008a\u0090\u0095\u009e\u00a5"+
+		"\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
+		"\3\33\3\33\3\33\3\33\5\33\u01da\n\33\3\33\3\33\3\33\3\33\3\33\3\33\3\33"+
+		"\3\33\7\33\u01e4\n\33\f\33\16\33\u01e7\13\33\3\34\3\34\3\34\7\34\u01ec"+
+		"\n\34\f\34\16\34\u01ef\13\34\3\35\3\35\5\35\u01f3\n\35\3\35\3\35\3\36"+
+		"\3\36\3\36\3\36\7\36\u01fb\n\36\f\36\16\36\u01fe\13\36\3\36\3\36\3\37"+
+		"\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\5\37\u020f"+
+		"\n\37\5\37\u0211\n\37\3 \7 \u0214\n \f \16 \u0217\13 \3!\3!\3!\5!\u021c"+
+		"\n!\3\"\3\"\3\"\3\"\5\"\u0222\n\"\3\"\5\"\u0225\n\"\3#\3#\5#\u0229\n#"+
+		"\3$\3$\3$\3$\7$\u022f\n$\f$\16$\u0232\13$\3%\3%\3%\3%\3%\3%\3%\3%\3%\3"+
+		"%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\5%\u024b\n%\3&\3&\3&\3&\3&\3"+
+		"&\3&\3&\3&\3&\3&\3&\3&\3&\5&\u025b\n&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3"+
+		"&\3&\7&\u0269\n&\f&\16&\u026c\13&\3&\2\7\22*\62\64J\'\2\4\6\b\n\f\16\20"+
+		"\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJ\2\r\3\2\36\37\3\2"+
+		"()\3\2*.\3\2\63\64\3\2/\60\4\2  \61\62\3\2*+\3\2\638\3\2>G\4\2*+\63\64"+
+		"\4\2  \61\61\2\u02c5\2L\3\2\2\2\4P\3\2\2\2\6V\3\2\2\2\bY\3\2\2\2\n]\3"+
+		"\2\2\2\fj\3\2\2\2\16o\3\2\2\2\20y\3\2\2\2\22|\3\2\2\2\24\u0087\3\2\2\2"+
+		"\26\u008c\3\2\2\2\30\u0099\3\2\2\2\32\u00a5\3\2\2\2\34\u00a7\3\2\2\2\36"+
+		"\u00bd\3\2\2\2 \u00bf\3\2\2\2\"\u00cc\3\2\2\2$\u011c\3\2\2\2&\u012e\3"+
+		"\2\2\2(\u0134\3\2\2\2*\u0142\3\2\2\2,\u0154\3\2\2\2.\u0157\3\2\2\2\60"+
+		"\u0163\3\2\2\2\62\u0166\3\2\2\2\64\u01a7\3\2\2\2\66\u01e8\3\2\2\28\u01f0"+
+		"\3\2\2\2:\u01f6\3\2\2\2<\u0210\3\2\2\2>\u0215\3\2\2\2@\u021b\3\2\2\2B"+
+		"\u0224\3\2\2\2D\u0226\3\2\2\2F\u022a\3\2\2\2H\u024a\3\2\2\2J\u025a\3\2"+
+		"\2\2LM\5\6\4\2MN\5\n\6\2NO\7\2\2\3O\3\3\2\2\2PQ\5> \2QR\7\2\2\3R\5\3\2"+
+		"\2\2SU\5\b\5\2TS\3\2\2\2UX\3\2\2\2VT\3\2\2\2VW\3\2\2\2W\7\3\2\2\2XV\3"+
+		"\2\2\2YZ\7\3\2\2Z[\7T\2\2[\t\3\2\2\2\\^\5\f\7\2]\\\3\2\2\2^_\3\2\2\2_"+
+		"]\3\2\2\2_`\3\2\2\2`\13\3\2\2\2ab\5\20\t\2bc\7\4\2\2ck\3\2\2\2de\5.\30"+
+		"\2ef\7\4\2\2fk\3\2\2\2gk\5\26\f\2hk\58\35\2ik\5\34\17\2ja\3\2\2\2jd\3"+
+		"\2\2\2jg\3\2\2\2jh\3\2\2\2ji\3\2\2\2k\r\3\2\2\2ln\5\36\20\2ml\3\2\2\2"+
+		"nq\3\2\2\2om\3\2\2\2op\3\2\2\2pr\3\2\2\2qo\3\2\2\2rv\5*\26\2su\5\36\20"+
+		"\2ts\3\2\2\2ux\3\2\2\2vt\3\2\2\2vw\3\2\2\2w\17\3\2\2\2xv\3\2\2\2yz\5\16"+
+		"\b\2z{\5\22\n\2{\21\3\2\2\2|}\b\n\1\2}~\5\24\13\2~\u0084\3\2\2\2\177\u0080"+
+		"\f\3\2\2\u0080\u0081\7\5\2\2\u0081\u0083\5\24\13\2\u0082\177\3\2\2\2\u0083"+
+		"\u0086\3\2\2\2\u0084\u0082\3\2\2\2\u0084\u0085\3\2\2\2\u0085\23\3\2\2"+
+		"\2\u0086\u0084\3\2\2\2\u0087\u008a\7`\2\2\u0088\u0089\7\6\2\2\u0089\u008b"+
+		"\5\64\33\2\u008a\u0088\3\2\2\2\u008a\u008b\3\2\2\2\u008b\25\3\2\2\2\u008c"+
+		"\u008d\5\16\b\2\u008d\u008e\7`\2\2\u008e\u0090\7\7\2\2\u008f\u0091\5\30"+
+		"\r\2\u0090\u008f\3\2\2\2\u0090\u0091\3\2\2\2\u0091\u0092\3\2\2\2\u0092"+
+		"\u0093\7\b\2\2\u0093\u0095\7\t\2\2\u0094\u0096\5\"\22\2\u0095\u0094\3"+
+		"\2\2\2\u0095\u0096\3\2\2\2\u0096\u0097\3\2\2\2\u0097\u0098\7\n\2\2\u0098"+
+		"\27\3\2\2\2\u0099\u009e\5\32\16\2\u009a\u009b\7\5\2\2\u009b\u009d\5\32"+
+		"\16\2\u009c\u009a\3\2\2\2\u009d\u00a0\3\2\2\2\u009e\u009c\3\2\2\2\u009e"+
+		"\u009f\3\2\2\2\u009f\31\3\2\2\2\u00a0\u009e\3\2\2\2\u00a1\u00a2\5\16\b"+
+		"\2\u00a2\u00a3\7`\2\2\u00a3\u00a6\3\2\2\2\u00a4\u00a6\7S\2\2\u00a5\u00a1"+
+		"\3\2\2\2\u00a5\u00a4\3\2\2\2\u00a6\33\3\2\2\2\u00a7\u00a8\5 \21\2\u00a8"+
+		"\u00a9\7\4\2\2\u00a9\35\3\2\2\2\u00aa\u00be\7\13\2\2\u00ab\u00be\7\f\2"+
+		"\2\u00ac\u00ad\7\r\2\2\u00ad\u00ae\7\7\2\2\u00ae\u00af\7W\2\2\u00af\u00be"+
+		"\7\b\2\2\u00b0\u00b1\7\16\2\2\u00b1\u00b2\7\7\2\2\u00b2\u00b3\7`\2\2\u00b3"+
+		"\u00be\7\b\2\2\u00b4\u00be\7\17\2\2\u00b5\u00be\7\20\2\2\u00b6\u00ba\7"+
+		"\21\2\2\u00b7\u00b8\7\7\2\2\u00b8\u00b9\7`\2\2\u00b9\u00bb\7\b\2\2\u00ba"+
+		"\u00b7\3\2\2\2\u00ba\u00bb\3\2\2\2\u00bb\u00be\3\2\2\2\u00bc\u00be\5 "+
+		"\21\2\u00bd\u00aa\3\2\2\2\u00bd\u00ab\3\2\2\2\u00bd\u00ac\3\2\2\2\u00bd"+
+		"\u00b0\3\2\2\2\u00bd\u00b4\3\2\2\2\u00bd\u00b5\3\2\2\2\u00bd\u00b6\3\2"+
+		"\2\2\u00bd\u00bc\3\2\2\2\u00be\37\3\2\2\2\u00bf\u00c0\7\22\2\2\u00c0\u00c1"+
+		"\7\7\2\2\u00c1\u00c6\7W\2\2\u00c2\u00c3\7\5\2\2\u00c3\u00c5\7W\2\2\u00c4"+
+		"\u00c2\3\2\2\2\u00c5\u00c8\3\2\2\2\u00c6\u00c4\3\2\2\2\u00c6\u00c7\3\2"+
+		"\2\2\u00c7\u00c9\3\2\2\2\u00c8\u00c6\3\2\2\2\u00c9\u00ca\7\b\2\2\u00ca"+
+		"!\3\2\2\2\u00cb\u00cd\5$\23\2\u00cc\u00cb\3\2\2\2\u00cd\u00ce\3\2\2\2"+
+		"\u00ce\u00cc\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cf#\3\2\2\2\u00d0\u00d1\5"+
+		"\20\t\2\u00d1\u00d2\7\4\2\2\u00d2\u011d\3\2\2\2\u00d3\u00d5\7\t\2\2\u00d4"+
+		"\u00d6\5\"\22\2\u00d5\u00d4\3\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\u00d7\3"+
+		"\2\2\2\u00d7\u011d\7\n\2\2\u00d8\u00d9\5\62\32\2\u00d9\u00da\7\4\2\2\u00da"+
+		"\u011d\3\2\2\2\u00db\u00dc\7\23\2\2\u00dc\u00dd\7\7\2\2\u00dd\u00de\5"+
+		"\62\32\2\u00de\u00df\7\b\2\2\u00df\u00e2\5$\23\2\u00e0\u00e1\7\24\2\2"+
+		"\u00e1\u00e3\5$\23\2\u00e2\u00e0\3\2\2\2\u00e2\u00e3\3\2\2\2\u00e3\u011d"+
+		"\3\2\2\2\u00e4\u00e6\5\36\20\2\u00e5\u00e4\3\2\2\2\u00e6\u00e9\3\2\2\2"+
+		"\u00e7\u00e5\3\2\2\2\u00e7\u00e8\3\2\2\2\u00e8\u00ea\3\2\2\2\u00e9\u00e7"+
+		"\3\2\2\2\u00ea\u00eb\7\25\2\2\u00eb\u00ec\7\7\2\2\u00ec\u00ed\5\62\32"+
+		"\2\u00ed\u00ee\7\b\2\2\u00ee\u00ef\5$\23\2\u00ef\u011d\3\2\2\2\u00f0\u00f2"+
+		"\5\36\20\2\u00f1\u00f0\3\2\2\2\u00f2\u00f5\3\2\2\2\u00f3\u00f1\3\2\2\2"+
+		"\u00f3\u00f4\3\2\2\2\u00f4\u00f6\3\2\2\2\u00f5\u00f3\3\2\2\2\u00f6\u00f7"+
+		"\7\26\2\2\u00f7\u00f8\5$\23\2\u00f8\u00f9\7\25\2\2\u00f9\u00fa\7\7\2\2"+
+		"\u00fa\u00fb\5\62\32\2\u00fb\u00fc\7\b\2\2\u00fc\u00fd\7\4\2\2\u00fd\u011d"+
+		"\3\2\2\2\u00fe\u0100\5\36\20\2\u00ff\u00fe\3\2\2\2\u0100\u0103\3\2\2\2"+
+		"\u0101\u00ff\3\2\2\2\u0101\u0102\3\2\2\2\u0102\u0104\3\2\2\2\u0103\u0101"+
+		"\3\2\2\2\u0104\u0105\7\27\2\2\u0105\u0106\7\7\2\2\u0106\u0107\5&\24\2"+
+		"\u0107\u0108\7\b\2\2\u0108\u0109\5$\23\2\u0109\u011d\3\2\2\2\u010a\u010c"+
+		"\7\30\2\2\u010b\u010d\5\62\32\2\u010c\u010b\3\2\2\2\u010c\u010d\3\2\2"+
+		"\2\u010d\u010e\3\2\2\2\u010e\u011d\7\4\2\2\u010f\u0110\7\31\2\2\u0110"+
+		"\u011d\7\4\2\2\u0111\u0112\7\32\2\2\u0112\u011d\7\4\2\2\u0113\u0115\7"+
+		"\33\2\2\u0114\u0116\5:\36\2\u0115\u0114\3\2\2\2\u0115\u0116\3\2\2\2\u0116"+
+		"\u0117\3\2\2\2\u0117\u0118\7\t\2\2\u0118\u0119\5> \2\u0119\u011a\7\n\2"+
+		"\2\u011a\u011d\3\2\2\2\u011b\u011d\58\35\2\u011c\u00d0\3\2\2\2\u011c\u00d3"+
+		"\3\2\2\2\u011c\u00d8\3\2\2\2\u011c\u00db\3\2\2\2\u011c\u00e7\3\2\2\2\u011c"+
+		"\u00f3\3\2\2\2\u011c\u0101\3\2\2\2\u011c\u010a\3\2\2\2\u011c\u010f\3\2"+
+		"\2\2\u011c\u0111\3\2\2\2\u011c\u0113\3\2\2\2\u011c\u011b\3\2\2\2\u011d"+
+		"%\3\2\2\2\u011e\u011f\5(\25\2\u011f\u0120\7\4\2\2\u0120\u0121\5\62\32"+
+		"\2\u0121\u0123\7\4\2\2\u0122\u0124\5\62\32\2\u0123\u0122\3\2\2\2\u0123"+
+		"\u0124\3\2\2\2\u0124\u012f\3\2\2\2\u0125\u0127\5\16\b\2\u0126\u0125\3"+
+		"\2\2\2\u0126\u0127\3\2\2\2\u0127\u0128\3\2\2\2\u0128\u0129\7`\2\2\u0129"+
+		"\u012a\7\34\2\2\u012a\u012b\5\64\33\2\u012b\u012c\7\35\2\2\u012c\u012d"+
+		"\5\64\33\2\u012d\u012f\3\2\2\2\u012e\u011e\3\2\2\2\u012e\u0126\3\2\2\2"+
+		"\u012f\'\3\2\2\2\u0130\u0132\5\20\t\2\u0131\u0130\3\2\2\2\u0131\u0132"+
+		"\3\2\2\2\u0132\u0135\3\2\2\2\u0133\u0135\5\62\32\2\u0134\u0131\3\2\2\2"+
+		"\u0134\u0133\3\2\2\2\u0135)\3\2\2\2\u0136\u0137\b\26\1\2\u0137\u0138\7"+
+		"\7\2\2\u0138\u0139\5*\26\2\u0139\u013a\7\b\2\2\u013a\u0143\3\2\2\2\u013b"+
+		"\u0143\7S\2\2\u013c\u013e\t\2\2\2\u013d\u013f\7S\2\2\u013e\u013d\3\2\2"+
+		"\2\u013e\u013f\3\2\2\2\u013f\u0143\3\2\2\2\u0140\u0143\5.\30\2\u0141\u0143"+
+		"\5,\27\2\u0142\u0136\3\2\2\2\u0142\u013b\3\2\2\2\u0142\u013c\3\2\2\2\u0142"+
+		"\u0140\3\2\2\2\u0142\u0141\3\2\2\2\u0143\u0151\3\2\2\2\u0144\u0145\f\7"+
+		"\2\2\u0145\u0150\7 \2\2\u0146\u0147\f\6\2\2\u0147\u0149\7!\2\2\u0148\u014a"+
+		"\5\64\33\2\u0149\u0148\3\2\2\2\u0149\u014a\3\2\2\2\u014a\u014b\3\2\2\2"+
+		"\u014b\u0150\7\"\2\2\u014c\u014d\f\5\2\2\u014d\u014e\7\7\2\2\u014e\u0150"+
+		"\7\b\2\2\u014f\u0144\3\2\2\2\u014f\u0146\3\2\2\2\u014f\u014c\3\2\2\2\u0150"+
+		"\u0153\3\2\2\2\u0151\u014f\3\2\2\2\u0151\u0152\3\2\2\2\u0152+\3\2\2\2"+
+		"\u0153\u0151\3\2\2\2\u0154\u0155\7#\2\2\u0155\u0156\7`\2\2\u0156-\3\2"+
+		"\2\2\u0157\u0159\7#\2\2\u0158\u015a\7`\2\2\u0159\u0158\3\2\2\2\u0159\u015a"+
+		"\3\2\2\2\u015a\u015b\3\2\2\2\u015b\u015d\7\t\2\2\u015c\u015e\5\60\31\2"+
+		"\u015d\u015c\3\2\2\2\u015e\u015f\3\2\2\2\u015f\u015d\3\2\2\2\u015f\u0160"+
+		"\3\2\2\2\u0160\u0161\3\2\2\2\u0161\u0162\7\n\2\2\u0162/\3\2\2\2\u0163"+
+		"\u0164\5\20\t\2\u0164\u0165\7\4\2\2\u0165\61\3\2\2\2\u0166\u0167\b\32"+
+		"\1\2\u0167\u0168\5\64\33\2\u0168\u016e\3\2\2\2\u0169\u016a\f\3\2\2\u016a"+
+		"\u016b\7\5\2\2\u016b\u016d\5\64\33\2\u016c\u0169\3\2\2\2\u016d\u0170\3"+
+		"\2\2\2\u016e\u016c\3\2\2\2\u016e\u016f\3\2\2\2\u016f\63\3\2\2\2\u0170"+
+		"\u016e\3\2\2\2\u0171\u0172\b\33\1\2\u0172\u0173\7\7\2\2\u0173\u0174\5"+
+		"\62\32\2\u0174\u0175\7\b\2\2\u0175\u01a8\3\2\2\2\u0176\u0177\7&\2\2\u0177"+
+		"\u017a\7\7\2\2\u0178\u017b\5*\26\2\u0179\u017b\5\64\33\2\u017a\u0178\3"+
+		"\2\2\2\u017a\u0179\3\2\2\2\u017b\u017c\3\2\2\2\u017c\u017d\7\b\2\2\u017d"+
+		"\u01a8\3\2\2\2\u017e\u017f\7\'\2\2\u017f\u0182\7\7\2\2\u0180\u0183\5*"+
+		"\26\2\u0181\u0183\5\64\33\2\u0182\u0180\3\2\2\2\u0182\u0181\3\2\2\2\u0183"+
+		"\u0184\3\2\2\2\u0184\u0185\7\b\2\2\u0185\u01a8\3\2\2\2\u0186\u0187\7\7"+
+		"\2\2\u0187\u0188\5*\26\2\u0188\u0189\7\b\2\2\u0189\u018a\5\64\33\32\u018a"+
+		"\u01a8\3\2\2\2\u018b\u018c\t\3\2\2\u018c\u01a8\5\64\33\31\u018d\u018e"+
+		"\7 \2\2\u018e\u01a8\5\64\33\27\u018f\u0190\t\4\2\2\u0190\u01a8\5\64\33"+
+		"\26\u0191\u0192\t\5\2\2\u0192\u01a8\5\64\33\22\u0193\u0194\7\t\2\2\u0194"+
+		"\u0199\5\64\33\2\u0195\u0196\7\5\2\2\u0196\u0198\5\64\33\2\u0197\u0195"+
+		"\3\2\2\2\u0198\u019b\3\2\2\2\u0199\u0197\3\2\2\2\u0199\u019a\3\2\2\2\u019a"+
+		"\u019c\3\2\2\2\u019b\u0199\3\2\2\2\u019c\u019d\7\n\2\2\u019d\u01a8\3\2"+
+		"\2\2\u019e\u01a8\7`\2\2\u019f\u01a8\7W\2\2\u01a0\u01a2\7T\2\2\u01a1\u01a0"+
+		"\3\2\2\2\u01a2\u01a3\3\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4"+
+		"\u01a8\3\2\2\2\u01a5\u01a8\7U\2\2\u01a6\u01a8\7V\2\2\u01a7\u0171\3\2\2"+
+		"\2\u01a7\u0176\3\2\2\2\u01a7\u017e\3\2\2\2\u01a7\u0186\3\2\2\2\u01a7\u018b"+
+		"\3\2\2\2\u01a7\u018d\3\2\2\2\u01a7\u018f\3\2\2\2\u01a7\u0191\3\2\2\2\u01a7"+
+		"\u0193\3\2\2\2\u01a7\u019e\3\2\2\2\u01a7\u019f\3\2\2\2\u01a7\u01a1\3\2"+
+		"\2\2\u01a7\u01a5\3\2\2\2\u01a7\u01a6\3\2\2\2\u01a8\u01e5\3\2\2\2\u01a9"+
+		"\u01aa\f\25\2\2\u01aa\u01ab\t\6\2\2\u01ab\u01e4\5\64\33\26\u01ac\u01ad"+
+		"\f\24\2\2\u01ad\u01ae\t\7\2\2\u01ae\u01e4\5\64\33\25\u01af\u01b0\f\23"+
+		"\2\2\u01b0\u01b1\t\b\2\2\u01b1\u01e4\5\64\33\24\u01b2\u01b3\f\21\2\2\u01b3"+
+		"\u01b4\t\t\2\2\u01b4\u01e4\5\64\33\22\u01b5\u01b6\f\20\2\2\u01b6\u01b7"+
+		"\7-\2\2\u01b7\u01e4\5\64\33\21\u01b8\u01b9\f\17\2\2\u01b9\u01ba\79\2\2"+
+		"\u01ba\u01e4\5\64\33\20\u01bb\u01bc\f\16\2\2\u01bc\u01bd\7:\2\2\u01bd"+
+		"\u01e4\5\64\33\17\u01be\u01bf\f\r\2\2\u01bf\u01c0\7;\2\2\u01c0\u01e4\5"+
+		"\64\33\16\u01c1\u01c2\f\f\2\2\u01c2\u01c3\7<\2\2\u01c3\u01e4\5\64\33\r"+
+		"\u01c4\u01c5\f\13\2\2\u01c5\u01c6\7=\2\2\u01c6\u01c7\5\64\33\2\u01c7\u01c8"+
+		"\7\34\2\2\u01c8\u01c9\5\64\33\f\u01c9\u01e4\3\2\2\2\u01ca\u01cb\f\n\2"+
+		"\2\u01cb\u01cc\7\6\2\2\u01cc\u01e4\5\64\33\n\u01cd\u01ce\f\t\2\2\u01ce"+
+		"\u01cf\t\n\2\2\u01cf\u01e4\5\64\33\t\u01d0\u01d1\f \2\2\u01d1\u01d2\7"+
+		"$\2\2\u01d2\u01e4\7`\2\2\u01d3\u01d4\f\37\2\2\u01d4\u01d5\7%\2\2\u01d5"+
+		"\u01e4\7`\2\2\u01d6\u01d7\f\36\2\2\u01d7\u01d9\7\7\2\2\u01d8\u01da\5\66"+
+		"\34\2\u01d9\u01d8\3\2\2\2\u01d9\u01da\3\2\2\2\u01da\u01db\3\2\2\2\u01db"+
+		"\u01e4\7\b\2\2\u01dc\u01dd\f\33\2\2\u01dd\u01de\7!\2\2\u01de\u01df\5\62"+
+		"\32\2\u01df\u01e0\7\"\2\2\u01e0\u01e4\3\2\2\2\u01e1\u01e2\f\30\2\2\u01e2"+
+		"\u01e4\t\3\2\2\u01e3\u01a9\3\2\2\2\u01e3\u01ac\3\2\2\2\u01e3\u01af\3\2"+
+		"\2\2\u01e3\u01b2\3\2\2\2\u01e3\u01b5\3\2\2\2\u01e3\u01b8\3\2\2\2\u01e3"+
+		"\u01bb\3\2\2\2\u01e3\u01be\3\2\2\2\u01e3\u01c1\3\2\2\2\u01e3\u01c4\3\2"+
+		"\2\2\u01e3\u01ca\3\2\2\2\u01e3\u01cd\3\2\2\2\u01e3\u01d0\3\2\2\2\u01e3"+
+		"\u01d3\3\2\2\2\u01e3\u01d6\3\2\2\2\u01e3\u01dc\3\2\2\2\u01e3\u01e1\3\2"+
+		"\2\2\u01e4\u01e7\3\2\2\2\u01e5\u01e3\3\2\2\2\u01e5\u01e6\3\2\2\2\u01e6"+
+		"\65\3\2\2\2\u01e7\u01e5\3\2\2\2\u01e8\u01ed\5\64\33\2\u01e9\u01ea\7\5"+
+		"\2\2\u01ea\u01ec\5\64\33\2\u01eb\u01e9\3\2\2\2\u01ec\u01ef\3\2\2\2\u01ed"+
+		"\u01eb\3\2\2\2\u01ed\u01ee\3\2\2\2\u01ee\67\3\2\2\2\u01ef\u01ed\3\2\2"+
+		"\2\u01f0\u01f2\7H\2\2\u01f1\u01f3\5:\36\2\u01f2\u01f1\3\2\2\2\u01f2\u01f3"+
+		"\3\2\2\2\u01f3\u01f4\3\2\2\2\u01f4\u01f5\7R\2\2\u01f59\3\2\2\2\u01f6\u01f7"+
+		"\7\7\2\2\u01f7\u01fc\5<\37\2\u01f8\u01f9\7\5\2\2\u01f9\u01fb\5<\37\2\u01fa"+
+		"\u01f8\3\2\2\2\u01fb\u01fe\3\2\2\2\u01fc\u01fa\3\2\2\2\u01fc\u01fd\3\2"+
+		"\2\2\u01fd\u01ff\3\2\2\2\u01fe\u01fc\3\2\2\2\u01ff\u0200\7\b\2\2\u0200"+
+		";\3\2\2\2\u0201\u0202\7I\2\2\u0202\u0211\7T\2\2\u0203\u0204\7J\2\2\u0204"+
+		"\u0211\7`\2\2\u0205\u0206\7K\2\2\u0206\u0211\7T\2\2\u0207\u0208\7L\2\2"+
+		"\u0208\u0211\5\64\33\2\u0209\u020a\7M\2\2\u020a\u0211\5\64\33\2\u020b"+
+		"\u020e\7N\2\2\u020c\u020f\7\17\2\2\u020d\u020f\5\64\33\2\u020e\u020c\3"+
+		"\2\2\2\u020e\u020d\3\2\2\2\u020f\u0211\3\2\2\2\u0210\u0201\3\2\2\2\u0210"+
+		"\u0203\3\2\2\2\u0210\u0205\3\2\2\2\u0210\u0207\3\2\2\2\u0210\u0209\3\2"+
+		"\2\2\u0210\u020b\3\2\2\2\u0211=\3\2\2\2\u0212\u0214\5@!\2\u0213\u0212"+
+		"\3\2\2\2\u0214\u0217\3\2\2\2\u0215\u0213\3\2\2\2\u0215\u0216\3\2\2\2\u0216"+
+		"?\3\2\2\2\u0217\u0215\3\2\2\2\u0218\u021c\5B\"\2\u0219\u021c\5D#\2\u021a"+
+		"\u021c\5F$\2\u021b\u0218\3\2\2\2\u021b\u0219\3\2\2\2\u021b\u021a\3\2\2"+
+		"\2\u021cA\3\2\2\2\u021d\u021e\7`\2\2\u021e\u0225\7\34\2\2\u021f\u0221"+
+		"\7,\2\2\u0220\u0222\7`\2\2\u0221\u0220\3\2\2\2\u0221\u0222\3\2\2\2\u0222"+
+		"\u0223\3\2\2\2\u0223\u0225\7\34\2\2\u0224\u021d\3\2\2\2\u0224\u021f\3"+
+		"\2\2\2\u0225C\3\2\2\2\u0226\u0228\7Q\2\2\u0227\u0229\5H%\2\u0228\u0227"+
+		"\3\2\2\2\u0228\u0229\3\2\2\2\u0229E\3\2\2\2\u022a\u022b\7O\2\2\u022b\u0230"+
+		"\5J&\2\u022c\u022d\7\5\2\2\u022d\u022f\5J&\2\u022e\u022c\3\2\2\2\u022f"+
+		"\u0232\3\2\2\2\u0230\u022e\3\2\2\2\u0230\u0231\3\2\2\2\u0231G\3\2\2\2"+
+		"\u0232\u0230\3\2\2\2\u0233\u024b\5J&\2\u0234\u0235\7P\2\2\u0235\u024b"+
+		"\5J&\2\u0236\u0237\5J&\2\u0237\u0238\7\5\2\2\u0238\u0239\7`\2\2\u0239"+
+		"\u024b\3\2\2\2\u023a\u023b\7\7\2\2\u023b\u023c\5J&\2\u023c\u023d\7\b\2"+
+		"\2\u023d\u023e\7\5\2\2\u023e\u023f\7`\2\2\u023f\u024b\3\2\2\2\u0240\u0241"+
+		"\7\7\2\2\u0241\u0242\5J&\2\u0242\u0243\7\5\2\2\u0243\u0244\7`\2\2\u0244"+
+		"\u0245\7\b\2\2\u0245\u024b\3\2\2\2\u0246\u0247\7\7\2\2\u0247\u0248\5J"+
+		"&\2\u0248\u0249\7\b\2\2\u0249\u024b\3\2\2\2\u024a\u0233\3\2\2\2\u024a"+
+		"\u0234\3\2\2\2\u024a\u0236\3\2\2\2\u024a\u023a\3\2\2\2\u024a\u0240\3\2"+
+		"\2\2\u024a\u0246\3\2\2\2\u024bI\3\2\2\2\u024c\u024d\b&\1\2\u024d\u024e"+
+		"\7!\2\2\u024e\u024f\5J&\2\u024f\u0250\7\"\2\2\u0250\u025b\3\2\2\2\u0251"+
+		"\u0252\t\13\2\2\u0252\u025b\5J&\n\u0253\u025b\7`\2\2\u0254\u025b\7a\2"+
+		"\2\u0255\u0256\7\t\2\2\u0256\u0257\7`\2\2\u0257\u025b\7\n\2\2\u0258\u025b"+
+		"\7W\2\2\u0259\u025b\7U\2\2\u025a\u024c\3\2\2\2\u025a\u0251\3\2\2\2\u025a"+
+		"\u0253\3\2\2\2\u025a\u0254\3\2\2\2\u025a\u0255\3\2\2\2\u025a\u0258\3\2"+
+		"\2\2\u025a\u0259\3\2\2\2\u025b\u026a\3\2\2\2\u025c\u025d\f\f\2\2\u025d"+
+		"\u025e\7$\2\2\u025e\u0269\5J&\r\u025f\u0260\f\13\2\2\u0260\u0261\t\6\2"+
+		"\2\u0261\u0269\5J&\f\u0262\u0263\f\t\2\2\u0263\u0264\t\f\2\2\u0264\u0269"+
+		"\5J&\n\u0265\u0266\f\b\2\2\u0266\u0267\t\b\2\2\u0267\u0269\5J&\t\u0268"+
+		"\u025c\3\2\2\2\u0268\u025f\3\2\2\2\u0268\u0262\3\2\2\2\u0268\u0265\3\2"+
+		"\2\2\u0269\u026c\3\2\2\2\u026a\u0268\3\2\2\2\u026a\u026b\3\2\2\2\u026b"+
+		"K\3\2\2\2\u026c\u026a\3\2\2\2=V_jov\u0084\u008a\u0090\u0095\u009e\u00a5"+
 		"\u00ba\u00bd\u00c6\u00ce\u00d5\u00e2\u00e7\u00f3\u0101\u010c\u0115\u011c"+
 		"\u0123\u0126\u012e\u0131\u0134\u013e\u0142\u0149\u014f\u0151\u0159\u015f"+
-		"\u016e\u017a\u0182\u0199\u01a3\u01a7\u01d3\u01dd\u01df\u01e7\u01ec\u01f6"+
-		"\u0208\u020a\u020f\u0215\u021b\u021e\u0222\u022a\u0244\u0254\u0262\u0264";
+		"\u016e\u017a\u0182\u0199\u01a3\u01a7\u01d9\u01e3\u01e5\u01ed\u01f2\u01fc"+
+		"\u020e\u0210\u0215\u021b\u0221\u0224\u0228\u0230\u024a\u025a\u0268\u026a";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
diff --git a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
index edb044629..0731b49ae 100644
--- a/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
+++ b/src/main/java/dk/camelot64/kickc/parser/KickCVisitor.java
@@ -426,6 +426,20 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
 	 * @return the visitor result
 	 */
 	T visitExprChar(KickCParser.ExprCharContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code exprArrow}
+	 * labeled alternative in {@link KickCParser#expr}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitExprArrow(KickCParser.ExprArrowContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code exprDot}
+	 * labeled alternative in {@link KickCParser#expr}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitExprDot(KickCParser.ExprDotContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code initList}
 	 * labeled alternative in {@link KickCParser#expr}.
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index 63febda6c..0cdfc6051 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -431,6 +431,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
    private List<Directive> declVarDirectives = null;
    /** Holds the declared comments when descending into a Variable Declaration. */
    private List<Comment> declVarComments = null;
+   /** State specifying that we are currently populating struct members. */
+   private boolean declVarStructMember = false;
 
    /**
     * Visit the type/directive part of a declaration. Setup the local decl-variables
@@ -496,6 +498,11 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
          lValue.setComments(ensureUnusedComments(comments));
       }
       KickCParser.ExprContext initializer = ctx.expr();
+      if(declVarStructMember) {
+         if(initializer != null) {
+            throw new CompileError("Initializers not supported inside structs " + type.getTypeName(), new StatementSource(ctx));
+         }
+      } else {
       if(initializer != null) {
          addInitialAssignment(initializer, lValue, comments);
       } else {
@@ -519,9 +526,15 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
             ConstantValue zero = new ConstantPointer(0L, typePointer.getElementType());
             Statement stmt = new StatementAssignment(lValue.getRef(), zero, new StatementSource(ctx), ensureUnusedComments(comments));
             sequence.addStatement(stmt);
+         } else if(type instanceof SymbolTypeStruct) {
+            // Add an zero-struct initializer
+            SymbolTypeStruct typeStruct = (SymbolTypeStruct) type;
+            Statement stmt = new StatementAssignment(lValue.getRef(), new StructZero(typeStruct), new StatementSource(ctx), ensureUnusedComments(comments));
+            sequence.addStatement(stmt);
          } else {
             throw new CompileError("Default initializer not implemented for type " + type.getTypeName(), new StatementSource(ctx));
          }
+      }
 
       }
       return null;
@@ -1119,6 +1132,28 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
       return SymbolType.get(ctx.getText());
    }
 
+
+
+
+   @Override
+   public Object visitStructDef(KickCParser.StructDefContext ctx) {
+      String structDefName;
+      if(ctx.NAME()!=null) {
+         structDefName = ctx.NAME().getText();
+      } else {
+         structDefName = getCurrentScope().allocateIntermediateVariableName();
+      }
+      StructDefinition structDefinition = getCurrentScope().addStructDefinition(structDefName);
+      scopeStack.push(structDefinition);
+      declVarStructMember = true;
+      for(KickCParser.StructMembersContext memberCtx : ctx.structMembers()) {
+         visit(memberCtx);
+      }
+      declVarStructMember = false;
+      scopeStack.pop();
+      return structDefinition.getType();
+   }
+
    @Override
    public SymbolType visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) {
       String signedness = ctx.getChild(0).getText();
@@ -1214,6 +1249,13 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
       }
    }
 
+   @Override
+   public Object visitExprDot(KickCParser.ExprDotContext ctx) {
+      RValue structExpr = (RValue) visit(ctx.expr());
+      String name = ctx.NAME().getText();
+      return new StructMemberRef(structExpr, name);
+   }
+
    @Override
    public RValue visitExprCast(KickCParser.ExprCastContext ctx) {
       RValue child = (RValue) this.visit(ctx.expr());
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java
index 9977d5211..55f1a9cd0 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AssertSymbols.java
@@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
 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.StructDefinition;
 import dk.camelot64.kickc.model.symbols.Symbol;
 import dk.camelot64.kickc.model.symbols.VariableUnversioned;
 import dk.camelot64.kickc.model.values.SymbolRef;
@@ -42,6 +43,7 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
       for(Symbol tableSymbol : tableSymbols) {
          if(tableSymbol instanceof VariableUnversioned) continue;
          if(tableSymbol instanceof ConstantVar) continue;
+         if(tableSymbol instanceof StructDefinition) continue;
          Symbol codeSymbol = null;
          String codeSymbolFullName = tableSymbol.getFullName();
          for(Symbol symbol : codeSymbols) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java
index e36e1348a..f181b9eb1 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4RegistersFinalize.java
@@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
 
 import dk.camelot64.kickc.model.*;
 import dk.camelot64.kickc.model.symbols.Procedure;
+import dk.camelot64.kickc.model.types.SymbolTypeStruct;
 import dk.camelot64.kickc.model.values.VariableRef;
 import dk.camelot64.kickc.model.symbols.ConstantVar;
 import dk.camelot64.kickc.model.symbols.Scope;
@@ -224,6 +225,10 @@ public class Pass4RegistersFinalize extends Pass2Base {
          Registers.RegisterZpWord registerZpWord =
                new Registers.RegisterZpWord(allocateZp(2));
          return registerZpWord;
+      } else if(varType instanceof SymbolTypeStruct) {
+         Registers.RegisterZpStruct registerZpStruct =
+               new Registers.RegisterZpStruct(allocateZp(varType.getSizeBytes()));
+         return registerZpStruct;
       } else {
          throw new RuntimeException("Unhandled variable type " + varType);
       }
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 5fb692d96..a91668f9b 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,6 +32,11 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testStruct0() throws IOException, URISyntaxException {
+      compileAndCompare("struct-0", log().verboseCreateSsa().verboseParse().verboseStatementSequence());
+   }
+
    @Test
    public void testC64DtvGfxExplorer() throws IOException, URISyntaxException {
       compileAndCompare("c64dtv-gfxexplorer", 10);
diff --git a/src/test/kc/struct-0.kc b/src/test/kc/struct-0.kc
new file mode 100644
index 000000000..6235eb405
--- /dev/null
+++ b/src/test/kc/struct-0.kc
@@ -0,0 +1,14 @@
+// Minimal struct - declaration & 
+
+struct Point {
+    byte x;
+    byte y;
+} point;
+
+void main() {
+    point.x = 2;
+    point.y = 3;
+    const byte* SCREEN = 0x0400;
+    SCREEN[0] = point.x;
+    SCREEN[1] = point.y;
+}
\ No newline at end of file
diff --git a/src/test/ref/struct-0.asm b/src/test/ref/struct-0.asm
new file mode 100644
index 000000000..16096b806
--- /dev/null
+++ b/src/test/ref/struct-0.asm
@@ -0,0 +1,23 @@
+// Minimal struct - declaration & 
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+  .label point = 2
+bbegin:
+  lda #0
+  sta point
+  sta point+1
+  jsr main
+  rts
+main: {
+    .label SCREEN = $400
+    lda #2
+    sta point+0
+    lda #3
+    sta point+1
+    lda point+0
+    sta SCREEN
+    lda point+1
+    sta SCREEN+1
+    rts
+}

From 9c682e37fe609d892c347a0189f1c5bb0caa800f Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 28 May 2019 22:28:17 +0200
Subject: [PATCH 90/93] Testing structs

---
 .../java/dk/camelot64/kickc/Compiler.java     |  6 ++--
 .../kickc/fragment/AsmFragmentInstance.java   | 16 ++++++---
 .../AsmFragmentInstanceSpecFactory.java       | 35 ++++++++++---------
 .../dk/camelot64/kickc/model/Registers.java   | 20 +++++++++++
 .../kickc/model/symbols/ProgramScope.java     | 18 ++++++++--
 .../kickc/model/symbols/StructDefinition.java | 31 ++++++++++++++++
 .../model/types/SymbolTypeProcedure.java      |  1 -
 .../kickc/model/types/SymbolTypeStruct.java   |  1 -
 .../Pass0GenerateStatementSequence.java       |  7 ++++
 .../dk/camelot64/kickc/test/TestPrograms.java | 15 ++++++--
 src/test/kc/for-two-vars.kc                   |  9 +++++
 src/test/kc/struct-0.kc                       |  2 +-
 src/test/kc/struct-1.kc                       | 18 ++++++++++
 src/test/ref/for-two-vars.asm                 | 27 ++++++++++++++
 src/test/ref/struct-0.asm                     |  2 +-
 src/test/ref/struct-1.asm                     | 29 +++++++++++++++
 16 files changed, 204 insertions(+), 33 deletions(-)
 create mode 100644 src/test/kc/for-two-vars.kc
 create mode 100644 src/test/kc/struct-1.kc
 create mode 100644 src/test/ref/for-two-vars.asm
 create mode 100644 src/test/ref/struct-1.asm

diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index fcfc80bcb..233be6497 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -159,7 +159,7 @@ public class Compiler {
 
       if(getLog().isVerbosePass1CreateSsa()) {
          getLog().append("SYMBOLS");
-         getLog().append(program.getScope().getSymbolTableContents(program));
+         getLog().append(program.getScope().toString(program, null));
       }
 
       new Pass1FixLValuesLoHi(program).execute();
@@ -206,7 +206,7 @@ public class Compiler {
       getLog().append(program.getGraph().toString(program));
 
       getLog().append("SYMBOL TABLE SSA");
-      getLog().append(program.getScope().getSymbolTableContents(program));
+      getLog().append(program.getScope().toString(program, null));
 
       return program;
    }
@@ -530,7 +530,7 @@ public class Compiler {
       new Pass5FixLongBranches(program).optimize();
 
       getLog().append("\nFINAL SYMBOL TABLE");
-      getLog().append(program.getScope().getSymbolTableContents(program));
+      getLog().append(program.getScope().toString(program, null));
 
       getLog().append("\nFINAL ASSEMBLER");
       getLog().append("Score: " + Pass4RegisterUpliftCombinations.getAsmScore(program) + "\n");
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
index 21f9e65f3..92ff9d606 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstance.java
@@ -3,14 +3,12 @@ package dk.camelot64.kickc.fragment;
 import dk.camelot64.kickc.NumberParser;
 import dk.camelot64.kickc.asm.*;
 import dk.camelot64.kickc.model.*;
-import dk.camelot64.kickc.model.values.ConstantInteger;
-import dk.camelot64.kickc.model.values.ConstantValue;
+import dk.camelot64.kickc.model.symbols.StructDefinition;
+import dk.camelot64.kickc.model.values.*;
 import dk.camelot64.kickc.model.symbols.ConstantVar;
 import dk.camelot64.kickc.model.symbols.Label;
 import dk.camelot64.kickc.model.symbols.Variable;
 import dk.camelot64.kickc.model.types.SymbolType;
-import dk.camelot64.kickc.model.values.ScopeRef;
-import dk.camelot64.kickc.model.values.Value;
 import dk.camelot64.kickc.parser.KickCBaseVisitor;
 import dk.camelot64.kickc.parser.KickCParser;
 
@@ -97,6 +95,16 @@ public class AsmFragmentInstance {
       } else if(boundValue instanceof Label) {
          String param = ((Label) boundValue).getLocalName().replace('@', 'b').replace(':', '_').replace("$", "_");
          return new AsmParameter(param, false);
+      } else if(boundValue instanceof StructMemberRef) {
+         StructMemberRef structMemberRef = (StructMemberRef) boundValue;
+         StructDefinition structDefinition = program.getScope().getStructDefinition(structMemberRef);
+         Variable structMember = structDefinition.getMember(structMemberRef.getMemberName());
+         int memberByteOffset = structDefinition.getMemberByteOffset(structMember);
+         VariableRef struct = (VariableRef) structMemberRef.getStruct();
+         Variable structVar = program.getScope().getVariable( struct);
+         Registers.RegisterZpStruct structRegister = (Registers.RegisterZpStruct) structVar.getAllocation();
+         // TODO Use STRUCT_OFFSET constants instead of hardcoded constants
+         return new AsmParameter(AsmFormat.getAsmParamName(structVar, codeScopeRef)+"+"+memberByteOffset,true);
       } else {
          throw new RuntimeException("Bound Value Type not implemented " + boundValue);
       }
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
index 760674038..d32b64004 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
@@ -249,9 +249,9 @@ public class AsmFragmentInstanceSpecFactory {
                   } else if(constantLiteral instanceof ConstantPointer) {
                      integerValue = ((ConstantPointer) constantLiteral).getValue();
                   } else {
-                     throw new InternalError("Not implemented "+constantLiteral);
+                     throw new InternalError("Not implemented " + constantLiteral);
                   }
-               } catch (ConstantNotLiteral e) {
+               } catch(ConstantNotLiteral e) {
                   // Assume it is a word
                   integerValue = 0xffffL;
                }
@@ -262,7 +262,7 @@ public class AsmFragmentInstanceSpecFactory {
                   } else if(toType.getSizeBytes() == 2) {
                      val = new ConstantBinary(new ConstantInteger(0xffffL, SymbolType.WORD), Operators.BOOL_AND, val);
                   } else {
-                     throw new InternalError("Not implemented "+toType);
+                     throw new InternalError("Not implemented " + toType);
                   }
                }
             }
@@ -304,25 +304,26 @@ public class AsmFragmentInstanceSpecFactory {
          bind(name, value);
          return name;
       } else if(value instanceof StructZero) {
-         return "vssf"+((StructZero) value).getTypeStruct().getSizeBytes();
+         return "vssf" + ((StructZero) value).getTypeStruct().getSizeBytes();
       } else if(value instanceof StructMemberRef) {
          StructMemberRef structMemberRef = (StructMemberRef) value;
+         StructDefinition structDefinition = program.getScope().getStructDefinition(structMemberRef);
+         Variable structMember = structDefinition.getMember(structMemberRef.getMemberName());
+         int memberByteOffset = structDefinition.getMemberByteOffset(structMember);
+
          RValue struct = structMemberRef.getStruct();
-         String memberName = structMemberRef.getMemberName();
-         SymbolType symbolType = SymbolTypeInference.inferType(program.getScope(), struct);
-         byte idx = 0;
-         if(symbolType instanceof SymbolTypeStruct) {
-            String structTypeName = ((SymbolTypeStruct) symbolType).getStructTypeName();
-            StructDefinition structDefinition = program.getScope().getStructDefinition(structTypeName);
-            for(Variable structMember : structDefinition.getAllVariables(false)) {
-               if(structMember.getLocalName().equals(memberName)) {
-                  break;
-               } else {
-                  idx += structMember.getType().getSizeBytes();
-               }
+         if(struct instanceof VariableRef) {
+            Variable structVar = program.getScope().getVariable((VariableRef) struct);
+            if(structVar.getAllocation() instanceof Registers.RegisterZpStruct) {
+               Registers.RegisterZpStruct structRegister = (Registers.RegisterZpStruct) structVar.getAllocation();
+               Registers.RegisterZpStructMember memberRegister = structRegister.getMemberRegister(memberByteOffset);
+               String name = getTypePrefix(structMember.getType()) + getRegisterName(memberRegister);
+               bind(name, structMemberRef);
+               return name;
             }
+         } else {
+            return bind(struct) + "_mbr_" + memberByteOffset;
          }
-         return bind(struct)+"_mbr_"+ idx;
       }
       throw new RuntimeException("Binding of value type not supported " + value);
    }
diff --git a/src/main/java/dk/camelot64/kickc/model/Registers.java b/src/main/java/dk/camelot64/kickc/model/Registers.java
index 7e2075931..0b36bb7d9 100644
--- a/src/main/java/dk/camelot64/kickc/model/Registers.java
+++ b/src/main/java/dk/camelot64/kickc/model/Registers.java
@@ -105,6 +105,7 @@ public class Registers {
       public int hashCode() {
          return zp;
       }
+
    }
 
 
@@ -158,6 +159,10 @@ public class Registers {
          super(zp);
       }
 
+      public RegisterZpStructMember getMemberRegister(int memberByteOffset) {
+         return new RegisterZpStructMember(getZp()+memberByteOffset);
+      }
+
       @Override
       public RegisterType getType() {
          return RegisterType.ZP_STRUCT;
@@ -165,6 +170,21 @@ public class Registers {
 
    }
 
+   /** Zero page addresses used as a register for a struct member variable. */
+   public static class RegisterZpStructMember extends RegisterZp {
+
+      public RegisterZpStructMember(int zp) {
+         super(zp);
+      }
+
+      @Override
+      public RegisterType getType() {
+         return RegisterType.ZP_STRUCT;
+      }
+
+   }
+
+
    /** 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/symbols/ProgramScope.java b/src/main/java/dk/camelot64/kickc/model/symbols/ProgramScope.java
index dc2c9554a..e78825414 100644
--- a/src/main/java/dk/camelot64/kickc/model/symbols/ProgramScope.java
+++ b/src/main/java/dk/camelot64/kickc/model/symbols/ProgramScope.java
@@ -4,7 +4,11 @@ import dk.camelot64.kickc.model.LiveRangeEquivalenceClass;
 import dk.camelot64.kickc.model.LiveRangeEquivalenceClassSet;
 import dk.camelot64.kickc.model.Program;
 import dk.camelot64.kickc.model.types.SymbolType;
+import dk.camelot64.kickc.model.types.SymbolTypeInference;
 import dk.camelot64.kickc.model.types.SymbolTypeProgram;
+import dk.camelot64.kickc.model.types.SymbolTypeStruct;
+import dk.camelot64.kickc.model.values.RValue;
+import dk.camelot64.kickc.model.values.StructMemberRef;
 
 /** The program scope containing the symbols of a program */
 public class ProgramScope extends Scope {
@@ -19,8 +23,18 @@ public class ProgramScope extends Scope {
       return new SymbolTypeProgram();
    }
 
-   public String getSymbolTableContents(Program program) {
-      return toString(program, null);
+
+   /**
+    * Get the struct definition for a struct
+    * @param structMemberRef
+    * @return
+    */
+   public StructDefinition getStructDefinition(StructMemberRef structMemberRef) {
+      RValue struct = structMemberRef.getStruct();
+      SymbolType structType = SymbolTypeInference.inferType(this, struct);
+      String structTypeName = ((SymbolTypeStruct) structType).getStructTypeName();
+      StructDefinition structDefinition = getStructDefinition(structTypeName);
+      return structDefinition;
    }
 
    @Override
diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java
index 165980096..32d7d3adc 100644
--- a/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java
+++ b/src/main/java/dk/camelot64/kickc/model/symbols/StructDefinition.java
@@ -18,6 +18,37 @@ public class StructDefinition extends Scope {
       return new SymbolTypeStruct(this);
    }
 
+   /**
+    * Get a struct member variable
+    * @param name The name of the member
+    * @return The member variable
+    */
+   public Variable getMember(String name) {
+      for(Variable member : getAllVariables(false)) {
+         if(member.getLocalName().equals(name)) {
+            return member;
+         }
+      }
+      return null;
+   }
+
+   /**
+    * Get the number of bytes that the member data is offset from the start of the struct
+    * @param member The member to find offset for
+    * @return The byte offset of the start of the member data
+    */
+   public int getMemberByteOffset(Variable member) {
+      int byteOffset=0;
+      for(Variable structMember : getAllVariables(false)) {
+         if(structMember.equals(member)) {
+            break;
+         } else {
+            byteOffset += structMember.getType().getSizeBytes();
+         }
+      }
+      return byteOffset;
+   }
+
    @Override
    public String toString(Program program) {
       return "block-"+getFullName();
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java
index 30f9e25bd..f38c140db 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeProcedure.java
@@ -40,7 +40,6 @@ public class SymbolTypeProcedure implements SymbolType {
 
    @Override
    public int hashCode() {
-
       return Objects.hash(returnType);
    }
 }
diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java
index 558f73708..bc6cb3082 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeStruct.java
@@ -48,7 +48,6 @@ public class SymbolTypeStruct implements SymbolType {
 
    @Override
    public int hashCode() {
-
       return Objects.hash(name, sizeBytes);
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index 0cdfc6051..ee926831a 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -1154,6 +1154,13 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
       return structDefinition.getType();
    }
 
+   @Override
+   public Object visitStructRef(KickCParser.StructRefContext ctx) {
+      String structDefName = ctx.NAME().getText();
+      StructDefinition structDefinition = getCurrentScope().getStructDefinition(structDefName);
+      return structDefinition.getType();
+   }
+
    @Override
    public SymbolType visitTypeSignedSimple(KickCParser.TypeSignedSimpleContext ctx) {
       String signedness = ctx.getChild(0).getText();
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index a91668f9b..011fd3e50 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,9 +32,19 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testStruct1() throws IOException, URISyntaxException {
+      compileAndCompare("struct-1");
+   }
+
    @Test
    public void testStruct0() throws IOException, URISyntaxException {
-      compileAndCompare("struct-0", log().verboseCreateSsa().verboseParse().verboseStatementSequence());
+      compileAndCompare("struct-0");
+   }
+
+   @Test
+   public void testForTwoVars() throws IOException, URISyntaxException {
+      compileAndCompare("for-two-vars");
    }
 
    @Test
@@ -49,7 +59,7 @@ public class TestPrograms {
 
    @Test
    public void testConstantStringConcat0() throws IOException, URISyntaxException {
-      compileAndCompare("constant-string-concat-0", log().verboseParse().verboseStatementSequence().verboseCreateSsa());
+      compileAndCompare("constant-string-concat-0");
    }
 
    @Test
@@ -57,7 +67,6 @@ public class TestPrograms {
       compileAndCompare("literals");
    }
 
-
    @Test
    public void testConstantStringConcat() throws IOException, URISyntaxException {
       compileAndCompare("constant-string-concat");
diff --git a/src/test/kc/for-two-vars.kc b/src/test/kc/for-two-vars.kc
new file mode 100644
index 000000000..10cf1e510
--- /dev/null
+++ b/src/test/kc/for-two-vars.kc
@@ -0,0 +1,9 @@
+// Test a for-loop with two iterating variables
+// Illustrates that for()-loops currently cannot contain two variable declarations.
+
+void main() {
+    const byte* SCREEN = 0x400;
+    byte *sc=SCREEN+39;
+    for( byte i=0; i<40; i++, sc--)
+        *sc = i;
+}
diff --git a/src/test/kc/struct-0.kc b/src/test/kc/struct-0.kc
index 6235eb405..fd81f7594 100644
--- a/src/test/kc/struct-0.kc
+++ b/src/test/kc/struct-0.kc
@@ -1,4 +1,4 @@
-// Minimal struct - declaration & 
+// Minimal struct - declaration, instantiation and usage
 
 struct Point {
     byte x;
diff --git a/src/test/kc/struct-1.kc b/src/test/kc/struct-1.kc
new file mode 100644
index 000000000..ddbd4a942
--- /dev/null
+++ b/src/test/kc/struct-1.kc
@@ -0,0 +1,18 @@
+// Minimal struct - two instances being used.
+
+struct Point {
+    byte x;
+    byte y;
+};
+
+struct Point point1, point2;
+
+void main() {
+    point1.x = 2;
+    point1.y = 3;
+    point2.x = point1.y;
+    point2.y = point1.x;
+    const byte* SCREEN = 0x0400;
+    SCREEN[0] = point2.x;
+    SCREEN[1] = point2.y;
+}
\ No newline at end of file
diff --git a/src/test/ref/for-two-vars.asm b/src/test/ref/for-two-vars.asm
new file mode 100644
index 000000000..cae2dddd5
--- /dev/null
+++ b/src/test/ref/for-two-vars.asm
@@ -0,0 +1,27 @@
+// Test a for-loop with two iterating variables
+// Illustrates that for()-loops currently cannot contain two variable declarations.
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label SCREEN = $400
+    .label sc = 2
+    lda #<SCREEN+$27
+    sta sc
+    lda #>SCREEN+$27
+    sta sc+1
+    ldx #0
+  b1:
+    txa
+    ldy #0
+    sta (sc),y
+    inx
+    lda sc
+    bne !+
+    dec sc+1
+  !:
+    dec sc
+    cpx #$28
+    bcc b1
+    rts
+}
diff --git a/src/test/ref/struct-0.asm b/src/test/ref/struct-0.asm
index 16096b806..46b08a2aa 100644
--- a/src/test/ref/struct-0.asm
+++ b/src/test/ref/struct-0.asm
@@ -1,4 +1,4 @@
-// Minimal struct - declaration & 
+// Minimal struct - declaration, instantiation and usage
 .pc = $801 "Basic"
 :BasicUpstart(bbegin)
 .pc = $80d "Program"
diff --git a/src/test/ref/struct-1.asm b/src/test/ref/struct-1.asm
new file mode 100644
index 000000000..b4b8782b8
--- /dev/null
+++ b/src/test/ref/struct-1.asm
@@ -0,0 +1,29 @@
+// Minimal struct - two instances being used.
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+  .label point1 = 2
+  .label point2 = 4
+bbegin:
+  lda #0
+  sta point1
+  sta point1+1
+  sta point2
+  sta point2+1
+  jsr main
+  rts
+main: {
+    .label SCREEN = $400
+    lda #2
+    sta point1+0
+    lda #3
+    sta point1+1
+    sta point2+0
+    lda point1+0
+    sta point2+1
+    lda point2+0
+    sta SCREEN
+    lda point2+1
+    sta SCREEN+1
+    rts
+}

From 837104f4fd3efdffb1ac680fea496241beefb972 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Tue, 28 May 2019 22:56:52 +0200
Subject: [PATCH 91/93] Working on structs

---
 .../fragment/_deref_pbuc1=vssz1_mbr_0.asm     |  2 --
 .../fragment/_deref_pbuc1=vssz1_mbr_1.asm     |  2 --
 src/main/fragment/vssz1=vssz2.asm             |  4 +++
 src/main/fragment/vssz1_mbr_0=vbuc1.asm       |  2 --
 src/main/fragment/vssz1_mbr_1=vbuc1.asm       |  2 --
 .../Pass0GenerateStatementSequence.java       |  3 ++
 .../dk/camelot64/kickc/test/TestPrograms.java |  5 +++
 src/test/kc/struct-2.kc                       | 20 +++++++++++
 src/test/ref/struct-2.asm                     | 36 +++++++++++++++++++
 9 files changed, 68 insertions(+), 8 deletions(-)
 delete mode 100644 src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm
 delete mode 100644 src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm
 create mode 100644 src/main/fragment/vssz1=vssz2.asm
 delete mode 100644 src/main/fragment/vssz1_mbr_0=vbuc1.asm
 delete mode 100644 src/main/fragment/vssz1_mbr_1=vbuc1.asm
 create mode 100644 src/test/kc/struct-2.kc
 create mode 100644 src/test/ref/struct-2.asm

diff --git a/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm b/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm
deleted file mode 100644
index f235c1aee..000000000
--- a/src/main/fragment/_deref_pbuc1=vssz1_mbr_0.asm
+++ /dev/null
@@ -1,2 +0,0 @@
-lda {z1}+0
-sta {c1}
\ No newline at end of file
diff --git a/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm b/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm
deleted file mode 100644
index 59a255b43..000000000
--- a/src/main/fragment/_deref_pbuc1=vssz1_mbr_1.asm
+++ /dev/null
@@ -1,2 +0,0 @@
-lda {z1}+1
-sta {c1}
\ No newline at end of file
diff --git a/src/main/fragment/vssz1=vssz2.asm b/src/main/fragment/vssz1=vssz2.asm
new file mode 100644
index 000000000..113613e13
--- /dev/null
+++ b/src/main/fragment/vssz1=vssz2.asm
@@ -0,0 +1,4 @@
+lda {z2}
+sta {z1}
+lda {z2}+1
+sta {z1}+1
\ No newline at end of file
diff --git a/src/main/fragment/vssz1_mbr_0=vbuc1.asm b/src/main/fragment/vssz1_mbr_0=vbuc1.asm
deleted file mode 100644
index cdbf628d1..000000000
--- a/src/main/fragment/vssz1_mbr_0=vbuc1.asm
+++ /dev/null
@@ -1,2 +0,0 @@
-lda #{c1}
-sta {z1}+0
\ No newline at end of file
diff --git a/src/main/fragment/vssz1_mbr_1=vbuc1.asm b/src/main/fragment/vssz1_mbr_1=vbuc1.asm
deleted file mode 100644
index 540828c77..000000000
--- a/src/main/fragment/vssz1_mbr_1=vbuc1.asm
+++ /dev/null
@@ -1,2 +0,0 @@
-lda #{c1}
-sta {z1}+1
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index ee926831a..f25f31473 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -497,6 +497,9 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
          // Add comments to constant
          lValue.setComments(ensureUnusedComments(comments));
       }
+      if(type instanceof SymbolTypeStruct) {
+         lValue.setDeclaredVolatile(true);
+      }
       KickCParser.ExprContext initializer = ctx.expr();
       if(declVarStructMember) {
          if(initializer != null) {
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 011fd3e50..4df4055da 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,6 +32,11 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testStruct2() throws IOException, URISyntaxException {
+      compileAndCompare("struct-2");
+   }
+
    @Test
    public void testStruct1() throws IOException, URISyntaxException {
       compileAndCompare("struct-1");
diff --git a/src/test/kc/struct-2.kc b/src/test/kc/struct-2.kc
new file mode 100644
index 000000000..a52a169db
--- /dev/null
+++ b/src/test/kc/struct-2.kc
@@ -0,0 +1,20 @@
+// Minimal struct - different instances and copying
+
+struct Point {
+    byte x;
+    byte y;
+};
+
+struct Point point1, point2;
+
+void main() {
+    point1.x = 2;
+    point1.y = 3;
+    point2 = point1;
+    point2.x = 4;
+    const byte* SCREEN = 0x0400;
+    SCREEN[0] = point1.x;
+    SCREEN[1] = point1.y;
+    SCREEN[2] = point2.x;
+    SCREEN[3] = point2.y;
+}
\ No newline at end of file
diff --git a/src/test/ref/struct-2.asm b/src/test/ref/struct-2.asm
new file mode 100644
index 000000000..29ff684c8
--- /dev/null
+++ b/src/test/ref/struct-2.asm
@@ -0,0 +1,36 @@
+// Minimal struct - different instances and copying
+.pc = $801 "Basic"
+:BasicUpstart(bbegin)
+.pc = $80d "Program"
+  .label point1 = 2
+  .label point2 = 4
+bbegin:
+  lda #0
+  sta point1
+  sta point1+1
+  sta point2
+  sta point2+1
+  jsr main
+  rts
+main: {
+    .label SCREEN = $400
+    lda #2
+    sta point1+0
+    lda #3
+    sta point1+1
+    lda point1
+    sta point2
+    lda point1+1
+    sta point2+1
+    lda #4
+    sta point2+0
+    lda point1+0
+    sta SCREEN
+    lda point1+1
+    sta SCREEN+1
+    lda point2+0
+    sta SCREEN+2
+    lda point2+1
+    sta SCREEN+3
+    rts
+}

From 007985111a4cbfa10ffbef63816ae187fa8e7898 Mon Sep 17 00:00:00 2001
From: jespergravgaard <jesper@balmangravgaard.dk>
Date: Wed, 29 May 2019 08:05:34 +0200
Subject: [PATCH 92/93] Temporary implementation for arrays of structs

---
 .../pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm      |  2 +
 .../pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm      |  2 +
 .../pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm      |  2 +
 .../pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm      |  2 +
 .../fragment/vbuaa=_deref_pssc1_mbr_0.asm     |  1 +
 .../fragment/vbuaa=_deref_pssc1_mbr_1.asm     |  1 +
 .../vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm      |  1 +
 .../vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm      |  1 +
 .../vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm      |  1 +
 .../vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm      |  1 +
 .../AsmFragmentInstanceSpecFactory.java       |  2 +
 .../kickc/passes/Pass4CodeGeneration.java     | 10 +++--
 .../dk/camelot64/kickc/test/TestPrograms.java |  5 +++
 src/test/kc/struct-3.kc                       | 20 ++++++++++
 src/test/ref/struct-3.asm                     | 39 +++++++++++++++++++
 15 files changed, 86 insertions(+), 4 deletions(-)
 create mode 100644 src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm
 create mode 100644 src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm
 create mode 100644 src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm
 create mode 100644 src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm
 create mode 100644 src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm
 create mode 100644 src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm
 create mode 100644 src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm
 create mode 100644 src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm
 create mode 100644 src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm
 create mode 100644 src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm
 create mode 100644 src/test/kc/struct-3.kc
 create mode 100644 src/test/ref/struct-3.asm

diff --git a/src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm b/src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm
new file mode 100644
index 000000000..916e765e0
--- /dev/null
+++ b/src/main/fragment/pssc1_derefidx_vbuxx_mbr_0=vbuaa.asm
@@ -0,0 +1,2 @@
+sta {c1},x
+
diff --git a/src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm b/src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm
new file mode 100644
index 000000000..778da5aff
--- /dev/null
+++ b/src/main/fragment/pssc1_derefidx_vbuxx_mbr_1=vbuaa.asm
@@ -0,0 +1,2 @@
+sta {c1}+1,x
+
diff --git a/src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm b/src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm
new file mode 100644
index 000000000..64fd3eaf2
--- /dev/null
+++ b/src/main/fragment/pssc1_derefidx_vbuyy_mbr_0=vbuaa.asm
@@ -0,0 +1,2 @@
+sta {c1},y
+
diff --git a/src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm b/src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm
new file mode 100644
index 000000000..91a797b27
--- /dev/null
+++ b/src/main/fragment/pssc1_derefidx_vbuyy_mbr_1=vbuaa.asm
@@ -0,0 +1,2 @@
+sta {c1}+1,y
+
diff --git a/src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm b/src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm
new file mode 100644
index 000000000..bee08251a
--- /dev/null
+++ b/src/main/fragment/vbuaa=_deref_pssc1_mbr_0.asm
@@ -0,0 +1 @@
+lda {c1}
\ No newline at end of file
diff --git a/src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm b/src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm
new file mode 100644
index 000000000..a836deba0
--- /dev/null
+++ b/src/main/fragment/vbuaa=_deref_pssc1_mbr_1.asm
@@ -0,0 +1 @@
+lda {c1}+1
\ No newline at end of file
diff --git a/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm b/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm
new file mode 100644
index 000000000..7454fa763
--- /dev/null
+++ b/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_0.asm
@@ -0,0 +1 @@
+lda {c1},x
\ No newline at end of file
diff --git a/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm b/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm
new file mode 100644
index 000000000..66ef35236
--- /dev/null
+++ b/src/main/fragment/vbuaa=pssc1_derefidx_vbuxx_mbr_1.asm
@@ -0,0 +1 @@
+lda {c1}+1,x
\ No newline at end of file
diff --git a/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm b/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm
new file mode 100644
index 000000000..b2b867b05
--- /dev/null
+++ b/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_0.asm
@@ -0,0 +1 @@
+lda {c1},y
\ No newline at end of file
diff --git a/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm b/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm
new file mode 100644
index 000000000..5c24499d4
--- /dev/null
+++ b/src/main/fragment/vbuaa=pssc1_derefidx_vbuyy_mbr_1.asm
@@ -0,0 +1 @@
+lda {c1}+1,y
\ No newline at end of file
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
index d32b64004..c50725d1b 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecFactory.java
@@ -383,6 +383,8 @@ public class AsmFragmentInstanceSpecFactory {
             return "ppr";
          } else if(elementType instanceof SymbolTypePointer) {
             return "ppt";
+         } else if(elementType instanceof SymbolTypeStruct) {
+            return "pss";
          } else {
             throw new RuntimeException("Not implemented " + type);
          }
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
index e758eb361..8a3920906 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java
@@ -6,10 +6,7 @@ import dk.camelot64.kickc.model.*;
 import dk.camelot64.kickc.model.operators.Operators;
 import dk.camelot64.kickc.model.statements.*;
 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.types.*;
 import dk.camelot64.kickc.model.values.*;
 
 import java.util.*;
@@ -438,6 +435,11 @@ public class Pass4CodeGeneration {
                   String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger(2L), Operators.MULTIPLY, arraySize), 99, scopeRef);
                   asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0");
                   added.add(asmName);
+               } else if(constantArrayFilled.getElementType() instanceof SymbolTypeStruct) {
+                  SymbolTypeStruct structElementType = (SymbolTypeStruct) constantArrayFilled.getElementType();
+                  String asmSize = AsmFormat.getAsmConstant(program, new ConstantBinary(new ConstantInteger((long) structElementType.getSizeBytes()), Operators.MULTIPLY, arraySize), 99, scopeRef);
+                  asm.addDataFilled(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.WORD, asmSize, size, "0");
+                  added.add(asmName);
                } else {
                   throw new RuntimeException("Unhandled constant array element type " + constantArrayFilled.toString(program));
                }
diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 4df4055da..96badfff4 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,6 +32,11 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testStruct3() throws IOException, URISyntaxException {
+      compileAndCompare("struct-3", log().verboseParse().verboseCreateSsa().verboseStatementSequence().verboseFragmentLog());
+   }
+
    @Test
    public void testStruct2() throws IOException, URISyntaxException {
       compileAndCompare("struct-2");
diff --git a/src/test/kc/struct-3.kc b/src/test/kc/struct-3.kc
new file mode 100644
index 000000000..6257aa033
--- /dev/null
+++ b/src/test/kc/struct-3.kc
@@ -0,0 +1,20 @@
+// Minimal struct - different instances and copying
+
+struct Point {
+    byte x;
+    byte y;
+};
+
+struct Point[4] points;
+
+void main() {
+    for( byte i: 0..4) {
+        points[i].x = i;
+        points[i].y = i+1;
+    }
+    const byte* SCREEN = 0x0400;
+    for( byte i: 0..4) {
+        SCREEN[i] = points[i].x;
+        (SCREEN+40)[i] = points[i].y;
+    }
+}
\ No newline at end of file
diff --git a/src/test/ref/struct-3.asm b/src/test/ref/struct-3.asm
new file mode 100644
index 000000000..650be77b8
--- /dev/null
+++ b/src/test/ref/struct-3.asm
@@ -0,0 +1,39 @@
+// Minimal struct - different instances and copying
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+main: {
+    .label SCREEN = $400
+    .label _5 = 2
+    ldx #0
+  b1:
+    txa
+    asl
+    sta _5
+    tay
+    txa
+    sta points,y
+    txa
+    tay
+    iny
+    tya
+    ldy _5
+    sta points+1,y
+    inx
+    cpx #5
+    bne b1
+    ldy #0
+  b2:
+    tya
+    asl
+    tax
+    lda points,x
+    sta SCREEN,y
+    lda points+1,x
+    sta SCREEN+$28,y
+    iny
+    cpy #5
+    bne b2
+    rts
+}
+  points: .fill 2*4, 0

From ef953a12b496f38cf8cd9e44f06f188c6672dd87 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Wed, 29 May 2019 17:45:17 +0200
Subject: [PATCH 93/93] Added some pointer-based struct tests (simulating the
 ASM we want for array indexing).

---
 .../dk/camelot64/kickc/test/TestPrograms.java | 12 +++-
 src/test/kc/struct-3.kc                       |  2 +-
 src/test/kc/struct-4.kc                       | 24 +++++++
 src/test/kc/struct-5.kc                       | 26 +++++++
 src/test/ref/struct-3.asm                     |  2 +-
 src/test/ref/struct-4.asm                     | 39 +++++++++++
 src/test/ref/struct-5.asm                     | 67 +++++++++++++++++++
 7 files changed, 169 insertions(+), 3 deletions(-)
 create mode 100644 src/test/kc/struct-4.kc
 create mode 100644 src/test/kc/struct-5.kc
 create mode 100644 src/test/ref/struct-4.asm
 create mode 100644 src/test/ref/struct-5.asm

diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
index 96badfff4..746e6faa5 100644
--- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
+++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java
@@ -32,9 +32,19 @@ public class TestPrograms {
    public TestPrograms() {
    }
 
+   @Test
+   public void testStruct5() throws IOException, URISyntaxException {
+      compileAndCompare("struct-5", log().verboseParse().verboseCreateSsa().verboseStatementSequence());
+   }
+
+   @Test
+   public void testStruct4() throws IOException, URISyntaxException {
+      compileAndCompare("struct-4", log().verboseParse().verboseCreateSsa().verboseStatementSequence());
+   }
+
    @Test
    public void testStruct3() throws IOException, URISyntaxException {
-      compileAndCompare("struct-3", log().verboseParse().verboseCreateSsa().verboseStatementSequence().verboseFragmentLog());
+      compileAndCompare("struct-3");
    }
 
    @Test
diff --git a/src/test/kc/struct-3.kc b/src/test/kc/struct-3.kc
index 6257aa033..d6d25f7df 100644
--- a/src/test/kc/struct-3.kc
+++ b/src/test/kc/struct-3.kc
@@ -1,4 +1,4 @@
-// Minimal struct - different instances and copying
+// Minimal struct - array of struct
 
 struct Point {
     byte x;
diff --git a/src/test/kc/struct-4.kc b/src/test/kc/struct-4.kc
new file mode 100644
index 000000000..504bb7265
--- /dev/null
+++ b/src/test/kc/struct-4.kc
@@ -0,0 +1,24 @@
+// Minimal struct - array of struct - near pointer math indexing
+
+struct Point {
+    byte x;
+    byte y;
+};
+
+struct Point[4] points;
+
+const byte SIZEOF_POINT = 2;
+const byte OFFS_X = 0;
+const byte OFFS_Y = 1;
+
+void main() {
+    for( byte i: 0..3) {
+        *((byte*)points+OFFS_X+i*SIZEOF_POINT) = i;    // points[i].x = i;
+        *((byte*)points+OFFS_Y+i*SIZEOF_POINT) = i+4;  // points[i].y = i+4;
+    }
+    const byte* SCREEN = 0x0400;
+    for( byte i: 0..3) {
+        SCREEN[i] = *((byte*)points+OFFS_X+i*SIZEOF_POINT);      // SCREEN[i] = points[i].x;
+        (SCREEN+40)[i] = *((byte*)points+OFFS_Y+i*SIZEOF_POINT); // (SCREEN+40)[i] = points[i].y;
+    }
+}
\ No newline at end of file
diff --git a/src/test/kc/struct-5.kc b/src/test/kc/struct-5.kc
new file mode 100644
index 000000000..1d2cf6cd5
--- /dev/null
+++ b/src/test/kc/struct-5.kc
@@ -0,0 +1,26 @@
+// Minimal struct - array of struct - far pointer math indexing
+
+struct Point {
+    byte x;
+    byte y;
+};
+
+struct Point[4] points;
+
+const byte SIZEOF_POINT = 2;
+const byte OFFS_X = 0;
+const byte OFFS_Y = 1;
+
+void main() {
+    for( byte i: 0..3) {
+        struct Point* point_i = points+i;
+        *((byte*)point_i+OFFS_X) = i;    // points[i].x = i;
+        *((byte*)point_i+OFFS_Y)  = i+4;  // points[i].y = i+4;
+    }
+    const byte* SCREEN = 0x0400;
+    for( byte i: 0..3) {
+        struct Point* point_i = points+i;
+        SCREEN[i] = *((byte*)point_i+OFFS_X);      // SCREEN[i] = points[i].x;
+        (SCREEN+40)[i] = *((byte*)point_i+OFFS_Y); // (SCREEN+40)[i] = points[i].y;
+    }
+}
\ No newline at end of file
diff --git a/src/test/ref/struct-3.asm b/src/test/ref/struct-3.asm
index 650be77b8..998d77eb6 100644
--- a/src/test/ref/struct-3.asm
+++ b/src/test/ref/struct-3.asm
@@ -1,4 +1,4 @@
-// Minimal struct - different instances and copying
+// Minimal struct - array of struct
 .pc = $801 "Basic"
 :BasicUpstart(main)
 .pc = $80d "Program"
diff --git a/src/test/ref/struct-4.asm b/src/test/ref/struct-4.asm
new file mode 100644
index 000000000..d8901027f
--- /dev/null
+++ b/src/test/ref/struct-4.asm
@@ -0,0 +1,39 @@
+// Minimal struct - array of struct - near pointer math indexing
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .const OFFS_X = 0
+  .const OFFS_Y = 1
+main: {
+    .label SCREEN = $400
+    ldx #0
+  b1:
+    txa
+    asl
+    tay
+    txa
+    sta points+OFFS_X,y
+    txa
+    clc
+    adc #4
+    // points[i].x = i;
+    sta points+OFFS_Y,y
+    inx
+    cpx #4
+    bne b1
+    ldy #0
+  b2:
+    tya
+    asl
+    tax
+    lda points+OFFS_X,x
+    sta SCREEN,y
+    // SCREEN[i] = points[i].x;
+    lda points+OFFS_Y,x
+    sta SCREEN+$28,y
+    iny
+    cpy #4
+    bne b2
+    rts
+}
+  points: .fill 2*4, 0
diff --git a/src/test/ref/struct-5.asm b/src/test/ref/struct-5.asm
new file mode 100644
index 000000000..3bbbba092
--- /dev/null
+++ b/src/test/ref/struct-5.asm
@@ -0,0 +1,67 @@
+// Minimal struct - array of struct - far pointer math indexing
+.pc = $801 "Basic"
+:BasicUpstart(main)
+.pc = $80d "Program"
+  .const OFFS_X = 0
+  .const OFFS_Y = 1
+main: {
+    .label SCREEN = $400
+    .label _1 = 4
+    .label _3 = 2
+    .label _8 = 4
+    .label _11 = 2
+    .label point_i = 2
+    .label point_i1 = 2
+    ldx #0
+  b1:
+    txa
+    asl
+    clc
+    adc #<points
+    sta point_i
+    lda #>points
+    adc #0
+    sta point_i+1
+    lda point_i
+    sta _1
+    lda point_i+1
+    sta _1+1
+    txa
+    ldy #OFFS_X
+    sta (_1),y
+    txa
+    clc
+    adc #4
+    // points[i].x = i;
+    ldy #OFFS_Y
+    sta (_3),y
+    inx
+    cpx #4
+    bne b1
+    ldx #0
+  b2:
+    txa
+    asl
+    clc
+    adc #<points
+    sta point_i1
+    lda #>points
+    adc #0
+    sta point_i1+1
+    lda point_i1
+    sta _8
+    lda point_i1+1
+    sta _8+1
+    ldy #OFFS_X
+    lda (_8),y
+    sta SCREEN,x
+    // SCREEN[i] = points[i].x;
+    ldy #OFFS_Y
+    lda (_11),y
+    sta SCREEN+$28,x
+    inx
+    cpx #4
+    bne b2
+    rts
+}
+  points: .fill 2*4, 0