Browse Source

object literals

master
Martin Dørum 3 years ago
parent
commit
a11c4a0351
7 changed files with 127 additions and 21 deletions
  1. 8
    0
      include/lang2/bytecode.h
  2. 3
    0
      include/lang2/gen/gen.h
  3. 1
    0
      include/lang2/parse/lex.h
  4. 18
    0
      lib/gen/gen.c
  5. 11
    11
      lib/parse/lex.c
  6. 75
    6
      lib/parse/parse.c
  7. 11
    4
      lib/vm/vm.c

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

@@ -169,6 +169,14 @@ enum l2_opcode {
*/
L2_OP_NAMESPACE_SET,

/*
* Set a namespace's name to a value.
* Pop <key>
* Pop <ns>
* Push <ns[<key>]>
*/
L2_OP_NAMESPACE_LOOKUP,

/*
* Halt execution.
*/

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

@@ -32,7 +32,10 @@ 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_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);
void l2_gen_stack_frame_lookup(struct l2_generator *gen, char **ident);
void l2_gen_func_call(struct l2_generator *gen);

#endif

+ 1
- 0
include/lang2/parse/lex.h View File

@@ -13,6 +13,7 @@ enum l2_token_kind {
L2_TOK_QUOT,
L2_TOK_COMMA,
L2_TOK_PERIOD,
L2_TOK_COLON,
L2_TOK_COLON_EQ,
L2_TOK_EOL,
L2_TOK_EOF,

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

@@ -114,7 +114,25 @@ void l2_gen_function(struct l2_generator *gen, l2_word pos) {
put(gen, L2_OP_ALLOC_FUNCTION);
}

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

void l2_gen_namespace_set(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_PUSH);
put(gen, atom_id);
put(gen, L2_OP_NAMESPACE_SET);
}

void l2_gen_namespace_lookup(struct l2_generator *gen, char **ident) {
size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_PUSH);
put(gen, atom_id);
put(gen, L2_OP_NAMESPACE_LOOKUP);
}

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_PUSH);
put(gen, atom_id);

+ 11
- 11
lib/parse/lex.c View File

