spl

a Simple Programming Language
Log | Files | Refs

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:
Mcback.c | 14++++++++++++++
Mlexer.c | 1+
Mlexer.h | 2++
Mparse.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++------
Mparse.h | 9++++++---
Mspl.c | 1+
Mtest.spl | 7+++++--
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); }