Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save andersonsp/34e0e6da5474ffa69acc62c9e88f5738 to your computer and use it in GitHub Desktop.
Save andersonsp/34e0e6da5474ffa69acc62c9e88f5738 to your computer and use it in GitHub Desktop.
int parse_expression(State *st, Lexer *lx, Scope *sc, Tree *ast, int lv) {
int root = ast_parse(st, lx, ast, 0, 1);
// int ty = ast_node_type(st, ast, sc, root);
Node *node = &ast->node[root];
if(node->tag == S_PRIM && node->val == S_EQUAL) { // assignment
node = &ast->node[node->child]; // left hand side
if(node->tag != S_ID) rg_error0(node->pos, "expected identifier"); // should evaluate to a var or selector
Object *obj = rg_sym_get(st, rg_sym_find(st, node->val, sc->tx));
if (!obj) rg_error(node->pos, "undefined symbol '%s'", spool_str(st, node->val));
if (obj->any.decl!=S_VAR) rg_error(node->pos, "assignment to non-varible '%s'", spool_str(st, node->val));
parse_assign(st, sc, obj, ast, node->next, lx->pos);
parse_sep(st, lx);
} else {
int ty = ast_node_type(st, ast, sc, root);
ast_compile(st, ast, sc, root, 0, sc->dx);
if (ty == st->void_ty) ast->px = 0; // clear only for empty expressions
}
return node->type;
}
void parse_local(State *st, Lexer *lx, Scope *sc, Tree *ast, int lv) {
uint32_t pos = lx->pos;
Object *res = parse_var(st, lx, sc, lv);
genS(st, OP_ASP, 1);
if (check_id(st, S_COLON)) {
res->any.kind = type_annotation(st, sc);
if(res->any.kind == st->void_ty) rg_error0(pos, "empty storage cannot be declared");
}
if (accept_id(st, S_EQUAL)) {
accept(st, '\n');
parse_assign(st, sc, res, ast, ast_parse(st, lx, ast, 0, 1), pos);
}
parse_sep(st, lx);
}
void parse_assign(State *st, Scope *sc, Object *obj, Tree *ast, int root, uint32_t pos) {
int ty = ast_node_type(st, ast, sc, root);
ast_compile(st, ast, sc, root, obj->var.addr, sc->dx);
if (ty == st->void_ty) rg_error0(pos, "empty expression cannot be used as RVal");
if (obj->any.kind == st->void_ty) obj->any.kind = ty; // if no type annotation given use the rval type
else expect_type(st, ty, obj->any.kind, pos);
if (ast->node[root].tag != S_PRIM) genS(st, OP_STO, obj->var.addr);
ast->px = 0; // clear tree
}
int ast_node_type(State *st, Tree *tr, Scope *sc, int i) {
Node *node = &tr->node[i];
if (node->tag == S_PRIM) {
uint64_t args = ast_node_args(st, tr, sc, node->child); // args digest
Object *obj = proc_find(st, sc, node->val, (uint32_t)(args>>32), (uint32_t)args, node->pos);
if(!obj) rg_error(node->pos, "%s(%d)@%u not found", spool_str(st, node->val), (uint32_t)(args>>32), (uint32_t)args);
node->type = obj->any.kind;
node->val = obj->any.decl == S_PRIM ? obj->prim.idx : -obj->proc.start;
} else if (node->tag == S_ID) {
Object *obj = rg_sym_get(st, rg_sym_find(st, node->val, sc->tx));
if(!obj || (obj->any.decl!=S_VAR && obj->any.decl!=S_CONST)) rg_error(node->pos, "not a lval: '%s'", spool_str(st, node->val));
node->type = obj->any.kind;
node->val = obj->any.decl == S_VAR ? obj->var.addr : obj->cst.val;
if(obj->any.decl == S_CONST) node->tag = S_INT;
} else if (node->tag == S_INT) {
node->type = st->int_ty;
} else {
rg_error(node->pos, "INVALID", 0);
}
return node->type;
}
void ast_compile(State *st, Tree *tr, Scope *sc, int root, int sto, int tmp) {
for (int i = root; i<0xffff; i = tr->node[i].next) {
Node *node = &tr->node[i];
if (node->tag == S_PRIM) {
// TODO: re-visit the addressing in this block
int addr = sto;
Object *ty = type_get(st, node->type, node->pos);
if(sto == 0 && ty->type.len > 0) {
genS(st, OP_ASP, ty->type.len);
addr = tmp++; // TODO: re-visit when sizes are bigger than 1
}
genX(st, OP_MST);
genS(st, OP_LOA, addr);
ast_compile(st, tr, sc, node->child, 0, tmp+CF_SIZE+1);
// END
if (node->val < 0) gen_jmp(st, OP_SR, -node->val);
else genU(st, OP_ESR, node->val);
} else if (node->tag == S_ID) {
// FIXME: take type and sizes into account here
tmp++;
genS(st, OP_LOD, node->val);
} else if (node->tag == S_INT) {
// FIXME: take type and sizes into account here
tmp++;
genS(st, OP_LIT, node->val);
} else {
rg_error(node->pos, "compilation invalid", 0); // should never happen, validator should catch it
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment