Created
July 25, 2019 16:23
-
-
Save andersonsp/34e0e6da5474ffa69acc62c9e88f5738 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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