/* | /* | ||||
* Allocate an array. | * Allocate an array. | ||||
* Pop <count> | |||||
* Pop count times | |||||
* Alloc array <var> | * Alloc array <var> | ||||
* Push <var> | * Push <var> | ||||
*/ | */ |
void l2_gen_string(struct l2_generator *gen, char **str); | void l2_gen_string(struct l2_generator *gen, char **str); | ||||
void l2_gen_atom(struct l2_generator *gen, char **ident); | void l2_gen_atom(struct l2_generator *gen, char **ident); | ||||
void l2_gen_function(struct l2_generator *gen, l2_word pos); | 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(struct l2_generator *gen); | ||||
void l2_gen_namespace_set(struct l2_generator *gen, char **ident); | 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_namespace_lookup(struct l2_generator *gen, char **ident); |
put(gen, L2_OP_ALLOC_FUNCTION); | 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) { | void l2_gen_namespace(struct l2_generator *gen) { | ||||
put(gen, L2_OP_ALLOC_NAMESPACE); | put(gen, L2_OP_ALLOC_NAMESPACE); | ||||
} | } |
static int parse_expression( | static int parse_expression( | ||||
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err); | 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( | static int parse_object_literal( | ||||
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) { | struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) { | ||||
l2_trace_scope("object literal"); | l2_trace_scope("object literal"); | ||||
if (tok->kind == L2_TOK_CLOSE_BRACE) { | if (tok->kind == L2_TOK_CLOSE_BRACE) { | ||||
l2_trace_scope("empty object literal"); | l2_trace_scope("empty object literal"); | ||||
l2_lexer_consume(lexer); // '}' | l2_lexer_consume(lexer); // '}' | ||||
l2_gen_namespace(gen); | |||||
} else if (tok->kind == L2_TOK_IDENT && tok2->kind == L2_TOK_COLON) { | } else if (tok->kind == L2_TOK_IDENT && tok2->kind == L2_TOK_COLON) { | ||||
if (parse_object_literal(lexer, gen, err) < 0) { | if (parse_object_literal(lexer, gen, err) < 0) { | ||||
return -1; | return -1; | ||||
return 0; | 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( | static int parse_arg_level_expression_base( | ||||
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) { | struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) { | ||||
l2_trace_scope("arg level expression base"); | l2_trace_scope("arg level expression base"); | ||||
if (parse_object_or_function_literal(lexer, gen, err) < 0) { | if (parse_object_or_function_literal(lexer, gen, err) < 0) { | ||||
return -1; | return -1; | ||||
} | } | ||||
} else if (tok->kind == L2_TOK_OPEN_BRACKET) { | |||||
if (parse_array_literal(lexer, gen, err) < 0) { | |||||
return -1; | |||||
} | |||||
} else { | } else { | ||||
l2_parse_err(err, tok, "Unexpected token %s", | l2_parse_err(err, tok, "Unexpected token %s", | ||||
l2_token_kind_name(tok->kind)); | l2_token_kind_name(tok->kind)); |
break; | break; | ||||
case L2_VAL_TYPE_BUFFER: | 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; | break; | ||||
case L2_VAL_TYPE_ARRAY: | case L2_VAL_TYPE_ARRAY: | ||||
if (val->array == NULL) { | |||||
printf("[]"); | |||||
break; | |||||
} | |||||
putchar('['); | putchar('['); | ||||
for (size_t i = 0; i < val->array->len; ++i) { | for (size_t i = 0; i < val->array->len; ++i) { | ||||
if (i != 0) { | if (i != 0) { | ||||
printf(", "); | |||||
putchar(' '); | |||||
} | } | ||||
print_val(vm, &vm->values[val->array->data[i]]); | print_val(vm, &vm->values[val->array->data[i]]); |
break; | break; | ||||
case L2_OP_ALLOC_ARRAY: | 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; | break; | ||||
case L2_OP_ALLOC_NAMESPACE: | case L2_OP_ALLOC_NAMESPACE: | ||||
l2_word arr = vm->stack[--vm->sptr]; | l2_word arr = vm->stack[--vm->sptr]; | ||||
// TODO: Error if out of bounds or incorrect type | // TODO: Error if out of bounds or incorrect type | ||||
vm->stack[vm->sptr++] = vm->values[arr].array->data[key]; | vm->stack[vm->sptr++] = vm->values[arr].array->data[key]; | ||||
break; | |||||
} | } | ||||
break; | |||||
case L2_OP_HALT: | case L2_OP_HALT: | ||||
break; | break; |