Files
l2/libs/fn.sl

375 lines
11 KiB
Plaintext
Raw Permalink Normal View History

#call-syntax-rewrite [* | fnameToken] -> [* | handled]
word call-syntax-rewrite
2026-01-03 09:04:50 +00:00
dup token-lexeme identifier? 0 == if drop 0 exit end
peek-token dup nil? if drop drop 0 exit end
dup token-lexeme "(" string= 0 == if drop drop 0 exit end
2025-12-11 20:07:10 +01:00
swap >r # stash fnameTok
drop # discard peeked '('
next-token drop # consume '('
list-new # out
list-new # out cur
begin
2026-01-03 09:04:50 +00:00
next-token dup nil? if "unterminated call expression" parse-error end
2025-12-11 20:07:10 +01:00
dup token-lexeme ")" string= if
drop
# flush current arg
list-extend # out'
r> list-append # out''
inject-tokens
1 exit
2026-01-03 09:04:50 +00:00
end
2025-12-11 20:07:10 +01:00
dup token-lexeme "," string= if
drop
list-extend # out'
list-new # out' cur
continue
2026-01-03 09:04:50 +00:00
end
2025-12-11 20:07:10 +01:00
# default: append tok to cur
list-append
again
end
2025-12-11 20:07:10 +01:00
immediate
compile-only
2026-02-18 13:58:08 +01:00
#extend-syntax [*] -> [*]
word extend-syntax
2025-12-11 20:07:10 +01:00
"call-syntax-rewrite" set-token-hook
end
2025-12-11 20:07:10 +01:00
immediate
compile-only
word fn-op-prec
2026-01-03 09:04:50 +00:00
dup "+" string= if drop 1 exit end
dup "-" string= if drop 1 exit end
dup "*" string= if drop 2 exit end
dup "/" string= if drop 2 exit end
dup "%" string= if drop 2 exit end
2025-12-11 20:07:10 +01:00
drop 0
end
2025-12-11 20:07:10 +01:00
compile-only
word fn-operator?
2025-12-11 20:07:10 +01:00
fn-op-prec 0 >
end
2025-12-11 20:07:10 +01:00
compile-only
word fn-check-dup
2025-12-11 20:07:10 +01:00
>r # params (r: name)
0 # params idx
begin
over list-length swap >= if # params flag
r> exit
2026-01-03 09:04:50 +00:00
end
2025-12-11 20:07:10 +01:00
dup >r # params idx (r: idx name)
over swap list-get # params elem
2026-01-03 09:04:50 +00:00
1 rpick string= if "duplicate parameter names in fn definition" parse-error end
2025-12-11 20:07:10 +01:00
drop # drop comparison flag when no error
r> 1 + # params idx+1
again
end
2025-12-11 20:07:10 +01:00
compile-only
word fn-params
2025-12-11 20:07:10 +01:00
list-new # lexer params
swap # params lexer
>r # params (r: lexer)
begin
0 rpick lexer-pop token-lexeme # params lex
swap drop # params lex (drop returned lexer)
2026-01-03 09:04:50 +00:00
dup ")" string= if drop r> exit end
dup "int" string= 0 == if "only 'int' parameters are supported in fn definitions" parse-error end
2025-12-11 20:07:10 +01:00
drop # params
0 rpick lexer-pop token-lexeme # params lexer pname
swap drop # params pname
2026-01-03 09:04:50 +00:00
dup identifier? 0 == if "invalid parameter name in fn definition" parse-error end
2025-12-11 20:07:10 +01:00
fn-check-dup # params pname
list-append # params
0 rpick lexer-pop token-lexeme # params lexer sep
swap drop # params sep
2026-01-03 09:04:50 +00:00
dup "," string= if drop continue end
dup ")" string= if drop r> exit end
2025-12-11 20:07:10 +01:00
"expected ',' or ')' in parameter list" parse-error
again
end
2025-12-11 20:07:10 +01:00
compile-only
word fn-collect-body
2025-12-11 20:07:10 +01:00
"{" lexer-expect drop # consume opening brace, keep lexer
lexer-collect-brace # lexer bodyTokens
swap drop # bodyTokens
end
2025-12-11 20:07:10 +01:00
compile-only
word fn-lexemes-from-tokens
2025-12-14 00:38:19 +01:00
>r # (r: tokens)
list-new # acc
2025-12-11 20:07:10 +01:00
begin
2025-12-14 00:38:19 +01:00
0 rpick list-empty? if
rdrop exit
2026-01-03 09:04:50 +00:00
end
2025-12-14 00:38:19 +01:00
0 rpick list-pop-front # acc tokens' first
rdrop # acc tokens'
swap # acc first tokens'
>r # acc first (r: tokens')
token-lexeme # acc lex
list-append # acc'
2025-12-11 20:07:10 +01:00
again
end
2025-12-11 20:07:10 +01:00
compile-only
word fn-validate-body
2026-01-03 09:04:50 +00:00
dup list-length 0 == if "empty function body" parse-error end
dup 0 list-get token-lexeme "return" string= 0 == if "function body must start with 'return'" parse-error end
dup list-last ";" string= 0 == if "function body must terminate with ';'" parse-error end
2025-12-14 00:38:19 +01:00
list-clone # body body'
list-pop drop # body expr' (trim trailing ';')
list-pop-front drop # body expr (trim leading 'return')
2026-01-03 09:04:50 +00:00
dup list-length 0 == if "missing return expression" parse-error end
end
2025-12-11 20:07:10 +01:00
compile-only
word fn-filter-raw-body # bodyLexemes -- tokens
list-new swap # out body
begin
dup list-empty? if
drop # out
exit
2026-01-03 09:04:50 +00:00
end
list-pop-front # out body' tok
swap >r # out tok (r: body')
dup "return" string= if
drop
r>
continue
2026-01-03 09:04:50 +00:00
end
dup ";" string= if
drop
r>
continue
2026-01-03 09:04:50 +00:00
end
list-append # out'
r> # out' body'
continue
again
end
compile-only
word fn-body->tokens # bodyLexemes -- tokens
2026-01-03 09:04:50 +00:00
dup list-length 0 == if "empty function body" parse-error end
dup 0 list-get token-lexeme "return" string= if
fn-validate-body # expr
shunt # postfix
exit
2026-01-03 09:04:50 +00:00
end
fn-filter-raw-body
2026-01-03 09:04:50 +00:00
dup list-length 0 == if "empty function body" parse-error end
end
compile-only
word fn-emit-prologue # params out -- params out
2025-12-14 16:34:02 +01:00
over list-length # params out n
begin
dup 0 > if
1 - # params out n-1
>r # params out (r: n-1)
">r" list-append # params out'
r> # params out' n-1
continue
2026-01-03 09:04:50 +00:00
end
2025-12-14 16:34:02 +01:00
drop # params out
exit
again
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-emit-epilogue # params out -- out
2025-12-14 16:34:02 +01:00
over list-length >r # params out (r: n)
begin
r> dup 0 > if
1 - >r
"rdrop" list-append
continue
2026-01-03 09:04:50 +00:00
end
2025-12-14 16:34:02 +01:00
drop # drop counter
swap drop # out
exit
again
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-translate-prologue-loop # count --
2025-12-14 16:34:02 +01:00
dup 0 > if
1 -
0 rpick ">r" list-append drop
fn-translate-prologue-loop
2026-01-03 09:04:50 +00:00
end
2025-12-14 16:34:02 +01:00
drop
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-translate-epilogue-loop # count --
2025-12-14 16:34:02 +01:00
dup 0 > if
1 -
0 rpick "rdrop" list-append drop
fn-translate-epilogue-loop
2026-01-03 09:04:50 +00:00
end
2025-12-14 16:34:02 +01:00
drop
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-param-index # params name -- params idx flag
2025-12-14 16:34:02 +01:00
>r # params (r: name)
0 # params idx
begin
over list-length over swap >= if # params idx flag (idx >= len?)
drop # params
r> drop # drop name
-1 0 exit # params -1 0
2026-01-03 09:04:50 +00:00
end # params idx
2025-12-14 16:34:02 +01:00
over over list-get # params idx elem
0 rpick string= # params idx flag
if
r> drop # drop name
1 exit # params idx 1
2026-01-03 09:04:50 +00:00
end
2025-12-14 16:34:02 +01:00
drop # params idx
1 + # params idx+1
again
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-build-param-map # params -- params map
2025-12-14 16:34:02 +01:00
map-new # params map
0 # params map idx
begin
2 pick list-length # params map idx len
over swap >= if # params map idx flag
drop # params map
exit
2026-01-03 09:04:50 +00:00
end # params map idx
2025-12-14 16:34:02 +01:00
2 pick over list-get # params map idx name
swap # params map name idx
dup >r # params map name idx (r: idx)
map-set # params map'
r> 1 + # params map' idx'
continue
again
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-translate-token # out map tok -- out map
2025-12-14 16:34:02 +01:00
# number?
dup string>number # out map tok num ok
if
2025-12-14 16:41:00 +01:00
# (out map tok num) -> (out' map)
>r # out map tok (r: num)
drop # out map
r> # out map num
swap >r # out num (r: map)
2025-12-14 16:34:02 +01:00
list-append # out'
r> # out' map
exit
2026-01-03 09:04:50 +00:00
end
2025-12-14 16:34:02 +01:00
drop # out map tok
# param?
2025-12-14 16:41:00 +01:00
dup >r # out map tok (r: tok)
2025-12-14 16:34:02 +01:00
map-get # out map idx|nil ok
if
# append idx
2025-12-14 16:41:00 +01:00
swap >r # out idx (r: map tok)
2025-12-14 16:34:02 +01:00
list-append # out'
r> # out' map
# append "rpick"
2025-12-14 16:41:00 +01:00
"rpick" swap >r # out' "rpick" (r: map tok)
2025-12-14 16:34:02 +01:00
list-append # out''
r> # out'' map
# drop saved tok
r> drop # out'' map
exit
2026-01-03 09:04:50 +00:00
end
2025-12-14 16:34:02 +01:00
# not a param: drop idx|nil, append original tok
drop # out map
r> # out map tok
2025-12-14 16:41:00 +01:00
swap >r # out tok (r: map)
2025-12-14 16:34:02 +01:00
list-append # out'
r> # out' map
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-translate-postfix-loop # map out postfix -- map out
2025-12-14 16:34:02 +01:00
begin
dup list-empty? if
drop
exit
2026-01-03 09:04:50 +00:00
end
2025-12-14 16:34:02 +01:00
list-pop-front # map out postfix' tok
swap >r # map out tok (r: postfix')
>r swap r> # out map tok (r: postfix')
fn-translate-token # out map
swap # map out
r> # map out postfix'
continue
again
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-translate-postfix # postfix params -- out
2025-12-14 16:34:02 +01:00
swap # params postfix
list-new # params postfix out
# prologue: stash args on return stack (emit ">r")
swap >r # params out (r: postfix)
fn-emit-prologue # params out
r> swap # params postfix out
# build param map (name -> index)
2 pick fn-build-param-map # params postfix out params map
>r drop r> # params postfix out map
# reorder to: params map out postfix
swap >r swap r> swap # params map out postfix
# translate tokens
fn-translate-postfix-loop # params map out
# drop map, emit epilogue
swap drop # params out
fn-emit-epilogue # out
end
2025-12-14 16:34:02 +01:00
compile-only
word fn-build-body
2025-12-11 20:07:10 +01:00
fn-translate-postfix # words
end
2025-12-11 20:07:10 +01:00
compile-only
word fn
2025-12-11 20:07:10 +01:00
"(),{};+-*/%," lexer-new # lexer
dup lexer-pop # lexer nameTok
dup >r # save nameTok
token-lexeme # lexer name
2026-01-03 09:04:50 +00:00
dup identifier? 0 == if "invalid function name for 'fn'" parse-error end
2025-12-11 20:07:10 +01:00
>r # save name string
drop # leave lexer only for params
"(" lexer-expect drop # consume '(' keep lexer
fn-params # params lexer
fn-collect-body # params bodyTokens
swap >r # bodyTokens (r: params)
fn-lexemes-from-tokens # lexemes
fn-body->tokens # tokens
2025-12-11 20:07:10 +01:00
r> # postfix params
fn-build-body # body
r> drop # drop name string
r> # name token
swap emit-definition
end
2025-12-11 20:07:10 +01:00
immediate
compile-only