Aria

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

commit 169777f038533a9820dc94dfcb664a2ab53068df
parent 82b27b67550b5b5d715db6f17b24cfca4cead61b
Author: m21c <ho*******@gmail.com>
Date:   Fri, 27 Jun 2025 21:20:25 +0200

worked on extract nested
functions

Diffstat:
Mcompiler.c | 169++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 168 insertions(+), 1 deletion(-)

diff --git a/compiler.c b/compiler.c @@ -591,6 +591,12 @@ struct Source { Env *implicitenv; + bool haspendingenv; + + /* pending nodes */ + Node *pendingnodes[512]; + int pendingcount; + /* parser state */ Node *lastis; @@ -2179,6 +2185,8 @@ deferfuncenv(Source *source, int keydeclinfunc) if (funcenv) { if (!funcenv->pending) { funcenv->pending = true; + /* @todo handle nested functions properly */ + source->haspendingenv = true; listappendex(source, funcenv, pendingenvhead, pendingenvtail, @@ -5525,7 +5533,166 @@ dataflow2(Analysis *analysis, Node *expr) // }}} -// @section intermediate code generation {{{ + +// @section extract nested functions {{{ + +Node *extracted[1024 * 4]; +int extractedtop = 0; + +static bool +isnestedfunction(Env *startenv) +{ + Env *env; + int n = 0; + + for (env = startenv; env; env = env->below) { + if (env->kind == SFUNCTION) + ++n; + } + + return n > 1; +} + +static void +extractnfs(Env *env, Node *expr); + +static void +substituenfs(Env *env, Node *expr) +{ + Decl *decl = expr->u.declref; + Node *enlist = NULL; + + assert(decl); + + if (decl->u.content) { + env = decl->contentenv ? decl->contentenv : env; + extractnfs(env, decl->u.content); + } + + if (decl->kind == DFUNCTION && isnestedfunction(decl->contentenv)) { + enlist = makenode(expr, NULL); + expr->kind = ADECLREF; + + assert(extractedtop < lengthof(extracted)); + extracted[extractedtop++] = enlist; + } +} + +static void +extractnfs(Env *env, Node *expr) +{ +advance: + assert(expr); + + if (isoperator(expr->kind)) { + switch (getnumops(expr->kind)) { + case 3: + assert(expr->u.payload); + extractnfs(env, expr->u.payload); + /* FALLTHROUGH */ + case 2: + assert(expr->rhs); + extractnfs(env, expr->rhs); + /* FALLTHROUGH */ + case 1: + assert(expr->lhs); + extractnfs(env, expr->lhs); + } + return; + } + + switch (expr->kind) { + case KRETURN: + case KIF: + case KCASE: + case KOF: + case KDO: + case KFOR: + case KLOOP: + case KWHILE: + case KUNTIL: + case AFORSTEP: + case AFOREACH: + if (expr->u.payload) + extractnfs(env, expr->u.payload); + if (expr->lhs) + extractnfs(env, expr->lhs); + if (expr->rhs) + extractnfs(env, expr->rhs); + break; + case ADEREF: + case ACONV: + case ASELFDISP: + assert(expr->lhs); + extractnfs(env, expr->lhs); + break; + case ACOMMA: + assert(expr->lhs); + assert(expr->rhs); + extractnfs(env, expr->lhs); + extractnfs(env, expr->rhs); + break; + case ASTMT: + assert(expr->lhs); + extractnfs(env, expr->lhs); + if (expr->rhs) { + expr = expr->rhs; + goto advance; + } + break; + case ADECL: + substituenfs(env, expr); + break; + case AENV: + case ASCOPE: + assert(expr->lhs); + assert(expr->u.env); + extractnfs(expr->u.env, expr->lhs); + break; + case TYPE: /* @note is this correct? */ + case CHAR: + case NUMBER: + case STRING: + case ADECLREF: + case IDENT: /* @note is this correct? */ + break; + + case ACOMPOUND: + /* @todo extract within type (lhs)? */ + assert(expr->rhs); + extractnfs(env, expr->lhs); + break; + + case AFIELDINIT: + assert(expr->rhs); + extractnfs(env, expr->rhs); + break; + + case KSTRUCT: + assert(expr->rhs); + extractnfs(env, expr->rhs); + break; + + default: + error(&expr->loc, "internal error: unknown expression kind" + " (%s).", nodestrings[expr->kind]); + break; + } +} + +static Node * +extractnestedfunctions(Env *env, Node *expr) +{ + extractedtop = 0; + + extractnfs(env, expr); + + assert(extractedtop < lengthof(extracted)); + extracted[extractedtop++] = expr; + return expr; +} + +// }}}