L2_OP_NAMESPACE_LOOKUP, | L2_OP_NAMESPACE_LOOKUP, | ||||
/* | /* | ||||
* Look up a value from an array; direct_array_lookup <key> | |||||
* Pop <val> | |||||
* Look up a value from an array; array_lookup <key> | |||||
* Pop <arr> | * Pop <arr> | ||||
* Assign <val> to <arr[<key>]> | |||||
* Push <arr[<key>]> | |||||
*/ | */ | ||||
L2_OP_ARRAY_LOOKUP, | L2_OP_ARRAY_LOOKUP, | ||||
/* | /* | ||||
* Set a value in an array; direct_array_set <key> | |||||
* Set a value in an array; array_set <key> | |||||
* Read <val> | |||||
* Read <arr> | * Read <arr> | ||||
* Push <arr[<key>]> | |||||
* Assign <val> to <arr[<key>]> | |||||
*/ | */ | ||||
L2_OP_ARRAY_SET, | L2_OP_ARRAY_SET, | ||||
/* | |||||
* Look up a runtime value in an array or object. | |||||
* Pop <key> | |||||
* Pop <container> | |||||
* Push <container[<key>]> | |||||
*/ | |||||
L2_OP_DYNAMIC_LOOKUP, | |||||
/* | |||||
* Set a value in an array or object. | |||||
* Pop <val> | |||||
* Pop <key> | |||||
* Pop <arr> | |||||
* Assign <val> to <arr[<key>]> | |||||
*/ | |||||
L2_OP_DYNAMIC_SET, | |||||
/* | /* | ||||
* Halt execution. | * Halt execution. | ||||
*/ | */ |
void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident); | void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident); | ||||
void l2_gen_array_lookup(struct l2_generator *gen, int number); | void l2_gen_array_lookup(struct l2_generator *gen, int number); | ||||
void l2_gen_array_set(struct l2_generator *gen, int number); | void l2_gen_array_set(struct l2_generator *gen, int number); | ||||
void l2_gen_dynamic_lookup(struct l2_generator *gen); | |||||
void l2_gen_dynamic_set(struct l2_generator *gen); | |||||
void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident); | void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident); | ||||
void l2_gen_stack_frame_set(struct l2_generator *gen, char **ident); | void l2_gen_stack_frame_set(struct l2_generator *gen, char **ident); | ||||
void l2_gen_stack_frame_replace(struct l2_generator *gen, char **ident); | void l2_gen_stack_frame_replace(struct l2_generator *gen, char **ident); |
put(gen, number); | put(gen, number); | ||||
} | } | ||||
void l2_gen_dynamic_lookup(struct l2_generator *gen) { | |||||
put(gen, L2_OP_DYNAMIC_LOOKUP); | |||||
} | |||||
void l2_gen_dynamic_set(struct l2_generator *gen) { | |||||
put(gen, L2_OP_DYNAMIC_SET); | |||||
} | |||||
void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident) { | void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident) { | ||||
size_t atom_id = l2_strset_put(&gen->atomset, ident); | size_t atom_id = l2_strset_put(&gen->atomset, ident); | ||||
put(gen, L2_OP_STACK_FRAME_LOOKUP); | put(gen, L2_OP_STACK_FRAME_LOOKUP); |
l2_lexer_consume(lexer); // dot-number | l2_lexer_consume(lexer); // dot-number | ||||
l2_gen_array_lookup(gen, number); | l2_gen_array_lookup(gen, number); | ||||
} else if (tok->kind == L2_TOK_PERIOD && tok2->kind == L2_TOK_OPEN_PAREN) { | |||||
l2_trace_scope("dynamic lookup"); | |||||
l2_lexer_consume(lexer); // '.' | |||||
l2_lexer_consume(lexer); // '(' | |||||
if (parse_expression(lexer, gen, err) < 0) { | |||||
return -1; | |||||
} | |||||
if (l2_lexer_peek(lexer, 1)->kind != L2_TOK_CLOSE_PAREN) { | |||||
l2_parse_err(err, tok, "Expected '(', got %s", | |||||
l2_token_kind_name(tok->kind)); | |||||
return -1; | |||||
} | |||||
l2_lexer_consume(lexer); // ')' | |||||
if (l2_lexer_peek(lexer, 1)->kind == L2_TOK_EQUALS) { | |||||
l2_lexer_consume(lexer); // '=' | |||||
if (parse_expression(lexer, gen, err) < 0) { | |||||
return -1; | |||||
} | |||||
l2_gen_dynamic_set(gen); | |||||
} else { | |||||
l2_gen_dynamic_lookup(gen); | |||||
} | |||||
} else { | } else { | ||||
break; | break; | ||||
} | } |
printf("ARRAY_SET %08x\n", ops[(*ptr)++]); | printf("ARRAY_SET %08x\n", ops[(*ptr)++]); | ||||
return; | return; | ||||
case L2_OP_DYNAMIC_LOOKUP: | |||||
printf("DYNAMIC_LOOKUP\n"); | |||||
return; | |||||
case L2_OP_DYNAMIC_SET: | |||||
printf("DYNAMIC_SET\n"); | |||||
return; | |||||
case L2_OP_HALT: | case L2_OP_HALT: | ||||
printf("HALT\n"); | printf("HALT\n"); | ||||
return; | return; |
} | } | ||||
break; | break; | ||||
case L2_OP_DYNAMIC_LOOKUP: | |||||
{ | |||||
l2_word key_id = vm->stack[--vm->sptr]; | |||||
l2_word container_id = vm->stack[--vm->sptr]; | |||||
struct l2_vm_value *key = &vm->values[key_id]; | |||||
struct l2_vm_value *container = &vm->values[container_id]; | |||||
if ( | |||||
l2_vm_value_type(key) == L2_VAL_TYPE_REAL && | |||||
l2_vm_value_type(container) == L2_VAL_TYPE_ARRAY) { | |||||
// TODO: Error if out of bounds | |||||
vm->stack[vm->sptr++] = container->array->data[(size_t)key->real]; | |||||
} else if ( | |||||
l2_vm_value_type(key) == L2_VAL_TYPE_ATOM && | |||||
l2_vm_value_type(container) == L2_VAL_TYPE_NAMESPACE) { | |||||
// TODO: Error if out of bounds | |||||
vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, container, key->atom); | |||||
} else { | |||||
// TODO: error | |||||
} | |||||
} | |||||
break; | |||||
case L2_OP_DYNAMIC_SET: | |||||
{ | |||||
l2_word val = vm->stack[--vm->sptr]; | |||||
l2_word key_id = vm->stack[--vm->sptr]; | |||||
l2_word container_id = vm->stack[--vm->sptr]; | |||||
vm->stack[vm->sptr++] = val; | |||||
struct l2_vm_value *key = &vm->values[key_id]; | |||||
struct l2_vm_value *container = &vm->values[container_id]; | |||||
if ( | |||||
l2_vm_value_type(key) == L2_VAL_TYPE_REAL && | |||||
l2_vm_value_type(container) == L2_VAL_TYPE_ARRAY) { | |||||
// TODO: Error if out of bounds | |||||
container->array->data[(size_t)key->real] = val; | |||||
} else if ( | |||||
l2_vm_value_type(key) == L2_VAL_TYPE_ATOM && | |||||
l2_vm_value_type(container) == L2_VAL_TYPE_NAMESPACE) { | |||||
// TODO: Error if out of bounds | |||||
l2_vm_namespace_set(container, key->atom, val); | |||||
} else { | |||||
// TODO: error | |||||
} | |||||
} | |||||
break; | |||||
case L2_OP_HALT: | case L2_OP_HALT: | ||||
break; | break; | ||||
} | } |
idx := 0 | |||||
arr := [100 20 30] | |||||
print arr.(idx) | |||||
arr.(+ idx 1) = 50 | |||||
print arr | |||||
print [10 20 30].(+ 1 1) | |||||
obj := {} | |||||
obj.('hello) = "what's up" | |||||
print obj.hello | |||||
get-ident := {'foo} | |||||
obj.(get-ident()) = 100 | |||||
print obj.foo |
100 | |||||
[100 50 30] | |||||
30 | |||||
what's up | |||||
100 |
check("namespaces.l2"); | check("namespaces.l2"); | ||||
check("arrays.l2"); | check("arrays.l2"); | ||||
check("functions.l2"); | check("functions.l2"); | ||||
check("dynamic-lookups.l2"); | |||||
if (error_message != NULL) { | if (error_message != NULL) { | ||||
free(error_message); | free(error_message); |