Skip to content

Commit

Permalink
Support raw comparison for records and arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Apr 2, 2020
1 parent 9683c40 commit 6cb5c5f
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 9 deletions.
53 changes: 52 additions & 1 deletion nelua/cbuiltins.lua
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,40 @@ function builtins.nelua_lt_(context, ltype, rtype)
end
end

function builtins.nelua_eq_(context, type)
assert(type.is_record)
local name = string.format('nelua_eq_%s', type.codename)
if context.usedbuiltins[name] then return name end
local ctype = context:ctype(type)
local defemitter = CEmitter(context)
defemitter:add_ln('{')
defemitter:inc_indent()
defemitter:add_indent('return ')
for i,field in ipairs(type.fields) do
if i > 1 then
defemitter:add(' && ')
end
if field.type.is_record then
local op = context:ensure_runtime_builtin('nelua_eq_', field.type)
defemitter:add(op, '(a.', field.name, ', b.', field.name, ')')
elseif field.type.is_array then
context:add_include('<string.h>')
defemitter:add('memcmp(a.', field.name, ', ', 'b.', field.name, ', sizeof(', type, ')) == 0')
else
defemitter:add('a.', field.name, ' == ', 'b.', field.name)
end
end
defemitter:add_ln(';')
defemitter:dec_indent()
defemitter:add_ln('}')
define_inline_builtin(context, name,
'bool',
string.format('(%s a, %s b)', ctype, ctype),
defemitter:generate())
return name
end


function builtins.nelua_idiv_(context, type)
local name = string.format('nelua_idiv_i%d', type.bitsize)
if context.usedbuiltins[name] then return name end
Expand Down Expand Up @@ -547,9 +581,18 @@ end

function operators.eq(_, emitter, lnode, rnode, lname, rname)
local ltype, rtype = lnode.attr.type, rnode.attr.type
if ltype.is_stringview and rtype.is_stringview then
if ltype.is_stringview then
assert(rtype.is_stringview)
emitter:add_builtin('nelua_stringview_eq')
emitter:add('(', lname, ', ', rname, ')')
elseif ltype.is_record then
assert(ltype == rtype)
local op = emitter.context:ensure_runtime_builtin('nelua_eq_', ltype)
emitter:add(op, '(', lname, ', ', rname, ')')
elseif ltype.is_array then
assert(ltype == rtype)
emitter.context:add_include('<string.h>')
emitter:add('(memcmp(&', lname, '.data[0], &', rname, '.data[0], sizeof(', ltype, ')) == 0)')
else
emitter:add(lname, ' == ', rname)
end
Expand All @@ -560,6 +603,14 @@ function operators.ne(_, emitter, lnode, rnode, lname, rname)
if ltype.is_stringview and rtype.is_stringview then
emitter:add_builtin('nelua_stringview_ne')
emitter:add('(', lname, ', ', rname, ')')
elseif ltype.is_record then
assert(ltype == rtype)
local op = emitter.context:ensure_runtime_builtin('nelua_eq_', ltype)
emitter:add('!', op, '(', lname, ', ', rname, ')')
elseif ltype.is_array then
assert(ltype == rtype)
emitter.context:add_include('<string.h>')
emitter:add('(memcmp(&', lname, '.data[0], &', rname, '.data[0], sizeof(', ltype, ')) != 0)')
else
emitter:add(lname, ' != ', rname)
end
Expand Down
12 changes: 5 additions & 7 deletions nelua/configer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,17 @@ local function merge_configs(conf, pconf)
for k,v in pairs(pconf) do
if conf[k] == nil then
conf[k] = v
elseif type(conf[k]) == 'table' and type(v) == 'table' and #v > 0 then
tabler.insertvalues(conf[k], 1, v)
end
end

if conf.lib_path then
local ss = sstream()
for _,libpath in ipairs(conf.lib_path) do
if libpath:find('?') then
ss:add(libpath)
ss:add(libpath, ';')
else
ss:add(libpath .. '/?.nelua;')
ss:add(libpath .. '/?/init.nelua;')
ss:add(libpath, '/?.nelua;')
ss:add(libpath, '/?/init.nelua;')
end
end
ss:add(conf.path)
Expand All @@ -82,11 +80,11 @@ local function create_parser(args)
argparser:flag('-t --timing', 'Debug compile timing information', defconfig.timing)
argparser:flag('--no-cache', "Don't use any cached compilation", defconfig.no_cache)
argparser:option('-D --define', 'Define values in the preprocessor')
:count("*"):convert(convert_define, defconfig.define)
:count("*"):convert(convert_define, tabler.copy(defconfig.define or {}))
argparser:option('-g --generator', "Code generator to use (lua/c)", defconfig.generator)
argparser:option('-d --standard', "Source standard (default/luacompat)", defconfig.standard)
argparser:option('-p --path', "Set module search path", defconfig.path)
argparser:option('-L --lib-path', "Add module search path", defconfig.lib_path)
argparser:option('-L --lib-path', "Add module search path", tabler.copy(defconfig.lib_path or {}))
:count("*"):convert(convert_add_path)
argparser:option('--cc', "C compiler to use", defconfig.cc)
argparser:option('--cpu-bits', "Target CPU architecture bit size (64/32)", defconfig.cpu_bits)
Expand Down
53 changes: 53 additions & 0 deletions spec/05-cgenerator_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,59 @@ it("string comparisons", function()
]])
end)

it("array comparisons", function()
assert.run_c([[
local A = @integer[4]
local a: A = {1,2,3,4}
local b: A = {1,2,3,4}
local c: A = {1,2,3,5}
assert(a == a)
assert(a == (@integer[4]){1,2,3,4})
assert(a == b)
assert(not (a ~= b))
assert(not (a == c))
assert(a ~= c)
]])
end)

it("record comparisons", function()
assert.run_c([[
local R = @record{x: integer, y: integer}
local a: R = {1,1}
local b: R = {1,1}
local c: R = {2,2}
assert(a == a)
assert(a == R{1,1})
assert(a == b)
assert(not (a ~= b))
assert(not (a == c))
assert(a ~= c)
local P = @record{x: R}
local a: P = {{1}}
local b: P = {{1}}
local c: P = {{2}}
assert(a == a)
assert(a == b)
assert(not (a ~= b))
assert(not (a == c))
assert(a ~= c)
local Q = @record{x: integer[2]}
local a: Q = {{1,2}}
local b: Q = {{1,2}}
local c: Q = {{1,3}}
assert(a == a)
assert(a == b)
assert(not (a ~= b))
assert(not (a == c))
assert(a ~= c)
]])
end)

it("binary conditional operators", function()
assert.generate_c("local a, b; do return a or b end", [[({
nelua_any t1_ = a;
Expand Down
2 changes: 1 addition & 1 deletion spec/08-runner_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ it("configure module search paths", function()
defconfig.lib_path = oldlibpath

assert.run({'--path', './examples', '--analyze', '--eval',[[
## assert(config.path == './examples')
## assert(config.path:match('examples'))
]]})
end)

Expand Down

0 comments on commit 6cb5c5f

Please sign in to comment.