From ea5991732cfc935a401b7a30423a66f2c253defd Mon Sep 17 00:00:00 2001 From: bog Date: Tue, 12 Sep 2023 11:05:34 +0200 Subject: [PATCH] ADD: recursive functions. --- examples/fun.gri | 15 ++++++++++++++- src/Compiler.cpp | 13 +++++++++++++ src/Compiler.hpp | 1 + src/VM.cpp | 5 ++++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/examples/fun.gri b/examples/fun.gri index 9c73d6e..af17598 100644 --- a/examples/fun.gri +++ b/examples/fun.gri @@ -15,4 +15,17 @@ ;; inner variable ($ (d x) ($ y 3) (+ x y)) -(assert-eq? 7 (d 4)) \ No newline at end of file +(assert-eq? 7 (d 4)) + +;; recursivity +($ (e n) + (if (eq? 0 n) 1 + (* n (e (- n 1))))) + +(assert-eq? 120 (e 5)) + +;; self keyword +(assert-eq? 720 ((-> (x) + (if (eq? x 0) + 1 + (* x (self (- x 1))))) 6)) diff --git a/src/Compiler.cpp b/src/Compiler.cpp index a9e196f..5bc2436 100644 --- a/src/Compiler.cpp +++ b/src/Compiler.cpp @@ -94,6 +94,16 @@ namespace grino m_scope.size()); } + std::string name = "self"; + + if (!m_decl_context.empty()) + { + name = m_decl_context.back(); + } + + sym.declare(node->loc(), name, get_local_address(), + m_scope.size()); + auto prog = std::make_shared(); auto body = node->child(1).lock(); compile(body, *prog, sym); @@ -128,9 +138,12 @@ namespace grino auto expr = node->child(1).lock(); size_t address = get_local_address(); + m_decl_context.push_back(ident); compile(expr, program, sym); + m_decl_context.pop_back(); sym.declare(node->loc(), ident, address, m_scope.size()); + program.push_instr(OPCODE_STORE_LOCAL, address); } break; diff --git a/src/Compiler.hpp b/src/Compiler.hpp index 522a8ae..4e1f555 100644 --- a/src/Compiler.hpp +++ b/src/Compiler.hpp @@ -33,6 +33,7 @@ namespace grino std::shared_ptr> m_statics; std::vector m_scope; + std::vector m_decl_context; size_t get_local_address(); void enter_scope(bool reset=false); diff --git a/src/VM.cpp b/src/VM.cpp index 68fcaf8..4d432a1 100644 --- a/src/VM.cpp +++ b/src/VM.cpp @@ -127,7 +127,8 @@ namespace grino args.insert(std::begin(args), program().constant(pop())); } - size_t ref = program().constant(pop())->as_ref(); + auto ref_val = program().constant(pop()); + size_t ref = ref_val->as_ref(); auto fun = heap(ref)->as_function(); if (fun->is_native()) @@ -149,6 +150,8 @@ namespace grino set_local(i, args[i]); } + set_local(args.size(), ref_val); + m_pc = 0; } } break;