commit 7986b5985409798dbe07374a507361cf20f6a159
parent 4bfe58b997ed954fb9ed0d7681fea10a6e4f9fde
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Thu, 18 Dec 2025 14:03:09 +0000
added full support for functions and for pointers!
Diffstat:
7 files changed, 78 insertions(+), 11 deletions(-)
diff --git a/cback.c b/cback.c
@@ -51,6 +51,10 @@ compiletype_C(type *t, FILE *f) {
case BASIC:
fprintf(f, "%s", toctype(t->name));
break;
+ case PTR:
+ compiletype_C(t->nested, f);
+ fprintf(f, "*");
+ break;
}
}
@@ -112,6 +116,14 @@ compilerexpr_C(rexpr *r, FILE *f) {
left = compilerexpr_C(r->expr[0], f);
compiletype_C(r->type, f);
fprintf(f, " v%d = -v%d;\n", vid++, left);
+ } else if (r->op == ADDROF) {
+ left = compilerexpr_C(r->expr[0], f);
+ compiletype_C(r->type, f);
+ fprintf(f, " v%d = &v%d;\n", vid++, left);
+ } else if (r->op == DEREF) {
+ left = compilerexpr_C(r->expr[0], f);
+ compiletype_C(r->type, f);
+ fprintf(f, " v%d = *v%d;\n", vid++, left);
}
return vid - 1;
}
@@ -145,6 +157,8 @@ compileassign_C(lexpr *l, FILE *f) {
fprintf(f, " %s", l->name);
if (l->rexpr)
fprintf(f, " = v%d;\n", id);
+ else
+ fprintf(f, ";\n");
}
void
diff --git a/lexer.c b/lexer.c
@@ -72,6 +72,7 @@ next(lex *l) {
case ASSIGN:
case SEMI:
case COMMA:
+ case ADDROF:
t.op = *l->ptr++;
return t;
}
diff --git a/lexer.h b/lexer.h
@@ -20,6 +20,7 @@ enum lex_ops {
ASSIGN = '=',
SEMI = ';',
COMMA = ',',
+ ADDROF = '&',
FUNC = 256,
INT,
FLOAT,
@@ -30,6 +31,7 @@ enum lex_ops {
/* used by the parser, wont be assigned by the lexer */
FUNCALL,
NEGATE,
+ DEREF,
};
typedef struct tok {
diff --git a/parse.c b/parse.c
@@ -12,6 +12,8 @@
#define SAME(s1, s2) (strcmp(s1, s2) == 0)
#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+int haserrored = 0;
+
char *builtintypes[] = {
"f32",
"f64",
@@ -103,6 +105,9 @@ findlowest(tok *start, tok *end) {
case SUB:
t->op = NEGATE;
break;
+ case MUL:
+ t->op = DEREF;
+ break;
}
}
else if (getpres(*t) < getpres(*lowest)) lowest = t;
@@ -137,7 +142,8 @@ isequaltype(type *t1, type *t2) {
if (atoi(t1->name + 1) >= atoi(t2->name + 1))
return 1;
}
- }
+ } else if (t1->type == PTR && t2->type == PTR)
+ return isequaltype(t1->nested, t2->nested);
return 0;
}
@@ -177,16 +183,23 @@ parsefcall(tok *start, tok *end, mctx *ctx) {
another:
while (!isterm(*exprend)) {
- if (exprend->op == ')')
- if (e->argc == 0)
+ if (exprend->op == ')') {
+ if (exprend == start)
goto noargs;
break;
+ }
exprend = &exprend[1];
}
e->argc++;
e->args = realloczctx(ctx, e->args, sizeof(rexpr) * e->argc);
e->args[e->argc - 1] = *parserexpr(start, &exprend[-1], ctx);
start = &exprend[1];
+
+ if (!isequaltype(e->args[e->argc - 1].type, &f->args[e->argc - 1])) {
+ parserErr("type missmatch");
+ return NULL;
+ }
+
if (exprend->op != ')')
goto another;
@@ -194,6 +207,14 @@ noargs:
return e;
}
+type *
+mkptrtype(type *t, mctx *ctx) {
+ type *new = alloczctx(ctx, sizeof(type));
+ new->type = PTR;
+ new->nested = t;
+ return new;
+}
+
rexpr *
parsesimple(tok *start, tok *end, tok *lowest, mctx *ctx) {
rexpr *e;
@@ -249,6 +270,18 @@ parsesimple(tok *start, tok *end, tok *lowest, mctx *ctx) {
e->e = parserexpr(&lowest[1], end, ctx);
e->type = e->e->type;
break;
+ case ADDROF:
+ e = alloczctx(ctx, sizeof(rexpr));
+ e->op = ADDROF;
+ e->e = parserexpr(&lowest[1], end, ctx);
+ e->type = mkptrtype(e->e->type, ctx);
+ break;
+ case DEREF:
+ e = alloczctx(ctx, sizeof(rexpr));
+ e->op = DEREF;
+ e->e = parserexpr(&lowest[1], end, ctx);
+ e->type = e->e->type->nested;
+ break;
default:
parserErr("Unexpected token type");
return NULL;
@@ -308,16 +341,21 @@ parsetype(lex *l, mctx *ctx) {
SAVE(l);
type *ty;
tok t = next(l);
- if (t.op != NAME) {
+ ty = alloczctx(ctx, sizeof(type));
+ if (t.op == MUL) {
+ ty->type = PTR;
+ ty->nested = parsetype(l, ctx);
+ return ty;
+ } else if (t.op != NAME) {
RESTORE(l);
return NULL;
}
+
if (!isbasictype(t.name)) {
parserErr("not a known type!");
RESTORE(l);
return NULL;
}
- ty = alloczctx(ctx, sizeof(type));
ty->type = BASIC;
ty->name = t.name;
return ty;
@@ -379,7 +417,7 @@ shortdec:
le->type = ty;
le->rexpr = r;
- if (!isequaltype(ty, r->type)) {
+ if (r && !isequaltype(ty, r->type)) {
parserErr("type missmatch");
RESTORE(l);
return NULL;
@@ -536,6 +574,7 @@ parselexpr(lex *l, mctx *ctx) {
le->rexpr = parsefcall(ts, &ts[tsc - 1], ctx);
if (!le->rexpr) {
RESTORE(l);
+ haserrored = 1;
return NULL;
}
le->op = LEXPR_FCALL;
@@ -547,6 +586,7 @@ parselexpr(lex *l, mctx *ctx) {
le = parsefunc(l, ctx); /* we can drop the FUNC token, as it doesnt hold any info */
if (!le) {
RESTORE(l);
+ haserrored = 1;
return NULL;
}
@@ -561,6 +601,7 @@ parselexpr(lex *l, mctx *ctx) {
if (lookupmap(funcs, f->name)) {
parserErr("function already exists");
RESTORE(l);
+ haserrored = 1;
return NULL;
}
funcs = addmap(funcs, f, f->name, ctx);
@@ -582,9 +623,11 @@ parselexpr(lex *l, mctx *ctx) {
return NULL;
default:
parserErr("unexpected tok type");
+ haserrored = 1;
}
if (!le) {
RESTORE(l);
+ haserrored = 1;
return NULL;
}
diff --git a/parse.h b/parse.h
@@ -13,14 +13,15 @@ enum lexpr_ops {
enum type_types {
BASIC,
+ PTR,
};
typedef struct type {
enum type_types type;
union {
- struct { /* basic types */
- char *name;
- };
+ char *name; /* basic types */
+ struct type *nested; /* ptr types */
+
};
} type;
@@ -66,6 +67,8 @@ typedef struct lexpr {
};
} lexpr;
+extern int haserrored;
+
void parserErr(const char *msg);
int getpres(tok t);
int isop(tok t);
diff --git a/spl.c b/spl.c
@@ -27,6 +27,7 @@ main(int argc, char **argv) {
xs = realloczctx(ctx, xs, ++lexprc * sizeof(lexpr));
xs[lexprc - 1] = *x;
}
+ if (haserrored) goto cleanup;
if (lexprc)
fprintf(stdout, "#include <stdint.h>\n");
for (int i = 0; i < lexprc; i++)
diff --git a/test.spl b/test.spl
@@ -1,5 +1,8 @@
-func foo() void;
+func foo(c *i32) i32 {
+ return *c;
+}
func main() i32 {
- foo();
+ a i32 = 5;
+ b i32 = foo(&a);
}