Browse Source

dynamic lookups

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

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

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.
*/ */

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

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);

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

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);

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

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;
} }

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

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;

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

} }
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;
} }

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

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

100
[100 50 30]
30
what's up
100

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

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);

Loading…
Cancel
Save