G

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

AuthorJakob Wakeling <[email protected]>
Date2023-05-02 11:13:39
Commit4bdd6fc6552ec5e4bc4d6c05c7f84ea03b3bc612
Parent6dd92231459df661805b3d79c648ceb86f29413c

Implement zero value variable initialisation

Diffstat

M examples/main.g | 3 +--
M src/analyse.c | 2 +-
M src/llvm.c | 32 ++++++++++++++++++++++++++++----
M src/parse.c | 3 ++-
M src/type.h | 1 +

5 files changed, 33 insertions, 8 deletions

diff --git a/examples/main.g b/examples/main.g
index dc809b6..02cf938 100644
--- a/examples/main.g
+++ b/examples/main.g
@@ -1,5 +1,4 @@
 main :: proc() -> s64 {
-	var := 42 + 8;
-	var += 2;
+	var: s64;
 	return var;
 }
diff --git a/src/analyse.c b/src/analyse.c
index d1a0e1f..3226257 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -61,7 +61,7 @@ static void analyse_stmt_decl(ast *a, syt *st) {
 	}
 
 	/* If the declaration is already typed, then ensure that it matches */
-	if (A.t) { if (A.t != t) {
+	if (A.t) { if (t != NULL && A.t != t) {
 		error(1, "%s:%zu:%zu: error: incorrect type", "", A.ln + 1, A.cl + 1);
 	}}
 
diff --git a/src/llvm.c b/src/llvm.c
index 5eeb3e6..2d917b3 100644
--- a/src/llvm.c
+++ b/src/llvm.c
@@ -40,6 +40,7 @@ static LLVMValueRef llvm_int(ast *a);
 static inline void llvm_init(void);
 static inline void llvm_free(void);
 static LLVMTypeRef llvm_type(type *t);
+static LLVMValueRef llvm_ival(type *t);
 
 #define A (*a)
 #define C (a->c.a) /* AST child shorthand "C[i]" */
@@ -108,7 +109,7 @@ static LLVMValueRef llvm_stmt_compound(ast *a, syt *st) {
 static LLVMValueRef llvm_stmt_decl(ast *a, syt *st) {
 	assert(a->k == AK_DECL);
 
-	if (C[0]->k == AK_PROC) {
+	if (a->c.al && C[0]->k == AK_PROC) {
 		/* TODO handle procedure arguments if present */
 		LLVMTypeRef ft = LLVMFunctionType(llvm_type(C[0]->t), NULL, 0, 0);
 		LLVMValueRef f = LLVMAddFunction(llvm_module, a->s, ft);
@@ -119,13 +120,15 @@ static LLVMValueRef llvm_stmt_decl(ast *a, syt *st) {
 		llvm_expr_proc(C[0], st); a->llvm_t = ft; a->llvm_v = f;
 	}
 	else {
-		if (a->p->k == AK_PROG) {
+		if (a->p->k == AK_PROG) { /* Global */
 			LLVMValueRef v = LLVMAddGlobal(llvm_module, llvm_type(A.t), a->s);
-			LLVMSetInitializer(v, llvm_expr(C[0], st)); a->llvm_v = v;
+			LLVMSetInitializer(v, a->c.al ? llvm_expr(C[0], st) : llvm_ival(a->t));
+			a->llvm_v = v;
 		}
-		else {
+		else { /* Local */
 			LLVMValueRef v = LLVMBuildAlloca(llvm_builder, llvm_type(A.t), a->s);
-			LLVMBuildStore(llvm_builder, llvm_expr(C[0], st), v); a->llvm_v = v;
+			LLVMBuildStore(llvm_builder, a->c.al ? llvm_expr(C[0], st) : llvm_ival(a->t), v);
+			a->llvm_v = v;
 		}
 	}
 
@@ -276,3 +279,20 @@ static LLVMTypeRef llvm_type(type *t) {
 	default: { return NULL; } break;
 	}
 }
+
+/* Return the default value for a G type. */
+static LLVMValueRef llvm_ival(type *t) {
+	switch (t->k) {
+	case TY_UINT: case TY_SINT: { return LLVMConstInt(LLVMIntType(64),  0, false); } break;
+	case TY_U8:   case TY_S8:   { return LLVMConstInt(LLVMIntType(8),   0, false); } break;
+	case TY_U16:  case TY_S16:  { return LLVMConstInt(LLVMIntType(16),  0, false); } break;
+	case TY_U32:  case TY_S32:  { return LLVMConstInt(LLVMIntType(32),  0, false); } break;
+	case TY_U64:  case TY_S64:  { return LLVMConstInt(LLVMIntType(64),  0, false); } break;
+	case TY_U128: case TY_S128: { return LLVMConstInt(LLVMIntType(128), 0, false); } break;
+	case TY_F16:  { return LLVMConstReal(LLVMHalfType(),   0.0); } break;
+	case TY_F32:  { return LLVMConstReal(LLVMFloatType(),  0.0); } break;
+	case TY_F64:  { return LLVMConstReal(LLVMDoubleType(), 0.0); } break;
+	case TY_F128: { return LLVMConstReal(LLVMFP128Type(),  0.0); } break;
+	default: { return NULL; } break;
+	}
+}
diff --git a/src/parse.c b/src/parse.c
index aa9b2ec..f4f8160 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -120,7 +120,6 @@ static ast *parse_stmt_decl(lex *l, syt *st) {
 	lex_kind(l, TK_COLON);
 
 	/* Store the declaration's type if one is specified */
-	/* TODO store type when one is specified */
 	if (T.k == TK_ID) {
 		ast *s = syt_search_h(st, T.h, T.s);
 
@@ -359,6 +358,7 @@ void ast_print(ast *a, UINT i) {
 	printf("%zu:%zu: %s: %s", a->ln + 1, a->cl + 1, ast_ks[a->k], a->s);
 
 	switch (a->k) {
+	case AK_DECL: { if (a->t == NULL) { break; }}
 	case AK_PROC: case AK_INT: { printf(" -> %s", a->t->s); } break;
 	default: {} break;
 	}
diff --git a/src/type.h b/src/type.h
index ec7bb41..e818f2f 100644
--- a/src/type.h
+++ b/src/type.h
@@ -52,6 +52,7 @@ typedef enum {
 	TF_NUM  = TF_INT | TF_FLT | TF_CLX,
 } type_f;
 
+/* k : Kind, f : Flags, l : Length, s : String */
 typedef struct type_s {
 	type_k k; type_f f; s64 l; char *s;
 	struct type_s *base;