G

G Programming Language
git clone http://git.omkov.net/G
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2023-06-16 13:22:50
Commitf782ab77f3815498c6a66fa186799d604ac01196
Parent19793bd05244bc52fa239c26f4fc71415de221bb

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);