@@ -40,6 +40,8 @@ const char *l2_token_kind_name(enum l2_token_kind kind) {
return "comma";
case L2_TOK_PERIOD:
return "period";
case L2_TOK_COLON:
return "colon";
case L2_TOK_COLON_EQ:
return "colon-equals";
case L2_TOK_EOL:
@@ -296,18 +298,16 @@ static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) {

case ':':
read_ch(lexer);
{
ch = read_ch(lexer);
switch (ch) {
case '=':
tok->kind = L2_TOK_COLON_EQ;
break;
ch = peek_ch(lexer);
switch (ch) {
case '=':
read_ch(lexer);
tok->kind = L2_TOK_COLON_EQ;
break;

default:
tok->kind = L2_TOK_ERROR;
tok->v.str = "Unexpected character";
break;
}
default:
tok->kind = L2_TOK_COLON;
break;
}
break;


+ 75
- 6
lib/parse/parse.c View File

@@ -12,10 +12,60 @@ static int is_end_tok(struct l2_token *tok) {
static int parse_expression(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err);

static int parse_object(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) {
// { and EOL are already skipped

l2_gen_namespace(gen);
while (1) {
struct l2_token *tok = l2_lexer_peek(lexer, 1);
if (tok->kind == L2_TOK_EOF) {
l2_parse_err(err, tok, "In object literal: Unexpected EOF");
return -1;
} else if (tok->kind == L2_TOK_CLOSE_BRACE) {
l2_lexer_consume(lexer); // }
break;
}

if (tok->kind != L2_TOK_IDENT) {
l2_parse_err(err, tok, "In object literal: Expected identifier, got %s\n",
l2_token_kind_name(tok->kind));
}

char *key = l2_token_extract_str(tok);
l2_lexer_consume(lexer); // ident

tok = l2_lexer_peek(lexer, 1);
if (tok->kind != L2_TOK_COLON) {
l2_parse_err(err, tok, "In object literal: Expected colon, got %s\n",
l2_token_kind_name(tok->kind));
}

l2_lexer_consume(lexer); // :

if (parse_expression(lexer, gen, err) < 0) {
return -1;
}

l2_gen_namespace_set(gen, &key);
l2_gen_pop(gen);

tok = l2_lexer_peek(lexer, 1);
if (tok->kind != L2_TOK_EOL) {
l2_parse_err(err, tok, "In object literal: Expected EOL, got %s\n",
l2_token_kind_name(tok->kind));
return -1;
}

l2_lexer_consume(lexer); // EOL
}

return 0;
}

static int parse_function_impl(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) {
l2_lexer_consume(lexer); // {
l2_lexer_skip_opt(lexer, L2_TOK_EOL);
// { and EOL are already skipped

int first = 1;
while (1) {
@@ -90,6 +140,25 @@ static int parse_function(
return 0;
}

static int parse_function_or_object(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) {
l2_lexer_consume(lexer); // {
l2_lexer_skip_opt(lexer, L2_TOK_EOL);

struct l2_token *tok = l2_lexer_peek(lexer, 1);
struct l2_token *tok2 = l2_lexer_peek(lexer, 2);

if (tok->kind == L2_TOK_CLOSE_BRACE) {
l2_lexer_consume(lexer); // }
l2_gen_namespace(gen);
return 0;
} else if (tok->kind == L2_TOK_IDENT && tok2->kind == L2_TOK_COLON) {
return parse_object(lexer, gen, err);
} else {
return parse_function(lexer, gen, err);
}
}

static int parse_sub_expression(
struct l2_lexer *lexer, struct l2_generator *gen, struct l2_parse_error *err) {
struct l2_token *tok = l2_lexer_peek(lexer, 1);
@@ -107,7 +176,7 @@ static int parse_sub_expression(
l2_lexer_consume(lexer); // )

l2_gen_push(gen, 0); // Arg count
l2_gen_namespace_lookup(gen, &ident);
l2_gen_stack_frame_lookup(gen, &ident);
l2_gen_func_call(gen);
return 0;
}
@@ -131,7 +200,7 @@ static int parse_sub_expression(
} else if (tok->kind == L2_TOK_IDENT) {
char *ident = l2_token_extract_str(tok);
l2_lexer_consume(lexer); // ident
l2_gen_namespace_lookup(gen, &ident);
l2_gen_stack_frame_lookup(gen, &ident);
return 0;
} else if (tok->kind == L2_TOK_QUOT && tok2->kind == L2_TOK_IDENT) {
char *str = l2_token_extract_str(tok2);
@@ -145,7 +214,7 @@ static int parse_sub_expression(
l2_gen_string(gen, &str);
return 0;
} else if (tok->kind == L2_TOK_OPEN_BRACE) {
return parse_function(lexer, gen, err);
return parse_function_or_object(lexer, gen, err);
}

l2_parse_err(err, tok, "In expression: Unexpected token %s",
@@ -183,7 +252,7 @@ static int parse_expression(
}

l2_gen_push(gen, count);
l2_gen_namespace_lookup(gen, &ident);
l2_gen_stack_frame_lookup(gen, &ident);
l2_gen_func_call(gen);
return 0;
}

+ 11
- 4
lib/vm/vm.c View File

@@ -380,11 +380,18 @@ void l2_vm_step(struct l2_vm *vm) {

case L2_OP_NAMESPACE_SET:
{
l2_word key = vm->stack[vm->sptr - 1];
l2_word val = vm->stack[vm->sptr - 2];
l2_word ns = vm->stack[vm->sptr - 3];
l2_word key = vm->stack[--vm->sptr];
l2_word val = vm->stack[vm->sptr - 1];
l2_word ns = vm->stack[vm->sptr - 2];
l2_vm_namespace_set(&vm->values[ns], key, val);
vm->sptr -= 1;
}
break;

case L2_OP_NAMESPACE_LOOKUP:
{
l2_word key = vm->stack[--vm->sptr];
l2_word ns = vm->stack[--vm->sptr];
vm->stack[vm->sptr++] = l2_vm_namespace_get(vm, &vm->values[ns], key);
}
break;


Loading…
Cancel
Save