private static ArrayList<String> pushVariable(Token t) throws Exception {
   ArrayList<String> res = new ArrayList<>();
   Variable v = Alzheimer.variables.get(t.valueWithoutIndex());
   if (v == null) {
     if (!t.isNumber() && !t.isString() && !t.isCharacter()) {
       if (!t.isType()) {
         throw new CompilerException("Unknown variable " + t.value, t.file, t.line);
       } else {
         Type T = Alzheimer.types.get(t.valueBeforeFirstDot());
         if (T == null) {
           throw new CompilerException("Unknown type " + t.valueBeforeFirstDot(), t.file, t.line);
         } else {
           switch (t.valueAfterFirstDot()) {
             case "size":
               exec("push " + T.size() + "; " + t.value, res);
               break;
             default:
               throw new CompilerException(
                   "Type '"
                       + t.valueBeforeFirstDot()
                       + "' does not have property '"
                       + t.valueAfterFirstDot()
                       + "' ",
                   t.file,
                   t.line);
           }
         }
       }
     } else {
       exec("push " + t.value + ";", res);
     }
   } else {
     if (v.isArray && !t.isArray()) {
       res.addAll(pushArray(v, t.file, t.line));
     } else {
       if (t.isArray()) {
         v = new Variable();
         v.name = t.value;
         String alz = "" + v.accessVarName() + "=( " + v.arrayIndex() + " );\n";
         res.addAll(Alzheimer.compile(alz));
         res.addAll(v.type.push(v.nameWithoutIndex() + "[" + v.accessVarName() + "]"));
       } else {
         res.addAll(v.type.push(t.value));
       }
     }
   }
   return res;
 }
 private ArrayList<String> expression(ArrayList<Token> tokens) throws Exception {
   ArrayList<String> res = new ArrayList<>();
   Token opTok = tokens.remove(0);
   if (tokens.size() < 1) {
     Variable v = Alzheimer.variables.get(opTok.valueWithoutIndex());
     if (v == null && !opTok.isType()) {
       if (!opTok.isNumber()) {
         throw new CompilerException(
             "Number, variable or type property expected", opTok.file, opTok.line);
       }
       res.add("push " + opTok.value + ";");
       return res;
     }
     res.addAll(pushVariable(opTok));
     return res;
   }
   if (!opTok.value.equals("(")) {
     if (tokens.size() != 0) {
       Token tmp = tokens.remove(0);
       if (!tmp.value.equals("(")) {
         throw new CompilerException("( expected", tmp.file, tmp.line);
       }
     } else {
       throw new CompilerException("Something is wrong!", opTok.file, opTok.line);
     }
   }
   ArrayList<String> args = new ArrayList<>();
   while (tokens.size() != 0) {
     Token t;
     if (tokens.size() > 1) {
       t = tokens.get(1);
       if (t.value.equals("(")) {
         res.addAll(expression(tokens));
         args.add("");
       } else {
         t = tokens.remove(0);
         if (t.value.equals(")")) {
           break;
         }
         if (t.isString()) {
           exec(t.pushString(), res);
         } else {
           res.addAll(pushVariable(t));
         }
       }
     } else {
       t = tokens.remove(0);
       if (t.value.equals(")")) {
         break;
       }
       if (t.isString()) {
         exec(t.pushString(), res);
       } else {
         res.addAll(pushVariable(t));
       }
     }
   }
   switch (opTok.value) {
     case "(":
       break;
     case "+":
     case "add":
       exec("add", res);
       break;
     case "-":
     case "sub":
       exec("sub", res);
       break;
     case "*":
     case "mul":
       exec("mul", res);
       break;
     case "/":
     case "div":
       exec("div", res);
       break;
     case "floor":
       exec("floor", res);
       break;
     case "ceil":
       exec("ceil", res);
       break;
     default:
       exec("call $" + opTok.value, res);
   }
   return res;
 }