diff --git a/NOTES.md b/NOTES.md index 48ba282..a0b76d5 100644 --- a/NOTES.md +++ b/NOTES.md @@ -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 diff --git a/ena/compiler.lua b/ena/compiler.lua index ea8ed36..9ba9de4 100644 --- a/ena/compiler.lua +++ b/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 = {} @@ -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) @@ -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 diff --git a/ena/parser.lua b/ena/parser.lua index 2b3e889..4b6ddef 100755 --- a/ena/parser.lua +++ b/ena/parser.lua @@ -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, diff --git a/ena/spec/e2e.lua b/ena/spec/e2e.lua index 29aa99d..40e934a 100644 --- a/ena/spec/e2e.lua +++ b/ena/spec/e2e.lua @@ -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