Aria

A low-level systems programming language
git clone git://git.m21c.me/Aria.git
Log | Files | Refs | LICENSE

commit d9f5d116423c707a253e4a7940158002ce47b480
parent eaec4d6f8bd856a809d4d69b6588c6019e07a76c
Author: m21c  <ho*******@gmail.com>
Date:   Sun,  3 Oct 2021 13:28:28 +0200

implemented declaration with type-inference

Diffstat:
Mcompiler.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;