nooc

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

commit 851ae9124493230ca2ca1f9ab767747701d615d2
parent 45d8d43dbefc75ce4b5d979a190071ea78527924
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Fri, 28 Jan 2022 23:33:06 -0600

more cleanup

hide blockstack internals, remove lex.h and parse.h, move finddecl to
blockstack, improve names, remove unused headers

Diffstat:
Mblockstack.c | 17++++++++++++++++-
Mblockstack.h | 4+---
Mir.c | 2--
Mlex.c | 10++--------
Dlex.h | 1-
Mmain.c | 6+++---
Mparse.c | 76+++++++++++++++++++++++++++++-----------------------------------------------
Dparse.h | 3---
Mtype.c | 36+++++++++++++++++-------------------
Mutil.c | 2+-
Mx64.c | 1-
11 files changed, 69 insertions(+), 89 deletions(-)

diff --git a/blockstack.c b/blockstack.c @@ -9,6 +9,21 @@ const struct block *blockstack[BLOCKSTACKSIZE]; size_t blocki; +struct decl * +finddecl(const struct slice s) +{ + for (int j = blocki - 1; j >= 0; j--) { + for (int i = 0; i < blockstack[j]->decls.len; i++) { + struct decl *decl = &blockstack[j]->decls.data[i]; + if (slice_cmp(&s, &decl->s) == 0) { + return decl; + } + } + } + + return NULL; +} + void blockpush(const struct block *const block) { @@ -33,7 +48,7 @@ const struct block *const blockpeek() { if (blocki == 0) - die("blockpop: cannot peek empty stack!"); + return NULL; return blockstack[blocki - 1]; } diff --git a/blockstack.h b/blockstack.h @@ -1,6 +1,4 @@ void blockpush(const struct block *const block); struct block *blockpop(); struct block *blockpeek(); - -extern const struct block *blockstack[BLOCKSTACKSIZE]; -extern size_t blocki; +struct decl *finddecl(struct slice s); diff --git a/ir.c b/ir.c @@ -4,11 +4,9 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <strings.h> #include "array.h" #include "nooc.h" -#include "parse.h" #include "ir.h" #include "util.h" #include "blockstack.h" diff --git a/lex.c b/lex.c @@ -6,7 +6,6 @@ #include "nooc.h" #include "ir.h" #include "util.h" -#include "lex.h" #define ADVANCE(n) \ start.data += (n) ; \ @@ -18,9 +17,7 @@ lex(struct slice start) { size_t line = 1; size_t col = 1; - struct token *const head = calloc(1, sizeof(struct token)); - if (!head) - return NULL; + struct token *const head = xcalloc(1, sizeof(struct token)); struct token *cur = head; while (start.len) { @@ -125,10 +122,7 @@ lex(struct slice start) error(line, col, "invalid token"); } - cur->next = calloc(1, sizeof(struct token)); - - if (!cur->next) - die("lex: failed to allocate next token"); + cur->next = xcalloc(1, sizeof(struct token)); cur = cur->next; } diff --git a/lex.h b/lex.h @@ -1 +0,0 @@ -struct token *lex(struct slice start); diff --git a/main.c b/main.c @@ -4,7 +4,6 @@ #include <string.h> #include <stdint.h> #include <stdio.h> -#include <stdlib.h> #include <sys/stat.h> #include <sys/mman.h> #include <unistd.h> @@ -14,8 +13,6 @@ #include "ir.h" #include "util.h" #include "elf.h" -#include "lex.h" -#include "parse.h" #include "type.h" #include "map.h" #include "blockstack.h" @@ -28,6 +25,9 @@ struct toplevel toplevel; struct map *typesmap; char *infile; +struct block parse(const struct token *const start); +struct token *lex(struct slice start); + uint64_t data_push(const char *const ptr, const size_t len) { diff --git a/parse.c b/parse.c @@ -4,7 +4,6 @@ #include <stdlib.h> #include "nooc.h" -#include "parse.h" #include "ir.h" #include "util.h" #include "array.h" @@ -12,26 +11,10 @@ #include "map.h" #include "blockstack.h" -const struct token *tok; - +static const struct token *tok; static void parsenametypes(struct nametypes *const nametypes); static size_t parsetype(); -struct decl * -finddecl(const struct slice s) -{ - for (int j = blocki - 1; j >= 0; j--) { - for (int i = 0; i < blockstack[j]->decls.len; i++) { - struct decl *decl = &(blockstack[j]->decls.data[i]); - if (slice_cmp(&s, &decl->s) == 0) { - return decl; - } - } - } - - return NULL; -} - static void expect(const enum tokentype type) { @@ -49,7 +32,7 @@ parsestring(struct expr *const expr) expr->kind = EXPR_LIT; expr->class = C_STR; expr->d.v.v.s = (struct slice){ 0 }; - struct slice str = tok->slice; + const struct slice str = tok->slice; for (size_t i = 0; i < str.len; i++) { switch (str.data[i]) { case '\\': @@ -99,7 +82,7 @@ parsenum(struct expr *const expr) tok = tok->next; } -enum class +static enum class typetoclass(const struct type *const type) { switch (type->class) { @@ -122,6 +105,8 @@ static size_t parseexpr(struct block *const block) { struct expr expr = { 0 }; + const struct type *type; + const struct decl *decl; switch (tok->type) { case TOK_LOOP: expr.start = tok; @@ -148,13 +133,11 @@ parseexpr(struct block *const block) expect(TOK_RPAREN); tok = tok->next; return ret; - break; case TOK_NAME: expr.start = tok; // a procedure definition if (slice_cmplit(&tok->slice, "proc") == 0) { - struct decl decl = { 0 }; - struct type *type; + struct decl param = { 0 }; int8_t offset = 0; expr.kind = EXPR_PROC; expr.class = C_PROC; @@ -164,46 +147,46 @@ parseexpr(struct block *const block) parsenametypes(&expr.d.proc.out); for (int i = expr.d.proc.in.len - 1; i >= 0; i--) { - decl.s = expr.d.proc.in.data[i].name; - decl.type = expr.d.proc.in.data[i].type; - decl.in = true; - type = &types.data[decl.type]; + param.s = expr.d.proc.in.data[i].name; + param.type = expr.d.proc.in.data[i].type; + param.in = true; + type = &types.data[param.type]; offset += type->size; - array_add((&expr.d.proc.block.decls), decl); + array_add((&expr.d.proc.block.decls), param); } for (size_t i = 0; i < expr.d.proc.out.len; i++) { - decl.s = expr.d.proc.out.data[i].name; - decl.type = typeref(expr.d.proc.out.data[i].type); - decl.in = decl.out = true; - type = &types.data[decl.type]; + param.s = expr.d.proc.out.data[i].name; + param.type = typeref(expr.d.proc.out.data[i].type); + param.in = param.out = true; + type = &types.data[param.type]; offset += type->size; - array_add((&expr.d.proc.block.decls), decl); + array_add((&expr.d.proc.block.decls), param); } parseblock(&expr.d.proc.block); // a function call } else if (tok->next && tok->next->type == TOK_LPAREN) { - size_t pidx; expr.d.call.name = tok->slice; - struct decl *decl = finddecl(expr.d.call.name); + decl = finddecl(expr.d.call.name); if (slice_cmplit(&expr.d.call.name, "syscall") == 0) { expr.class = C_INT; } else { if (decl == NULL) error(expr.start->line, expr.start->col, "undeclared procedure '%.*s'", expr.d.s.len, expr.d.s.data); - struct type *proctype = &types.data[decl->type]; - if (proctype->d.params.out.len == 1) { - struct type *rettype = &types.data[*proctype->d.params.out.data]; + type = &types.data[decl->type]; + if (type->d.params.out.len == 1) { + struct type *rettype = &types.data[*type->d.params.out.data]; expr.class = typetoclass(rettype); - } + } else if (type->d.params.out.len > 1) + error(tok->line, tok->col, "only one return supported"); } tok = tok->next->next; expr.kind = EXPR_FCALL; while (tok->type != TOK_RPAREN) { - pidx = parseexpr(block); + size_t pidx = parseexpr(block); array_add((&expr.d.call.params), pidx); if (tok->type == TOK_RPAREN) break; @@ -217,7 +200,7 @@ parseexpr(struct block *const block) expr.kind = EXPR_IDENT; expr.d.s = tok->slice; - struct decl *decl = finddecl(expr.d.s); + decl = finddecl(expr.d.s); if (decl == NULL) error(expr.start->line, expr.start->col, "undeclared identifier '%.*s'", expr.d.s.len, expr.d.s.data); expr.class = typetoclass(&types.data[decl->type]); @@ -289,7 +272,7 @@ binary_common: return exprs.len - 1; } -void +static void parsetypelist(struct typelist *const list) { expect(TOK_LPAREN); @@ -391,7 +374,7 @@ static void parseblock(struct block *const block) { struct statement statement; - bool curlies = false; + bool curlies = false, toplevel_decl = blockpeek() == NULL; blockpush(block); if (tok->type == TOK_LCURLY) { @@ -404,7 +387,7 @@ parseblock(struct block *const block) statement.start = tok; if (tok->type == TOK_LET) { struct decl decl = { 0 }; - decl.toplevel = !(blocki - 1); + decl.toplevel = toplevel_decl; decl.start = tok; statement.kind = STMT_DECL; tok = tok->next; @@ -417,15 +400,14 @@ parseblock(struct block *const block) expect(TOK_EQUAL); tok = tok->next; - if (finddecl(decl.s)) { + if (finddecl(decl.s)) error(tok->line, tok->col, "repeat declaration!"); - } decl.val = parseexpr(block); array_add((&block->decls), decl); statement.idx = block->decls.len - 1; - array_add((block), statement); + array_add(block, statement); } else if (tok->type == TOK_RETURN) { statement.kind = STMT_RETURN; tok = tok->next; diff --git a/parse.h b/parse.h @@ -1,3 +0,0 @@ -struct block parse(const struct token *const tok); -struct nametype *findparam(struct nametypes *params, struct slice s); -struct decl *finddecl(struct slice s); diff --git a/type.c b/type.c @@ -5,13 +5,13 @@ #include <string.h> #include "nooc.h" -#include "parse.h" #include "ir.h" #include "util.h" #include "type.h" #include "map.h" #include "blake3.h" #include "array.h" +#include "blockstack.h" // hashtable based on cproc's map.c @@ -165,8 +165,8 @@ type_put(const struct type *const type) void typecompat(const size_t typei, const size_t expri) { - struct type *type = &types.data[typei]; - struct expr *expr = &exprs.data[expri]; + const struct type *const type = &types.data[typei]; + const struct expr *const expr = &exprs.data[expri]; switch (type->class) { case TYPE_INT: @@ -201,7 +201,7 @@ typecompat(const size_t typei, const size_t expri) const size_t typeref(const size_t typei) { - struct type ref = { + const struct type ref = { .class = TYPE_REF, .size = 8, .d.subtype = typei @@ -214,30 +214,28 @@ static void typecheckcall(const struct expr *const expr) { assert(expr->kind == EXPR_FCALL); - struct decl *fdecl = finddecl(expr->d.call.name); + const struct decl *const decl = finddecl(expr->d.call.name); - if (fdecl == NULL) { - if (slice_cmplit(&expr->d.call.name, "syscall") == 0) { + if (decl == NULL) { + if (slice_cmplit(&expr->d.call.name, "syscall") == 0) return; - } else { + else error(expr->start->line, expr->start->col, "unknown function '%.*s'", expr->d.call.name.len, expr->d.call.name.data); - } } - struct type *ftype = &types.data[fdecl->type]; - assert(ftype->class == TYPE_PROC); + const struct type *const type = &types.data[decl->type]; + assert(type->class == TYPE_PROC); // should this throw an error instead and we move the check out of parsing? - assert(expr->d.call.params.len == ftype->d.params.in.len); - for (int i = 0; i < ftype->d.params.in.len; i++) { - typecompat(ftype->d.params.in.data[i], expr->d.call.params.data[i]); - } + assert(expr->d.call.params.len == type->d.params.in.len); + for (int i = 0; i < type->d.params.in.len; i++) + typecompat(type->d.params.in.data[i], expr->d.call.params.data[i]); } static void typecheckexpr(const size_t expri) { - struct expr *expr = &exprs.data[expri]; + const struct expr *const expr = &exprs.data[expri]; switch (expr->kind) { case EXPR_BINARY: typecheckexpr(expr->d.bop.left); @@ -267,8 +265,8 @@ typecheck(const struct block *const block) { for (size_t i = 0; i < block->len; i++) { const struct statement *const statement = &block->data[i]; - struct decl *decl; - struct assgn *assgn; + const struct decl *decl; + const struct assgn *assgn; switch (block->data[i].kind) { case STMT_ASSGN: assgn = &assgns.data[statement->idx]; @@ -278,7 +276,7 @@ typecheck(const struct block *const block) typecheckexpr(assgn->val); if (decl->out) { - struct type *type = &types.data[decl->type]; + const struct type *const type = &types.data[decl->type]; typecompat(type->d.subtype, assgn->val); } else { typecompat(decl->type, assgn->val); diff --git a/util.c b/util.c @@ -240,7 +240,7 @@ slice_cmp(const struct slice *const s1, const struct slice *const s2) int slice_cmplit(const struct slice *const s1, const char *const s2) { - size_t len = strlen(s2); + const size_t len = strlen(s2); if (s1->len < len) return 1; diff --git a/x64.c b/x64.c @@ -2,7 +2,6 @@ #include <stdbool.h> #include <stdint.h> #include <string.h> -#include <strings.h> #include "nooc.h" #include "ir.h"