Aria

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

commit b927e23f373b60c35a1282d31595be9a96d6133d
parent 5f57a40e5cd965c1ac9d9378c78189f6270b8604
Author: m21c <ho*******@gmail.com>
Date:   Mon, 20 Apr 2026 21:11:32 +0200

worked on processing record fields + folding sizeof/alignof operators

Diffstat:
Mcompiler.c | 234+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 228 insertions(+), 6 deletions(-)

diff --git a/compiler.c b/compiler.c @@ -529,13 +529,23 @@ struct Type { Decl *module; /* module and record info */ }; -typedef struct Field { - Decl *fielddecl; +typedef struct Field Field; + +typedef struct Record { + Field *head, *tail; + + bool isunion; +} Record; + +struct Field { + Decl *decl; size_t offset, size; /* in bytes */ bool use; -} Field; + + Field *prev, *next; +}; struct Decl { DeclKind kind; @@ -543,6 +553,7 @@ struct Decl { Type *type; Decl *module; /* module or bundle */ + Record *record; int key; DeclFlags flags; @@ -2426,6 +2437,53 @@ defertypedeclaration(Source *source, int key) // }}} +// @section record {{{ + +Record recordbuf[4096]; +int recordtop; + +static Record * +makerecord(Decl *recorddecl) +{ + Record *record; + + assert(recordtop < lengthof(recordbuf)); + record = recordbuf + recordtop++; + record->head = record->tail = NULL; + + recorddecl->record = record; + + assert(recorddecl->type); + record->isunion = recorddecl->type->kind == TUNION; + + return record; +} + +Field fieldbuf[4096 * 16]; +int fieldtop; + +static Field * +makefield(Record *record, Decl *decl) +{ + Field *field; + + assert(fieldtop < lengthof(fieldbuf)); + field = fieldbuf + fieldtop++; + field->decl = decl; + field->offset = field->size = 0; + field->use = false; + field->prev = field->next = NULL; + + assert(record); + listappend(record, field); + + return field; +} + + + +// }}} + // @section parser {{{ #define getkind(source) \ @@ -3108,11 +3166,75 @@ readident(Source *source, int flags) return lhs; } +static void +extractfields(Record *record, Node *recordscope) +{ + Node *stmt; + + for (stmt = recordscope->lhs; stmt; stmt = stmt->rhs) { + Node *expr; + + assert(stmt->kind == ASTMT); + + expr = stmt->lhs; + + /* @fixme expr might be validly NULL */ + assert(expr); + + if (expr->kind == ACOMMA) { + for (; expr; expr = expr->lhs) { + Node *nested; + + if (expr->kind == ADECL) + makefield(record, expr->u.declref); + + if (expr->kind != ACOMMA) + break; + + nested = expr->rhs; + + if (nested->kind != ADECL) + continue; + + makefield(record, nested->u.declref); + } + continue; + } + if (expr->kind != ADECL) + continue; + + makefield(record, expr->u.declref); + } +} + +static void +calculatefields(Record *record, Type *recordtype) +{ + Field *field; + + for (field = record->head; field; field = field->next) { + size_t mod = 0, padding; + Type *type; + + type = field->decl->type; + + if (recordtype->align < type->align) + recordtype->align = type->align; + + if (recordtype->align) + mod = recordtype->size % recordtype->align; + + padding = mod ? recordtype->align - mod : 0; + recordtype->size += padding + type->size; + } +} + static Node * readrecord(Source *source, bool isunion) { Node *recordnode; Decl *module; + Record *record; int indent = source->lastindent; EnvKind envkind = SSTRUCT; @@ -3161,9 +3283,17 @@ readrecord(Source *source, bool isunion) module->contentenv = recordnode->rhs->u.env; } + record = makerecord(module); + /* TODO(m21c): validate record body, extract declarations, * compute size and align, resolve aliases */ + if (recordnode->rhs) { + assert(recordnode->rhs->kind == ASCOPE); + extractfields(record, recordnode->rhs); + } + + calculatefields(record, recordnode->type); return recordnode; } @@ -3234,6 +3364,17 @@ readrecordinitfieldlist(Source *source, Type *recordtype) } static Node * +finishcontrolflow(Source *source, Node *lhs, int indent) +{ + if (skipnewlineontok(source, KELSE, indent)) { + gettok(source); + lhs->rhs = stmtlist(source, indent, SELSE, NULL, false); + } + + return wrapenv(lhs, popenv(source)); +} + +static Node * readatom(Source *source, int flags) { Node *lhs = NULL, *savedis = source->lastis; @@ -3484,6 +3625,8 @@ readatom(Source *source, int flags) goto joinelse; /* skip postfix-operators */ + // return finishcontrolflow(source, lhs, indent); + return wrapenv(lhs, popenv(source)); case KFOR: @@ -3537,6 +3680,7 @@ readatom(Source *source, int flags) /* @todo maybe use SFOR instead of SLOOP */ lhs->lhs = stmtlist(source, indent, SLOOP, NULL, false); goto joinelse; + return finishcontrolflow(source, lhs, indent); case KWHILE: indent = source->lastindent; @@ -3546,6 +3690,7 @@ readatom(Source *source, int flags) lhs->u.payload = readexpr(source, POR); lhs->lhs = stmtlist(source, indent, SWHILE, NULL, false); goto joinelse; + return finishcontrolflow(source, lhs, indent); case KIF: indent = source->lastindent; @@ -3564,6 +3709,7 @@ readatom(Source *source, int flags) gettok(source); lhs->rhs = stmtlist(source, indent, SELSE, NULL, false); } + return finishcontrolflow(source, lhs, indent); /* skip postfix-operators */ return wrapenv(lhs, popenv(source)); @@ -4865,6 +5011,32 @@ typecheck(Env *env, Node *expr) } static Node * +foldexpr(Env *env, Node *expr); + +static Node * +folddeclaration(Env *env, Node *expr) +{ + Decl *decl = expr->u.declref; + + assert(decl); + + if (decl->kind == DFUNCTION) { + if (decl->u.content) + /* @todo make sure the correct env is used */ + decl->u.content = foldexpr(env, decl->u.content); + + } else if (decl->kind == DPARAM || decl->kind == DVAR) { + + /* @todo remove condition. it is only for testing structs. + * content may not be NULL otherwise (needs validation) */ + if (decl->u.content) + decl->u.content = foldexpr(env, decl->u.content); + } + + return expr; +} + +static Node * foldexpr(Env *env, Node *expr) { Node *lhs = expr->lhs, *rhs = expr->rhs; @@ -5058,6 +5230,8 @@ foldexpr(Env *env, Node *expr) } deletenode(lhs); + /* @todo delete type */ + expr->type = prim + TUSIZE; expr->kind = NUMBER; return expr; @@ -5069,6 +5243,9 @@ foldexpr(Env *env, Node *expr) return expr; + case ADECL: + return folddeclaration(env, expr); + case TYPE: error(&expr->loc, "exptected expression, not type"); /* FALLTHROUGH */ @@ -5446,7 +5623,6 @@ fetchblocks(Block *block, Node *expr) } } - #if 0 static void debugprintconduct(Conduct *conduct, int indent); @@ -5637,6 +5813,7 @@ advance: case KUNTIL: case AFORSTEP: case AFOREACH: + case ALOOPUNTIL: if (expr->u.payload) extractnfs(env, expr->u.payload); if (expr->lhs) @@ -5697,6 +5874,16 @@ advance: extractnfs(env, expr->rhs); break; + case KBREAK: + case KCONTINUE: + case KGOTO: + break; + + case KSIZEOF: + case KALIGNOF: + /* @todo check for nested functions and report error */ + break; + default: error(&expr->loc, "internal error: unknown expression kind" " (%s).", nodestrings[expr->kind]); @@ -5777,6 +5964,12 @@ cginit(CodeGen *cg, Env *toplevel, FILE *out) cgprintf(cg, "#include <stdlib.h>\n"); cgprintf(cg, "#include <string.h>\n"); + cgprintf(cg, "typedef int16_t s16;\n"); + cgprintf(cg, "typedef uint16_t u16;\n"); + cgprintf(cg, "typedef unsigned int uint;\n"); + cgprintf(cg, "typedef int64_t s64;\n"); + cgprintf(cg, "typedef uint64_t u64;\n"); + cgprintf(cg, "\n"); } @@ -6265,7 +6458,6 @@ codegen(CodeGen *cg, Node *expr) case ADECLREF: cgdeclname(cg, expr->u.declref); break; - case ALOOPUNTIL: case ALABEL: case ASWITCH: case ACASE: @@ -6509,10 +6701,40 @@ codegen(CodeGen *cg, Node *expr) cgprintf(cg, ")"); break; case AFOREACH: + break; + case KLOOP: + cgprintf(cg, "for (;;) "); + if (expr->lhs) + cgprintclause(cg, expr->lhs); + /* @todo implement else-case properly? */ + /* @note else-clause might be useless for an infinite loop */ + /* + if (expr->rhs) { + cgprintf(cg, " else "); + cgprintclause(cg, expr->rhs); + } + */ + cgprintf(cg, "\n"); + break; + case ALOOPUNTIL: + cgprintf(cg, "do "); + if (expr->lhs) + cgprintclause(cg, expr->lhs); + cgprintf(cg, " while (!("); + if (expr->u.payload) + codegen(cg, expr->u.payload); + cgprintf(cg, "));\n"); + /* @todo implement else-case properly */ + /* + if (expr->rhs) { + cgprintf(cg, " else "); + cgprintclause(cg, expr->rhs); + } + */ + break; case KCASE: case KOF: case KDO: - case KLOOP: case KUNTIL: /* @todo implement c version correctly */ break;