diff --git a/examples/fun.gri b/examples/fun.gri index 088a5a2..9c73d6e 100644 --- a/examples/fun.gri +++ b/examples/fun.gri @@ -11,4 +11,8 @@ ;; syntaxic sugar for function declaration ($ (c n) (* 2 n)) -(assert-eq? 18 (c 9)) \ No newline at end of file +(assert-eq? 18 (c 9)) + +;; inner variable +($ (d x) ($ y 3) (+ x y)) +(assert-eq? 7 (d 4)) \ No newline at end of file diff --git a/examples/if.gri b/examples/if.gri new file mode 100644 index 0000000..17cdeec --- /dev/null +++ b/examples/if.gri @@ -0,0 +1,11 @@ +(assert-eq? 7 (if true 7 9)) +(assert-eq? 9 (if false 7 9)) + +($ (max x y) + (if (> x y) + x + y +)) + +(assert-eq? 32 (max 3 32)) +(assert-eq? 329 (max 329 32)) diff --git a/lib/core.cpp b/lib/core.cpp index 3e756d1..fe103ef 100644 --- a/lib/core.cpp +++ b/lib/core.cpp @@ -4,6 +4,28 @@ GRINO_ERROR(assertion_error); +extern "C" void lib_flow_control(grino::Loader& loader) +{ + loader.add_static("if", [](auto& compiler, auto node, auto& prog, auto& sym) { + auto cond_node = node->child(1).lock(); + auto then_node = node->child(2).lock(); + auto else_node = node->child(3).lock(); + + compiler.compile(cond_node, prog, sym); + size_t brf = prog.size(); + prog.push_instr(grino::OPCODE_BRF, 0); + + compiler.compile(then_node, prog, sym); + size_t br = prog.size(); + prog.push_instr(grino::OPCODE_BR, 0); + + prog.set_param(brf, prog.size()); + compiler.compile(else_node, prog, sym); + + prog.set_param(br, prog.size()); + }); +} + extern "C" void lib_int(grino::Loader& loader) { loader.add_native("+", [](auto args){ @@ -306,6 +328,7 @@ extern "C" void lib(grino::Loader& loader) lib_int(loader); lib_cmp(loader); lib_bool(loader); + lib_flow_control(loader); loader.add_native("dump", [](auto args){ std::string sep; diff --git a/src/Compiler.cpp b/src/Compiler.cpp index 22145b6..07cadba 100644 --- a/src/Compiler.cpp +++ b/src/Compiler.cpp @@ -30,7 +30,6 @@ namespace grino } } break; - case NODE_BLOCK: case NODE_BODY: { for (size_t i=0; isize(); i++) { @@ -41,6 +40,26 @@ namespace grino program.push_instr(OPCODE_POP); } } + } break; + + case NODE_BLOCK: { + enter_scope(); + + for (size_t i=0; isize(); i++) + { + compile(node->child(i).lock(), program, sym); + + if (i < node->size() - 1) + { + program.push_instr(OPCODE_POP); + } + } + std::cout << "-------------------------" << std::endl; + std::cout << sym.string() << std::endl; + + leave_scope(); + sym.purge(m_scope.size()); + } break; case NODE_FUNCALL: {