diff --git a/snek-code.c b/snek-code.c index e662ded..991b546 100644 --- a/snek-code.c +++ b/snek-code.c @@ -45,6 +45,7 @@ snek_op_operand_size(snek_op_t op) case snek_op_string: case snek_op_list: case snek_op_tuple: + case snek_op_func: return sizeof (snek_offset_t); case snek_op_id: case snek_op_global: @@ -265,31 +266,34 @@ snek_code_patch_forward(snek_offset_t start, snek_offset_t stop, snek_forward_t * Reset compiler state to mark the compiler buffer as empty */ void -snek_code_reset(void) +snek_code_reset(snek_offset_t size) { - snek_compile_size = 0; - compile_alloc = 0; - snek_compile = NULL; + snek_compile_size = size; + if (!size) { + compile_alloc = 0; + snek_compile = NULL; + } } /* * Construct a code object from the current bytecode buffer */ snek_code_t * -snek_code_finish(void) +snek_code_finish(snek_offset_t start) { - if (snek_compile_size == 0) + snek_offset_t size = snek_compile_size - start; + if (size == 0) return NULL; - snek_code_t *code = snek_alloc(sizeof (snek_code_t) + snek_compile_size); + snek_code_t *code = snek_alloc(sizeof (snek_code_t) + size); if (code) { - memcpy(&code->code, snek_compile, snek_compile_size); - code->size = snek_compile_size; + memcpy(&code->code, snek_compile + start, size); + code->size = size; #ifdef DEBUG_COMPILE snek_code_dump(code); #endif } - snek_code_reset(); + snek_code_reset(start); return code; } @@ -336,6 +340,10 @@ code_mark(uint8_t *code, snek_offset_t size) memcpy(&o, &code[ip], sizeof (snek_offset_t)); snek_mark_offset(snek_mems(snek_string), o); break; + case snek_op_func: + memcpy(&o, &code[ip], sizeof (snek_offset_t)); + snek_mark_offset(snek_mems(snek_func), o); + break; default: break; } @@ -446,6 +454,7 @@ static const char * const snek_op_names[] = { [snek_op_string] = "string", [snek_op_list] = "list", [snek_op_tuple] = "tuple", + [snek_op_func] = "func", [snek_op_id] = "id", @@ -530,6 +539,10 @@ snek_code_dump_instruction(snek_code_t *code, snek_offset_t ip) memcpy(&o, &code->code[ip], sizeof(snek_offset_t)); dbg("%u\n", o); break; + case snek_op_func: + memcpy(&o, &code->code[ip], sizeof(snek_offset_t)); + dbg("%u\n", o); + break; case snek_op_id: case snek_op_global: case snek_op_assign: diff --git a/snek-exec.c b/snek-exec.c index 5352d4d..f234763 100644 --- a/snek-exec.c +++ b/snek-exec.c @@ -844,6 +844,11 @@ snek_exec(snek_code_t *code_in) ip += sizeof (snek_offset_t); snek_a = snek_list_imm(o, op - snek_op_list); break; + case snek_op_func: + memcpy(&o, &snek_code->code[ip], sizeof(snek_offset_t)); + ip += sizeof (snek_offset_t); + snek_a = snek_func_to_poly(snek_pool_addr(o)); + break; case snek_op_id: memcpy(&id, &snek_code->code[ip], sizeof(snek_id_t)); ip += sizeof (snek_id_t); diff --git a/snek-gram.ll b/snek-gram.ll index ecb95b9..bb7663b 100644 --- a/snek-gram.ll +++ b/snek-gram.ll @@ -16,7 +16,7 @@ start : command @{ snek_parse_middle = false; }@ start ; command : @{ snek_print_val = snek_interactive; }@ stat @{ - snek_code_t *code = snek_code_finish(); + snek_code_t *code = snek_code_finish(0); SNEK_CODE_HOOK_START snek_poly_t p = snek_exec(code); SNEK_CODE_HOOK_STOP @@ -42,7 +42,7 @@ command : @{ snek_print_val = snek_interactive; }@ stat snek_code_delete_prev(); else snek_code_add_op(snek_op_null); - snek_code_t *code = snek_code_finish(); + snek_code_t *code = snek_code_finish(0); if (!code) break; snek_func_t *func = snek_func_alloc(code); @@ -298,6 +298,25 @@ suite : simple-stat }@ ; expr : expr-and expr-or-p + | LAMBDA + @{ + value_push_offset(snek_compile_size); + snek_parse_nformal = 0; + snek_parse_nnamed = 0; + }@ + opt-formals + COLON + expr + @{ + snek_offset_t start = value_pop().offset; + snek_code_t *code = snek_code_finish(start); + if (!code) + break; + snek_func_t *func = snek_func_alloc(code); + if (!func) + break; + snek_code_add_op_offset(snek_op_func, snek_pool_offset(func)); + }@ ; expr-or-p : OR @{ diff --git a/snek-keyword.builtin b/snek-keyword.builtin index 2370dc5..aede0ee 100644 --- a/snek-keyword.builtin +++ b/snek-keyword.builtin @@ -31,3 +31,4 @@ and, AND is, IS in, IN not, NOT +lambda, LAMBDA diff --git a/snek-parse.c b/snek-parse.c index fcd7a1f..55b5a17 100644 --- a/snek-parse.c +++ b/snek-parse.c @@ -228,7 +228,7 @@ snek_parse(void) for_depth = 0; /* Reset codegen state */ - snek_code_reset(); + snek_code_reset(0); /* Reset error state */ snek_abort = false; diff --git a/snek.h b/snek.h index 1ed7b53..aac902a 100644 --- a/snek.h +++ b/snek.h @@ -136,6 +136,7 @@ typedef enum { #ifndef SNEK_NO_DICT snek_op_dict, #endif + snek_op_func, snek_op_id, snek_op_not, @@ -488,10 +489,10 @@ snek_code_patch_branch(snek_offset_t branch, snek_offset_t target) } void -snek_code_reset(void); +snek_code_reset(snek_offset_t size); snek_code_t * -snek_code_finish(void); +snek_code_finish(snek_offset_t start); snek_offset_t snek_code_line(snek_code_t *code);