Skip to content

Add support for lambda-style functions #2720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased
<!-- Add all new changes here. They will be moved under a version at release -->
* `NEW` Add postfix snippet for `unpack`
* `NEW` Add support for lambda style functions, `|paramList| expr` is syntactic sugar for `function(paramList) return expr end`

## 3.9.3
`2024-6-11`
Expand Down
1 change: 1 addition & 0 deletions doc/en-us/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -1829,6 +1829,7 @@ Array<string>
* ``"!"``
* ``"!="``
* ``"continue"``
* ``"|lambda|"``

## default

Expand Down
1 change: 1 addition & 0 deletions doc/pt-br/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -1829,6 +1829,7 @@ Array<string>
* ``"!"``
* ``"!="``
* ``"continue"``
* ``"|lambda|"``

## default

Expand Down
98 changes: 95 additions & 3 deletions script/parser/compile.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2188,13 +2188,14 @@ local function parseActions()
end
end

local function parseParams(params)
local function parseParams(params, isLambda)
local lastSep
local hasDots
local endToken = isLambda and '|' or ')'
while true do
skipSpace()
local token = Tokens[Index + 1]
if not token or token == ')' then
if not token or token == endToken then
if lastSep then
missName()
end
Expand Down Expand Up @@ -2269,7 +2270,7 @@ local function parseParams(params)
Index = Index + 2
goto CONTINUE
end
skipUnknownSymbol '%,%)%.'
skipUnknownSymbol ('%,%' .. endToken .. '%.')
::CONTINUE::
end
return params
Expand Down Expand Up @@ -2393,6 +2394,91 @@ local function parseFunction(isLocal, isAction)
return func
end

local function parseLambda(isDoublePipe)
local lambdaLeft = getPosition(Tokens[Index], 'left')
local lambdaRight = getPosition(Tokens[Index], 'right')
local lambda = {
type = 'function',
start = lambdaLeft,
finish = lambdaRight,
bstart = lambdaRight,
keyword = {
[1] = lambdaLeft,
[2] = lambdaRight,
},
hasReturn = true
}
Index = Index + 2
local pipeLeft = getPosition(Tokens[Index], 'left')
local pipeRight = getPosition(Tokens[Index], 'right')
skipSpace(true)
local params
local LastLocalCount = LocalCount
-- if nonstandardSymbol for '||' is true it is possible for token to be || when there are no params
if isDoublePipe then
params = {
start = pipeLeft,
finish = pipeRight,
parent = lambda,
type = 'funcargs'
}
else
-- fake chunk to store locals
pushChunk(lambda)
LocalCount = 0
params = parseParams({}, true)
params.type = 'funcargs'
params.start = pipeLeft
params.finish = lastRightPosition()
params.parent = lambda
lambda.args = params
skipSpace()
if Tokens[Index + 1] == '|' then
pipeRight = getPosition(Tokens[Index], 'right')
lambda.finish = pipeRight
lambda.bstart = pipeRight
if params then
params.finish = pipeRight
end
Index = Index + 2
skipSpace()
else
lambda.finish = lastRightPosition()
lambda.bstart = lambda.finish
if params then
params.finish = lambda.finish
end
missSymbol '|'
end
end
local child = parseExp()


-- don't want popChunk logic here as this is not a real chunk
Chunk[#Chunk] = nil

if child then
-- create dummy return
local rtn = {
type = 'return',
start = child.start,
finish = child.finish,
parent = lambda,
[1] = child}
child.parent = rtn
lambda[1] = rtn
lambda.returns = {rtn}
lambda.finish = child.finish
lambda.keyword[3] = child.finish
lambda.keyword[4] = child.finish
else
lambda.finish = lastRightPosition()
missExp()
end
LocalCount = LastLocalCount
return lambda
end

local function checkNeedParen(source)
local token = Tokens[Index + 1]
if token ~= '.'
Expand Down Expand Up @@ -2485,6 +2571,12 @@ local function parseExpUnit()
return parseFunction()
end

-- FIXME: Use something other than nonstandardSymbol to check for lambda support
if State.options.nonstandardSymbol['|lambda|'] and (token == '|'
or token == '||') then
return parseLambda(token == '||')
end

local node = parseName()
if node then
local nameNode = resolveName(node)
Expand Down
Loading