Browse Source

array literals

master
Martin Dørum 3 years ago
parent
commit
9d2d3c3a01
6 changed files with 73 additions and 8 deletions
  1. 2
    0
      include/lang2/bytecode.h
  2. 1
    0
      include/lang2/gen/gen.h
  3. 6
    0
      lib/gen/gen.c
  4. 34
    0
      lib/parse/parse.c
  5. 9
    2
      lib/vm/builtins.c
  6. 21
    6
      lib/vm/vm.c

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

@@ -123,6 +123,8 @@ enum l2_opcode {

/*
* Allocate an array.
* Pop <count>
* Pop count times
* Alloc array <var>
* Push <var>
*/

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

@@ -32,6 +32,7 @@ void l2_gen_number(struct l2_generator *gen, double num);
void l2_gen_string(struct l2_generator *gen, char **str);
void l2_gen_atom(struct l2_generator *gen, char **ident);
void l2_gen_function(struct l2_generator *gen, l2_word pos);
void l2_gen_array(struct l2_generator *gen, l2_word count);
void l2_gen_namespace(struct l2_generator *gen);
void l2_gen_namespace_set(struct l2_generator *gen, char **ident);
void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident);

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

@@ -122,6 +122,12 @@ void l2_gen_function(struct l2_generator *gen, l2_word pos) {
put(gen, L2_OP_ALLOC_FUNCTION);
}

void l2_gen_array(struct l2_generator *gen, l2_word count) {
put(gen, L2_OP_PUSH);
put(gen, count);
put(gen, L2_OP_ALLOC_ARRAY);
}

void l2_gen_namespace(struct l2_generator *gen) {
put(gen, L2_OP_ALLOC_NAMESPACE);
}

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

@@ -13,6 +13,9 @@ static int tok_is_end(struct l2_token *tok) {
static int parse_expression(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err);

static int parse_arg_level_expression(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err);

static int parse_object_literal(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) {
l2_trace_scope("object literal");
@@ -156,6 +159,8 @@ static int parse_object_or_function_literal(
if (tok->kind == L2_TOK_CLOSE_BRACE) {
l2_trace_scope("empty object literal");
l2_lexer_consume(lexer); // '}'

l2_gen_namespace(gen);
} else if (tok->kind == L2_TOK_IDENT && tok2->kind == L2_TOK_COLON) {
if (parse_object_literal(lexer, gen, err) < 0) {
return -1;
@@ -169,6 +174,31 @@ static int parse_object_or_function_literal(
return 0;
}

static int parse_array_literal(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) {
l2_trace_scope("array literal");
l2_lexer_consume(lexer); // '['
l2_lexer_skip_opt(lexer, L2_TOK_EOL);

int count = 0;
while (1) {
if (l2_lexer_peek(lexer, 1)->kind == L2_TOK_CLOSE_BRACKET) {
l2_lexer_consume(lexer); // ']'
break;
}

count += 1;
if (parse_arg_level_expression(lexer, gen, err) < 0) {
return -1;
}

l2_lexer_skip_opt(lexer, L2_TOK_EOL);
}

l2_gen_array(gen, count);
return 0;
}

static int parse_arg_level_expression_base(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) {
l2_trace_scope("arg level expression base");
@@ -224,6 +254,10 @@ static int parse_arg_level_expression_base(
if (parse_object_or_function_literal(lexer, gen, err) < 0) {
return -1;
}
} else if (tok->kind == L2_TOK_OPEN_BRACKET) {
if (parse_array_literal(lexer, gen, err) < 0) {
return -1;
}
} else {
l2_parse_err(err, tok, "Unexpected token %s",
l2_token_kind_name(tok->kind));

+ 9
- 2
lib/vm/builtins.c View File

@@ -17,14 +17,21 @@ static void print_val(struct l2_vm *vm, struct l2_vm_value *val) {
break;

case L2_VAL_TYPE_BUFFER:
fwrite(val->buffer->data, 1, val->buffer->len, stdout);
if (val->buffer != NULL) {
fwrite(val->buffer->data, 1, val->buffer->len, stdout);
}
break;

case L2_VAL_TYPE_ARRAY:
if (val->array == NULL) {
printf("[]");
break;
}

putchar('[');
for (size_t i = 0; i < val->array->len; ++i) {
if (i != 0) {
printf(", ");
putchar(' ');
}

print_val(vm, &vm->values[val->array->data[i]]);

+ 21
- 6
lib/vm/vm.c View File

@@ -363,11 +363,26 @@ void l2_vm_step(struct l2_vm *vm) {
break;

case L2_OP_ALLOC_ARRAY:
word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_ARRAY;
vm->values[word].array = NULL; // Will be allocated on first insert
vm->stack[vm->sptr] = word;
vm->sptr += 1;
{
l2_word count = vm->stack[--vm->sptr];
l2_word arr_id = alloc_val(vm);
struct l2_vm_value *arr = &vm->values[arr_id];
arr->flags = L2_VAL_TYPE_ARRAY;
if (count == 0) {
arr->array = NULL;
vm->stack[vm->sptr++] = arr_id;
break;
}

arr->array = malloc(sizeof(struct l2_vm_array) + count * sizeof(l2_word));
arr->array->len = count;
arr->array->size = count;
for (l2_word i = 0; i < count; ++i) {
arr->array->data[count - 1 - i] = vm->stack[--vm->sptr];
}

vm->stack[vm->sptr++] = arr_id;
}
break;

case L2_OP_ALLOC_NAMESPACE:
@@ -411,8 +426,8 @@ void l2_vm_step(struct l2_vm *vm) {
l2_word arr = vm->stack[--vm->sptr];
// TODO: Error if out of bounds or incorrect type
vm->stack[vm->sptr++] = vm->values[arr].array->data[key];
break;
}
break;

case L2_OP_HALT:
break;

Loading…
Cancel
Save