Skip to content

Commit

Permalink
Use C like arrays in records
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Jan 29, 2020
1 parent 1b44e5e commit ec918f2
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 100 deletions.
2 changes: 1 addition & 1 deletion docs/pages/nelua.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ for existing Lua projects by generating Lua code.
* We want type safety and optimizations.
* We want to have efficient code while maintaining readability and safety.
* We want the language features and manual to be minimalistic and fit our brain.
* We want to deploy anywhere Lua or C runs.
* We want to deploy anywhere C runs.
* We want to extended the language features by meta programming or modding the compiler.
* We want to code with or without garbage collection depending on our use case.
* We want to abuse of static dispatch instead of dynamic dispatch to gain performance and correctness.
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ are similar to Lua, thus if you know Lua you probably know Nelua too. However Ne
additions to code with type annotations, to make more efficient code and to meta program.
This overview try to focus more on those features.

Although copying Lua code without or minor changes is a goal of Nelua, not all Lua
Although copying Lua code with minor changes is a goal of Nelua, not all Lua
features are implemented yet. Mostly the dynamic part such as tables and dynamic typing
are not implemented yet, thus at the moment is best to try Nelua using type notations.

Expand Down Expand Up @@ -882,7 +882,7 @@ print(deg2rad, hello, mybool)

### Name replacement

For placing identifier names generated by the processor you should use `#( )`:
For placing identifier names generated by the processor you should use `#( )#`:

