Author | Jakob Wakeling <[email protected]> |
Date | 2023-06-16 13:22:50 |
Commit | f782ab77f3815498c6a66fa186799d604ac01196 |
Parent | 19793bd05244bc52fa239c26f4fc71415de221bb |
Implement pointer chain types
Diffstat
M | examples/main.g | | | 4 | ++-- |
M | src/main.c | | | 8 | +++++--- |
M | src/parse.c | | | 15 | ++++++++------- |
M | src/type.c | | | 45 | ++++++++++++++++++++++++++++++++++++++------- |
M | src/type.h | | | 6 | ++++-- |
5 files changed, 57 insertions, 21 deletions
diff --git a/examples/main.g b/examples/main.g index 09b6fc1..bb04a56 100644 --- a/examples/main.g +++ b/examples/main.g @@ -1,4 +1,4 @@ main :: proc() -> u32 { - #syscall(u64(60), u64(42)); - return u32(s32(-1.0)); + var : *u32 = &u32(4); + return *var; } diff --git a/src/main.c b/src/main.c index 3d25b5b..4e412fd 100644 --- a/src/main.c +++ b/src/main.c @@ -29,6 +29,7 @@ static char *aw[] = { static bool bflag = false, Bflag = false, cflag = false; static bool Eflag = false, pflag = false, Pflag = false; +static bool qflag = false; static void compile(const char *file, char *src, UINT len); static void compile_file(const char *file); @@ -44,7 +45,7 @@ int main(int ac, char *av[]) { A0 = av[0]; /* DEBUG */ if (ac == 1) { ac = (sizeof (aw) / sizeof (*aw)) - 1; av = aw; } - struct opt opt = OPTGET_INIT; opt.str = "bBcEf:O:pPW:"; opt.lops = lops; + struct opt opt = OPTGET_INIT; opt.str = "bBcEf:O:pPqW:"; opt.lops = lops; for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { case 'b': { bflag = true; } break; /* Output LLVM IR files */ case 'B': { Bflag = true; } break; /* Output LLVM bitcode files */ @@ -54,6 +55,7 @@ int main(int ac, char *av[]) { A0 = av[0]; case 'O': { opt_O(opt.arg); } break; /* Configure optimisation */ case 'p': { pflag = true; } break; /* Output parser AST */ case 'P': { Pflag = true; } break; /* Output analyser AST */ + case 'q': { qflag = true; } break; /* Silence certain outputs (for benchmarking) */ case 'W': { opt_W(opt.arg); } break; /* Configure warnings and errors */ case 256: { hlp(); } return 0; case 257: { ver(); } return 0; @@ -73,10 +75,10 @@ static void compile(const char * file, char *src, UINT len) { if (Eflag) { lex_debug(&l); goto end; } ast *a = parse(&l); - if (pflag) { ast_print(a, 0); goto end; } + if (pflag) { if (!qflag) { ast_print(a, 0); } goto end; } analyse(a); - if (Pflag) { ast_print(a, 0); goto end; } + if (Pflag) { if (!qflag) { ast_print(a, 0); } goto end; } if (bflag) { llvm_ir(a); } else if (Bflag) { llvm_bitcode(a); } diff --git a/src/parse.c b/src/parse.c index c896a3c..3274d20 100644 --- a/src/parse.c +++ b/src/parse.c @@ -170,6 +170,8 @@ static ast *parse_stmt_decl(lex *l, syt *st, ast *a) { a->k = AK_DECL; lex_kind(l, TK_COLON); + u64 pn = 0; for (; T.k == TK_OP_MUL; lex_next(l), pn += 1); + /* Store the declaration's type if one is specified */ if (T.k == TK_ID) { ast *s = syt_search_h(st, T.h, T.s); @@ -183,13 +185,11 @@ static ast *parse_stmt_decl(lex *l, syt *st, ast *a) { l->n, T.ln + 1, T.cl + 1 ); } - a->t = s->t; lex_next(l); + a->t = type_ptrc(s->t, pn); lex_next(l); if (T.k == TK_SCOLON) { lex_next(l); goto end; } } - else if (T.k == TK_SCOLON) { error( - 1, "%s:%zu:%zu: error: a declaration without a type is invalid", - l->n, T.ln + 1, T.cl + 1 - ); } + else if (pn != 0) { note(l->n, T.ln, T.cl, 1, "Expected a type identifier for pointer type"); } + else if (T.k == TK_SCOLON) { note(l->n, T.ln, T.cl, 1, "A declaration without a type is invalid"); } /* Assign a constant or variable value */ if (T.k == TK_COLON || T.k == TK_ASSIGN) { lex_next(l); ast_push(a, parse_expr(l, st, 0)); } @@ -449,6 +449,9 @@ void ast_print(ast *a, UINT i) { case AK_DECL: { if (a->t == NULL) { break; }} case AK_PROC: case AK_CAST: case AK_INT: case AK_FLT: { printf(" -> %s", a->t != NULL ? a->t->s : "untyped"); + if (a->t != NULL) for (type *t = a->t->base; t != NULL; t = t->base) { + printf(" -> %s", t->s); + } } break; default: {} break; } diff --git a/src/type.c b/src/type.c index e053f0e..f5b7a4d 100644 --- a/src/type.c +++ b/src/type.c @@ -4,6 +4,9 @@ // All rights reserved. #include "type.h" +#include "util/error.h" + +#include <stdlib.h> type types[] = { { TY_ZERO, 0, 0, "void" }, @@ -97,17 +100,41 @@ type types[] = { { TY_STR, TF_STR, -1, "str" }, }; -/* Initialise a new type. */ -// type *type_init(type *base) { -// type *t = calloc(1, sizeof (type)); if (!t) { return NULL; } -// *t = *base; t->base = base; return t; -// } +type_a types_a = { NULL, 0, 0 }; + +/* Ensure that the types array has a minimum number of spaces. */ +static inline void types_alloc(type_a *ta, u64 min) { + if (ta->a == NULL) { + ta->ac = 128; ta->a = malloc(ta->ac * sizeof (type)); + if (ta->a == NULL) { error(1, "types: %s", SERR); } + } + + register u64 mul = 1, sp = ta->ac - ta->al; + for (; sp < min; mul *= 2, sp = (ta->ac * mul) - ta->al); + + if (mul > 1) { + ta->ac *= mul; ta->a = realloc(ta->a, ta->ac * sizeof (type)); + if (ta->a == NULL) { error(1, "types: %s", SERR); } + } +} + +/* Get the next type slot in the type array. */ +static inline type *types_next(type_a *ta) { + if ((ta->ac - ta->al) < 1) { types_alloc(ta, 1); } + register type *r = &ta->a[ta->al]; ta->al += 1; return r; +} -/* Initialise a new pointer type. */ -// type *ptrt_init(type *base) { -// type *t = calloc(1, sizeof (type)); if (!t) { return NULL; } -// t->k = TY_PTR; t->l = -1; t->base = base; return t; -// } +/* Initialise a new pointer chain type. */ +type *type_ptrc(type *base, u64 n) { + types_alloc(&types_a, n); type *r = base; + + for (u64 i = 0; i < n; i += 1) { + register type *t = types_next(&types_a); + *t = TYPE(TY_PTR); t->base = r; r = t; + } + + return r; +} /* Check if a type is numerical. */ inline bool is_num(type *t) { return (t->f & TF_NUM); } diff --git a/src/type.h b/src/type.h index 9a56b7a..fc07919 100644 --- a/src/type.h +++ b/src/type.h @@ -58,10 +58,12 @@ typedef struct type_s { struct type_s *base; } type; +typedef struct { type *a; UINT al, ac; } type_a; + extern type types[]; +extern type_a types_a; -// extern type *type_init(type *base); -// extern type *ptrt_init(type *base); +extern type *type_ptrc(type *base, u64 n); extern bool is_num(type *t); extern bool is_int(type *t);