diff --git a/spec/execution_tests.lua b/spec/execution_tests.lua index d71dc8b0..df5fdf85 100644 --- a/spec/execution_tests.lua +++ b/spec/execution_tests.lua @@ -1390,11 +1390,9 @@ function execution_tests.run(compile_file, backend, _ENV, only_compile) end) it("check record tags", function() - -- TODO: change this message to mention the relevant record types - -- instead of only saying "userdata" run_test([[ local prim = test.make_prim(123) - assert_pallene_error("expected userdata but found userdata", test.get_x, prim) + assert_pallene_error("expected Foo but found Prim", test.get_x, prim) ]]) end) diff --git a/src/pallene/coder.lua b/src/pallene/coder.lua index 6725cda5..ed70a210 100644 --- a/src/pallene/coder.lua +++ b/src/pallene/coder.lua @@ -173,15 +173,15 @@ end local function pallene_type_tag(typ) local tag = typ._tag - if tag == "types.T.Nil" then return "LUA_TNIL" - elseif tag == "types.T.Boolean" then return "LUA_TBOOLEAN" - elseif tag == "types.T.Integer" then return "LUA_VNUMINT" - elseif tag == "types.T.Float" then return "LUA_VNUMFLT" - elseif tag == "types.T.String" then return "LUA_TSTRING" - elseif tag == "types.T.Function" then return "LUA_TFUNCTION" - elseif tag == "types.T.Array" then return "LUA_TTABLE" - elseif tag == "types.T.Table" then return "LUA_TTABLE" - elseif tag == "types.T.Record" then return "LUA_TUSERDATA" + if tag == "types.T.Nil" then return "nil" + elseif tag == "types.T.Boolean" then return "boolean" + elseif tag == "types.T.Integer" then return "integer" + elseif tag == "types.T.Float" then return "float" + elseif tag == "types.T.String" then return "string" + elseif tag == "types.T.Function" then return "function" + elseif tag == "types.T.Array" then return "table" + elseif tag == "types.T.Table" then return "table" + elseif tag == "types.T.Record" then return typ.name elseif tag == "types.T.Any" then assert(false) -- 'Any' is not a type tag else tagged_union.error(tag) end @@ -248,14 +248,14 @@ function Coder:get_stack_slot(typ, dst, slot, loc, description_fmt, ...) check_tag = util.render([[ if (l_unlikely(!$test)) { pallene_runtime_tag_check_error(L, - $file, $line, $expected_tag, rawtt($slot), + $file, $line, $expected_type, $slot, ${description_fmt}${opt_comma}${extra_args}); } ]], { test = self:test_tag(typ, slot), file = C.string(loc and loc.file_name or ""), line = C.integer(loc and loc.line or 0), - expected_tag = pallene_type_tag(typ), + expected_type = C.string(pallene_type_tag(typ)), slot = slot, description_fmt = C.string(description_fmt), opt_comma = (#extra_args == 0 and "" or ", "), @@ -1771,11 +1771,13 @@ function Coder:generate_luaopen_function() if tag == "coder.Constant.Metatable" then is_upvalue_box = upv.typ.is_upvalue_box if not is_upvalue_box then - table.insert(init_constants, [[ - lua_newtable(L); + table.insert(init_constants, util.render([[ + luaL_newmetatable(L, $type_name); lua_pushstring(L, "__metatable"); lua_pushboolean(L, 0); - lua_settable(L, -3); ]]) + lua_settable(L, -3); ]], { + type_name = C.string(upv.typ.name) + })) end elseif tag == "coder.Constant.String" then table.insert(init_constants, util.render([[ diff --git a/src/pallene/pallenelib.lua b/src/pallene/pallenelib.lua index a696f48d..097892d0 100644 --- a/src/pallene/pallenelib.lua +++ b/src/pallene/pallenelib.lua @@ -47,7 +47,7 @@ return [==[ #define PALLENE_UNREACHABLE __builtin_unreachable() /* Type tags */ -static const char *pallene_tag_name(int raw_tag); +static const char *pallene_type_name(lua_State *L, const TValue *v); static int pallene_is_truthy(const TValue *v); static int pallene_is_record(const TValue *v, const TValue *meta_table); static int pallene_bvalue(TValue *obj); @@ -57,7 +57,8 @@ static void pallene_setbvalue(TValue *obj, int b); static void pallene_barrierback_unboxed(lua_State *L, GCObject *p, GCObject *v); /* Runtime errors */ -static l_noret pallene_runtime_tag_check_error(lua_State *L, const char* file, int line, int expected_tag, int received_tag,const char *description_fmt, ...); +static l_noret pallene_runtime_tag_check_error(lua_State *L, const char* file, int line, + const char *expected_type_name, const TValue *received_type, const char *description_fmt, ...); static l_noret pallene_runtime_arity_error(lua_State *L, const char *name, int expected, int received); static l_noret pallene_runtime_divide_by_zero_error(lua_State *L, const char* file, int line); static l_noret pallene_runtime_mod_by_zero_error(lua_State *L, const char* file, int line); @@ -96,14 +97,14 @@ static TString *pallene_tostring(lua_State *L, const char* file, int line, TValu static void pallene_io_write(lua_State *L, TString *str); -static const char *pallene_tag_name(int raw_tag) +static const char *pallene_type_name(lua_State *L, const TValue *v) { - if (raw_tag == LUA_VNUMINT) { + if (rawtt(v) == LUA_VNUMINT) { return "integer"; - } else if (raw_tag == LUA_VNUMFLT) { + } else if (rawtt(v) == LUA_VNUMFLT) { return "float"; } else { - return ttypename(novariant(raw_tag)); + return luaT_objtypename(L, v); } } @@ -147,13 +148,12 @@ static void pallene_runtime_tag_check_error( lua_State *L, const char* file, int line, - int expected_tag, - int received_tag, + const char *expected_type_name, + const TValue *received_type, const char *description_fmt, ... ){ - const char *expected_type = pallene_tag_name(expected_tag); - const char *received_type = pallene_tag_name(received_tag); + const char *received_type_name = pallene_type_name(L, received_type); /* This code is inspired by luaL_error */ luaL_where(L, 1); @@ -170,7 +170,7 @@ static void pallene_runtime_tag_check_error( va_end(argp); } lua_pushfstring(L, ", expected %s but found %s", - expected_type, received_type); + expected_type_name, received_type_name); lua_concat(L, 5); lua_error(L); PALLENE_UNREACHABLE;