diff --git a/src/lobject.h b/src/lobject.h index 492019c..c1626b1 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -89,15 +89,15 @@ typedef uint32_t ravi_type_map; #define RAVI_TM_TRUISH (~RAVI_TM_FALSISH) #define RAVI_TM_BOOLEAN (RAVI_TM_FALSE | RAVI_TM_TRUE) #define RAVI_TM_NUMBER (RAVI_TM_INTEGER | RAVI_TM_FLOAT) -#define RAVI_TM_INTEGER_OR_NIL (RAVI_TM_INTEGER | RAVI_TM_NIL) -#define RAVI_TM_FLOAT_OR_NIL (RAVI_TM_FLOAT | RAVI_TM_NIL) #define RAVI_TM_STRING_OR_NIL (RAVI_TM_STRING | RAVI_TM_NIL) -#define RAVI_TM_TABLE_OR_NIL (RAVI_TM_TABLE | RAVI_TM_NIL) #define RAVI_TM_FUNCTION_OR_NIL (RAVI_TM_FUNCTION | RAVI_TM_NIL) #define RAVI_TM_BOOLEAN_OR_NIL (RAVI_TM_BOOLEAN | RAVI_TM_NIL) #define RAVI_TM_USERDATA_OR_NIL (RAVI_TM_USERDATA | RAVI_TM_NIL) -#define RAVI_TM_ANY (~0) +#define RAVI_TM_INTEGER_OR_NIL (RAVI_TM_INTEGER | RAVI_TM_NIL) +#define RAVI_TM_FLOAT_OR_NIL (RAVI_TM_FLOAT | RAVI_TM_NIL) +#define RAVI_TM_TABLE_OR_NIL (RAVI_TM_TABLE | RAVI_TM_NIL) #define RAVI_TM_INDEXABLE (RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_TABLE) +#define RAVI_TM_ANY (~0) typedef enum { RAVI_TNIL = RAVI_TM_NIL, /* NIL */ diff --git a/src/lopcodes.c b/src/lopcodes.c index c7d0388..bf1872e 100644 --- a/src/lopcodes.c +++ b/src/lopcodes.c @@ -113,6 +113,13 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "TOBOOLEAN", "TOCLOSURE", "TOTYPE", + "TOINT_NIL", /* A R(A) := toint(R(A)) */ + "TOFLT_NIL", /* A R(A) := tofloat(R(A)) */ + "TOTAB_NIL", /* A R(A) := to_table(R(A)) */ + "TOSTRING_NIL", + "TOBOOLEAN_NIL", + "TOCLOSURE_NIL", + "TOTYPE_NIL", "TOIARRAY", /* A R(A) := to_arrayi(R(A)) */ "TOFARRAY", /* A R(A) := to_arrayf(R(A)) */ @@ -257,7 +264,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOCLOSURE */ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_RAVI_TOTYPE */ - ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOINT_NIL A R(A) := toint(R(A)) */ + ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOINT_NIL A R(A) := toint(R(A)) */ ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOFLT_NIL A R(A) := tonumber(R(A)) */ ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOTAB_NIL A R(A) := check_table(R(A)) */ ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOSTRING_NIL */ diff --git a/src/lvm.c b/src/lvm.c index 371bb47..a9da4ba 100644 --- a/src/lvm.c +++ b/src/lvm.c @@ -2546,6 +2546,7 @@ int luaV_execute (lua_State *L) { luaG_runerror(L, "table expected"); vmbreak; } + // mandatory types vmcase(OP_RAVI_TOINT) { lua_Integer j; if (RAVI_LIKELY(tointeger(ra, &j))) { setivalue(ra, j); } @@ -2581,46 +2582,50 @@ int luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_RAVI_TOTYPE) { - TValue *rb = k + GETARG_Bx(i); - if (!ttisshrstring(rb)) - luaG_runerror(L, "type name must be string"); - TString *key = tsvalue(rb); - if (!raviV_check_usertype(L, key, ra)) - luaG_runerror(L, "type mismatch: expected %s", getstr(key)); + TValue *rb = k + GETARG_Bx(i); + if (!ttisshrstring(rb)) + luaG_runerror(L, "type name must be string"); + TString *key = tsvalue(rb); + if (!raviV_check_usertype(L, key, ra)) + luaG_runerror(L, "type mismatch: expected %s", getstr(key)); vmbreak; } // optional types vmcase(OP_RAVI_TOINT_NIL) { lua_Integer j; - if (RAVI_LIKELY(tointeger(ra, &j))) { setivalue(ra, j); } - else if(!ttisnil(ra)) - luaG_runerror(L, "TOINT: integer expected"); + if(!ttisnil(ra)) { + if (RAVI_LIKELY(tointeger(ra, &j))) { setivalue(ra, j); } + else + luaG_runerror(L, "TOINT: integer expected"); + } vmbreak; } vmcase(OP_RAVI_TOFLT_NIL) { lua_Number j; - if (RAVI_LIKELY(tonumber(ra, &j))) { setfltvalue(ra, j); } - else if(!ttisnil(ra)) - luaG_runerror(L, "TOFLT: number expected"); + if(!ttisnil(ra)) { + if (RAVI_LIKELY(tonumber(ra, &j))) { setfltvalue(ra, j); } + else + luaG_runerror(L, "TOFLT: number expected"); + } vmbreak; } vmcase(OP_RAVI_TOTAB_NIL) { - if (RAVI_UNLIKELY(!ttisLtable(ra)) && !ttisnil(ra)) + if (!ttisnil(ra) && RAVI_UNLIKELY(!ttisLtable(ra))) luaG_runerror(L, "table expected"); vmbreak; } vmcase(OP_RAVI_TOSTRING_NIL) { - if (RAVI_UNLIKELY(!ttisstring(ra)) && !ttisnil(ra)) + if (!ttisnil(ra) && RAVI_UNLIKELY(!ttisstring(ra))) luaG_runerror(L, "string expected"); vmbreak; } vmcase(OP_RAVI_TOBOOLEAN_NIL) { - if (RAVI_UNLIKELY(!ttisboolean(ra)) && !ttisnil(ra)) + if (!ttisnil(ra) && RAVI_UNLIKELY(!ttisboolean(ra))) luaG_runerror(L, "boolean expected"); vmbreak; } vmcase(OP_RAVI_TOCLOSURE_NIL) { - if (RAVI_UNLIKELY(!ttisclosure(ra)) && !ttisnil(ra)) + if (!ttisnil(ra) && RAVI_UNLIKELY(!ttisclosure(ra))) luaG_runerror(L, "closure expected"); vmbreak; } diff --git a/src/ravi_jitshared.c b/src/ravi_jitshared.c index 851289f..d9e243b 100644 --- a/src/ravi_jitshared.c +++ b/src/ravi_jitshared.c @@ -330,11 +330,14 @@ static const char Lua_header[] = "#define RAVI_TM_TRUISH (~RAVI_TM_FALSISH)\n" "#define RAVI_TM_BOOLEAN (RAVI_TM_FALSE | RAVI_TM_TRUE)\n" "#define RAVI_TM_NUMBER (RAVI_TM_INTEGER | RAVI_TM_FLOAT)\n" - "#define RAVI_TM_INDEXABLE (RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_TABLE)\n" "#define RAVI_TM_STRING_OR_NIL (RAVI_TM_STRING | RAVI_TM_NIL)\n" "#define RAVI_TM_FUNCTION_OR_NIL (RAVI_TM_FUNCTION | RAVI_TM_NIL)\n" "#define RAVI_TM_BOOLEAN_OR_NIL (RAVI_TM_BOOLEAN | RAVI_TM_NIL)\n" "#define RAVI_TM_USERDATA_OR_NIL (RAVI_TM_USERDATA | RAVI_TM_NIL)\n" + "#define RAVI_TM_INTEGER_OR_NIL (RAVI_TM_INTEGER | RAVI_TM_NIL)\n" + "#define RAVI_TM_FLOAT_OR_NIL (RAVI_TM_FLOAT | RAVI_TM_NIL)" + "#define RAVI_TM_TABLE_OR_NIL (RAVI_TM_TABLE | RAVI_TM_NIL)" + "#define RAVI_TM_INDEXABLE (RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_TABLE)\n" "#define RAVI_TM_ANY (~0)\n" "typedef enum {\n" "RAVI_TNIL = RAVI_TM_NIL, /* NIL */\n" @@ -344,12 +347,12 @@ static const char Lua_header[] = "RAVI_TARRAYINT = RAVI_TM_INTEGER_ARRAY, /* array of ints */\n" "RAVI_TARRAYFLT = RAVI_TM_FLOAT_ARRAY, /* array of doubles */\n" "RAVI_TTABLE = RAVI_TM_TABLE, /* Lua table */\n" - "RAVI_TSTRING = RAVI_TM_STRING_OR_NIL, /* string */\n" - "RAVI_TFUNCTION = RAVI_TM_FUNCTION_OR_NIL, /* Lua or C Function */\n" - "RAVI_TBOOLEAN = RAVI_TM_BOOLEAN_OR_NIL, /* boolean */\n" + "RAVI_TSTRING = RAVI_TM_STRING, /* string */\n" + "RAVI_TFUNCTION = RAVI_TM_FUNCTION, /* Lua or C Function */\n" + "RAVI_TBOOLEAN = RAVI_TM_BOOLEAN, /* boolean */\n" "RAVI_TTRUE = RAVI_TM_TRUE,\n" "RAVI_TFALSE = RAVI_TM_FALSE,\n" - "RAVI_TUSERDATA = RAVI_TM_USERDATA_OR_NIL, /* userdata or lightuserdata */\n" + "RAVI_TUSERDATA = RAVI_TM_USERDATA, /* userdata or lightuserdata */\n" "RAVI_TANY = RAVI_TM_ANY, /* Lua dynamic type */\n" "} ravitype_t;\n" "typedef struct Upvaldesc {\n" @@ -596,11 +599,7 @@ static const char Lua_header[] = " (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))\n" "extern int luaV_tonumber_(const TValue *obj, lua_Number *n);\n" "extern int luaV_tointeger(const TValue *obj, lua_Integer *p, int mode);\n" -#ifdef RAVI_DEFER_STATEMENT "extern int luaF_close (lua_State *L, StkId level, int status);\n" -#else - "extern void luaF_close (lua_State *L, StkId level);\n" -#endif "extern int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres);\n" "extern int luaV_equalobj(lua_State *L, const TValue *t1, const TValue *t2);\n" "extern int luaV_lessthan(lua_State *L, const TValue *l, const TValue *r);\n" @@ -636,9 +635,7 @@ static const char Lua_header[] = "extern void raviV_settable_sskey(lua_State *L, const TValue *t, TValue *key, TValue *val);\n" "extern void raviV_gettable_i(lua_State *L, const TValue *t, TValue *key, TValue *val);\n" "extern void raviV_settable_i(lua_State *L, const TValue *t, TValue *key, TValue *val);\n" -#ifdef RAVI_DEFER_STATEMENT "extern void raviV_op_defer(lua_State *L, TValue *ra);\n" -#endif "extern lua_Integer luaV_shiftl(lua_Integer x, lua_Integer y);\n" "extern void ravi_dump_value(lua_State *L, const struct lua_TValue *v);\n" "extern void raviV_op_bnot(lua_State *L, TValue *ra, TValue *rb);\n" @@ -1055,12 +1052,8 @@ static void emit_comparison(struct function *fn, int A, int B, int C, int j, int membuff_add_fstring(&fn->body, "if (result == %d) {\n", A); if (jA > 0) { membuff_add_fstring(&fn->body, " ra = R(%d);\n", jA - 1); -#ifdef RAVI_DEFER_STATEMENT membuff_add_string(&fn->body, " luaF_close(L, ra, LUA_OK);\n"); membuff_add_string(&fn->body, " base = ci->u.l.base;\n"); -#else - membuff_add_string(&fn->body, " luaF_close(L, ra);\n"); -#endif } membuff_add_fstring(&fn->body, " goto Lbc_%d;\n", j); membuff_add_string(&fn->body, "}\n"); @@ -1098,13 +1091,9 @@ static void emit_op_loadk(struct function *fn, int A, int Bx, int pc) { static void emit_op_return(struct function *fn, int A, int B, int pc) { (void)pc; -#ifdef RAVI_DEFER_STATEMENT membuff_add_string(&fn->body, "if (cl->p->sizep > 0) {\n luaF_close(L, base, LUA_OK);\n"); membuff_add_string(&fn->body, " base = ci->u.l.base;\n"); membuff_add_string(&fn->body, "}\n"); -#else - membuff_add_string(&fn->body, "if (cl->p->sizep > 0) luaF_close(L, base);\n"); -#endif emit_reg(fn, "ra", A); membuff_add_fstring(&fn->body, "result = (%d != 0 ? %d - 1 : cast_int(L->top - ra));\n", B, B); membuff_add_string(&fn->body, "return luaD_poscall(L, ci, ra, result);\n"); @@ -1130,12 +1119,8 @@ static void emit_op_jmp(struct function *fn, int A, int sBx, int pc) { (void)pc; if (A > 0) { membuff_add_fstring(&fn->body, "ra = R(%d);\n", A - 1); -#ifdef RAVI_DEFER_STATEMENT membuff_add_string(&fn->body, "luaF_close(L, ra, LUA_OK);\n"); membuff_add_string(&fn->body, "base = ci->u.l.base;\n"); -#else - membuff_add_string(&fn->body, "luaF_close(L, ra);\n"); -#endif } membuff_add_fstring(&fn->body, "goto Lbc_%d;\n", sBx); } @@ -1163,12 +1148,8 @@ static void emit_op_test(struct function *fn, int A, int B, int C, int j, int jA membuff_add_fstring(&fn->body, "if (!result) {\n", A); if (jA > 0) { membuff_add_fstring(&fn->body, " ra = R(%d);\n", jA - 1); -#ifdef RAVI_DEFER_STATEMENT membuff_add_string(&fn->body, " luaF_close(L, ra, LUA_OK);\n"); membuff_add_string(&fn->body, " base = ci->u.l.base;\n"); -#else - membuff_add_string(&fn->body, " luaF_close(L, ra);\n"); -#endif } membuff_add_fstring(&fn->body, " goto Lbc_%d;\n", j); membuff_add_string(&fn->body, " }\n"); @@ -1188,12 +1169,8 @@ static void emit_op_testset(struct function *fn, int A, int B, int C, int j, int membuff_add_string(&fn->body, " setobjs2s(L, ra, rb);"); if (jA > 0) { membuff_add_fstring(&fn->body, " ra = R(%d);\n", jA - 1); -#ifdef RAVI_DEFER_STATEMENT membuff_add_string(&fn->body, " luaF_close(L, ra, LUA_OK);\n"); membuff_add_string(&fn->body, " base = ci->u.l.base;\n"); -#else - membuff_add_string(&fn->body, " luaF_close(L, ra);\n"); -#endif } membuff_add_fstring(&fn->body, " goto Lbc_%d;\n", j); membuff_add_string(&fn->body, " }\n"); @@ -1460,13 +1437,11 @@ static void emit_op_divii(struct function *fn, int A, int B, int C, int pc) { "(lua_Number)(ivalue(rc)));\n"); } -#ifdef RAVI_DEFER_STATEMENT static void emit_op_defer(struct function *fn, int A, int pc) { (void)pc; emit_reg(fn, "ra", A); membuff_add_string(&fn->body, "raviV_op_defer(L, ra);\n"); } -#endif static void emit_op_loadfz(struct function *fn, int A, int pc) { (void)pc; @@ -1558,10 +1533,12 @@ static void emit_op_movetab(struct function *fn, int A, int B, int pc) { membuff_add_string(&fn->body, "}\n"); } -static void emit_op_toint(struct function *fn, int A, int pc) { +static void emit_op_toint(struct function *fn, int A, int pc, int allow_nil) { (void)pc; emit_reg(fn, "ra", A); membuff_add_string(&fn->body, "i = 0;\n"); + if(allow_nil) + membuff_add_string(&fn->body, "if(!ttisnil(ra)) { \n"); membuff_add_string(&fn->body, "if (ttisinteger(ra)) {i = ivalue(ra); setivalue(ra, i); }\n"); membuff_add_string(&fn->body, "else {\n"); #if GOTO_ON_ERROR @@ -1571,15 +1548,17 @@ static void emit_op_toint(struct function *fn, int A, int pc) { membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_integer_expected); #endif membuff_add_string(&fn->body, "}\n"); + if(allow_nil) + membuff_add_string(&fn->body, "}\n"); } -static void emit_op_toflt(struct function *fn, int A, int pc) { +static void emit_op_toflt(struct function *fn, int A, int pc, int allow_nil) { (void)pc; emit_reg(fn, "ra", A); membuff_add_string(&fn->body, "n = 0.0;\n"); - membuff_add_string( - &fn->body, - "if (ttisnumber(ra)) { n = (ttisinteger(ra) ? (double) ivalue(ra) : fltvalue(ra)); setfltvalue(ra, n); }\n"); + if(allow_nil) + membuff_add_string(&fn->body, "if(!ttisnil(ra)) { \n"); + membuff_add_string(&fn->body, "if (ttisnumber(ra)) { n = (ttisinteger(ra) ? (double) ivalue(ra) : fltvalue(ra)); setfltvalue(ra, n); }\n"); membuff_add_string(&fn->body, "else {\n"); #if GOTO_ON_ERROR membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_number_expected); @@ -1588,37 +1567,15 @@ static void emit_op_toflt(struct function *fn, int A, int pc) { membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_number_expected); #endif membuff_add_string(&fn->body, "}\n"); + if(allow_nil) + membuff_add_string(&fn->body, "}\n"); } -static void emit_op_toai(struct function *fn, int A, int pc) { - (void)pc; - emit_reg(fn, "ra", A); - membuff_add_string(&fn->body, "if (!ttisiarray(ra)) {\n"); -#if GOTO_ON_ERROR - membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_integer_array_expected); - membuff_add_string(&fn->body, " goto Lraise_error;\n"); -#else - membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_integer_array_expected); -#endif - membuff_add_string(&fn->body, "}\n"); -} - -static void emit_op_toaf(struct function *fn, int A, int pc) { - (void)pc; - emit_reg(fn, "ra", A); - membuff_add_string(&fn->body, "if (!ttisfarray(ra)) {\n"); -#if GOTO_ON_ERROR - membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_number_array_expected); - membuff_add_string(&fn->body, " goto Lraise_error;\n"); -#else - membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_number_array_expected); -#endif - membuff_add_string(&fn->body, "}\n"); -} - -static void emit_op_totab(struct function *fn, int A, int pc) { +static void emit_op_totab(struct function *fn, int A, int pc, int allow_nil) { (void)pc; emit_reg(fn, "ra", A); + if(allow_nil) + membuff_add_string(&fn->body, "if(!ttisnil(ra)) { \n"); membuff_add_string(&fn->body, "if (!ttisLtable(ra)) {\n"); #if GOTO_ON_ERROR membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_table_expected); @@ -1627,11 +1584,15 @@ static void emit_op_totab(struct function *fn, int A, int pc) { membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_table_expected); #endif membuff_add_string(&fn->body, "}\n"); + if(allow_nil) + membuff_add_string(&fn->body, "}\n"); } -static void emit_op_toclosure(struct function *fn, int A, int pc) { +static void emit_op_toclosure(struct function *fn, int A, int pc, int allow_nil) { (void)pc; emit_reg(fn, "ra", A); + if(allow_nil) + membuff_add_string(&fn->body, "if(!ttisnil(ra)) { \n"); membuff_add_string(&fn->body, "if (!ttisclosure(ra)) {\n"); #if GOTO_ON_ERROR membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_closure_expected); @@ -1640,11 +1601,15 @@ static void emit_op_toclosure(struct function *fn, int A, int pc) { membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_closure_expected); #endif membuff_add_string(&fn->body, "}\n"); + if(allow_nil) + membuff_add_string(&fn->body, "}\n"); } -static void emit_op_tostring(struct function *fn, int A, int pc) { +static void emit_op_tostring(struct function *fn, int A, int pc, int allow_nil) { (void)pc; emit_reg(fn, "ra", A); + if(allow_nil) + membuff_add_string(&fn->body, "if(!ttisnil(ra)) { \n"); membuff_add_string(&fn->body, "if (!ttisstring(ra)) {\n"); #if GOTO_ON_ERROR membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_string_expected); @@ -1653,12 +1618,15 @@ static void emit_op_tostring(struct function *fn, int A, int pc) { membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_string_expected); #endif membuff_add_string(&fn->body, "}\n"); + if(allow_nil) + membuff_add_string(&fn->body, "}\n"); } -static void emit_op_totype(struct function *fn, int A, int Bx, int pc) { +static void emit_op_totype(struct function *fn, int A, int Bx, int pc, int allow_nil) { (void)pc; emit_reg(fn, "ra", A); - membuff_add_string(&fn->body, "if (!ttisnil(ra)) {\n"); + if(allow_nil) + membuff_add_string(&fn->body, "if(!ttisnil(ra)) { \n"); membuff_add_fstring(&fn->body, " rb = K(%d);\n", Bx); membuff_add_string(&fn->body, " if (!ttisshrstring(rb) || !raviV_check_usertype(L, tsvalue(rb), ra)) {\n"); #if 0 // GOTO_ON_ERROR @@ -1668,6 +1636,33 @@ static void emit_op_totype(struct function *fn, int A, int Bx, int pc) { membuff_add_fstring(&fn->body, " raviV_raise_error_with_info(L, %d, getstr(tsvalue(rb)));\n", Error_type_mismatch); #endif membuff_add_string(&fn->body, " }\n"); + if(allow_nil) + membuff_add_string(&fn->body, "}\n"); +} + +static void emit_op_toai(struct function *fn, int A, int pc) { + (void)pc; + emit_reg(fn, "ra", A); + membuff_add_string(&fn->body, "if (!ttisiarray(ra)) {\n"); +#if GOTO_ON_ERROR + membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_integer_array_expected); + membuff_add_string(&fn->body, " goto Lraise_error;\n"); +#else + membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_integer_array_expected); +#endif + membuff_add_string(&fn->body, "}\n"); +} + +static void emit_op_toaf(struct function *fn, int A, int pc) { + (void)pc; + emit_reg(fn, "ra", A); + membuff_add_string(&fn->body, "if (!ttisfarray(ra)) {\n"); +#if GOTO_ON_ERROR + membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_number_array_expected); + membuff_add_string(&fn->body, " goto Lraise_error;\n"); +#else + membuff_add_fstring(&fn->body, " raviV_raise_error(L, %d);\n", Error_number_array_expected); +#endif membuff_add_string(&fn->body, "}\n"); } @@ -2245,29 +2240,50 @@ bool raviJ_codegen(struct lua_State *L, struct Proto *p, struct ravi_compile_opt case OP_RAVI_LOADIZ: { emit_op_loadiz(&fn, A, pc); } break; + // mandatory types case OP_RAVI_TOINT: { - emit_op_toint(&fn, A, pc); + emit_op_toint(&fn, A, pc, 0); } break; case OP_RAVI_TOFLT: { - emit_op_toflt(&fn, A, pc); + emit_op_toflt(&fn, A, pc, 0); } break; case OP_RAVI_TOTAB: { - emit_op_totab(&fn, A, pc); - } break; - case OP_RAVI_TOIARRAY: { - emit_op_toai(&fn, A, pc); - } break; - case OP_RAVI_TOFARRAY: { - emit_op_toaf(&fn, A, pc); + emit_op_totab(&fn, A, pc, 0); } break; case OP_RAVI_TOSTRING: { - emit_op_tostring(&fn, A, pc); + emit_op_tostring(&fn, A, pc, 0); } break; case OP_RAVI_TOCLOSURE: { - emit_op_toclosure(&fn, A, pc); + emit_op_toclosure(&fn, A, pc, 0); } break; case OP_RAVI_TOTYPE: { - emit_op_totype(&fn, A, GETARG_Bx(i), pc); + emit_op_totype(&fn, A, GETARG_Bx(i), pc, 0); + } break; + // optional types + case OP_RAVI_TOINT_NIL: { + emit_op_toint(&fn, A, pc, 1); + } break; + case OP_RAVI_TOFLT_NIL: { + emit_op_toflt(&fn, A, pc, 1); + } break; + case OP_RAVI_TOTAB_NIL: { + emit_op_totab(&fn, A, pc, 1); + } break; + case OP_RAVI_TOSTRING_NIL: { + emit_op_tostring(&fn, A, pc, 1); + } break; + case OP_RAVI_TOCLOSURE_NIL: { + emit_op_toclosure(&fn, A, pc, 1); + } break; + case OP_RAVI_TOTYPE_NIL: { + emit_op_totype(&fn, A, GETARG_Bx(i), pc, 1); + } break; + // tables + case OP_RAVI_TOIARRAY: { + emit_op_toai(&fn, A, pc); + } break; + case OP_RAVI_TOFARRAY: { + emit_op_toaf(&fn, A, pc); } break; case OP_RAVI_MOVEI: { int B = GETARG_B(i); @@ -2330,11 +2346,9 @@ bool raviJ_codegen(struct lua_State *L, struct Proto *p, struct ravi_compile_opt int B = GETARG_B(i); emit_op_len(&fn, A, B, pc); } break; -#ifdef RAVI_DEFER_STATEMENT case OP_RAVI_DEFER: { emit_op_defer(&fn, A, pc); } break; -#endif case OP_RAVI_SHR_II: case OP_RAVI_SHL_II: case OP_RAVI_BXOR_II: