spl

a Simple Programming Language
Log | Files | Refs

commit cd52eda689ea5f02b61f126fd0ffc456a35391da
parent da26e040551f989e0a85f9c617625d833f7fc41c
Author: thing1 <thing1@seacrossedlovers.xyz>
Date:   Sat, 17 Jan 2026 18:32:50 +0000

update

Diffstat:
Mcback.c | 21++++++++++++++++++++-
Mlexer.c | 11+++++++++++
Mlexer.h | 3+++
Mparse.c | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mparse.h | 12+++++++++++-
Mrt/array.c | 4++--
Mtest.spl | 7+------
7 files changed, 103 insertions(+), 18 deletions(-)

diff --git a/cback.c b/cback.c @@ -55,6 +55,9 @@ compiletype_C(type *t, FILE *f) { compiletype_C(t->nested, f); fprintf(f, "*"); break; + case ARR: + fprintf(f, "array*"); + break; } } @@ -95,6 +98,10 @@ compilerexpr_C(rexpr *r, FILE *f) { compiletype_C(r->type, f); fprintf(f, " v%d = %s;\n", vid++, r->name); return vid - 1; + case DQUOTE: + compiletype_C(r->type, f); + fprintf(f, " v%d;\n", vid++); + return vid - 1; case FUNCALL: right = compilefcall_C(r, f); compiletype_C(r->type, f); @@ -157,11 +164,23 @@ compilefunc_C(lexpr *l, FILE *f) { void compileassign_C(lexpr *l, FILE *f) { - int id; + int id, sizeid; if (l->rexpr) id = compilerexpr_C(l->rexpr, f); + if (l->type->type == ARR && l->type->size) + sizeid = compilerexpr_C(l->type->size, f); + compiletype_C(l->type, f); fprintf(f, " %s", l->name); + + if (l->type->type == ARR) { + fprintf(f, " = newarray("); + if (l->type->size) fprintf(f, "v%d, sizeof(", sizeid); + else fprintf(f, "0, sizeof("); + + compiletype_C(l->type->nested, f); + fprintf(f, "))"); + } if (l->rexpr) fprintf(f, " = v%d;\n", id); else diff --git a/lexer.c b/lexer.c @@ -69,6 +69,8 @@ next(lex *l) { l->prev = l->ptr; tok t = {0}; t.l = *l; + char *estring; + switch (*l->ptr) { case 0: t.op = LEOF; @@ -81,6 +83,13 @@ next(lex *l) { l->ptr++; return next(l); + case DQUOTE: + t.op = DQUOTE; + *(estring = strchr(++l->ptr, '\"')) = 0; + t.name = strdup(l->ptr); + l->ptr = estring + 1; + return t; + case ADD: case SUB: case MUL: @@ -89,6 +98,8 @@ next(lex *l) { case CBRACE: case OCBRACE: case CCBRACE: + case OSBRACE: + case CSBRACE: case ASSIGN: case SEMI: case COMMA: diff --git a/lexer.h b/lexer.h @@ -16,6 +16,9 @@ enum lex_ops { CBRACE = ')', OCBRACE = '{', CCBRACE = '}', + OSBRACE = '[', + CSBRACE = ']', + DQUOTE = '\"', LEOF = '$', ASSIGN = '=', SEMI = ';', diff --git a/parse.c b/parse.c @@ -56,6 +56,22 @@ isbasictype(char *t) { return 0; } +type * +mkbasictype(char *name, mctx *ctx) { + type *t = alloczctx(ctx, sizeof(type)); + t->type = BASIC; + t->name = strdup(name); + return t; +} + +type * +mkarrtype(type *nested, mctx *ctx) { + type *t = alloczctx(ctx, sizeof(type)); + t->type = ARR; + t->nested = nested; + return t; +} + int getpres(tok t) { switch (t.op) { @@ -142,13 +158,6 @@ findlowest(tok *start, tok *end) { return lowest; } -type * -mkbasictype(char *name, mctx *ctx) { - type *t = alloczctx(ctx, sizeof(type)); - t->type = BASIC; - t->name = strdup(name); - return t; -} /* checks if t2 can be losslessly casted to t1 */ int @@ -160,6 +169,8 @@ isequaltype(type *t1, type *t2) { } } else if (t1->type == PTR && t2->type == PTR) return isequaltype(t1->nested, t2->nested); + else if (t1->type == ARR && t2->type == ARR) + return isequaltype(t1->nested, t2->nested); return 0; } @@ -243,9 +254,18 @@ mkptrtype(type *t, mctx *ctx) { } rexpr * +mklitteral(uint64_t n, type *t, mctx *ctx) { + rexpr *e = alloczctx(ctx, sizeof(rexpr)); + e->type = t; + e->n = n; + return e; +} + +rexpr * parsesimple(tok *start, tok *end, tok *lowest, mctx *ctx) { rexpr *e; var *v; + tok *current; switch (lowest->op) { case NAME: @@ -285,6 +305,15 @@ parsesimple(tok *start, tok *end, tok *lowest, mctx *ctx) { break; } break; + case DQUOTE: + e = alloczctx(ctx, sizeof(rexpr)); + e->op = DQUOTE; + for (e->elementc = 0; e->elementc < strlen(lowest->name); e->elementc++) { + e->elements = realloczctx(ctx, e->elements, (1 + e->elementc) * sizeof(rexpr)); + e->elements[e->elementc] = *mklitteral(lowest->name[e->elementc], mkbasictype("i8", ctx), ctx); + } + e->type = mkarrtype(mkbasictype("i8", ctx), ctx); + break; case OBRACE: e = alloczctx(ctx, sizeof(rexpr)); e->op = OBRACE; @@ -361,12 +390,30 @@ type * parsetype(lex *l, mctx *ctx) { SAVE(l); type *ty; - tok t = next(l); + tok t = next(l), *ts = NULL; + int tcount = 0; ty = alloczctx(ctx, sizeof(type)); + if (t.op == MUL) { ty->type = PTR; ty->nested = parsetype(l, ctx); return ty; + } else if (t.op == OSBRACE) { + if ((t = next(l)).op != CSBRACE) { + do { + ts = realloczctx(ctx, ts, ++tcount * sizeof(tok)); + ts[tcount - 1] = t; + } while ((t = next(l)).op != CSBRACE); + ty->size = parserexpr(ts, &ts[tcount - 1], ctx); + if (!isequaltype(mkbasictype("i64", ctx), ty->size->type)) { + parserErr("can not use non int type as array size", *l); + RESTORE(l); + return NULL; + } + } + ty->type = ARR; + ty->nested = parsetype(l, ctx); + return ty; } else if (t.op != NAME) { RESTORE(l); return NULL; diff --git a/parse.h b/parse.h @@ -14,13 +14,19 @@ enum lexpr_ops { enum type_types { BASIC, PTR, + ARR, }; +typedef struct rexpr rexpr; + typedef struct type { enum type_types type; union { char *name; /* basic types */ - struct type *nested; /* ptr types */ + struct { + struct type *nested; /* ptr types */ + rexpr *size; + }; }; } type; @@ -44,6 +50,10 @@ typedef struct rexpr { uint64_t n; double f; char *name; + struct { /* array litterals */ + rexpr *elements; + int elementc; + }; }; } rexpr; diff --git a/rt/array.c b/rt/array.c @@ -9,8 +9,8 @@ array * newarray(int cap, int size) { cap = (!cap) ? 1 : cap; array *a = malloc(sizeof(array)); - a->arr = malloc(cap); - a->cap = cap; + a->arr = malloc(cap * size); + a->cap = cap * size; a->len = 0; a->size = size; return a; diff --git a/test.spl b/test.spl @@ -1,8 +1,3 @@ -func foo() i32 { - a i32 = 21; - return a; -} - func main() i32 { - a i32 = i16(400); + arr []i8 = "hello world"; }