Compare commits

..

3 Commits

Author SHA1 Message Date
bog f7b470c0b1 ADD: set! function. 2023-09-12 12:20:29 +02:00
bog 29fded5cb9 ADD: nested function.
ADD: function can returns other function or lambda.
2023-09-12 11:16:05 +02:00
bog ea5991732c ADD: recursive functions. 2023-09-12 11:05:34 +02:00
6 changed files with 84 additions and 2 deletions

View File

@ -16,3 +16,37 @@
;; inner variable ;; inner variable
($ (d x) ($ y 3) (+ x y)) ($ (d x) ($ y 3) (+ x y))
(assert-eq? 7 (d 4)) (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))
;; inner functions
($ (f n)
($ (inner n) (+ n 1))
(inner (inner n)))
(assert-eq? 3 (f 1))
;; return function
($ (g)
($ (inner n) (* 7 n))
inner)
(assert-eq? 42 ( (g) 6 ))
;; return lambda
($ (h)
(-> (n)
(* 3 (- n 2))))
(assert-eq? 15 ( (h) 7 ))

10
examples/set.gri Normal file
View File

@ -0,0 +1,10 @@
($ a 1)
(set! a 2)
(assert-eq? 2 a )
($ (b x) (+ x 1))
($ (c x) (* x 2))
($ d b)
(assert-eq? 3 (d 2))
(set! d c)
(assert-eq? 4 (d 2))

View File

@ -1,6 +1,7 @@
#include "../src/Loader.hpp" #include "../src/Loader.hpp"
#include "src/Logger.hpp" #include "src/Logger.hpp"
#include "src/Value.hpp" #include "src/Value.hpp"
#include "src/opcodes.hpp"
GRINO_ERROR(assertion_error); GRINO_ERROR(assertion_error);
@ -345,6 +346,24 @@ extern "C" void lib(grino::Loader& loader)
return grino::Value::make_nil(args.back()->loc()); return grino::Value::make_nil(args.back()->loc());
}); });
loader.add_static("set!", [](auto& compiler,
auto node,
auto& program,
auto& sym){
std::string ident = node->child(1).lock()->repr();
auto expr = node->child(2).lock();
auto entry = sym.find(ident, compiler.scope());
if (entry)
{
compiler.compile(expr, program, sym);
program.push_instr(grino::OPCODE_STORE_LOCAL, entry->addr);
}
program.push_value(grino::Value::make_nil(node->loc()));
});
loader.add_native("eq?", [](auto args){ loader.add_native("eq?", [](auto args){
auto lhs = args.front(); auto lhs = args.front();

View File

@ -94,6 +94,16 @@ namespace grino
m_scope.size()); 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<Program>(); auto prog = std::make_shared<Program>();
auto body = node->child(1).lock(); auto body = node->child(1).lock();
compile(body, *prog, sym); compile(body, *prog, sym);
@ -128,9 +138,12 @@ namespace grino
auto expr = node->child(1).lock(); auto expr = node->child(1).lock();
size_t address = get_local_address(); size_t address = get_local_address();
m_decl_context.push_back(ident);
compile(expr, program, sym); compile(expr, program, sym);
m_decl_context.pop_back();
sym.declare(node->loc(), ident, address, m_scope.size()); sym.declare(node->loc(), ident, address, m_scope.size());
program.push_instr(OPCODE_STORE_LOCAL, address); program.push_instr(OPCODE_STORE_LOCAL, address);
} break; } break;

View File

@ -20,6 +20,8 @@ namespace grino
explicit Compiler(Logger& logger); explicit Compiler(Logger& logger);
virtual ~Compiler(); virtual ~Compiler();
size_t scope() const { return m_scope.size(); }
void compile(std::shared_ptr<Node> node, void compile(std::shared_ptr<Node> node,
Program& program, Program& program,
SymTable& sym); SymTable& sym);
@ -33,6 +35,7 @@ namespace grino
std::shared_ptr<StaticFunction>> m_statics; std::shared_ptr<StaticFunction>> m_statics;
std::vector<size_t> m_scope; std::vector<size_t> m_scope;
std::vector<std::string> m_decl_context;
size_t get_local_address(); size_t get_local_address();
void enter_scope(bool reset=false); void enter_scope(bool reset=false);

View File

@ -127,7 +127,8 @@ namespace grino
args.insert(std::begin(args), program().constant(pop())); 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(); auto fun = heap(ref)->as_function();
if (fun->is_native()) if (fun->is_native())
@ -149,6 +150,8 @@ namespace grino
set_local(i, args[i]); set_local(i, args[i]);
} }
set_local(args.size(), ref_val);
m_pc = 0; m_pc = 0;
} }
} break; } break;