albertodemichelis / squirrel

Official repository for the programming language Squirrel
http://www.squirrel-lang.org
MIT License
917 stars 158 forks source link

Squirrel opcode description ? #22

Open mingodad opened 8 years ago

mingodad commented 8 years ago

Hello ! Is it possible to have a description of squirrel opcodes ?

I'm trying to dump the compiled code to be manipulated by a script but I'm having some trouble to understand it by looking at the compiler/sqmv files.

Cheers !

For example in lua lopcodes.h, it's also a bit crypt but better than nothing:

typedef enum {
/*----------------------------------------------------------------------
name        args    description
------------------------------------------------------------------------*/
OP_MOVE,/*  A B R(A) := R(B)                    */
OP_LOADK,/* A Bx    R(A) := Kst(Bx)                 */
OP_LOADBOOL,/*  A B C   R(A) := (Bool)B; if (C) pc++            */
OP_LOADNIL,/*   A B R(A) := ... := R(B) := nil          */
OP_GETUPVAL,/*  A B R(A) := UpValue[B]              */

OP_GETGLOBAL,/* A Bx    R(A) := Gbl[Kst(Bx)]                */
OP_GETTABLE,/*  A B C   R(A) := R(B)[RK(C)]             */

OP_SETGLOBAL,/* A Bx    Gbl[Kst(Bx)] := R(A)                */
OP_SETUPVAL,/*  A B UpValue[B] := R(A)              */
OP_SETTABLE,/*  A B C   R(A)[RK(B)] := RK(C)                */

OP_NEWTABLE,/*  A B C   R(A) := {} (size = B,C)             */

OP_SELF,/*  A B C   R(A+1) := R(B); R(A) := R(B)[RK(C)]     */

OP_ADD,/*   A B C   R(A) := RK(B) + RK(C)               */
OP_SUB,/*   A B C   R(A) := RK(B) - RK(C)               */
OP_MUL,/*   A B C   R(A) := RK(B) * RK(C)               */
OP_DIV,/*   A B C   R(A) := RK(B) / RK(C)               */
OP_MOD,/*   A B C   R(A) := RK(B) % RK(C)               */
OP_POW,/*   A B C   R(A) := RK(B) ^ RK(C)               */
OP_UNM,/*   A B R(A) := -R(B)                   */
OP_NOT,/*   A B R(A) := not R(B)                */
OP_LEN,/*   A B R(A) := length of R(B)              */

OP_CONCAT,/*    A B C   R(A) := R(B).. ... ..R(C)           */

OP_JMP,/*   sBx pc+=sBx                 */

OP_EQ,/*    A B C   if ((RK(B) == RK(C)) ~= A) then pc++        */
OP_LT,/*    A B C   if ((RK(B) <  RK(C)) ~= A) then pc++        */
OP_LE,/*    A B C   if ((RK(B) <= RK(C)) ~= A) then pc++        */

OP_TEST,/*  A C if not (R(A) <=> C) then pc++           */ 
OP_TESTSET,/*   A B C   if (R(B) <=> C) then R(A) := R(B) else pc++ */ 

OP_CALL,/*  A B C   R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/*  A B C   return R(A)(R(A+1), ... ,R(A+B-1))      */
OP_RETURN,/*    A B return R(A), ... ,R(A+B-2)  (see note)  */

OP_FORLOOP,/*   A sBx   R(A)+=R(A+2);
            if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
OP_FORPREP,/*   A sBx   R(A)-=R(A+2); pc+=sBx               */

OP_TFORLOOP,/*  A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); 
                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++   */ 
OP_SETLIST,/*   A B C   R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B    */

OP_CLOSE,/* A   close all variables in the stack up to (>=) R(A)*/
OP_CLOSURE,/*   A Bx    R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))  */

OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg        */
} OpCode;

#define NUM_OPCODES (cast(int, OP_VARARG) + 1)

