Browse Source

dynamic lookups

master
Martin Dørum 3 years ago
parent
commit
1c184b3111

+ 22
- 5
include/lang2/bytecode.h View File

@@ -149,20 +149,37 @@ enum l2_opcode {
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>
* Assign <val> to <arr[<key>]>
* Push <arr[<key>]>
*/
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>
* Push <arr[<key>]>
* Assign <val> to <arr[<key>]>
*/
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.
*/

+ 2
- 0
include/lang2/gen/gen.h View File

@@ -38,6 +38,8 @@ void l2_gen_namespace_set(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_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_set(struct l2_generator *gen, char **ident);
void l2_gen_stack_frame_replace(struct l2_generator *gen, char **ident);

+ 8
- 0
lib/gen/gen.c View File

@@ -142,6 +142,14 @@ void l2_gen_array_set(struct l2_generator *gen, int 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) {
size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_STACK_FRAME_LOOKUP);

+ 26
- 0
lib/parse/parse.c View File

@@ -327,6 +327,32 @@ static int parse_arg_level_expression(
l2_lexer_consume(lexer); // dot-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 {
break;
}

+ 8
- 0
lib/vm/print.c View File

@@ -211,6 +211,14 @@ void l2_vm_print_op(l2_word *ops, size_t opcount, size_t *ptr) {
printf("ARRAY_SET %08x\n", ops[(*ptr)++]);
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:
printf("HALT\n");
return;

+ 49
- 0
lib/vm/vm.c View File

@@ -451,6 +451,55 @@ void l2_vm_step(struct l2_vm *vm) {
}
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:
break;
}

+ 16
- 0
test/examples/dynamic-lookups.l2 View File

@@ -0,0 +1,16 @@
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

+ 5
- 0
test/examples/dynamic-lookups.l2.expected View File

@@ -0,0 +1,5 @@
100
[100 50 30]
30
what's up
100

+ 1
- 0
test/src/examples.t.c View File

@@ -132,6 +132,7 @@ describe(exaples) {
check("namespaces.l2");
check("arrays.l2");
check("functions.l2");
check("dynamic-lookups.l2");

if (error_message != NULL) {
free(error_message);

Loading…
Cancel
Save