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



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


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


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


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


while (l2_vm_gc(&vm)); while (l2_vm_gc(&vm));


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


l2_vm_free(&vm); l2_vm_free(&vm);

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

void l2_gen_assignment(struct l2_generator *gen, char **ident); void l2_gen_assignment(struct l2_generator *gen, char **ident);
void l2_gen_number(struct l2_generator *gen, double num); void l2_gen_number(struct l2_generator *gen, double num);
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_function(struct l2_generator *gen, l2_word pos); 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_namespace_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);

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

L2_TOK_CLOSE_BRACE, L2_TOK_CLOSE_BRACE,
L2_TOK_OPEN_BRACKET, L2_TOK_OPEN_BRACKET,
L2_TOK_CLOSE_BRACKET, L2_TOK_CLOSE_BRACKET,
L2_TOK_QUOT,
L2_TOK_COMMA, L2_TOK_COMMA,
L2_TOK_PERIOD, L2_TOK_PERIOD,
L2_TOK_COLON_EQ, L2_TOK_COLON_EQ,

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

}; };


struct l2_vm_namespace { struct l2_vm_namespace {
struct l2_vm_value *parent;
l2_word parent;
size_t len; size_t len;
size_t size; size_t size;
l2_word mask; l2_word mask;
}; };


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 *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 { struct l2_vm {
l2_word *ops; l2_word *ops;

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

put(gen, L2_OP_ALLOC_REAL_64); 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) { void l2_gen_string(struct l2_generator *gen, char **str) {
size_t id = l2_strset_get(&gen->stringset, *str); size_t id = l2_strset_get(&gen->stringset, *str);
if (id == 0) { if (id == 0) {
put(gen, len); put(gen, len);
put(gen, L2_OP_ALLOC_BUFFER_STATIC); put(gen, L2_OP_ALLOC_BUFFER_STATIC);
} else { } else {
free(*str);
struct l2_generator_string *s = &gen->strings[id - 1]; struct l2_generator_string *s = &gen->strings[id - 1];
put(gen, L2_OP_PUSH_2); put(gen, L2_OP_PUSH_2);
put(gen, s->pos); put(gen, s->pos);

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

return "open-bracket"; return "open-bracket";
case L2_TOK_CLOSE_BRACKET: case L2_TOK_CLOSE_BRACKET:
return "close-bracket"; return "close-bracket";
case L2_TOK_QUOT:
return "single-quote";
case L2_TOK_COMMA: case L2_TOK_COMMA:
return "comma"; return "comma";
case L2_TOK_PERIOD: case L2_TOK_PERIOD:
case '}': case '}':
case '[': case '[':
case ']': case ']':
case '\'':
case ',': case ',':
case '.': case '.':
case ':': case ':':
} while (peek_ch(lexer) == ';'); } while (peek_ch(lexer) == ';');
break; break;


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

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

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

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);
struct l2_token *tok2 = l2_lexer_peek(lexer, 2);


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


// Special case: (foo) should be interpreted as a function call // 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); char *ident = l2_token_extract_str(tok);
l2_lexer_consume(lexer); // ident l2_lexer_consume(lexer); // ident
l2_lexer_consume(lexer); // ) l2_lexer_consume(lexer); // )
l2_lexer_consume(lexer); // ident l2_lexer_consume(lexer); // ident
l2_gen_namespace_lookup(gen, &ident); l2_gen_namespace_lookup(gen, &ident);
return 0; 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) { } else if (tok->kind == L2_TOK_STRING) {
char *str = l2_token_extract_str(tok); char *str = l2_token_extract_str(tok);
l2_lexer_consume(lexer); // string l2_lexer_consume(lexer); // string

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

for (l2_word i = 0; ; ++i) { for (l2_word i = 0; ; ++i) {
l2_word hash = (key + i) & ns->mask; l2_word hash = (key + i) & ns->mask;
l2_word k = ns->data[hash]; 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) { } else if (k == key) {
return ns->data[ns->size + hash]; 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) { if (val == 0) {
del(ns->data, key);
del(v->data, key);
} else { } 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

} }


struct l2_vm_namespace *ns = (struct l2_vm_namespace *)val->data; 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; break;



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

} else if (typ == L2_VAL_TYPE_NAMESPACE) { } else if (typ == L2_VAL_TYPE_NAMESPACE) {
gc_mark_namespace(vm, val); gc_mark_namespace(vm, val);
} else if (typ == L2_VAL_TYPE_FUNCTION) { } else if (typ == L2_VAL_TYPE_FUNCTION) {
gc_mark_namespace(vm, &vm->values[val->func.namespace]);
gc_mark(vm, val->func.namespace);
} }
} }


gc_mark(vm, ns->data[ns->size + i]); 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);
} }
} }


vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE; vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE;
vm->values[ns_id].data = calloc(1, sizeof(struct l2_vm_namespace)); vm->values[ns_id].data = calloc(1, sizeof(struct l2_vm_namespace));
struct l2_vm_namespace *ns = vm->values[ns_id].data; 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->nstack[vm->nsptr++] = ns_id;


vm->iptr = func->func.pos; vm->iptr = func->func.pos;
{ {
l2_word key = vm->stack[vm->sptr - 1]; l2_word key = vm->stack[vm->sptr - 1];
struct l2_vm_value *ns = &vm->values[vm->nstack[vm->nsptr - 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; break;


word = alloc_val(vm); word = alloc_val(vm);
vm->values[word].flags = L2_VAL_TYPE_INTEGER; vm->values[word].flags = L2_VAL_TYPE_INTEGER;
vm->values[word].integer = vm->stack[--vm->sptr]; vm->values[word].integer = vm->stack[--vm->sptr];
vm->stack[vm->sptr] = word;
vm->sptr += 1;
vm->stack[vm->sptr++] = word;
break; break;


case L2_OP_ALLOC_INTEGER_64: case L2_OP_ALLOC_INTEGER_64:

Loading…
Cancel
Save