Closed jrfondren closed 10 months ago
At first, I thought it was the missing do
from switch wd
, but it seems switch
is not supported with preprocessor's parsing yet.
Nelua processor is very different from other programming languages preprocessors in a unique way, it does not work at syntax and token level, but at AST (abstract syntax tree) level and with type inference. This has unique advantages like being able to introspect AST nodes and variables while in the preprocessor context, not many languages can do this. But there are drawbacks, like you cannot insert any set of tokens between preprocessor directives. This is specially true for ifelse blocks and switches, you cannot break them apart between preprocessor directives, the code between the directives must be a complete and valid AST node.
So your last example, is not fine:
if false then
print 'a'
## if true then
else
print 'b'
## end
end
This is how the compiler understands, luckily it will compile, but it was not doing what you expected.
Given this limitation, you have two choices, one is to use multiple if conditions like you suggested, and it's fine to do this, because switches are converted to ifs most of the time anyway when compiling. The second, if you really want to emit a switch, is to generate AST by hand, like the following example:
local Weekdays = @enum{
Sunday = 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
-- way 1
function Weekdays.show1(wd: Weekdays): string
##[[
local cases = {}
for _, field in ipairs(Weekdays.value.fields) do
table.insert(cases, {aster.Number{tostring(field.value)}})
table.insert(cases, aster.Block{aster.Return{aster.String{'Weekdays.'..field.name}}})
end
inject_statement(aster.Switch{aster.Id{'wd'}, cases})
]]
assert(false, 'invalid weekday')
return ''
end
print(Weekdays.Sunday:show1())
But this way you have to manually emit AST nodes by hand, after reading astdefs.lua
to understand the AST schema. This can be more difficult but also more powerful, because you can generate any kind of code.
But what if you want to mix manual AST node creation with usual code, thinking of this, in commit https://github.com/edubart/nelua-lang/commit/cd6986b26dba1ed63b7b5a2cebd108720b9335fd I introduced wrap_statement
macro, so there is a new way:
local Weekdays = @enum{
Sunday = 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
-- way 2
function Weekdays.show2(wd: Weekdays): string
## local cases = {}
## for _, field in ipairs(Weekdays.value.fields) do
## table.insert(cases, {aster.Number{tostring(field.value)}})
## table.insert(cases, wrap_statement(function()
-- back to normal code context
return #['Weekdays.'..field.name]#
## end))
## end
## inject_statement(aster.Switch{aster.Id{'wd'}, cases})
assert(false, 'invalid weekday')
return ''
end
print(Weekdays.Saturday:show2())
...so, remind me when are you going to write that Compiler book? /jk :rofl: I honestly wish I had the financial resources to fund you in any project you would like to invest your time and effort, because I learn so many things from you.
I get syntax errors when trying to generate the cases of a switch statement, when very similar code can emit other conditionals and even parts of other conditionals.
Code example
Environment
x86_64 linux Nelua 0.2.0-dev Build number: 1588 Git date: 2023-09-16 16:20:44 -0300 Git hash: 596fcca5c77932da8a07c249de59a9dff3099495 Semantic version: 0.2.0-dev.1588+596fcca5 Copyright (C) 2019-2022 Eduardo Bart (https://nelua.io/)