Skip to content

Commit

Permalink
[lua] refactor runtime tostring to separate lua file
Browse files Browse the repository at this point in the history
  • Loading branch information
jdonaldson committed Feb 27, 2020
1 parent a0ed7f3 commit 0bab113
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 120 deletions.
9 changes: 6 additions & 3 deletions src/generators/genlua.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1965,13 +1965,16 @@ let generate com =
print ctx "%s\n" file_content;
in

(* table-to-array helper *)
(* base table-to-array helpers and metatables *)
print_file (Common.find_file com "lua/_lua/_hx_tab_array.lua");

(* lua workarounds for basic anonymous object functionality *)
(* base lua "toString" functionality for haxe objects*)
print_file (Common.find_file com "lua/_lua/_hx_tostring.lua");

(* base lua metatables for prototypes, inheritance, etc. *)
print_file (Common.find_file com "lua/_lua/_hx_anon.lua");

(* class reflection metadata *)
(* base runtime class stubs for haxe value types (Int, Float, etc) *)
print_file (Common.find_file com "lua/_lua/_hx_classes.lua");

let include_files = List.rev com.include_files in
Expand Down
104 changes: 0 additions & 104 deletions std/lua/Boot.hx
Original file line number Diff line number Diff line change
Expand Up @@ -153,110 +153,6 @@ class Boot {
throw "Cannot cast " + Std.string(o) + " to " + Std.string(t);
}

/**
Helper method to generate a string representation of an enum
**/
static function printEnum(o:Array<Dynamic>, s:String) {
if (o.length == 2) {
return o[0];
} else {
// parameterized enums are arrays
var str = o[0] + "(";
s += "\t";
for (i in 2...o.length) {
if (i != 2)
str += "," + __string_rec(o[i], s);
else
str += __string_rec(o[i], s);
}
return str + ")";
}
}

/**
Helper method to generate a string representation of a class
**/
static inline function printClass(c:Table<String, Dynamic>, s:String):String {
return '{${printClassRec(c, '', s)}}';
}

/**
Helper method to generate a string representation of a class
**/
static function printClassRec(c:Table<String, Dynamic>, result = '', s:String):String {
var f = Boot.__string_rec;
untyped __lua__("for k,v in pairs(c) do if result ~= '' then result = result .. ', ' end result = result .. k .. ':' .. f(v, s.. '\t') end");
return result;
}

/**
Generate a string representation for arbitrary object.
**/
@:ifFeature("has_enum")
static function __string_rec(o:Dynamic, s:String = "") {
if (s.length >= 5)
return "<...>";
return switch (untyped __type__(o)) {
case "nil": "null";
case "number": {
if (o == std.Math.POSITIVE_INFINITY)
"Infinity";
else if (o == std.Math.NEGATIVE_INFINITY)
"-Infinity";
else if (o == 0)
"0";
else if (o != o)
"NaN";
else
untyped tostring(o);
}
case "boolean": untyped tostring(o);
case "string": o;
case "userdata": {
var mt = lua.Lua.getmetatable(o);
if (mt != null && mt.__tostring != null) {
lua.Lua.tostring(o);
} else {
"<userdata>";
}
}
case "function": "<function>";
case "thread": "<thread>";
case "table": {
if (o.__enum__ != null)
printEnum(o, s);
else if (o.toString != null && !isArray(o))
o.toString();
else if (isArray(o)) {
var o2:Array<Dynamic> = untyped o;
if (s.length > 5)
"[...]"
else
'[${[for (i in o2) __string_rec(i, s + 1)].join(",")}]';
} else if (o.__class__ != null)
printClass(o, s + "\t");
else {
var fields = fieldIterator(o);
var buffer:Table<Int, String> = Table.create();
var first = true;
Table.insert(buffer, "{ ");
for (f in fields) {
if (first)
first = false;
else
Table.insert(buffer, ", ");
Table.insert(buffer, '${Std.string(f)} : ${untyped __string_rec(o[f], s + "\t")}');
}
Table.insert(buffer, " }");
Table.concat(buffer, "");
}
};
default: {
throw "Unknown Lua type";
null;
}
}
}