/*===========================================================================
  Notes:
  (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
      and can be 0: OP_CALL then sets `top' to last_result+1, so
      next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.

  (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
      set top (like in OP_CALL with C == 0).

  (*) In OP_RETURN, if (B == 0) then return up to `top'

  (*) In OP_SETLIST, if (B == 0) then B = `top';
      if (C == 0) then next `instruction' is real C

  (*) For comparisons, A specifies what condition the test should accept
      (true or false).

  (*) All `skips' (pc++) assume that next instruction is a jump
===========================================================================*/

/*
** masks for instruction properties. The format is:
** bits 0-1: op mode
** bits 2-3: C arg mode
** bits 4-5: B arg mode
** bit 6: instruction set register A
** bit 7: operator is a test
*/  

enum OpArgMask {
  OpArgN,  /* argument is not used */
  OpArgU,  /* argument is used */
  OpArgR,  /* argument is a register or a jump offset */
  OpArgK   /* argument is a constant or register/constant */
};
albertodemichelis commented 8 years ago

I'll try to write something about it, asap.

mattnewport commented 1 month ago

Did anything ever get written up for this? I'm trying to understand the opcode format as well and having some documentation would be helpful.

mingodad commented 1 month ago

I've tried to make sense of it by adding an extra option -s to my fork here https://github.com/mingodad/squilu:

squilu -h
usage: sq <options> <scriptpath [args]>.
Available options are:
   -s              compiles the file to bytecode(default output 'out.cnut')
   -o              specifies output file for the -c option
   -c              compiles only
   -d              generates debug infos
   -v              displays version infos
   -p              preload given script file
   -i              set the include_path
   -D              define a preprocesor named constant
   -h              prints help
SquiLu based on Squirrel 3.1 stable and Lua 5.1.5 Copyright (C) 2003-2017 Alberto Demichelis, Domingo Alvarez Duarte (64 bits)

Sample:

//squilu _fix-non-terminal.nut srcML-dad.g
if(vargv.len() < 2) {
    print("usage:", vargv[0], " grammar_file");
    os.exit(1);
}

auto cmd = "./parsertl-playground " + vargv[1] + " test.empty 2>&1";
print(cmd);

auto txt = popen(cmd, "r").read_all();
//print(txt);

txt = txt.gsub("Warning: Token \"[^\n]-\" is not used in the grammar.\n", "");
txt = txt.replace("Non-terminal '", "%token ");
txt = txt.replace("' does not have any productions.", "");

txt = txt.gsub("Warning: Token \"([^\n]-)\" does not have a lexer definiton%.", function(m) {
    if(m[0] == '\'') return format("\"%s\"\t%s", m.slice(1,-1), m);
    return format("%s\t%s", m, m);
    });
txt = txt.gsub("Unknown token \"([^\n]-)\"%.", "%%token %1");

auto lines = txt.split('\n');
lines.sort(@(a,b) a<=>b);

auto prevLine;
foreach(line in lines) {
    if(line == prevLine) continue;
    prevLine = line;
    print(line);
}

Output:

