aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analyzer.c46
-rw-r--r--src/analyzer.h18
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);