From d017ebe096ee310bfe73431dbd4a54a4350c6243 Mon Sep 17 00:00:00 2001 From: "Johan B.W. de Vries" Date: Sun, 25 May 2025 14:42:31 +0200 Subject: [PATCH] Support tail calls --- phasm/compiler.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/phasm/compiler.py b/phasm/compiler.py index 4eaf1b2..cc7aa1e 100644 --- a/phasm/compiler.py +++ b/phasm/compiler.py @@ -369,21 +369,31 @@ def expression(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Expression) raise NotImplementedError(expression, inp) -def statement_return(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.StatementReturn) -> None: +def statement_return(wgn: WasmGenerator, mod: ourlang.Module, fun: ourlang.Function, inp: ourlang.StatementReturn) -> None: """ Compile: Return statement """ + # Support tail calls + # https://github.com/WebAssembly/tail-call + # These help a lot with some functional programming techniques + if isinstance(inp.value, ourlang.FunctionCall) and inp.value.function is fun: + for arg in inp.value.arguments: + expression(wgn, mod, arg) + + wgn.add_statement('return_call', '${}'.format(inp.value.function.name)) + return + expression(wgn, mod, inp.value) wgn.return_() -def statement_if(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.StatementIf) -> None: +def statement_if(wgn: WasmGenerator, mod: ourlang.Module, fun: ourlang.Function, inp: ourlang.StatementIf) -> None: """ Compile: If statement """ expression(wgn, mod, inp.test) with wgn.if_(): for stat in inp.statements: - statement(wgn, mod, stat) + statement(wgn, mod, fun, stat) if inp.else_statements: raise NotImplementedError @@ -391,16 +401,16 @@ def statement_if(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Statement # for stat in inp.else_statements: # statement(wgn, stat) -def statement(wgn: WasmGenerator, mod: ourlang.Module, inp: ourlang.Statement) -> None: +def statement(wgn: WasmGenerator, mod: ourlang.Module, fun: ourlang.Function, inp: ourlang.Statement) -> None: """ Compile: any statement """ if isinstance(inp, ourlang.StatementReturn): - statement_return(wgn, mod, inp) + statement_return(wgn, mod, fun, inp) return if isinstance(inp, ourlang.StatementIf): - statement_if(wgn, mod, inp) + statement_if(wgn, mod, fun, inp) return if isinstance(inp, ourlang.StatementPass): @@ -443,7 +453,7 @@ def function(mod: ourlang.Module, inp: ourlang.Function) -> wasm.Function: _generate_struct_constructor(wgn, inp) else: for stat in inp.statements: - statement(wgn, mod, stat) + statement(wgn, mod, inp, stat) return wasm.Function( inp.name,