nooc

nooc programming language compiler
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit 9797b0e5dbf37f729865a3b22b10e0981fb5dcf3
parent fcebb5df2e5bfbc79e36561c7643ee70cd44b062
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Fri, 17 Dec 2021 13:11:15 -0600

refactor parameter parsing, parse function out nametypes

Code doesn't generate correctly, but they are parsed now

Diffstat:
Mmain.c | 14+++++++-------
Mnooc.h | 8++++++--
Mparse.c | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mtest/assign_int.pass.nooc | 2+-
Mtest/curly.fail.nooc | 2+-
Mtest/exit.pass.nooc | 2+-
Mtest/exitwrite.pass.nooc | 12++++++------
Mtest/mainexit.pass.nooc | 2+-
Mtest/mismatch_proc_type_expr_param_len.fail.nooc | 4++--
Mtest/proc.pass.nooc | 4++--
Mtest/proc_type_mismatch.fail.nooc | 2+-
Mtest/syscall_ret.pass.nooc | 2+-
Mtest/yes.pass.nooc | 2+-
Mtype.c | 3++-
14 files changed, 91 insertions(+), 54 deletions(-)

diff --git a/main.c b/main.c @@ -161,7 +161,7 @@ dumpval(struct expr *e) fprintf(stderr, "\"%.*s\"", (int)e->d.v.v.s.len, e->d.v.v.s.data); break; case C_PROC: - fprintf(stderr, "proc with %lu params", e->d.proc.params.len); + fprintf(stderr, "proc with %lu params", e->d.proc.in.len); break; } } @@ -247,11 +247,11 @@ typecheck(struct block items) if (expr->class != C_PROC) error(decl->start->line, decl->start->col, "expected proc expression for proc declaration"); - if (expr->d.proc.params.len != type->d.typelist.len) - error(decl->start->line, decl->start->col, "procedure expression takes %u parameters, but declaration has type which takes %u", expr->d.proc.params.len, type->d.typelist.len); + if (expr->d.proc.in.len != type->d.params.in.len) + error(decl->start->line, decl->start->col, "procedure expression takes %u parameters, but declaration has type which takes %u", expr->d.proc.in.len, type->d.params.in.len); - for (size_t j = 0; j < expr->d.proc.params.len; j++) { - if (expr->d.proc.params.data[j].type != type->d.typelist.data[j]) + for (size_t j = 0; j < expr->d.proc.in.len; j++) { + if (expr->d.proc.in.data[j].type != type->d.params.in.data[j]) error(decl->start->line, decl->start->col, "unexpected type for parameter %u in procedure declaration", j); } break; @@ -424,10 +424,10 @@ genexpr(char *buf, size_t idx, enum reg reg) return total; } - struct nametype *param = findparam(&curproc->params, expr->d.s); + struct nametype *param = findparam(&curproc->in, expr->d.s); if (param != NULL) { // calculate offset - int8_t offset = paramoffset(&curproc->params, param); + int8_t offset = paramoffset(&curproc->in, param); total += mov_disp8_m64_r64(buf ? buf + total : NULL, reg, offset, RBP); return total; } diff --git a/nooc.h b/nooc.h @@ -69,7 +69,10 @@ struct type { enum typeclass class; size_t size; union { - struct typelist typelist; + struct { + struct typelist in; + struct typelist out; + } params; } d; }; @@ -164,7 +167,8 @@ struct loop { }; struct proc { - struct nametypes params; + struct nametypes in; + struct nametypes out; struct block block; }; diff --git a/parse.c b/parse.c @@ -26,6 +26,7 @@ extern struct map *typesmap; struct token *tok; static void parsenametypes(struct nametypes *nametypes); +static size_t parsetype(); struct decl * finddecl(struct slice s) @@ -105,7 +106,7 @@ parsestring(struct expr *expr) static struct block parseblock(); static size_t -parseexpr() +parseexpr(struct block *block) { struct expr expr = { 0 }; switch (tok->type) { @@ -119,7 +120,7 @@ parseexpr() expr.start = tok; expr.kind = EXPR_COND; tok = tok->next; - expr.d.cond.cond = parseexpr(); + expr.d.cond.cond = parseexpr(block); expr.d.cond.bif = parseblock(); if (tok->type == TOK_ELSE) { tok = tok->next; @@ -128,7 +129,7 @@ parseexpr() break; case TOK_LPAREN: tok = tok->next; - size_t ret = parseexpr(); + size_t ret = parseexpr(block); expect(TOK_RPAREN); tok = tok->next; return ret; @@ -137,12 +138,34 @@ parseexpr() expr.start = tok; // a procedure definition if (slice_cmplit(&tok->slice, "proc") == 0) { + struct decl decl = { 0 }; + struct type *type; + int8_t offset = 0; expr.kind = EXPR_PROC; expr.class = C_PROC; tok = tok->next; + parsenametypes(&expr.d.proc.in); if (tok->type == TOK_LPAREN) - parsenametypes(&expr.d.proc.params); + parsenametypes(&expr.d.proc.out); expr.d.proc.block = parseblock(); + for (size_t i = 0; i < expr.d.proc.in.len; i++) { + decl.s = expr.d.proc.in.data[i].name; + decl.type = expr.d.proc.in.data[i].type; + type = &types.data[decl.type]; + offset += type->size; + decl.loc.off = offset; + array_add((&block->decls), decl); + } + + for (size_t i = 0; i < expr.d.proc.out.len; i++) { + decl.s = expr.d.proc.out.data[i].name; + decl.type = expr.d.proc.out.data[i].type; + decl.declared = true; + type = &types.data[decl.type]; + offset += type->size; + decl.loc.off = offset; + array_add((&block->decls), decl); + } // a function call } else if (tok->next && tok->next->type == TOK_LPAREN) { size_t pidx; @@ -151,7 +174,7 @@ parseexpr() expr.kind = EXPR_FCALL; while (tok->type != TOK_RPAREN) { - pidx = parseexpr(); + pidx = parseexpr(block); array_add((&expr.d.call.params), pidx); if (tok->type == TOK_RPAREN) break; @@ -188,8 +211,8 @@ parseexpr() binary_common: expr.start = tok; tok = tok->next; - expr.left = parseexpr(); - expr.right = parseexpr(); + expr.left = parseexpr(block); + expr.right = parseexpr(block); if (exprs.data[expr.left].class != exprs.data[expr.right].class) error(tok->line, tok->col, "expected binary expression operands to be of same class"); expr.class = exprs.data[expr.left].class; @@ -206,6 +229,29 @@ binary_common: return exprs.len - 1; } +void +parsetypelist(struct typelist *list) +{ + expect(TOK_LPAREN); + tok = tok->next; + size_t type; + + while (tok->type != TOK_RPAREN) { + expect(TOK_NAME); + + type = parsetype(); + array_add(list, type); + + if (tok->type == TOK_RPAREN) + break; + + expect(TOK_COMMA); + tok = tok->next; + } + + tok = tok->next; +} + static size_t parsetype() { @@ -214,26 +260,12 @@ parsetype() union mapval val; if (strncmp(tok->slice.data, "proc", 3) == 0) { - size_t subtype; type.class = TYPE_PROC; tok = tok->next; - if (tok->type == TOK_LPAREN) { - tok = tok->next; - while (tok->type != TOK_RPAREN) { - expect(TOK_NAME); - subtype = parsetype(); - array_add((&type.d.typelist), subtype); - - if (tok->type == TOK_RPAREN) - break; - - expect(TOK_COMMA); - tok = tok->next; - } - - tok = tok->next; - } + parsetypelist(&type.d.params.in); + if (tok->type == TOK_LPAREN) + parsetypelist(&type.d.params.out); } else { mapkey(&key, tok->slice.data, tok->slice.len); val = mapget(typesmap, &key); @@ -309,7 +341,7 @@ parseblock() error(tok->line, tok->col, "repeat declaration!"); } - decl.val = parseexpr(); + decl.val = parseexpr(&items); array_add((&items.decls), decl); item.idx = items.decls.len - 1; @@ -325,14 +357,14 @@ parseblock() assgn.s = tok->slice; tok = tok->next->next; - assgn.val = parseexpr(); + assgn.val = parseexpr(&items); array_add((&assgns), assgn); item.idx = assgns.len - 1; array_add((&items), item); } else { item.kind = ITEM_EXPR; - item.idx = parseexpr(); + item.idx = parseexpr(&items); array_add((&items), item); } } diff --git a/test/assign_int.pass.nooc b/test/assign_int.pass.nooc @@ -1,4 +1,4 @@ -let main proc = proc { +let main proc() = proc() { let i i64 = 10 i = 5 diff --git a/test/curly.fail.nooc b/test/curly.fail.nooc @@ -1,3 +1,3 @@ -let main proc = proc { +let main proc() = proc() { } }}}}}}}}}}}}}}}}}}}}}}}}}} diff --git a/test/exit.pass.nooc b/test/exit.pass.nooc @@ -3,6 +3,6 @@ let exit proc(i64) = proc(code i64) { return } -let main proc = proc { +let main proc() = proc() { exit(0) } diff --git a/test/exitwrite.pass.nooc b/test/exitwrite.pass.nooc @@ -1,6 +1,5 @@ -let write proc(i64, str, i64) = proc(fd i64, string str, len i64) { - let r1 i64 = 0 - syscall(1, fd, string, len) +let write proc(i64, str, i64) (i64) = proc(fd i64, string str, len i64) (out i64) { + out = syscall(1, fd, string, len) return } @@ -9,8 +8,9 @@ let exit proc(i64) = proc(code i64) { syscall(60, code) } -let main proc = proc { - write(1, "hello", 5) - write(1, " world\n", 7) +let main proc() = proc() { + let ret i64 = 0 + ret = write(1, "hello", 5) + ret = write(1, " world\n", 7) exit(0) } diff --git a/test/mainexit.pass.nooc b/test/mainexit.pass.nooc @@ -1,4 +1,4 @@ -let main proc = proc { +let main proc() = proc() { syscall(60, 0) } diff --git a/test/mismatch_proc_type_expr_param_len.fail.nooc b/test/mismatch_proc_type_expr_param_len.fail.nooc @@ -1,8 +1,8 @@ -let exit proc = proc(code i64) { +let exit proc() = proc(code i64) { syscall(60, code) return } -let main proc = proc { +let main proc() = proc() { exit(0) } diff --git a/test/proc.pass.nooc b/test/proc.pass.nooc @@ -1,9 +1,9 @@ -let hello proc = proc { +let hello proc() = proc() { syscall(1, 1, "hello\n", 6) return } -let main proc = proc { +let main proc() = proc() { hello() syscall(60, 0) } diff --git a/test/proc_type_mismatch.fail.nooc b/test/proc_type_mismatch.fail.nooc @@ -3,6 +3,6 @@ let exit proc(str) = proc(code i64) { return } -let main proc = proc { +let main proc() = proc() { exit(0) } diff --git a/test/syscall_ret.pass.nooc b/test/syscall_ret.pass.nooc @@ -1,4 +1,4 @@ -let main proc = proc { +let main proc() = proc() { let ret i64 = syscall(1, 1, "syscall_ret", 11) if > ret 0 { syscall(60, 0) diff --git a/test/yes.pass.nooc b/test/yes.pass.nooc @@ -1,4 +1,4 @@ -let main proc = proc { +let main proc() = proc() { let write i64 = 1 let stdout i64 = 1 let count i64 = 0 diff --git a/type.c b/type.c @@ -63,7 +63,8 @@ hashtype(struct type *type, uint8_t *out) blake3_update(&b3, &type->class, sizeof(enum typeclass)); switch (type->class) { case TYPE_PROC: - blake3_update(&b3, type->d.typelist.data, type->d.typelist.len * sizeof(*type->d.typelist.data)); + blake3_update(&b3, type->d.params.in.data, type->d.params.in.len * sizeof(*type->d.params.in.data)); + blake3_update(&b3, type->d.params.out.data, type->d.params.out.len * sizeof(*type->d.params.out.data)); default: }