@table(Op, Desc) scene2_opcode_table:
{
    { None,                        "does nothing (effectivly a nop)"                                                                          },
    
    // sixten: interfacing with user
    { Call,                         "stages runtime hook"                                                                                     },
    { Wait,                         "executes staged actions and waits for user input"                                                        },
    
    // sixten: stack manipulation
    { Pop,                          "pops object from stack"                                                                                  },
    { PushBool,                     "pushes a boolean onto the stack"                                                                         },
    { PushNumber,                   "pushes a number onto the stack"                                                                          },
    { PushString,                   "pushes a string onto the stack"                                                                          },
    { PushNil,                      "pushes `nil` onto the stack"                                                                             },
    { PushVariable,                 "pushes a variable onto the stack"                                                                        },
    { DuplicateStack,               "duplicates the top N-most elements of the stack (specified in Arg as u64)"                               },
    
    // sixten: variables
    { SetVariable,                  "pops the stack and stores the value in a variable"                                                       },
    { SetLocal,                     "defines a locally scoped variable"                                                                       },
    
    // sixten: blocks
    { BeginBlock,                   "increases the variable stack depth"                                                                      },
    { EndBlock,                     "decreases the variable stack depth"                                                                      },
    
    // sixten: jumps
    { Jump,                         "performs a relative jump (specified in Arg as s64)"                                                      },
    { CondJump,                     "performs a relative jump (specified in Arg as s64) if the topmost element on the stack is non-zero"      },
    
    // sixten: operations
    { Add,                          "adds the two topmost elements of the stack"                                                              },
    { Subtract,                     "subtracts the topmost element of the stack by the second topmost element"                                },
    { Multiply,                     "multiplies the two topmost elements of the stack"                                                        },
    { Divide,                       "divides the topmost element of the stack by the second topmost element"                                  },
    { Equals,                       ""                                                                                                        },
    { Greater,                      ""                                                                                                        },
    { Less,                         ""                                                                                                        },
    { Not,                          "performs a not operation on the topmost element of the stack"                                            },
    { Negate,                       "negates the topmost element of the stack"                                                                },
}

@table(Name, Operator) scene2_operator_table:
{
    { Invalid,              "###" }
    { Not,                  "!"   }
    { Equal,                "="   }
    { Equals,               "=="  }
    { NotEquals,            "!="  }
    { GreaterThanOrEquals,  ">="  }
    { LessThanOrEquals,     "<="  }
    { Greater,              ">"   }
    { Less,                 "<"   }
    { Add,                  "+"   }
    { Minus,                "-"   }
    { Multiply              "*"   }
    { Divide,               "/"   }
}

@table(Name, Binding, Desc) scene2_call_table:
{
    { none,                  S2_Call_Stub,                     "does nothing"                                     },
    
    // sixten: debugging
    { stack_sanity,          S2_Call_StackSanity,              "does checks that the stack is at a certain depth" },
    
    // sixten: textbox management calls
    { text_append,           S2_Call_TextAppend,               "pops a value and appends it to the textbox"       },
    { text_newline,          S2_Call_NewLine,                  "appends a newline to the textbox"                 },
    { text_clear,            S2_Call_TextClear,                "clears the textbox"                               },
    
    // sixten: proc management calls
    { proc_set,              S2_Call_ProcSet,                  "sets the current proc"                            },
    
    // sixten: character management calls
    { ctr_set,               S2_Call_CharacterSet,             "sets the state of a character"                    },
    { ctr_remove,            S2_Call_CharacterRemove,          "removes a character"                              },
    { ctr_set_talking,       S2_Call_CharacterSetTalking,      "makes a character talking"                        },
    { ctr_unset_all_talking, S2_Call_CharacterUnsetAllTalking, "makes no characters talking"                      },
    
    // sixten: nav management calls
    { nav_load,              S2_Call_NavLoad,                  "loads a nav scene"                                },
    
    // sixten: puzzle management calls
    { puzzle_15,             S2_Call_Puzzle15,                 "plays the 15-puzzle"                              },
}

@table_gen
{
    `enum scene2_opcode`;
    `{`;
        @expand(scene2_opcode_table s) `S2_Op_$(s.Op), $(=>50) // $(s.Desc)`;
            `S2_Op_COUNT,`
            `};`;
}

@table_gen
{
    `global read_only string S2_InstructionInfoLookup[] =`;
    `{`;
        @expand(scene2_opcode_table s) `StrComp("$(s.Op)"),`;
        `};`;
}

@table_gen
{
    `global read_only string S2_InstructionNameLookup[] =`;
    `{`;
        @expand(scene2_opcode_table s) `StrComp("$(s.Desc)"),`;
        `};`;
}

@table_gen
{
    `enum scene2_operator`;
    `{`;
        @expand(scene2_operator_table s) `S2_Operator_$(s.Name),`;
        `};`;
}

@table_gen
{
    `inline scene2_operator S2_OperatorFromString(string String)`;
    `{`;
        `scene2_operator Result = S2_Operator_Invalid;`;
        `if(0) {}`;
        @expand(scene2_operator_table s) `else if(AreEqual(String, StrLit("$(s.Operator)")))$(=>40) { Result = S2_Operator_$(s.Name); }`;
        `return(Result);`;
        `}`;
}

@table_gen
{
    @expand(scene2_call_table s) `static S2_CALL_FUNCTION($(s.Binding)); $(=>50) // $(s.Desc)`;
}

@table_gen
{
    `global read_only scene2_call_function *S2_CallBindingLookup[] =`;
    `{`;
        @expand(scene2_call_table s) `$(s.Binding), `;
        `};`;
}

@table_gen
{
    `global read_only string S2_CallNameLookup[] =`;
    `{`;
        @expand(scene2_call_table s) `StrComp("$(s.Name)"), `;
        `};`;
}