/**
Define an array from the given table
Expand Down
4 changes: 2 additions & 2 deletions std/lua/_lua/_hx_anon.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
local function _hx_obj_newindex(t,k,v) t.__fields__[k] = true; rawset(t,k,v); end
local _hx_obj_mt = {__newindex=_hx_anon_newindex}
local _hx_obj_mt = {__newindex=_hx_obj_newindex, __tostring=_hx_tostring}
local function _hx_a(...)
local __fields__ = {};
local ret = {__fields__ = __fields__};
Expand All @@ -24,5 +24,5 @@ local function _hx_o(obj)
end

local function _hx_new(prototype)
return setmetatable({__fields__ = {}}, {__newindex=_hx_anon_newindex, __index=prototype})
return setmetatable({__fields__ = {}}, {__newindex=_hx_anon_newindex, __index=prototype, __tostring=_hx_tostring})
end
26 changes: 17 additions & 9 deletions std/lua/_lua/_hx_tab_array.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
local _hx_array_mt = {
__newindex = function(t,k,v)
local len = t.length
t.length = k >= len and (k + 1) or len
rawset(t,k,v)
end
_hx_array_mt = {
__newindex = function(t,k,v)
local len = t.length
t.length = k >= len and (k + 1) or len
rawset(t,k,v)
end
}

local function _hx_tab_array(tab,length)
tab.length = length
return setmetatable(tab, _hx_array_mt)
function _hx_is_array(o)
return type(o) == "table"
and o.__enum__ == nil
and getmetatable(o) == _hx_array_mt
end



function _hx_tab_array(tab, length)
tab.length = length
return setmetatable(tab, _hx_array_mt)
end
93 changes: 93 additions & 0 deletions std/lua/_lua/_hx_tostring.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
local _hx_hidden = {__id__=true, hx__closures=true, super=true, prototype=true, __fields__=true, __ifields__=true, __class__=true, __properties__=true}

function _hx_print_class(obj, depth)
local first = true
local result = ''
for k,v in pairs(obj) do
if first then
result = result .. ','
first = false
end
if _hx_hidden[k] == nil then
result = result .. k .. ':' .. _hx_tostring(v, depth+1)
end
end
return result
end

function _hx_print_enum(o, depth)
if o.length == 2 then
return o[0]
else
local str = o[0] .. "(";
for i = 2, (o.length-1) do
if i ~= 2 then
str = str .. "," .. _hx_tostring(o[i], depth+1);
else
str = str .. _hx_tostring(o[i], depth+1);
end
end
return str .. ")";
end
end

function _hx_tostring(obj, depth)
if depth == nil then
depth = 0
elseif depth > 5 then
return "<...>"
end

local tstr = type(obj)
if tstr == "string" then return obj
elseif tstr == "nil" then return "null";
elseif tstr == "number" then
if obj == _G.math.POSITIVE_INFINITY then return "Infinity";
elseif obj == _G.math.NEGATIVE_INFINITY then return "-Infinity";
elseif obj == 0 then return "0";
elseif obj ~= obj then return "NaN";
else return _G.tostring(obj);
end
elseif tstr == "boolean" then return _G.tostring(obj);
elseif tstr == "userdata" then
local mt = _G.getmetatable(obj);
if mt ~= nil and mt.__tostring ~= nil then
return _G.tostring(obj);
else
return "<userdata>";
end
elseif tstr == "function" then return "<function>";
elseif tstr == "thread" then return "<thread>";
elseif tstr == "table" then
if obj.__enum__ ~= nil then
return _hx_print_enum(obj, depth)
elseif obj.toString ~= nil and not _hx_is_array(obj) then return obj:toString()
elseif _hx_is_array(obj) then
if obj.length > 5 then
return "[...]"
else
str = ""
for i=0, (obj.length-1) do
if i == 0 then
str = str .. _hx_tostring(obj[i])
else
str = str .. "," .. _hx_tostring(obj[i])
end
end
return "[" .. str .. "]"
end
elseif obj.__class__ ~= nil then
return _hx_print_class(obj, depth)
else
first = true
buffer = {}
for k,v in pairs(obj) do
_G.table.insert(buffer, _hx_tostring(k, depth) .. ' : ' .. _hx_tostring(obj[k], depth))
end
return "{ " .. table.concat(buffer, ", ") .. " }"
end
else
_G.error("Unknown Lua type", 0)
return ""
end
end
4 changes: 2 additions & 2 deletions std/lua/_std/Std.hx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ import lua.NativeStringTools;
}

@:keep
public static function string(s:Dynamic):String {
return untyped lua.Boot.__string_rec(s);
public static function string(s:Dynamic) : String {
return untyped _hx_tostring(s, 0);
}

public static function int(x:Float):Int {
Expand Down

0 comments on commit 0bab113

Please sign in to comment.