```nelua
local #('my' .. 'var')# = 1
Expand Down
5 changes: 3 additions & 2 deletions examples/snakesdl.nelua
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,13 @@ end

local function draw_tile(pos: Point2D, color: Color)
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255)
SDL_RenderFillRect(renderer, &SDL_Rect{
local rect = SDL_Rect{
x = (@cint)(pos.x * TILE_SIZE),
y = (@cint)(pos.y * TILE_SIZE),
w = TILE_SIZE,
h = TILE_SIZE
})
}
SDL_RenderFillRect(renderer, &rect)
end

local function draw_apple()
Expand Down
47 changes: 21 additions & 26 deletions nelua/analyzer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,9 @@ local function visitor_ArrayTable_literal(context, node, littype)
context:traverse(childnode)
local childtype = childnode.attr.type
if childtype then
if childtype == subtype then
childnode.attr.initializer = true
else
local ok, err = subtype:is_convertible_from(childnode.attr)
if not ok then
childnode:raisef("in array table literal at index %d: %s", i, err)
end
local ok, err = subtype:is_convertible_from(childnode.attr)
if not ok then
childnode:raisef("in array table literal at index %d: %s", i, err)
end
end
end
Expand All @@ -118,13 +114,12 @@ local function visitor_Array_literal(context, node, littype)
context:traverse(childnode)
local childtype = childnode.attr.type
if childtype then
if childtype == subtype then
childnode.attr.initializer = true
else
local ok, err = subtype:is_convertible_from(childnode.attr)
if not ok then
childnode:raisef("in array literal at index %d: %s", i, err)
end
if not childtype:is_initializable_from_attr(childnode.attr) then
comptime = nil
end
local ok, err = subtype:is_convertible_from(childnode.attr)
if not ok then
childnode:raisef("in array literal at index %d: %s", i, err)
end
end
if not childnode.attr.comptime then
Expand Down Expand Up @@ -168,33 +163,31 @@ local function visitor_Record_literal(context, node, littype)
lastfieldindex = fieldindex
local fieldvaltype = fieldvalnode.attr.type
if fieldvaltype then
if fieldvaltype == fieldtype then
fieldvalnode.attr.initializer = true
else
local ok, err = fieldtype:is_convertible_from(fieldvalnode.attr)
if not ok then
childnode:raisef("in record literal field '%s': %s", fieldname, err)
end
if not fieldvaltype:is_initializable_from_attr(fieldvalnode.attr) then
comptime = nil
end
local ok, err = fieldtype:is_convertible_from(fieldvalnode.attr)
if not ok then
childnode:raisef("in record literal field '%s': %s", fieldname, err)
end
end
childnode.attr.parenttype = littype
if not fieldvalnode.attr.comptime then
comptime = nil
end
childnode.attr.parenttype = littype
childnode.attr.fieldname = fieldname
end
attr.type = littype
attr.comptime = comptime
end


local function visitor_Table_literal(context, node)
local attr = node.attr
local childnodes = node:args()
context:traverse(childnodes)
attr.type = primtypes.table
end


function visitors.Table(context, node)
local desiredtype = node.desiredtype
if not desiredtype or desiredtype:is_table() then
Expand Down Expand Up @@ -833,8 +826,10 @@ local function visitor_Call_typeassertion(context, node, argnodes, type)
argnode:raisef("in type assertion: %s", err)
end
if argnode.attr.comptime then
attr.comptime = argnode.attr.comptime
attr.value = type:normalize_value(argnode.attr.value)
if attr.value or argtype == type then
attr.comptime = true
end
end
end
attr.sideeffect = argnode.attr.sideeffect
Expand Down Expand Up @@ -1215,7 +1210,7 @@ function visitors.VarDecl(context, node)
varnode:raisef("cannot assign imported variables, only imported types can be assigned")
end

if valtype == vartype and valnode.attr.comptime then
if vartype and vartype:is_initializable_from_attr(valnode.attr) then
valnode.attr.initializer = true
end
else
Expand Down
2 changes: 1 addition & 1 deletion nelua/cbuiltins.lua
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ end

function operators.range(node, emitter, lnode, rnode)
local subtype = node.attr.type.subtype
emitter:add_nodectypecast(node)
emitter:add_ctypecast(node.attr.type)
emitter:add('{')
emitter:add_val2type(subtype, lnode)
emitter:add(',')
Expand Down
2 changes: 1 addition & 1 deletion nelua/ccontext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function CContext:runctype(type)
end

function CContext:funcretctype(functype)
if functype:has_multiple_returns() then
if functype:has_enclosed_return() then
return functype.codename .. '_ret'
else
return self:ctype(functype:get_return_type(1))
Expand Down
2 changes: 1 addition & 1 deletion nelua/cdefs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ cdefs.compiler_base_flags = {
cflags_warn = {
"-Wall",
"-Wextra",
--"-Wno-incompatible-pointer-types", -- importing C functions can cause this warn
"-Wno-incompatible-pointer-types", -- importing C functions can cause this warn
"-Wno-missing-field-initializers", -- records without all fields explicity initialized
"-Wno-unused-parameter", -- functions with unused parameters
"-Wno-unused-const-variable", -- consts can be left unused
Expand Down
24 changes: 4 additions & 20 deletions nelua/cemitter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ function CEmitter:zeroinit(type)
s = 'NULL'
elseif type:is_boolean() then
s = 'false'
else
elseif type.size > 0 then
s = '{0}'
else
s = '{}'
end
return s
end
Expand All @@ -47,15 +49,7 @@ function CEmitter:add_zeroinit(type)
self:add(self:zeroinit(type))
end

function CEmitter:add_nodezerotype(node)
local type = node.attr.type
if not (type:is_boolean() or type:is_arithmetic() or type:is_pointer()) then
self:add_nodectypecast(node)
end
self:add(self:zeroinit(type))
end

function CEmitter:add_castedzerotype(type)
function CEmitter:add_ctyped_zerotype(type)
if not (type:is_boolean() or type:is_arithmetic() or type:is_pointer()) then
self:add_ctypecast(type)
end
Expand All @@ -72,16 +66,6 @@ function CEmitter:add_ctypecast(type)
self:add(')')
end

function CEmitter:add_nodectypecast(node)
if node.attr.initializer then
-- skip casting inside initializers
return
end
self:add('(')
self:add_ctype(node.attr.type)
self:add(')')
end

function CEmitter:add_booleanlit(value)
assert(type(value) == 'boolean')
self:add(value and 'true' or 'false')
Expand Down
Loading

0 comments on commit ec918f2

Please sign in to comment.