Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions examples/func.zn
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
foreign u0 printf(*char)
foreign *u8 malloc(u64)

struct Vec {
f32 x
f32 y
}

u0 print() *Vec self {
printf("Received\n")
}

i32 main() {
*Vec v = malloc(sizeof Vec)

v.print()

return 0
}
18 changes: 18 additions & 0 deletions examples/function.zn
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
foreign u0 printf(*char)
struct Vec {
f32 x
f32 y
}

u0 print() Vec self {
printf("Received\n")
}

i32 main() {
v := Vec{ x: 10, y: 10 }

v.print()

return 0
}

4 changes: 3 additions & 1 deletion examples/input.zn
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
foreign i32 read(i32, *u8, u64)
foreign u0 printf(*char)
foreign u64 write(i32, *u8, u64)
foreign *u8 malloc(u64)
foreign *u8 memset(*u8, i32, u64)

Expand All @@ -10,7 +11,8 @@ i32 main() {
for bytesRead > 0 {
memset(buf, 0, 1024)
bytesRead = read(0, buf, 1024)
printf(buf)

write(1, buf, bytesRead)
}

printf("Exited\n")
Expand Down
12 changes: 12 additions & 0 deletions zcolors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef Z_COLORS_H
#define Z_COLORS_H

#define COLOR_RESET "\033[0m"
#define COLOR_RED "\033[1;31m"
#define COLOR_GREEN "\033[1;32m"
#define COLOR_YELLOW "\033[1;33m"
#define COLOR_BLUE "\033[1;34m"
#define COLOR_CYAN "\033[1;36m"
#define COLOR_BOLD "\033[1m"

#endif // Z_COLORS_H
69 changes: 57 additions & 12 deletions zgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,10 +541,14 @@ static LLVMValueRef genCall(ZCodegen *ctx, ZNode *node) {
static LLVMValueRef genLvalue(ZCodegen *ctx, ZNode *node) {
switch (node->type) {
case NODE_IDENTIFIER: {
char *key = node->identNode.mangled ? node->identNode.mangled : node->tok->str;
char *key = node->identNode.mangled ?
node->identNode.mangled :
node->tok->str;
LLVMValueRef val = getLLVMValueRef(ctx, key);
if (!val) {
error(ctx->state, node->tok, "'%s' not found in the current scope", node->tok->str);
error(ctx->state, node->tok,
"'%s' not found in the current scope",
node->tok->str);
return NULL;
}
return val;
Expand All @@ -566,7 +570,6 @@ static LLVMValueRef genLvalue(ZCodegen *ctx, ZNode *node) {
);
}
case NODE_MEMBER: {

ZType *objType = node->memberAccess.object->resolved;
ZToken *tok = node->memberAccess.field;
i32 index = typeIndex(objType, tok->str);
Expand Down Expand Up @@ -782,8 +785,38 @@ static LLVMValueRef castValue(ZCodegen *ctx, LLVMValueRef val, ZType *from, ZTyp
}

static LLVMValueRef genCast(ZCodegen *ctx, ZNode *node) {
ZType *from = node->castExpr.expr->resolved;
ZType *to = node->castExpr.toType;

/* Array-literal cast: [n]T as []U — write each element directly into
* the pre-allocated slot with per-element casting.
* genArrayLit can't be used here because the stack slot is keyed on
* this cast node, not on the inner array-literal node. */
if (from->kind == Z_TYPE_ARRAY && to->kind == Z_TYPE_ARRAY &&
node->castExpr.expr->type == NODE_ARRAY_LIT) {
ZLLVMStack *stack = getStackValue(ctx, node);
if (!stack) {
error(ctx->state, node->tok, "Missing stack value for array cast");
return NULL;
}
ZNode *lit = node->castExpr.expr;
for (usize i = 0; i < veclen(lit->arraylit); i++) {
LLVMValueRef indices[] = {
LLVMConstInt(i32Type, 0, false),
LLVMConstInt(i32Type, i, false)
};
LLVMValueRef gep = LLVMBuildGEP2(
ctx->builder, stack->type,
stack->stack, indices, 2, label(ctx));
LLVMValueRef elem = genExpr(ctx, lit->arraylit[i]);
elem = castValue(ctx, elem, from->array.base, to->array.base);
LLVMBuildStore(ctx->builder, elem, gep);
}
return stack->stack;
}

LLVMValueRef val = genExpr(ctx, node->castExpr.expr);
return castValue(ctx, val, node->castExpr.expr->resolved, node->castExpr.toType);
return castValue(ctx, val, from, to);
}

/* dest: optional pre-allocated slot to write into (e.g. an array element GEP).
Expand Down Expand Up @@ -842,7 +875,7 @@ static LLVMValueRef genArrayLit(ZCodegen *ctx, ZNode *node) {
ZLLVMStack *stack = getStackValue(ctx, node);

if (!stack) {
error(ctx->state, node->tok, "Missing stack value");
error(ctx->state, node->tok, "Missing stack value %p", node);
return NULL;
}

Expand Down Expand Up @@ -1245,6 +1278,7 @@ static void buildFuncVar(ZCodegen *ctx, ZNode *node, const char *name, ZType *ty
ZLLVMStack *item = zalloc(ZLLVMStack);
*item = (ZLLVMStack){ .stack = val, .type = type, .node = node };

info(ctx->state, node->tok, "Pushed %p, %p", ctx->scope, node);
vecpush(ctx->scope->stackAlloca, item);
}

Expand Down Expand Up @@ -1274,7 +1308,9 @@ static void genFuncVars(ZCodegen *ctx, ZNode *node) {
genFuncVars(ctx, node->ifStmt.body);
break;
case NODE_VAR_DECL:
buildFuncVar(ctx, node->varDecl.rvalue, node->varDecl.ident->identNode.tok->str, node->resolved);
buildFuncVar(ctx, node->varDecl.rvalue,
node->varDecl.ident->identNode.tok->str,
node->resolved);
break;
case NODE_CALL:
if (!node->resolved) {
Expand Down Expand Up @@ -1325,17 +1361,26 @@ static LLVMValueRef genFunc(ZCodegen *ctx, ZNode *f) {

LLVMTypeRef funcType = LLVMFunctionType(ret, args, veclen(args), false);
LLVMValueRef func = LLVMAddFunction(ctx->mod, f->funcDef.mangled, funcType);

for (usize i = 0; i < veclen(f->funcDef.args); i++) {
char *name = f->funcDef.args[i]->field.identifier->str;
putLLVMValueRef(ctx, name, LLVMGetParam(func, i));
}
ctx->currentFunc = func;

LLVMBasicBlockRef entry = makeblock(ctx);
LLVMPositionBuilderAtEnd(ctx->builder, entry);

/* All variable declarations are declared ad the start of the function. */
/* Allocate a stack slot for each parameter so they can be reassigned.
* The receiver (if present) occupies param index 0, so regular args
* start at offset 1. */
usize paramOffset = f->funcDef.receiver ? 1 : 0;
for (usize i = 0; i < veclen(f->funcDef.args); i++) {
char *name = f->funcDef.args[i]->field.identifier->str;
LLVMTypeRef paramType = genType(ctx, f->funcDef.args[i]->field.type);

LLVMValueRef slot = LLVMBuildAlloca(ctx->builder, paramType, name);
LLVMBuildStore(ctx->builder, LLVMGetParam(func, i + paramOffset), slot);

putLLVMValueRef(ctx, name, slot);
}

/* All variable declarations are declared at the start of the function. */
genFuncVars(ctx, f->funcDef.body);

genBlock(ctx, f->funcDef.body);
Expand Down
6 changes: 5 additions & 1 deletion zinc.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "zinc.h"
#include "zcolors.h"

#include <stdlib.h>
#include <stdio.h>
Expand Down Expand Up @@ -159,7 +160,10 @@ int main(int argc, char **argv) {

allocator.close();

printf("Elapsed time: %.02f seconds\n", elapsed);
if (!res) {
printf(" " COLOR_BOLD COLOR_GREEN "Finished" COLOR_RESET
" build in %.02fs\n", elapsed);
}

return res;
}
15 changes: 13 additions & 2 deletions zmod.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "zinc.h"
#include "zvec.h"
#include "zcolors.h"

#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -134,11 +135,20 @@ static void _stype(ZType *type, char **buff) {
vecunion(*buff, "struct ", 7);
vecunion(*buff, type->strct.name->str, strlen(type->strct.name->str));
break;
case Z_TYPE_ARRAY:
case Z_TYPE_ARRAY: {
vecpush(*buff, '[');

usize len = type->array.size;

while (len > 0) {
vecpush(*buff, 48 + len % 10);
len /= 10;
}

vecpush(*buff, ']');
_stype(type->array.base, buff);
break;
}
case Z_TYPE_TUPLE:
vecpush(*buff, '(');
for (usize i = 0; i < veclen(type->tuple); i++) {
Expand Down Expand Up @@ -418,7 +428,7 @@ void printNode(ZNode *node, u8 depth) {
printNode(node->deferStmt.expr, depth);
break;
case NODE_ARRAY_LIT:
printf("\n");
printf(" %zu\n", veclen(node->arraylit));
for(usize i = 0; i < veclen(node->arraylit); i++) {
printNode(node->arraylit[i], depth);
}
Expand Down Expand Up @@ -681,6 +691,7 @@ bool visit(ZState *state, char *filename) {
if (strcmp(state->pathFiles[i], filename) == 0) return false;
}

printf(" " COLOR_BOLD COLOR_GREEN "Building" COLOR_RESET " %s\n", filename);
vecpush(state->visitedFiles, filename);
vecpush(state->pathFiles, filename);
state->filename = filename;
Expand Down
45 changes: 38 additions & 7 deletions zsem.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
static void analyzeStmt(ZSemantic *, ZNode *);
static void analyzeBlock(ZSemantic *, ZNode *, bool);
static ZType *resolveTypeRef(ZSemantic *, ZType *);
static ZType *resolveReceiverCall(ZSemantic *, ZType *, ZToken *);

/* ================== Scope / Symbol helpers ================== */

Expand Down Expand Up @@ -157,13 +158,17 @@ static void putReceiverFunc(ZSemantic *semantic, ZNode *node) {

ZNode *receiver = node->funcDef.receiver;
ZFuncTable **funcs = semantic->table->funcs;
for (usize i = 0; i < veclen(funcs); i++) {
ZFuncTable *table = NULL;
for (usize i = 0; i < veclen(funcs) && !table; i++) {
if (typesEqual(funcs[i]->base, receiver->field.type)) {
vecpush(funcs[i]->funcDef, node);
return;
table = funcs[i];
}
}

if (!table) table = makefunctable(receiver->field.type);

vecpush(table->funcDef, node);
vecpush(semantic->table->funcs, table);
}

static void putStaticFunc(ZSemantic *semantic, ZNode *node) {
Expand Down Expand Up @@ -380,7 +385,7 @@ ZType *typesCompatible(ZState *state, ZType *a, ZType *b) {
return a;
}

if (typesEqual(a, b)) return a;
if (typesEqual(a, b)) return b;

if (a->kind != Z_TYPE_PRIMITIVE || b->kind != Z_TYPE_PRIMITIVE)
return NULL;
Expand Down Expand Up @@ -468,6 +473,13 @@ bool typesEqual(ZType *a, ZType *b) {
case Z_TYPE_POINTER:
return typesEqual(a->base, b->base);
case Z_TYPE_ARRAY:
if (a->array.size == 0 && b->array.size > 0) {
a->array.size = b->array.size;
} else if (b->array.size == 0 && a->array.size > 0) {
b->array.size = a->array.size;
} else if (a->array.size != b->array.size) {
printf("Mismatch array size\n");
}
return typesEqual(a->array.base, b->array.base);
case Z_TYPE_STRUCT:
case Z_TYPE_FUNCTION:
Expand Down Expand Up @@ -686,6 +698,13 @@ static ZType *resolveFuncCall(ZSemantic *semantic, ZNode *curr) {
expectedArgs = func->resolved->func.args;
}
}
} else if (callee->type == NODE_MEMBER) {
ZType *obj = resolveType(semantic, callee->memberAccess.object);

ZToken *prop = callee->memberAccess.field;

result = resolveReceiverCall(semantic, obj, prop);
printType(result);
} else {
/* Expression call: resolve callee type and extract return type. */
ZType *calleeType = resolveType(semantic, callee);
Expand Down Expand Up @@ -891,6 +910,8 @@ static ZType *resolveArrayLiteral(ZSemantic *semantic, ZNode *curr) {
ZType *result = maketype(Z_TYPE_ARRAY);
result->array.base = arrType;
result->array.size = len;


return result;
}

Expand Down Expand Up @@ -986,12 +1007,19 @@ ZType *resolveType(ZSemantic *semantic, ZNode *curr) {
}
break;

case NODE_CAST:
case NODE_CAST: {
/* Resolve the inner expression type (for side-effects / validation). */
resolveType(semantic, curr->castExpr.expr);
ZType *expr = resolveType(semantic, curr->castExpr.expr);
result = resolveTypeRef(semantic, curr->castExpr.toType);

if (expr->kind == Z_TYPE_ARRAY &&
result->kind == Z_TYPE_ARRAY) {
result->array.size = expr->array.size;
}

curr->castExpr.toType = result;
break;
}

case NODE_SIZEOF: {
/* sizeof yields u64. */
Expand Down Expand Up @@ -1028,14 +1056,16 @@ static ZType *resolveReceiverCall(ZSemantic *semantic,
ZFuncTable **table = semantic->table->funcs;
ZNode **funcs = NULL;

for (usize i = 0; i < veclen(table) && !funcs; i++) {
for (usize i = 0; i < veclen(table); i++) {
ZType *receiverType = resolveTypeRef(semantic, table[i]->base);
table[i]->base = receiverType;
table[i]->base = receiverType;
if (typesEqual(receiverType, caller)) {
funcs = table[i]->funcDef;
break;
}
}

if (!funcs) return NULL;

for (usize i = 0; i < veclen(funcs); i++) {
Expand Down Expand Up @@ -1230,6 +1260,7 @@ static void analyzeFunc(ZSemantic *semantic, ZNode *curr) {
if (curr->funcDef.receiver) {
ZNode *receiver = curr->funcDef.receiver;
ZType *recType = resolveTypeRef(semantic, receiver->field.type);
curr->funcDef.receiver->resolved = recType;
receiver->field.type = recType;

ZSymbol *sym = makesymbol(Z_SYM_VAR);
Expand Down
Loading
Loading