Skip to content

Commit

Permalink
Add lambda support
Browse files Browse the repository at this point in the history
This was an experiment to discover how much work this would involve,
which turned out to be 'not much'. As it consumes quite a bit of ROM
space, and doesn't seem to fit early programming education
environments, I've left it on a separate branch.

Signed-off-by: Keith Packard <keithp@keithp.com>
  • Loading branch information
keith-packard committed Mar 23, 2021
1 parent 619867b commit 07919c7
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 15 deletions.
33 changes: 23 additions & 10 deletions snek-code.c
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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",


Expand Down Expand Up @@ -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:
Expand Down
5 changes: 5 additions & 0 deletions snek-exec.c
Expand Up @@ -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);
Expand Down
23 changes: 21 additions & 2 deletions snek-gram.ll
Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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
@{
Expand Down
1 change: 1 addition & 0 deletions snek-keyword.builtin
Expand Up @@ -31,3 +31,4 @@ and, AND
is, IS
in, IN
not, NOT
lambda, LAMBDA
2 changes: 1 addition & 1 deletion snek-parse.c
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions snek.h
Expand Up @@ -136,6 +136,7 @@ typedef enum {
#ifndef SNEK_NO_DICT
snek_op_dict,
#endif
snek_op_func,
snek_op_id,

snek_op_not,
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 07919c7

Please sign in to comment.