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

*/ */
L2_OP_NAMESPACE_SET, 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. * Halt execution.
*/ */

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

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_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_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); void l2_gen_func_call(struct l2_generator *gen);


#endif #endif

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

L2_TOK_QUOT, L2_TOK_QUOT,
L2_TOK_COMMA, L2_TOK_COMMA,
L2_TOK_PERIOD, L2_TOK_PERIOD,
L2_TOK_COLON,
L2_TOK_COLON_EQ, L2_TOK_COLON_EQ,
L2_TOK_EOL, L2_TOK_EOL,
L2_TOK_EOF, L2_TOK_EOF,

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

put(gen, L2_OP_ALLOC_FUNCTION); 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) { 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); size_t atom_id = l2_strset_put(&gen->atomset, ident);
put(gen, L2_OP_PUSH); put(gen, L2_OP_PUSH);
put(gen, atom_id); put(gen, atom_id);

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

return "comma"; return "comma";
case L2_TOK_PERIOD: case L2_TOK_PERIOD:
return "period"; return "period";
case L2_TOK_COLON:
return "colon";
case L2_TOK_COLON_EQ: case L2_TOK_COLON_EQ:
return "colon-equals"; return "colon-equals";
case L2_TOK_EOL: case L2_TOK_EOL:


case ':': case ':':
read_ch(lexer); 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; break;



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

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_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( static int parse_function_impl(
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_lexer_consume(lexer); // {
l2_lexer_skip_opt(lexer, L2_TOK_EOL);
// { and EOL are already skipped


int first = 1; int first = 1;
while (1) { while (1) {
return 0; 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( static int parse_sub_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) {
struct l2_token *tok = l2_lexer_peek(lexer, 1); struct l2_token *tok = l2_lexer_peek(lexer, 1);
l2_lexer_consume(lexer); // ) l2_lexer_consume(lexer); // )


l2_gen_push(gen, 0); // Arg count 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); l2_gen_func_call(gen);
return 0; return 0;
} }
} else if (tok->kind == L2_TOK_IDENT) { } else if (tok->kind == L2_TOK_IDENT) {
char *ident = l2_token_extract_str(tok); char *ident = l2_token_extract_str(tok);
l2_lexer_consume(lexer); // ident l2_lexer_consume(lexer); // ident
l2_gen_namespace_lookup(gen, &ident);
l2_gen_stack_frame_lookup(gen, &ident);
return 0; return 0;
} else if (tok->kind == L2_TOK_QUOT && tok2->kind == L2_TOK_IDENT) { } else if (tok->kind == L2_TOK_QUOT && tok2->kind == L2_TOK_IDENT) {
char *str = l2_token_extract_str(tok2); char *str = l2_token_extract_str(tok2);
l2_gen_string(gen, &str); l2_gen_string(gen, &str);
return 0; return 0;
} else if (tok->kind == L2_TOK_OPEN_BRACE) { } 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", l2_parse_err(err, tok, "In expression: Unexpected token %s",
} }


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

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



case L2_OP_NAMESPACE_SET: 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); 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; break;



Loading…
Cancel
Save