commit 4bfe58b997ed954fb9ed0d7681fea10a6e4f9fde
parent 9fd16cd66e2bb0908953a30acb648b1ca59825bd
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Thu, 18 Dec 2025 12:34:29 +0000
added propper support for functions, returns and the like
Diffstat:
| M | cback.c | | | 45 | ++++++++++++++++++++++++++++++++++----------- |
| M | lexer.c | | | 6 | ++++-- |
| M | lexer.h | | | 1 | + |
| D | note.md | | | 99 | ------------------------------------------------------------------------------- |
| M | parse.c | | | 71 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
| M | parse.h | | | 2 | ++ |
| M | spl.c | | | 16 | +++++++++------- |
| M | test.spl | | | 4 | +++- |
8 files changed, 119 insertions(+), 125 deletions(-)
diff --git a/cback.c b/cback.c
@@ -38,6 +38,10 @@ toctype(char *type) {
strcpy(ret, "float");
else if (SAME(type, "f64"))
strcpy(ret, "double");
+ else if (SAME(type, "void"))
+ strcpy(ret, "void");
+ else
+ return NULL;
return ret;
}
@@ -53,15 +57,19 @@ compiletype_C(type *t, FILE *f) {
int
compilefcall_C(rexpr *r, FILE *f) {
mctx *ctx = newctx();
- int i, *ids;
+ int i, *ids = NULL;
for (i = 0; i < r->argc; i++) {
ids = realloczctx(ctx, ids, i + 1);
ids[i] = compilerexpr_C(&r->args[i], f);
}
- compiletype_C(r->type, f);
- fprintf(f, " v%d = %s(", vid++, r->fname);
- for (int j = 0; j < i; j++)
- printf("v%d%s", ids[j], (j == i - 1) ? ");\n" : ", ");
+ if (!(r->type->type == BASIC && SAME(r->type->name, "void"))) {
+ compiletype_C(r->type, f);
+ fprintf(f, " v%d = %s(", vid++, r->fname);
+ } else fprintf(f, "%s(", r->fname);
+ if (!r->argc) fprintf(f, ");\n");
+ else
+ for (int j = 0; j < i; j++)
+ printf("v%d%s", ids[j], (j == i - 1) ? ");\n" : ", ");
freectx(ctx);
return vid - 1;
@@ -98,9 +106,12 @@ compilerexpr_C(rexpr *r, FILE *f) {
fprintf(f, " v%d = v%d %c v%d;\n", vid++, left, r->op, right);
} else if (r->op == OBRACE) {
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 == NEGATE) {
+ left = compilerexpr_C(r->expr[0], f);
+ compiletype_C(r->type, f);
+ fprintf(f, " v%d = -v%d;\n", vid++, left);
}
return vid - 1;
}
@@ -113,13 +124,16 @@ compilefunc_C(lexpr *l, FILE *f) {
compiletype_C(l->args[i].type, f);
fprintf(f, " %s%s", l->args[i].name, (i == l->argc - 1) ? "" : ", ");
}
- fprintf(f, ") {\n");
+ if (l->bodyc) {
+ fprintf(f, ") {\n");
- for (int i = 0; i < l->bodyc; i++) {
- compilelexpr_C(&l->body[i], f);
- }
+ for (int i = 0; i < l->bodyc; i++) {
+ compilelexpr_C(&l->body[i], f);
+ }
- fprintf(f, "}\n");
+ fprintf(f, "}\n");
+ }
+ else fprintf(f, ");\n");
}
void
@@ -153,5 +167,14 @@ compilelexpr_C(lexpr *l, FILE *f) {
case LEXPR_REASSIGN:
compilereassign_C(l, f);
break;
+ case RETURN:
+ if (l->ret)
+ fprintf(f, "return v%d;\n", compilerexpr_C(l->ret, f));
+ else
+ fprintf(f, "return;\n");
+ break;
+ case LEXPR_FCALL:
+ compilefcall_C(l->rexpr, f);
+ break;
}
}
diff --git a/lexer.c b/lexer.c
@@ -78,8 +78,10 @@ next(lex *l) {
if (memcmp(l->ptr, ":=", 2) == 0) {
l->ptr += 2;
t.op = WALRUS;
- }
- if (memcmp(l->ptr, "func", 4) == 0) {
+ } else if (memcmp(l->ptr, "return", 6) == 0) {
+ l->ptr += 6;
+ t.op = RETURN;
+ } else if (memcmp(l->ptr, "func", 4) == 0) {
l->ptr += 4;
t.op = FUNC;
} else if (isdigit(*l->ptr)) {
diff --git a/lexer.h b/lexer.h
@@ -25,6 +25,7 @@ enum lex_ops {
FLOAT,
NAME,
WALRUS,
+ RETURN,
/* used by the parser, wont be assigned by the lexer */
FUNCALL,
diff --git a/note.md b/note.md
@@ -1,99 +0,0 @@
-pivot parser
-============
-
-a parser could work like so
-
-2 + 4 * 3 - 1 = 13
-
-loop through all tokens and find the first token with the lowest presidence
-
-2 + 4 * 3 - 1
- ^
-
-split the list
-
-2
-+
-4 * 3 - 1
-
-repeat
-
-4 * 3
--
-1
-
-4
-*
-3
-
-assemble the tree
-
- +
- / \
- 2 -
- / \
- * 1
- / \
- 4 3
-
-2 + ((4 * 3) - 1)
-2 + (12 - 1)
-2 + 11
-13
-
-another example
-
-4 * 2 + (4 - 1) = 11
-
-4 * 2
-+
-(4 - 1)
-
-4
-*
-2
-
- +
- / \
- * (4 - 1)
- / \
- 4 2
-
-4 - 1
-
-4
--
-1
-
- +
- / \
- * \
- / \ \
- 4 2 \
- -
- / \
- 4 1
-
-(4 * 2) + (4 - 1)
-8 + 3
-11
-
-
-func(a) * (10 - 4)
-
-func(a)
-*
-(10 - 4)
-
- *
- / \
- func(a) \
- (10 - 4)
-
- *
- / \
- func(a) -
- / \
- 10 4
-
-func(a) * (10 - 4)
diff --git a/parse.c b/parse.c
@@ -12,6 +12,16 @@
#define SAME(s1, s2) (strcmp(s1, s2) == 0)
#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+char *builtintypes[] = {
+ "f32",
+ "f64",
+ "i8",
+ "i16",
+ "i32",
+ "i64",
+ "void",
+};
+
char *builtinfns[] = {
"f32",
"f64",
@@ -168,6 +178,8 @@ parsefcall(tok *start, tok *end, mctx *ctx) {
another:
while (!isterm(*exprend)) {
if (exprend->op == ')')
+ if (e->argc == 0)
+ goto noargs;
break;
exprend = &exprend[1];
}
@@ -226,11 +238,13 @@ parsesimple(tok *start, tok *end, tok *lowest, mctx *ctx) {
}
break;
case OBRACE:
+ e = alloczctx(ctx, sizeof(rexpr));
e->op = OBRACE;
e->e = parserexpr(&lowest[1], &findend(lowest, end)[-1], ctx);
e->type = e->e->type;
break;
case NEGATE:
+ e = alloczctx(ctx, sizeof(rexpr));
e->op = NEGATE;
e->e = parserexpr(&lowest[1], end, ctx);
e->type = e->e->type;
@@ -256,7 +270,11 @@ parsebin(tok *start, tok *end, tok *lowest, mctx *ctx) {
e->expr[0] = parserexpr(start, &lowest[-1], ctx);
e->expr[1] = parserexpr(&lowest[1], end, ctx);
- /* TODO make this check both sides */
+ if (!isequaltype(e->expr[0]->type, e->expr[1]->type)) {
+ parserErr("Type missmatch");
+ return NULL;
+ }
+
e->type = e->expr[0]->type;
return e;
@@ -274,10 +292,17 @@ parserexpr(tok *start, tok *end, mctx *ctx) {
/* binary ops */
else e = parsebin(start, end, lowest, ctx);
- /* TODO something here that sets the type of an rexpr */
return e;
}
+int
+isbasictype(char *t) {
+ for (int i = 0; i < SIZE(builtintypes); i++)
+ if (SAME(t, builtintypes[i]))
+ return 1;
+ return 0;
+}
+
type *
parsetype(lex *l, mctx *ctx) {
SAVE(l);
@@ -287,6 +312,11 @@ parsetype(lex *l, mctx *ctx) {
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;
@@ -489,13 +519,29 @@ parselexpr(lex *l, mctx *ctx) {
SAVE(l);
lexpr *le;
fn *f;
- tok t = next(l);
+ tok t = next(l), *ts = NULL;
+ int tsc = 0;
switch (t.op) {
case NAME:
- if (!(le = parseassign(l, t, ctx))) {
- le = parsereassign(l, t, ctx);
+ if (*l->ptr == '(') {
+ ts = alloczctx(ctx, sizeof(tok));
+ ts[tsc++] = t;
+ while ((t = next(l)).op != ';') {
+ ts = realloczctx(ctx, ts, ++tsc * sizeof(tok));
+ ts[tsc - 1] = t;
+ }
+
+ le = alloczctx(ctx, sizeof(lexpr));
+ le->rexpr = parsefcall(ts, &ts[tsc - 1], ctx);
+ if (!le->rexpr) {
+ RESTORE(l);
+ return NULL;
+ }
+ le->op = LEXPR_FCALL;
}
+ else if (!(le = parseassign(l, t, ctx)))
+ le = parsereassign(l, t, ctx);
break;
case FUNC:
le = parsefunc(l, ctx); /* we can drop the FUNC token, as it doesnt hold any info */
@@ -519,6 +565,21 @@ parselexpr(lex *l, mctx *ctx) {
}
funcs = addmap(funcs, f, f->name, ctx);
break;
+ case RETURN:
+ le = alloczctx(ctx, sizeof(lexpr));
+ le->op = RETURN;
+ if (*l->ptr == ';')
+ break;
+
+ while ((t = next(l)).op != ';') {
+ ts = realloczctx(ctx, ts, ++tsc * sizeof(tok));
+ ts[tsc - 1] = t;
+ }
+
+ le->ret = parserexpr(ts, &ts[tsc - 1], ctx);
+ break;
+ case LEOF:
+ return NULL;
default:
parserErr("unexpected tok type");
}
diff --git a/parse.h b/parse.h
@@ -8,6 +8,7 @@ enum lexpr_ops {
LEXPR_ASSIGN,
LEXPR_FUNC,
LEXPR_REASSIGN,
+ LEXPR_FCALL,
};
enum type_types {
@@ -61,6 +62,7 @@ typedef struct lexpr {
struct lexpr *body;
int bodyc;
};
+ rexpr *ret; /* the return value for return statements */
};
} lexpr;
diff --git a/spl.c b/spl.c
@@ -21,14 +21,16 @@ main(int argc, char **argv) {
lex l = mklexer(file);
mctx *ctx = newctx();
- lexpr *e = parselexpr(&l, ctx);
- if (!e) {
- parserErr("failed to parse lexpr");
- goto cleanup;
+ lexpr *xs = NULL, *x;
+ int lexprc = 0;
+ while (x = parselexpr(&l, ctx)) {
+ xs = realloczctx(ctx, xs, ++lexprc * sizeof(lexpr));
+ xs[lexprc - 1] = *x;
}
-
- fprintf(stdout, "#include <stdint.h>\n");
- compilelexpr_C(e, stdout);
+ if (lexprc)
+ fprintf(stdout, "#include <stdint.h>\n");
+ for (int i = 0; i < lexprc; i++)
+ compilelexpr_C(&xs[i], stdout);
cleanup:
free(file);
diff --git a/test.spl b/test.spl
@@ -1,3 +1,5 @@
+func foo() void;
+
func main() i32 {
- a i64 = i32(30);
+ foo();
}