Skip to content

Commit

Permalink
feat: scan the entire AST to collect function names, instead of forwa…
Browse files Browse the repository at this point in the history
…rd declarations
  • Loading branch information
pgagnidze committed May 31, 2023
1 parent 4ba337b commit 1cc04b1
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 16 deletions.
5 changes: 3 additions & 2 deletions NOTES.md
Expand Up @@ -61,8 +61,9 @@ Execute the [input.ena](./example/input.ena) for the input program. `input.ena`

Check out the new [sysinfo.ena](./example/sysinfo.ena) program that shows various system informations for Linux and Darwin os.

**Summary of changes:**
- optional statement separator (;)
**Summary of modifications:**
- Optional statement separator (;)
- Scan the entire AST and collect function names (instead of forward declarations)

## New Features

Expand Down
28 changes: 15 additions & 13 deletions ena/compiler.lua
@@ -1,6 +1,7 @@
local module = {}
local translator = require "ena.lang.translator"
local literals = require "ena.lang.literals"
local pt = require "ena.helper.pt".pt
local lop = literals.op

local Compiler = {}
Expand Down Expand Up @@ -327,19 +328,7 @@ function Compiler:findFirstDuplicateParam(ast)
end

function Compiler:codeFunction(ast)
if not ast.block then
if not self.functions[ast.name] then
self.functions[ast.name] = {code = {}, forwardDeclaration = true}
end
end
local functionCode = self.functions[ast.name] and self.functions[ast.name].code or {}
if #functionCode > 0 and not self.functions[ast.name].forwardDeclaration then
error(
(self.translate and translator.err.compileErrDuplicateFunctionName or "Duplicate function name") ..
' "' .. ast.name .. '()"'
)
end
self.functions[ast.name] = {code = functionCode, params = ast.params, defaultArgument = ast.defaultArgument}
local functionCode = self.functions[ast.name].code
self.code = functionCode
self.params = ast.params
local firstDuplicate = self:findFirstDuplicateParam(ast)
Expand All @@ -357,7 +346,20 @@ function Compiler:codeFunction(ast)
end
end

function Compiler:collectFunctions(ast)
for i = 1, #ast do
local functionDeclaration = ast[i]
if not self.functions[functionDeclaration.name] then
self.functions[functionDeclaration.name] = {code = {}, params = functionDeclaration.params, defaultArgument = functionDeclaration.defaultArgument}
else
error("Duplicate function name '" .. functionDeclaration.name .. "()'")
end
end
end

function Compiler:compile(ast)
self:collectFunctions(ast)

for i = 1, #ast do
self:codeFunction(ast[i])
end
Expand Down
2 changes: 1 addition & 1 deletion ena/parser.lua
Expand Up @@ -276,7 +276,7 @@ local grammar = {
funcDec = KW_function * identifier * delim.openFunctionParameterList * funcParams *
((op.assign * expression) + Cc({})) *
delim.closeFunctionParameterList *
(blockStatement + sep.statement ^ -1) /
blockStatement /
nodeFunction,
funcParams = Ct((identifier * (delim.functionParameterSeparator * identifier) ^ 0) ^ -1),
statementList = statement * (sep.statement ^ -1 * statementList) ^ -1 / nodeStatementSequence,
Expand Down
20 changes: 20 additions & 0 deletions ena/spec/e2e.lua
Expand Up @@ -512,6 +512,26 @@ function module:testOptionalStatementSeparator()
)
end

function module:testFunctionOrdering()
lu.assertEquals(
self:endToEnd(
[[
function a() {
return 1
}
function main() {
return a() + b()
}
function b() {
return 2
}
]]
),
3
)
end

return module

0 comments on commit 1cc04b1

Please sign in to comment.