Browse Source

parsing and vm stuff

master
Martin Dørum 3 years ago
parent
commit
abb1277e83
10 changed files with 60 additions and 28 deletions
  1. 5
    4
      cmd/main.c
  2. 1
    0
      include/lang2/gen/gen.h
  3. 1
    0
      include/lang2/parse/lex.h
  4. 2
    2
      include/lang2/vm/vm.h
  5. 8
    0
      lib/gen/gen.c
  6. 8
    0
      lib/parse/lex.c
  7. 9
    3
      lib/parse/parse.c
  8. 13
    11
      lib/vm/namespace.c
  9. 7
    1
      lib/vm/print.c
  10. 6
    7
      lib/vm/vm.c

+ 5
- 4
cmd/main.c View File

@@ -63,20 +63,21 @@ int main(int argc, char **argv) {

printf("Generated bytecode:\n");
l2_vm_print_bytecode((l2_word *)w.mem, w.len / sizeof(l2_word));
fprintf(stderr, "\n");
printf("\n");

struct l2_vm vm;
l2_vm_init(&vm, (void *)w.mem, w.len / sizeof(l2_word));

step_through(&vm);
l2_vm_run(&vm);
free(w.mem);

printf("State after executing:\n");
printf("State before GC:\n");
l2_vm_print_state(&vm);
printf("\n");

while (l2_vm_gc(&vm));

printf("State after GC:\n");
printf("\nState after GC:\n");
l2_vm_print_state(&vm);

l2_vm_free(&vm);

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

@@ -30,6 +30,7 @@ void l2_gen_ret(struct l2_generator *gen);
void l2_gen_assignment(struct l2_generator *gen, char **ident);
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_lookup(struct l2_generator *gen, char **ident);
void l2_gen_func_call(struct l2_generator *gen);

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

@@ -10,6 +10,7 @@ enum l2_token_kind {
L2_TOK_CLOSE_BRACE,
L2_TOK_OPEN_BRACKET,
L2_TOK_CLOSE_BRACKET,
L2_TOK_QUOT,
L2_TOK_COMMA,
L2_TOK_PERIOD,
L2_TOK_COLON_EQ,

+ 2
- 2
include/lang2/vm/vm.h View File

@@ -49,7 +49,7 @@ struct l2_vm_array {
};

struct l2_vm_namespace {
struct l2_vm_value *parent;
l2_word parent;
size_t len;
size_t size;
l2_word mask;
@@ -57,7 +57,7 @@ struct l2_vm_namespace {
};

void l2_vm_namespace_set(struct l2_vm_value *ns, l2_word key, l2_word val);
l2_word l2_vm_namespace_get(struct l2_vm_value *ns, l2_word key);
l2_word l2_vm_namespace_get(struct l2_vm *vm, struct l2_vm_value *ns, l2_word key);

struct l2_vm {
l2_word *ops;

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

@@ -63,6 +63,13 @@ void l2_gen_number(struct l2_generator *gen, double num) {
put(gen, L2_OP_ALLOC_REAL_64);
}

void l2_gen_atom(struct l2_generator *gen, char **str) {
size_t id = l2_strset_put(&gen->atomset, str);
put(gen, L2_OP_PUSH);
put(gen, id);
put(gen, L2_OP_ALLOC_INTEGER_32);
}

void l2_gen_string(struct l2_generator *gen, char **str) {
size_t id = l2_strset_get(&gen->stringset, *str);
if (id == 0) {
@@ -92,6 +99,7 @@ void l2_gen_string(struct l2_generator *gen, char **str) {
put(gen, len);
put(gen, L2_OP_ALLOC_BUFFER_STATIC);
} else {
free(*str);
struct l2_generator_string *s = &gen->strings[id - 1];
put(gen, L2_OP_PUSH_2);
put(gen, s->pos);

+ 8
- 0
lib/parse/lex.c View File

@@ -34,6 +34,8 @@ const char *l2_token_kind_name(enum l2_token_kind kind) {
return "open-bracket";
case L2_TOK_CLOSE_BRACKET:
return "close-bracket";
case L2_TOK_QUOT:
return "single-quote";
case L2_TOK_COMMA:
return "comma";
case L2_TOK_PERIOD:
@@ -199,6 +201,7 @@ static void read_ident(struct l2_lexer *lexer, struct l2_token *tok) {
case '}':
case '[':
case ']':
case '\'':
case ',':
case '.':
case ':':
@@ -276,6 +279,11 @@ static void read_tok(struct l2_lexer *lexer, struct l2_token *tok) {
} while (peek_ch(lexer) == ';');
break;

case '\'':
read_ch(lexer);
tok->kind = L2_TOK_QUOT;
break;

case ',':
read_ch(lexer);
tok->kind = L2_TOK_COMMA;

+ 9
- 3
lib/parse/parse.c View File

@@ -88,15 +88,15 @@ static int parse_function(
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);
struct l2_token *tok2 = l2_lexer_peek(lexer, 2);

if (tok->kind == L2_TOK_OPEN_PAREN) {
l2_lexer_consume(lexer); // (
tok = l2_lexer_peek(lexer, 1);
tok2 = l2_lexer_peek(lexer, 2);

// Special case: (foo) should be interpreted as a function call
if (
tok->kind == L2_TOK_IDENT &&
l2_lexer_peek(lexer, 2)->kind == L2_TOK_CLOSE_PAREN) {
if (tok->kind == L2_TOK_IDENT && tok2->kind == L2_TOK_CLOSE_PAREN) {
char *ident = l2_token_extract_str(tok);
l2_lexer_consume(lexer); // ident
l2_lexer_consume(lexer); // )
@@ -128,6 +128,12 @@ static int parse_sub_expression(
l2_lexer_consume(lexer); // ident
l2_gen_namespace_lookup(gen, &ident);
return 0;
} else if (tok->kind == L2_TOK_QUOT && tok2->kind == L2_TOK_IDENT) {
char *str = l2_token_extract_str(tok2);
l2_lexer_consume(lexer); // '
l2_lexer_consume(lexer); // ident
l2_gen_atom(gen, &str);
return 0;
} else if (tok->kind == L2_TOK_STRING) {
char *str = l2_token_extract_str(tok);
l2_lexer_consume(lexer); // string

+ 13
- 11
lib/vm/namespace.c View File

@@ -90,26 +90,28 @@ static l2_word get(struct l2_vm_namespace *ns, l2_word key) {
for (l2_word i = 0; ; ++i) {
l2_word hash = (key + i) & ns->mask;
l2_word k = ns->data[hash];
if (k == 0) {
if (ns->parent == NULL) {
return 0;
} else {
return get(ns->parent->data, key);
}
if (k == 0 || k == tombstone) {
return 0;
} else if (k == key) {
return ns->data[ns->size + hash];
}
}
}

void l2_vm_namespace_set(struct l2_vm_value *ns, l2_word key, l2_word val) {
void l2_vm_namespace_set(struct l2_vm_value *v, l2_word key, l2_word val) {
if (val == 0) {
del(ns->data, key);
del(v->data, key);
} else {
ns->data = set(ns->data, key, val);
v->data = set(v->data, key, val);
}
}

l2_word l2_vm_namespace_get(struct l2_vm_value *ns, l2_word key) {
return get(ns->data, key);
l2_word l2_vm_namespace_get(struct l2_vm *vm, struct l2_vm_value *v, l2_word key) {
struct l2_vm_namespace *ns = v->data;
l2_word ret = get(ns, key);
if (ret == 0 && ns != NULL && ns->parent != 0) {
return l2_vm_namespace_get(vm, &vm->values[ns->parent], key);
}

return ret;
}

+ 7
- 1
lib/vm/print.c View File

@@ -55,7 +55,13 @@ void l2_vm_print_val(struct l2_vm_value *val) {
}

struct l2_vm_namespace *ns = (struct l2_vm_namespace *)val->data;
printf("NAMESPACE, len %zu\n", ns->len);
printf("NAMESPACE, len %zu, parent %u\n", ns->len, ns->parent);
for (size_t i = 0; i < ns->size; ++i) {
l2_word key = ns->data[i];
l2_word val = ns->data[ns->size + i];
if (key == 0 || key == ~(l2_word)0) continue;
printf(" %u: %u\n", key, val);
}
}
break;


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

@@ -52,7 +52,7 @@ static void gc_mark(struct l2_vm *vm, l2_word id) {
} else if (typ == L2_VAL_TYPE_NAMESPACE) {
gc_mark_namespace(vm, val);
} else if (typ == L2_VAL_TYPE_FUNCTION) {
gc_mark_namespace(vm, &vm->values[val->func.namespace]);
gc_mark(vm, val->func.namespace);
}
}

@@ -82,8 +82,8 @@ static void gc_mark_namespace(struct l2_vm *vm, struct l2_vm_value *val) {
gc_mark(vm, ns->data[ns->size + i]);
}

if (ns->parent != NULL) {
gc_mark_namespace(vm, ns->parent);
if (ns->parent != 0) {
gc_mark(vm, ns->parent);
}
}

@@ -248,7 +248,7 @@ void l2_vm_step(struct l2_vm *vm) {
vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE;
vm->values[ns_id].data = calloc(1, sizeof(struct l2_vm_namespace));
struct l2_vm_namespace *ns = vm->values[ns_id].data;
ns->parent = &vm->values[func->func.namespace]; // TODO: This won't work if values is realloc'd
ns->parent = func->func.namespace;
vm->nstack[vm->nsptr++] = ns_id;

vm->iptr = func->func.pos;
@@ -265,7 +265,7 @@ void l2_vm_step(struct l2_vm *vm) {
{
l2_word key = vm->stack[vm->sptr - 1];
struct l2_vm_value *ns = &vm->values[vm->nstack[vm->nsptr - 1]];
vm->stack[vm->sptr - 1] = l2_vm_namespace_get(ns, key);
vm->stack[vm->sptr - 1] = l2_vm_namespace_get(vm, ns, key);
}
break;

@@ -294,8 +294,7 @@ void l2_vm_step(struct l2_vm *vm) {
word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_INTEGER;
vm->values[word].integer = vm->stack[--vm->sptr];
vm->stack[vm->sptr] = word;
vm->sptr += 1;
vm->stack[vm->sptr++] = word;
break;

case L2_OP_ALLOC_INTEGER_64:

Loading…
Cancel
Save