/** NB! Must be called in correct order! */
  public void addArg(String name, PhantomType type) throws PlcException {
    if (type == null) {
      // Object a = null;        a.getClass();
      throw new PlcException("Method add_arg", "null type of arg", name);
    }

    args_def.add(new ArgDefinition(name, type));
    svars.add_stack_var(new PhantomVariable(name, type));
  }
  public void generate_code(CodeGeneratorState s) throws PlcException, IOException {
    if (code == null) {
      c.emitRet(); // empty function code
      return;
    }

    // ------------------------------------------
    // traverse tree to allocate automatic vars?
    // ------------------------------------------
    int n_auto_vars = svars.getUsedSlots();
    int n_int_auto_vars = isvars.getUsedSlots();
    // ------------------------------------------

    // ------------------------------------------
    // generate prologue code here
    // ------------------------------------------

    // check number of args
    int n_args = args_def.size();
    String good_args_label = c.getLabel();

    c.emitIConst_32bit(n_args);
    c.emitISubLU();
    c.emitJz(good_args_label);

    // wrong count - throw string
    // BUG! Need less consuming way of reporting this. Maybe by
    // calling class object Method? Or by summoning something?
    c.emitString("arg count: " + name + " in " + s.get_class().getName());
    c.emitThrow();

    c.markLabel(good_args_label);

    if (requestDebug) c.emitDebug((byte) 0x1, "Enabled debug");

    // push nulls to reserve stack space for autovars
    // BUG! We can execute vars initialization code here, can we?
    // We can if code does not depend on auto vars itself, or depends only on
    // previous ones.
    // TODO: BUG! autovars in arguments are already on stack, we don't have to reserve space
    for (int i = n_auto_vars; i > 0; i--) c.emitPushNull();

    // TODO introduce instruction to reserve o+i space in one step
    // Reserve integer stack place for int vars
    for (int i = n_int_auto_vars; i > 0; i--) c.emitIConst_0();

    // ------------------------------------------

    // ------------------------------------------
    // generate main code by descending the tree
    // ------------------------------------------
    code.generate_code(c, s);
    // ------------------------------------------

    // ------------------------------------------
    // generate epilogue code here
    // ------------------------------------------
    if (requestDebug) c.emitDebug((byte) 0x2, "Disabled debug");
    c.emitRet(); // catch the fall-out
    // ------------------------------------------

  }