local bytecode = {
    source_name = "_fix-non-terminal.nut",
    function_name = "main",
    function_return_type = null,
    literals = [
        /*0*/ "len",
        /*1*/ "print",
        /*2*/ "usage:",
        /*3*/ " grammar_file",
        /*4*/ "os",
        /*5*/ "exit",
        /*6*/ "./parsertl-playground ",
        /*7*/ " test.empty 2>&1",
        /*8*/ "popen",
        /*9*/ "r",
        /*10*/ "read_all",
        /*11*/ "gsub",
        /*12*/ [==[Warning: Token "[^
]-" is not used in the grammar.
]==],
        /*13*/ null,
        /*14*/ "replace",
        /*15*/ "Non-terminal '",
        /*16*/ "%token ",
        /*17*/ "' does not have any productions.",
        /*18*/ [==[Warning: Token "([^
]-)" does not have a lexer definiton%.]==],
        /*19*/ [==[Unknown token "([^
]-)"%.]==],
        /*20*/ "%%token %1",
        /*21*/ "split",
        /*22*/ "sort",
    ],
    parameters = [
        /*0*/ "this",
        /*1*/ "vargv",
    ],
    outervalues = [
        //[type, src, name],
    ],
    localvarinfos = [
        //[pos, name, start_op, end_op, scope, type, type_name, dtype_name],
        /*0*/ [0, "this", 0, 68, 1, 1, "ANY", ""],
        /*1*/ [1, "vargv", 0, 68, 1, 1, "ANY", ""],
        /*2*/ [2, "cmd", 20, 67, 0, 1, "ANY", "TK_LOCAL"],
        /*3*/ [3, "txt", 29, 67, 0, 1, "ANY", "TK_LOCAL"],
        /*4*/ [4, "lines", 53, 67, 0, 1, "ANY", "TK_LOCAL"],
        /*5*/ [5, "prevLine", 57, 67, 0, 1, "ANY", "TK_LOCAL"],
        /*6*/ [6, "@INDEX@", 57, 67, 1, 1, "ANY", ""],
        /*7*/ [7, "line", 58, 67, 1, 1, "ANY", ""],
        /*8*/ [8, "@ITERATOR@", 58, 67, 1, 1, "ANY", ""],
    ],
    lineinfos = [
        //[op, line],
        /*0*/ [0, 2], /*_OP_PREPCALLK*/
        /*1*/ [4, 3], /*_OP_PREPCALLK*/
        /*2*/ [10, 4], /*_OP_GETK*/
        /*3*/ [14, 7], /*_OP_LOAD*/
        /*4*/ [20, 8], /*_OP_PREPCALLK*/
        /*5*/ [23, 10], /*_OP_PREPCALLK*/
        /*6*/ [29, 13], /*_OP_PREPCALLK*/
        /*7*/ [33, 14], /*_OP_PREPCALLK*/
        /*8*/ [37, 15], /*_OP_PREPCALLK*/
        /*9*/ [41, 17], /*_OP_PREPCALLK*/
        /*10*/ [46, 21], /*_OP_PREPCALLK*/
        /*11*/ [50, 23], /*_OP_PREPCALLK*/
        /*12*/ [53, 24], /*_OP_PREPCALLK*/
        /*13*/ [56, 26], /*_OP_LOADNULLS*/
        /*14*/ [57, 27], /*_OP_LOADNULLS*/
        /*15*/ [60, 28], /*_OP_EQ*/
        /*16*/ [63, 29], /*_OP_MOVE*/
        /*17*/ [64, 30], /*_OP_PREPCALLK*/
        /*18*/ [68, 33], /*_OP_RETURN*/
    ],
    defaultparams = [],
    instructions = [ /*stack*/
        //[op_str, op, arg0, arg1, arg2, arg3],
        /*0*/ ["_OP_PREPCALLK", 8, 2, 0, 1, 3], /* closure_at_stk[2], stk[1].get(literals[0]) -> stk[3] */
        /*1*/ ["_OP_CALL", 6, 2, 2, 3, 1],      /* target[2], lvi[2]("cmd"), stackbase(3), nargs(1) */
        /*2*/ ["_OP_LOADINT", 2, 3, 2, 0, 0],   /* stk[3] <- arg1(2) */
        /*3*/ ["_OP_JCMP", 29, 3, 10, 2, 3],        /* IsFalse(STK(2) CMP_L STK(3)) (ci->_ip+=(10) -> goto[14]) */
        /*4*/ ["_OP_PREPCALLK", 8, 2, 1, 0, 3], /* closure_at_stk[2], stk[0].get(literals[1]) -> stk[3] */
        /*5*/ ["_OP_LOAD", 1, 4, 2, 0, 0],      /* stk[4] <- literals[2]("usage:") */
        /*6*/ ["_OP_LOADINT", 2, 5, 0, 0, 0],   /* stk[5] <- arg1(0) */
        /*7*/ ["_OP_GET", 14, 5, 1, 5, 0],  /* stk_at_arg0[5] = stk_at_arg1[1].get(stk_at_arg2(5)) */
        /*8*/ ["_OP_LOAD", 1, 6, 3, 0, 0],      /* stk[6] <- literals[3](" grammar_file") */
        /*9*/ ["_OP_CALL", 6, 255, 2, 3, 4],        /* target[255], lvi[2]("cmd"), stackbase(3), nargs(4) */
        /*10*/ ["_OP_GETK", 9, 2, 4, 0, 0],     /* stk[2] <- literals[4]("os") */
        /*11*/ ["_OP_PREPCALLK", 8, 2, 5, 2, 3],    /* closure_at_stk[2], stk[2].get(literals[5]) -> stk[3] */
        /*12*/ ["_OP_LOADINT", 2, 4, 1, 0, 0],  /* stk[4] <- arg1(1) */
        /*13*/ ["_OP_CALL", 6, 255, 2, 3, 2],       /* target[255], lvi[2]("cmd"), stackbase(3), nargs(2) */
        /*14*/ ["_OP_LOAD", 1, 2, 6, 0, 0],     /* stk[2] <- literals[6]("./parsertl-playground ") */
        /*15*/ ["_OP_LOADINT", 2, 3, 1, 0, 0],  /* stk[3] <- arg1(1) */
        /*16*/ ["_OP_GET", 14, 3, 1, 3, 0], /* stk_at_arg0[3] = stk_at_arg1[1].get(stk_at_arg2(3)) */
        /*17*/ ["_OP_ADD", 17, 2, 3, 2, 0],     /* stk[2] = stk[2]("cmd") + stk[3]("txt") */
        /*18*/ ["_OP_LOAD", 1, 3, 7, 0, 0],     /* stk[3] <- literals[7](" test.empty 2>&1") */
        /*19*/ ["_OP_ADD", 17, 2, 3, 2, 0],     /* stk[2] = stk[2]("cmd") + stk[3]("txt") */
        /*20*/ ["_OP_PREPCALLK", 8, 3, 1, 0, 4],    /* closure_at_stk[3], stk[0].get(literals[1]) -> stk[4] */
        /*21*/ ["_OP_MOVE", 10, 5, 2, 0, 0],        /* stk[5] <- lvi[2]("cmd") */
        /*22*/ ["_OP_CALL", 6, 255, 3, 4, 2],       /* target[255], lvi[3]("txt"), stackbase(4), nargs(2) */
        /*23*/ ["_OP_PREPCALLK", 8, 3, 8, 0, 4],    /* closure_at_stk[3], stk[0].get(literals[8]) -> stk[4] */
        /*24*/ ["_OP_MOVE", 10, 5, 2, 0, 0],        /* stk[5] <- lvi[2]("cmd") */
        /*25*/ ["_OP_LOAD", 1, 6, 9, 0, 0],     /* stk[6] <- literals[9]("r") */
        /*26*/ ["_OP_CALL", 6, 3, 3, 4, 3],     /* target[3], lvi[3]("txt"), stackbase(4), nargs(3) */
        /*27*/ ["_OP_PREPCALLK", 8, 3, 10, 3, 4],   /* closure_at_stk[3], stk[3].get(literals[10]) -> stk[4] */
        /*28*/ ["_OP_CALL", 6, 3, 3, 4, 1],     /* target[3], lvi[3]("txt"), stackbase(4), nargs(1) */
        /*29*/ ["_OP_PREPCALLK", 8, 4, 11, 3, 5],   /* closure_at_stk[4], stk[3].get(literals[11]) -> stk[5] */
        /*30*/ ["_OP_DLOAD", 4, 6, 12, 7, 13],      /* stk[6] <- literals[12]("Warning: Token "[^
]-" is not used in the grammar.
") */ /* stk[7] <- literals[13] null */
        /*31*/ ["_OP_CALL", 6, 4, 4, 5, 3],     /* target[4], lvi[4]("lines"), stackbase(5), nargs(3) */
        /*32*/ ["_OP_MOVE", 10, 3, 4, 0, 0],        /* stk[3] <- lvi[4]("lines") */
        /*33*/ ["_OP_PREPCALLK", 8, 4, 14, 3, 5],   /* closure_at_stk[4], stk[3].get(literals[14]) -> stk[5] */
        /*34*/ ["_OP_DLOAD", 4, 6, 15, 7, 16],      /* stk[6] <- literals[15]("Non-terminal '") */ /* stk[7] <- literals[16] "%token " */
        /*35*/ ["_OP_CALL", 6, 4, 4, 5, 3],     /* target[4], lvi[4]("lines"), stackbase(5), nargs(3) */
        /*36*/ ["_OP_MOVE", 10, 3, 4, 0, 0],        /* stk[3] <- lvi[4]("lines") */
        /*37*/ ["_OP_PREPCALLK", 8, 4, 14, 3, 5],   /* closure_at_stk[4], stk[3].get(literals[14]) -> stk[5] */
        /*38*/ ["_OP_DLOAD", 4, 6, 17, 7, 13],      /* stk[6] <- literals[17]("' does not have any productions.") */ /* stk[7] <- literals[13] null */
        /*39*/ ["_OP_CALL", 6, 4, 4, 5, 3],     /* target[4], lvi[4]("lines"), stackbase(5), nargs(3) */
        /*40*/ ["_OP_MOVE", 10, 3, 4, 0, 0],        /* stk[3] <- lvi[4]("lines") */
        /*41*/ ["_OP_PREPCALLK", 8, 4, 11, 3, 5],   /* closure_at_stk[4], stk[3].get(literals[11]) -> stk[5] */
        /*42*/ ["_OP_LOAD", 1, 6, 18, 0, 0],        /* stk[6] <- literals[18]("Warning: Token "([^
]-)" does not have a lexer definiton%.") */
        /*43*/ ["_OP_CLOSURE", 48, 7, 0, 0, 0], /* stk_at_arg0[7] <- functions[0](null), isLanbda(0) */
        /*44*/ ["_OP_CALL", 6, 4, 4, 5, 3],     /* target[4], lvi[4]("lines"), stackbase(5), nargs(3) */
        /*45*/ ["_OP_MOVE", 10, 3, 4, 0, 0],        /* stk[3] <- lvi[4]("lines") */
        /*46*/ ["_OP_PREPCALLK", 8, 4, 11, 3, 5],   /* closure_at_stk[4], stk[3].get(literals[11]) -> stk[5] */
        /*47*/ ["_OP_DLOAD", 4, 6, 19, 7, 20],      /* stk[6] <- literals[19]("Unknown token "([^
]-)"%.") */ /* stk[7] <- literals[20] "%%token %1" */
        /*48*/ ["_OP_CALL", 6, 4, 4, 5, 3],     /* target[4], lvi[4]("lines"), stackbase(5), nargs(3) */
        /*49*/ ["_OP_MOVE", 10, 3, 4, 0, 0],        /* stk[3] <- lvi[4]("lines") */
        /*50*/ ["_OP_PREPCALLK", 8, 4, 21, 3, 5],   /* closure_at_stk[4], stk[3].get(literals[21]) -> stk[5] */
        /*51*/ ["_OP_LOADINT", 2, 6, 10, 0, 0], /* stk[6] <- arg1(10) */
        /*52*/ ["_OP_CALL", 6, 4, 4, 5, 2],     /* target[4], lvi[4]("lines"), stackbase(5), nargs(2) */
        /*53*/ ["_OP_PREPCALLK", 8, 5, 22, 4, 6],   /* closure_at_stk[5], stk[4].get(literals[22]) -> stk[6] */
        /*54*/ ["_OP_CLOSURE", 48, 7, 1, 1, 0], /* stk_at_arg0[7] <- functions[1](null), isLanbda(1) */
        /*55*/ ["_OP_CALL", 6, 255, 5, 6, 2],       /* target[255], lvi[5]("prevLine"), stackbase(6), nargs(2) */
        /*56*/ ["_OP_LOADNULLS", 24, 5, 1, 0, 0],   /* stk_at_arg0[5.. (arg0 + arg1(1))] = null */
        /*57*/ ["_OP_LOADNULLS", 24, 6, 3, 0, 0],   /* stk_at_arg0[6.. (arg0 + arg1(3))] = null */
        /*58*/ ["_OP_FOREACH", 51, 4, 9, 6, 0],
        /*59*/ ["_OP_POSTFOREACH", 52, 4, 9, 6, 0],
        /*60*/ ["_OP_EQ", 15, 9, 5, 7, 0],      /* stk_at_arg0[9] = stk_at_arg2[7] == (arg3(0) !=0 ? literals_at_arg1[5] : stk_at_arg1[5]) */
        /*61*/ ["_OP_JZ", 30, 9, 1, 0, 0],      /* IsFalse(STK(9) (ci->_ip+=(1) -> goto[63]) */
        /*62*/ ["_OP_JMP", 28, 0, -5, 0, 0],        /* (ci->_ip+=(-5)) -> goto[58] */
        /*63*/ ["_OP_MOVE", 10, 5, 7, 0, 0],        /* stk[5] <- lvi[7]("line") */
        /*64*/ ["_OP_PREPCALLK", 8, 9, 1, 0, 10],   /* closure_at_stk[9], stk[0].get(literals[1]) -> stk[10] */
        /*65*/ ["_OP_MOVE", 10, 11, 7, 0, 0],       /* stk[11] <- lvi[7]("line") */
        /*66*/ ["_OP_CALL", 6, 255, 9, 10, 2],      /* target[255], lvi[9]("?"), stackbase(10), nargs(2) */
        /*67*/ ["_OP_JMP", 28, 0, -10, 0, 0],       /* (ci->_ip+=(-10)) -> goto[58] */
        /*68*/ ["_OP_RETURN", 23, 255, 0, 0, 0],    /* _arg0(255) != 255 ? stk[0] : null */
    ],
    functions = [
/*function 0*/{
    source_name = "_fix-non-terminal.nut",
    function_name = null,
    function_return_type = null,
    literals = [
        /*0*/ "format",
        /*1*/ [==["%s"  %s]==],
        /*2*/ "slice",
        /*3*/ -1,
        /*4*/ "%s   %s",
    ],
    parameters = [
        /*0*/ "this",
        /*1*/ "m",
    ],
    outervalues = [
        //[type, src, name],
    ],
    localvarinfos = [
        //[pos, name, start_op, end_op, scope, type, type_name, dtype_name],
        /*0*/ [0, "this", 0, 19, 1, 1, "ANY", ""],
        /*1*/ [1, "m", 0, 19, 1, 1, "ANY", ""],
    ],
    lineinfos = [
        //[op, line],
        /*0*/ [0, 17], /*_OP_LOADINT*/
        /*1*/ [0, 18], /*_OP_LOADINT*/
        /*2*/ [14, 19], /*_OP_PREPCALLK*/
        /*3*/ [19, 20], /*_OP_RETURN*/
    ],
    defaultparams = [],
    instructions = [ /*stack*/
        //[op_str, op, arg0, arg1, arg2, arg3],
        /*0*/ ["_OP_LOADINT", 2, 2, 0, 0, 0],   /* stk[2] <- arg1(0) */
        /*1*/ ["_OP_GET", 14, 2, 1, 2, 0],  /* stk_at_arg0[2] = stk_at_arg1[1].get(stk_at_arg2(2)) */
        /*2*/ ["_OP_LOADINT", 2, 3, 39, 0, 0],  /* stk[3] <- arg1(39) */
        /*3*/ ["_OP_EQ", 15, 2, 3, 2, 0],       /* stk_at_arg0[2] = stk_at_arg2[2] == (arg3(0) !=0 ? literals_at_arg1[3] : stk_at_arg1[3]) */
        /*4*/ ["_OP_JZ", 30, 2, 9, 0, 0],       /* IsFalse(STK(2) (ci->_ip+=(9) -> goto[14]) */
        /*5*/ ["_OP_PREPCALLK", 8, 2, 0, 0, 3], /* closure_at_stk[2], stk[0].get(literals[0]) -> stk[3] */
        /*6*/ ["_OP_DLOAD", 4, 4, 1, 5, 2],     /* stk[4] <- literals[1](""%s"  %s") */ /* stk[5] <- literals[2] "slice" */
        /*7*/ ["_OP_PREPCALL", 7, 5, 5, 1, 6],  /* closure_at_stk[5], stk[1].get(stk[5]) -> stk[6] */
        /*8*/ ["_OP_LOADINT", 2, 7, 1, 0, 0],   /* stk[7] <- arg1(1) */
        /*9*/ ["_OP_LOAD", 1, 8, 3, 0, 0],      /* stk[8] <- literals[3]("?") */
        /*10*/ ["_OP_CALL", 6, 5, 5, 6, 3],     /* target[5], lvi[5]("?"), stackbase(6), nargs(3) */
        /*11*/ ["_OP_MOVE", 10, 6, 1, 0, 0],        /* stk[6] <- lvi[1]("m") */
        /*12*/ ["_OP_TAILCALL", 5, 2, 2, 3, 4],
        /*13*/ ["_OP_RETURN", 23, 1, 2, 3, 0],  /* _arg0(1) != 255 ? stk[2] : null */
        /*14*/ ["_OP_PREPCALLK", 8, 2, 0, 0, 3],    /* closure_at_stk[2], stk[0].get(literals[0]) -> stk[3] */
        /*15*/ ["_OP_LOAD", 1, 4, 4, 0, 0],     /* stk[4] <- literals[4]("%s    %s") */
        /*16*/ ["_OP_DMOVE", 27, 5, 1, 6, 1],   /* stk[5] <- lvi[1]("m"), stk[6] <- lvi[1]("m") */
        /*17*/ ["_OP_TAILCALL", 5, 2, 2, 3, 4],
        /*18*/ ["_OP_RETURN", 23, 1, 2, 3, 0],  /* _arg0(1) != 255 ? stk[2] : null */
        /*19*/ ["_OP_RETURN", 23, 255, 0, 0, 0],    /* _arg0(255) != 255 ? stk[0] : null */
    ],
    functions = [
    ],
    stacksize = 9,
    bgenerator = 0,
    varparams = 0,
},
/*function 1*/{
    source_name = "_fix-non-terminal.nut",
    function_name = null,
    function_return_type = null,
    literals = [
    ],
    parameters = [
        /*0*/ "this",
        /*1*/ "a",
        /*2*/ "b",
    ],
    outervalues = [
        //[type, src, name],
    ],
    localvarinfos = [
        //[pos, name, start_op, end_op, scope, type, type_name, dtype_name],
        /*0*/ [0, "this", 0, 2, 1, 1, "ANY", ""],
        /*1*/ [1, "a", 0, 2, 1, 1, "ANY", ""],
        /*2*/ [2, "b", 0, 2, 1, 1, "ANY", ""],
    ],
    lineinfos = [
        //[op, line],
        /*0*/ [2, 24], /*_OP_RETURN*/
    ],
    defaultparams = [],
    instructions = [ /*stack*/
        //[op_str, op, arg0, arg1, arg2, arg3],
        /*0*/ ["_OP_CMP", 40, 3, 2, 1, 5],
        /*1*/ ["_OP_RETURN", 23, 1, 3, 0, 0],   /* _arg0(1) != 255 ? stk[3] : null */
        /*2*/ ["_OP_RETURN", 23, 255, 0, 0, 0], /* _arg0(255) != 255 ? stk[0] : null */
    ],
    functions = [
    ],
    stacksize = 4,
    bgenerator = 0,
    varparams = 0,
},
    ],
    stacksize = 12,
    bgenerator = 0,
    varparams = 1,
}