commit d9f5d116423c707a253e4a7940158002ce47b480
parent eaec4d6f8bd856a809d4d69b6588c6019e07a76c
Author: m21c <ho*******@gmail.com>
Date: Sun, 3 Oct 2021 13:28:28 +0200
implemented declaration with type-inference
Diffstat:
| M | compiler.c | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
1 file changed, 65 insertions(+), 8 deletions(-)
diff --git a/compiler.c b/compiler.c
@@ -1721,6 +1721,13 @@ makedecl(Source *source, int key, DeclKind kind)
assert(currenv);
+ /* TODO(m21c): maybe remove check if already declared,
+ * since many functions that call makedecl
+ * already try to obtain a declaration for
+ * other reasons. So the check if it is
+ * already declared can be done by those
+ * functions */
+
decl = finddeclinenv(key, currenv);
if (decl) {
@@ -2019,6 +2026,7 @@ static Node *
declaration(Source *source, Type *ty)
{
bool selfparam = false;
+ Type *module = NULL;
Decl *decl = NULL;
Node *result = NULL;
@@ -2041,13 +2049,26 @@ declaration(Source *source, Type *ty)
/* variable name */
if (getkind(source) == 'I') {
+ decl = finddeclaration(source, source->currenv, source->tok.u.key);
+
+ if (decl && decl->kind != DFUNCTION && decl->kind != DPARAM &&
+ decl->kind != DVAR)
+ {
+ module = decl->type;
+ decl = NULL;
+ goto readvarmodule;
+ }
+
decl = makedecl(source, source->tok.u.key, DVAR);
decl->type = ty;
gettok(source);
-
/* module for variable */
} else if (getkind(source) == 'T') {
- Type *module = gettype(source, source->tok.type);
+ module = source->tok.type;
+
+ readvarmodule:
+ gettok(source);
+ module = gettype(source, module);
if (getkind(source) == ODISP || getkind(source) == ':') {
selfparam = getkind(source) == ':';
@@ -2062,11 +2083,12 @@ declaration(Source *source, Type *ty)
/* variable name */
if (getkind(source) == 'I') {
+ decl = makedecl(source, source->tok.u.key, DVAR);
+ decl->type = ty;
gettok(source);
} else {
error(getloc(source), "expected identifier");
}
-
} else {
result = tokennode(source, NULL);
result->kind = 'T';
@@ -2103,14 +2125,21 @@ declaration(Source *source, Type *ty)
}
expect(source, ')', "expected ')'");
+ if (module && ty->kind == TINFER) {
+ ty = module;
+ } else if (ty->kind == TINFER) {
+ error(&decl->loc,
+ "cannot infer return type of function");
+ }
+
decl->type = maketype(&decl->loc, prim + TFUNCTION, paramtype);
decl->type->u.rtarget = ty;
+ ty = decl->type;
/* function body */
if (getkind(source) != OASS) {
body = stmtlist(source, source->lastindent,
SFUNCTION, decl);
-
/* function init (body defined by assigment) */
} else if (getkind(source) == OASS) {
gettok(source);
@@ -2119,7 +2148,6 @@ declaration(Source *source, Type *ty)
body = readexpr(source, PASSIGN);
popenv(source);
-
/* no function body */
} else {
popenv(source);
@@ -2155,11 +2183,16 @@ declaration(Source *source, Type *ty)
} else {
assert(decl);
decl->u.content = NULL;
+
+ if (ty->kind == TINFER) {
+ error(&decl->loc,
+ "cannot infer type, expected initialization");
+ }
}
finish:
result = tokennode(source, decl->u.content);
- result->type = decl->type;
+ result->type = ty;
result->u.declref = decl;
result->loc = decl->loc;
result->kind = ADECL;
@@ -2386,6 +2419,11 @@ readatom(Source *source, int flags)
break;
+ case KVAR:
+ gettok(source);
+ lhs = declaration(source, prim + TINFER);
+ break;
+
case KFALSE:
case KTRUE:
lhs = tokennode(source, NULL);
@@ -3034,6 +3072,26 @@ arithtuplereorder(Env *env, Node *expr, int numops)
return false;
}
+static Type *
+typecheckdecl(Env *env, Decl *decl)
+{
+ if (decl->kind == DPARAM || decl->kind == DVAR) {
+ if (!decl->u.content)
+ return decl->type;
+
+ decl->u.content = typecheck(env, decl->u.content);
+
+ if (decl->type->kind == TINFER) {
+ decl->u.content = conv(decl->u.content);
+ decl->type = decl->u.content->type;
+ } else {
+ decl->u.content = wrap(decl->type, decl->u.content);
+ }
+ }
+
+ return decl->type;
+}
+
static Node *
typecheck(Env *env, Node *expr)
{
@@ -3269,8 +3327,7 @@ typecheck(Env *env, Node *expr)
return expr;
case ADECL:
- if (expr->lhs)
- expr->lhs = wrap(expr->type, typecheck(env, expr->lhs));
+ expr->type = typecheckdecl(env, expr->u.declref);
return expr;