commit bf837c7dd7ee04d8c06f17597b761382e8695da1
parent 35fc11dff76120101e2129b1ebe0753a61d71822
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Mon, 20 Dec 2021 17:29:45 -0600
typecheck all blocks, set appropriate classes for proc calls and idents
Diffstat:
6 files changed, 77 insertions(+), 34 deletions(-)
diff --git a/main.c b/main.c
@@ -256,28 +256,28 @@ dumpexpr(int indent, struct expr *expr)
}
void
-typecheck(struct block items)
+typecheck(struct block *block)
{
- for (size_t i = 0; i < items.len; i++) {
- struct item *item = &items.data[i];
+ for (size_t i = 0; i < block->len; i++) {
+ struct item *item = &block->data[i];
struct expr *expr;
struct decl *decl;
struct type *type;
struct assgn *assgn;
size_t line, col;
- switch (items.data[i].kind) {
+ switch (block->data[i].kind) {
case ITEM_ASSGN:
assgn = &assgns.data[item->idx];
decl = finddecl(assgn->s);
if (decl == NULL)
- error(assgn->start->line, assgn->start->col, "unknown name");
+ error(assgn->start->line, assgn->start->col, "typecheck: unknown name '%.*s'", assgn->s.len, assgn->s.data);
type = &types.data[decl->type];
line = assgn->start->line;
col = assgn->start->col;
goto check;
case ITEM_DECL:
- decl = &items.decls.data[item->idx];
+ decl = &block->decls.data[item->idx];
type = &types.data[decl->type];
line = decl->start->line;
col = decl->start->col;
@@ -285,13 +285,11 @@ check:
switch (type->class) {
case TYPE_I64:
expr = &exprs.data[decl->val];
- // FIXME: we should be able to deal with ident or fcalls
if (expr->class != C_INT)
error(line, col, "expected integer expression for integer declaration");
break;
case TYPE_STR:
expr = &exprs.data[decl->val];
- // FIXME: we should be able to deal with ident or fcalls
if (expr->class != C_STR)
error(line, col, "expected string expression for string declaration");
break;
@@ -314,6 +312,7 @@ check:
}
break;
case ITEM_EXPR:
+ case ITEM_RETURN:
break;
default:
error(item->start->line, item->start->col, "unknown item type");
@@ -494,6 +493,7 @@ size_t
genblock(char *buf, struct block *block, bool toplevel)
{
blockpush(block);
+ typecheck(block);
size_t total = 0;
for (int i = 0; i < block->len; i++) {
struct item *item = &block->data[i];
@@ -600,7 +600,6 @@ main(int argc, char *argv[])
typesmap = mkmap(16);
inittypes();
struct block items = parse(head);
- typecheck(items);
clearreg();
size_t len = genblock(NULL, &items, true);
diff --git a/nooc.h b/nooc.h
@@ -196,7 +196,7 @@ enum exprkind {
};
enum class {
- C_INT,
+ C_INT = 1,
C_STR,
C_PROC,
};
diff --git a/parse.c b/parse.c
@@ -103,7 +103,22 @@ parsestring(struct expr *expr)
tok = tok->next;
}
-static struct block parseblock();
+enum class
+typetoclass(struct type *type)
+{
+ switch (type->class) {
+ case TYPE_I64:
+ return C_INT;
+ case TYPE_STR:
+ return C_STR;
+ default:
+ die("unknown type class");
+ }
+
+ return 0; // warning
+}
+
+static void parseblock(struct block *block);
static size_t
parseexpr(struct block *block)
@@ -114,17 +129,17 @@ parseexpr(struct block *block)
expr.start = tok;
expr.kind = EXPR_LOOP;
tok = tok->next;
- expr.d.loop.block = parseblock();
+ parseblock(&expr.d.loop.block);
break;
case TOK_IF:
expr.start = tok;
expr.kind = EXPR_COND;
tok = tok->next;
expr.d.cond.cond = parseexpr(block);
- expr.d.cond.bif = parseblock();
+ parseblock(&expr.d.cond.bif);
if (tok->type == TOK_ELSE) {
tok = tok->next;
- expr.d.cond.belse = parseblock();
+ parseblock(&expr.d.cond.belse);
}
break;
case TOK_LPAREN:
@@ -147,14 +162,13 @@ parseexpr(struct block *block)
parsenametypes(&expr.d.proc.in);
if (tok->type == TOK_LPAREN)
parsenametypes(&expr.d.proc.out);
- expr.d.proc.block = parseblock();
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;
type = &types.data[decl.type];
offset += type->size;
decl.loc.off = -offset - 8;
- array_add((&block->decls), decl);
+ array_add((&expr.d.proc.block.decls), decl);
}
for (size_t i = 0; i < expr.d.proc.out.len; i++) {
@@ -164,12 +178,27 @@ parseexpr(struct block *block)
type = &types.data[decl.type];
offset += type->size;
decl.loc.off = -offset;
- array_add((&block->decls), decl);
+ array_add((&expr.d.proc.block.decls), decl);
}
+ 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);
+ 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];
+ expr.class = typetoclass(rettype);
+ }
+ }
+
tok = tok->next->next;
expr.kind = EXPR_FCALL;
@@ -187,6 +216,11 @@ parseexpr(struct block *block)
} else {
expr.kind = EXPR_IDENT;
expr.d.s = tok->slice;
+
+ struct decl *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]);
tok = tok->next;
}
break;
@@ -306,14 +340,13 @@ parsenametypes(struct nametypes *nametypes)
tok = tok->next;
}
-static struct block
-parseblock()
+static void
+parseblock(struct block *block)
{
- struct block items = { 0 };
struct item item;
bool curlies = false;
- blockpush(&items);
+ blockpush(block);
if (tok->type == TOK_LCURLY) {
curlies = true;
tok = tok->next;
@@ -341,15 +374,15 @@ parseblock()
error(tok->line, tok->col, "repeat declaration!");
}
- decl.val = parseexpr(&items);
- array_add((&items.decls), decl);
+ decl.val = parseexpr(block);
+ array_add((&block->decls), decl);
- item.idx = items.decls.len - 1;
- array_add((&items), item);
+ item.idx = block->decls.len - 1;
+ array_add((block), item);
} else if (tok->type == TOK_RETURN) {
item.kind = ITEM_RETURN;
tok = tok->next;
- array_add((&items), item);
+ array_add((block), item);
} else if (tok->type == TOK_NAME && tok->next && tok->next->type == TOK_EQUAL) {
struct assgn assgn = { 0 };
assgn.start = tok;
@@ -357,15 +390,15 @@ parseblock()
assgn.s = tok->slice;
tok = tok->next->next;
- assgn.val = parseexpr(&items);
+ assgn.val = parseexpr(block);
array_add((&assgns), assgn);
item.idx = assgns.len - 1;
- array_add((&items), item);
+ array_add(block, item);
} else {
item.kind = ITEM_EXPR;
- item.idx = parseexpr(&items);
- array_add((&items), item);
+ item.idx = parseexpr(block);
+ array_add(block, item);
}
}
@@ -375,12 +408,13 @@ parseblock()
}
blockpop();
- return items;
}
struct block
parse(struct token *start)
{
tok = start;
- return parseblock();
+ struct block block = { 0 };
+ parseblock(&block);
+ return block;
}
diff --git a/test/declare_from_ident.pass.nooc b/test/declare_from_ident.pass.nooc
@@ -0,0 +1,6 @@
+let a i64 = 10
+
+let main proc() = proc() {
+ let b i64 = a
+ syscall(60, 0)
+}
diff --git a/test/ident_type_mismatch.fail.nooc b/test/ident_type_mismatch.fail.nooc
@@ -0,0 +1,4 @@
+let main proc() = proc() {
+ let a i64 = 5
+ let b str = a
+}+
\ No newline at end of file
diff --git a/test/syntax1.fail.nooc b/test/syntax1.fail.nooc
@@ -1 +1 @@
-a i64 =-
\ No newline at end of file
+let a i64 =