@Override
 public void compile() {
   Debugger debugContext = DinaCompiler.getDebugger();
   int variablesWithValue = 0;
   int variablesAmount = getVariablesAmount();
   for (int variableIndex = 0; variableIndex < variablesAmount; variableIndex++) {
     Variable variable = getVariable(variableIndex);
     if (variable.getValue() != null) {
       if (constructor == null) {
         constructor = new Function(ParserConstants.CONSTRUCTOR);
         constructor.setStatement(new Block());
         constructor.getStatement().setFunction(constructor);
       }
       Assignment assignment = new Assignment(variable, variable.getValue());
       constructor.getStatement().insertNode(assignment, variablesWithValue);
       variablesWithValue++;
     }
   }
   if (constructor != null) {
     Output.writeSystemInformation(Constants.BEGIN_FUNCTION);
     constructor.compile();
     if (Debugger.DEVELOPMENT_MODE) {
       debugContext.putFunction("<constructor>", constructor.getAddress());
     }
     Output.writeSystemInformation(Constants.END_FUNCTION);
   }
   int functionsAmount = functions.size();
   for (int functionIndex = 0; functionIndex < functionsAmount; functionIndex++) {
     Function function = functions.getValue(functionIndex);
     Output.writeSystemInformation(Constants.BEGIN_FUNCTION);
     function.compile();
     if (Debugger.DEVELOPMENT_MODE) {
       debugContext.putFunction(
           function.getSignatureLabel() + function.getNodeType().getSignature(),
           function.getAddress());
     }
     Output.writeSystemInformation(Constants.END_FUNCTION);
   }
   if (destructor != null) {
     Output.writeSystemInformation(Constants.BEGIN_FUNCTION);
     destructor.compile();
     if (Debugger.DEVELOPMENT_MODE) {
       debugContext.putFunction("<destructor>", destructor.getAddress());
     }
     Output.writeSystemInformation(Constants.END_FUNCTION);
   }
 }
  /**
   * Visit a variable node. The value of the variable is obtained from the symbol table (symTab) and
   * pushed onto the stack.
   */
  public Object visit(ASTVarNode node, Object data) throws ParseException {

    // try to get the variable object
    Variable var = symTab.getVar(node.getVarName());
    if (var == null) {
      String message = "Could not evaluate " + node.getVarName() + ": ";
      throw new ParseException(message + "the variable was not found in the symbol table");
    }

    // get the variable value
    // Object temp = var.getValue();
    Object temp = var.getValue();

    if (trapNullValues && temp == null) {
      String message = "Could not evaluate " + node.getVarName() + ": ";
      throw new ParseException(message + "variable not set");
    }
    // all is fine
    // push the value on the stack
    stack.push(temp);
    return data;
  }
  public Integer handleVar(ASTVar node) {
    System.out.println(node.jjtGetParent());
    Integer value = -256;
    int index = -10000;
    String name = node.getName();
    if (node.isArg()) {
      name += "_";
    }

    if (JustCalling) {
      return value;
    }
    Variable v = Global.getCurrentSymbolTable().getVariable(name);
    if (v instanceof ByNameVariable) {
      v = Global.getCurrentSymbolTable().getCacheVariable(name);
      System.out.println(v + " should be null the first time");
      if (v != null) {
        int ret = 0;
        try {
          ret = v.getValue();
        } catch (VizIndexOutOfBoundsException e) {
          System.out.println(e);
        }
        return ret;
      }
    } else {
      v = Global.getCurrentSymbolTable().getVariable(name);
    }

    boolean cached = false;
    if (v == null) {

      v = Global.getCurrentSymbolTable().getVariable(name);
      System.out.println(v);
      int val = 0;
      try {
        val = v.getValue();

        Global.getCurrentSymbolTable().addCacheVariable(name, val);

      } catch (VizIndexOutOfBoundsException e) {
        System.out.println(e);
      }
      if (node.getIsArray()) {
        name += "[" + ((SimpleNode) node.jjtGetChild(0)).getCode() + "]";
      }
      connector.addVariableToCache(name, val, "foo");
    } else {
      cached = true;
    }

    if (v instanceof ByNameVariable) {
      try {
        value = v.getValue();
      } catch (VizIndexOutOfBoundsException e) {
        System.out.println(e);
      }
    } else {
      if (node.getIsArray()) {
        index = (Integer) node.jjtGetChild(0).jjtAccept(this, null);
        node.setIndex(index);
        try {
          value = v.getValue(index);

        } catch (VizIndexOutOfBoundsException e) {
          System.out.println(e);
          ASTExpression exp = (ASTExpression) node.jjtGetChild(0);
          ASTNum num = new ASTNum(JJTNUM);
          Random r = new Random();
          num.setValue(r.nextInt(6));
          exp.jjtAddChild(num, 0);
          try {
            index = (Integer) exp.jjtAccept(this, null);
            value = v.getValue(index);
          } catch (VizIndexOutOfBoundsException f) {
            System.out.println("oops...");
          }
          program.codeBuilt = false;
          Global.lineNumber = 1;
          program.buildCode();
        }
      } else {
        try {
          value = v.getValue();
        } catch (VizIndexOutOfBoundsException f) {
          System.out.println(f);
        }
      }
      System.out.println("F*****g " + value + v + cached);
    }
    if (v instanceof ByNameVariable) {
      if (cached) {
        connector.highlightVarByName(v);
      } else {

        connector.greyScope("foo");

        connector.highlightScopeByName("main");
        if (((ByNameVariable) v).getVariable().getIsArray()) {
          connector.highlightVarByName(
              ((ByNameVariable) v).getVariable(), ((ByNameVariable) v).getIndex());
        } else {
          connector.highlightVarByName(((ByNameVariable) v).getVariable());
        }
      }
    } else {

      if (node.getIsArray()) {
        // connector.highlightVarByName(v, index);
      } else {
        // connector.highlightVarByName(v);
      }
    }
    return value;
  }