diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-06-17 16:53:38 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-06-17 16:53:38 +0200 |
commit | a1657b2baebb8569395c1314bb1f9bdeab32ea6d (patch) | |
tree | d828144ed7aa7bd8579e37667da7f63de2d74ca8 | |
parent | 7e6ade6682c26d7ed40eaa22ae152686d44982d0 (diff) |
Implement super simple function type-checking
-rw-r--r-- | src/analyzer.c | 46 | ||||
-rw-r--r-- | src/analyzer.h | 18 |
2 files changed, 52 insertions, 12 deletions
diff --git a/src/analyzer.c b/src/analyzer.c index 6687856..d02096e 100644 --- a/src/analyzer.c +++ b/src/analyzer.c @@ -29,9 +29,18 @@ struct environs { static struct environ *create_environments(struct ast, struct lexemes, struct environs *, idx_t_, idx_t_, arena *) - __attribute__((nonnull)); + __attribute__((returns_nonnull, nonnull)); static void typecheck_environment(struct environs, struct ast, struct lexemes, idx_t_); +static struct type typecheck_constdecl(struct environs, struct ast, + struct lexemes, idx_t_, idx_t_); +static struct type typecheck_expr(struct environs, struct ast, struct lexemes, + idx_t_, idx_t_); +static struct type typecheck_fn(struct environs, struct ast, struct lexemes, + idx_t_, idx_t_); +static const struct type *typegrab(struct ast, struct lexemes, idx_t_) + __attribute__((returns_nonnull)); +static bool typecompat(struct type, struct type); /* Defined in primitives.gperf */ const struct type *typelookup(const uchar *, size_t) @@ -104,13 +113,6 @@ create_environments(struct ast ast, struct lexemes toks, struct environs *evs, return ev; } -static struct type typegrab(struct ast, struct lexemes, idx_t_); -static struct type typecheck_constdecl(struct environs, struct ast, - struct lexemes, idx_t_, idx_t_); -static struct type typecheck_expr(struct environs, struct ast, struct lexemes, - idx_t_, idx_t_); -static bool typecompat(struct type, struct type); - void typecheck_environment(struct environs evs, struct ast ast, struct lexemes toks, idx_t_ i) @@ -120,14 +122,14 @@ typecheck_environment(struct environs evs, struct ast ast, struct lexemes toks, typecheck_constdecl(evs, ast, toks, j, i); } -struct type +const struct type * typegrab(struct ast ast, struct lexemes toks, idx_t_ i) { struct strview sv = toks.strs[ast.lexemes[i]]; const struct type *tp = typelookup(sv.p, sv.len); if (tp == NULL) err("analyzer: Unknown type ā%.*sā", (int)sv.len, sv.p); - return *tp; + return tp; } struct type @@ -147,7 +149,7 @@ typecheck_constdecl(struct environs evs, struct ast ast, struct lexemes toks, assert(p.rhs != AST_EMPTY); if (p.lhs != AST_EMPTY) - ltype = typegrab(ast, toks, p.lhs); + ltype = *typegrab(ast, toks, p.lhs); rtype = typecheck_expr(evs, ast, toks, p.rhs, evi); if (ltype.kind == TYPE_UNSET) @@ -187,16 +189,36 @@ typecheck_expr(struct environs evs, struct ast ast, struct lexemes toks, } } case ASTFN: - assert(!"not implemented"); + return typecheck_fn(evs, ast, toks, i, evi); default: err("analyzer: Unexpected AST kind %u", ast.kinds[i]); __builtin_unreachable(); } } +struct type +typecheck_fn(struct environs evs, struct ast ast, struct lexemes toks, + idx_t_ i, idx_t_ evi) +{ + struct type t = {.kind = TYPE_FN}; + struct pair p = ast.kids[i]; + + idx_t_ proto = p.lhs; + if (ast.kids[proto].rhs == AST_EMPTY) + return t; + + t.ret = typegrab(ast, toks, ast.kids[proto].rhs); + return t; + + /* TODO: Typecheck function body */ +} + bool typecompat(struct type lhs, struct type rhs) { + if (rhs.kind == TYPE_FN) + return lhs.ret == rhs.ret; + if (lhs.kind == rhs.kind) return true; diff --git a/src/analyzer.h b/src/analyzer.h index c3c9b57..f44cbac 100644 --- a/src/analyzer.h +++ b/src/analyzer.h @@ -10,6 +10,7 @@ enum { TYPE_UNSET = 0, TYPE_CHECKING = 1, + /* Signed integers */ TYPE_I8, TYPE_I16, TYPE_I32, @@ -17,21 +18,38 @@ enum { TYPE_INT, TYPE_INT_UNTYPED, + /* Unsigned integers */ TYPE_U8, TYPE_U16, TYPE_U32, TYPE_U64, TYPE_UINT, + /* Floating point numbers */ + TYPE_F32, + TYPE_F64, + + /* Unicode codepoint */ TYPE_RUNE, + + /* Function type */ + TYPE_FN, + + _TYPE_LAST_ENT, }; typedef uint8_t type_kind_t_; +static_assert(_TYPE_LAST_ENT - 1 <= (type_kind_t_)-1, + "Too many AST tokens to fix in TYPE_KIND_T_"); struct type { type_kind_t_ kind; uint8_t size : 7; /* bytes */ bool issigned : 1; + + /* For functions */ + const struct type *params, *ret; + idx_t_ paramcnt; }; void analyzeast(struct ast, struct lexemes); |