G

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

AuthorJakob Wakeling <[email protected]>
Date2023-06-21 10:05:21
Commite91c41c67b91e52b496da535c5e020965e7c19b5
Parent74972c29942d72717c2d02e107d1d035fbc75494

Implement booleans

Diffstat

M README.md | 4 ++--
M examples/main.g | 5 ++---
M src/analyse.c | 11 ++++++++++-
M src/llvm.c | 26 +++++++++++++++++++++-----
M src/parse.c | 6 +++++-
M src/parse.h | 2 +-
M src/type.c | 4 ++++
M src/type.h | 1 +

8 files changed, 46 insertions, 13 deletions

diff --git a/README.md b/README.md
index eb424cf..289bad9 100644
--- a/README.md
+++ b/README.md
@@ -61,10 +61,10 @@ command. The second command will output an executable file, *a.out* by default.
 - [x] Implement procedure calls
 - [ ] Implement procedure arguments
 - [x] Implement variables
-- [ ] Implement booleans
+- [x] Implement booleans
 - [x] Implement integers
 - [x] Implement reals
-- [ ] Implement pointers
+- [x] Implement pointers
 - [ ] Implement arrays
 - [x] Implement expressions
 - [x] Implement type casting
diff --git a/examples/main.g b/examples/main.g
index 60b4b2f..ffc53d8 100644
--- a/examples/main.g
+++ b/examples/main.g
@@ -1,5 +1,4 @@
 main :: proc() -> u64 {
-	var1 : f32 = f32(1.0);
-	var2 : *f32 = &var1;
-	return u64(var2);
+	var := true;
+	return u64(var);
 }
diff --git a/src/analyse.c b/src/analyse.c
index 7f69f18..56683a6 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -57,6 +57,15 @@ static void analyse_stmt_decl(ast *a, syt *st) {
 	type *value_type = ast_type(C[0], st);
 
 	if (C[0]->k == AK_PROC) { return; /* TODO */ }
+	else if (is_bool(value_type)) {
+		/* If a type has not been specified, set the type based on the value */
+		if (a->t == NULL) { a->t = C[0]->t; }
+		
+		/* If the type has been specified, check that the value is compatible */
+		else {
+			/* TODO */
+		}
+	}
 	else if (is_int(value_type)) {
 		/* If a type has not been specified, set the type based on the value */
 		if (a->t == NULL) {
@@ -96,7 +105,7 @@ static void analyse_stmt_decl(ast *a, syt *st) {
 		}
 	}
 
-	else { note("TODO", a->ln, a->cl, -1, "unhandled value kind %s", ast_ks[a->c.a[0]->k]); }
+	else { note("TODO", A.ln, A.cl, -1, "Unhandled value kind %s", ast_ks[C[0]->k]); }
 }
 
 /* Analyse a return statement. */
diff --git a/src/llvm.c b/src/llvm.c
index 2fbc9d1..416afa6 100644
--- a/src/llvm.c
+++ b/src/llvm.c
@@ -40,6 +40,7 @@ static LLVMValueRef llvm_expr(ast *a, syt *st);
 static LLVMValueRef llvm_expr_proc(ast *a, syt *st);
 static LLVMValueRef llvm_expr_cast(ast *a, syt *st);
 
+static LLVMValueRef llvm_bool(ast *a);
 static LLVMValueRef llvm_int(ast *a);
 static LLVMValueRef llvm_flt(ast *a);
 
@@ -238,8 +239,9 @@ static LLVMValueRef llvm_expr(ast *a, syt *st) {
 	switch (A.k) {
 	case AK_PROC: { return llvm_expr_proc(a, st); } break;
 	case AK_CAST: { return llvm_expr_cast(a, st); } break;
-	case AK_INT: { return llvm_int(a); } break;
-	case AK_FLT: { return llvm_flt(a); } break;
+	case AK_BOOL: { return llvm_bool(a); } break;
+	case AK_INT:  { return llvm_int(a); } break;
+	case AK_FLT:  { return llvm_flt(a); } break;
 	case AK_ID_VAR: {
 		ast *v = syt_search(st, a->s);
 		if (v == NULL) { note(file_name, A.ln, A.cl, 0, "Undefined variable %s", A.s); }
@@ -310,9 +312,14 @@ static LLVMValueRef llvm_expr_cast(ast *a, syt *st) {
 			return LLVMBuildPtrToInt(llvm_builder, llvm_expr(C[0], st), llvm_type(a->t), "");
 		}
 	}
-	else if (is_int(expr_type)) {
+	else if (is_bool(expr_type)) {
 		if (is_int(a->t)) {
-			return LLVMBuildIntCast2(llvm_builder, llvm_expr(C[0], st), llvm_type(a->t), is_sign(a->t), "cast");
+			return LLVMBuildIntCast2(llvm_builder, llvm_expr(C[0], st), llvm_type(a->t), is_sign(a->t), "");
+		}
+	}
+	else if (is_int(expr_type)) {
+		if (is_bool(a->t) || is_int(a->t)) {
+			return LLVMBuildIntCast2(llvm_builder, llvm_expr(C[0], st), llvm_type(a->t), is_sign(a->t), "");
 		}
 		else if (is_flt(a->t)) {
 			if (is_sign(expr_type)) {
@@ -340,6 +347,11 @@ static LLVMValueRef llvm_expr_cast(ast *a, syt *st) {
 	note(file_name, A.ln, A.cl, -1, "unhandled type %s or %s (llvm:llvm_expr_cast)", expr_type->s, a->t->s);
 }
 
+/* Generate IR for a boolean. */
+static LLVMValueRef llvm_bool(ast *a) {
+	return LLVMConstInt(llvm_type(a->t), a->v.v_bool, false);
+}
+
 /* Generate IR for an integer. */
 static LLVMValueRef llvm_int(ast *a) {
 	return LLVMConstInt(llvm_type(a->t), a->v.v_int, false);
@@ -414,6 +426,7 @@ static LLVMTypeRef llvm_type(type *t) {
 	switch (t->k) {
 	case TY_VOID: { return LLVMVoidType();  } break;
 	case TY_PTR:  { return LLVMPointerType(llvm_type(t->base), 0); } break;
+	case TY_BOOL: { return LLVMIntType(8);  } break;
 	case TY_B8:   { return LLVMIntType(8);  } break;
 	case TY_B16:  { return LLVMIntType(16); } break;
 	case TY_B32:  { return LLVMIntType(32); } break;
@@ -438,6 +451,7 @@ static LLVMTypeRef llvm_type(type *t) {
 static LLVMValueRef llvm_ival(type *t) {
 	switch (t->k) {
 	case TY_PTR:  { return LLVMConstNull(llvm_type(t->base)); } break;
+	case TY_BOOL: { return LLVMConstInt(LLVMIntType(8),   0, false); } break;
 	case TY_B8:   { return LLVMConstInt(LLVMIntType(8),   0, false); } break;
 	case TY_B16:  { return LLVMConstInt(LLVMIntType(16),  0, false); } break;
 	case TY_B32:  { return LLVMConstInt(LLVMIntType(32),  0, false); } break;
diff --git a/src/parse.c b/src/parse.c
index d8449eb..c800c0d 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -26,7 +26,7 @@ char *ast_ks[] = {
 
 	"AK_ASSIGN", "AK_AS_ADD", "AK_AS_SUB", "AK_AS_MUL", "AK_AS_DIV", "AK_AS_MOD",
 
-	"AK_ID_VAR", "AK_CALL", "AK_INT", "AK_FLT",
+	"AK_ID_VAR", "AK_CALL", "AK_INT", "AK_FLT", "AK_BOOL",
 
 	"AK_HASH_SYSCALL"
 };
@@ -42,6 +42,7 @@ static ast *parse_stmt_for(lex *l, syt *st);
 static ast *parse_expr(lex *l, syt *st, s32 o);
 static ast *parse_expr_proc(lex *l, syt *st);
 
+static inline ast *parse_bool(lex *l, syt *st);
 static ast *parse_num(lex *l, syt *st);
 static ast *parse_int(lex *l, syt *st);
 static ast *parse_flt(lex *l, syt *st);
@@ -271,6 +272,9 @@ static ast *parse_expr(lex *l, syt *st, s32 o) {
 
 		if (!(left->s = strdup(t.s))) { error(1, "%s", SERR); }
 	} break;
+	case TK_TRUE:   { left = ast_kind(AK_BOOL); left->v.v_bool = true;  } goto boolean;
+	case TK_FALSE:  { left = ast_kind(AK_BOOL); left->v.v_bool = false; } goto boolean;
+	boolean: { left->ln = T.ln; left->cl = T.cl; left->t = &TYPE(TY_BOOL); lex_next(l); } break;
 	case TK_NUM:    { left = parse_num(l, st);       } break;
 	case TK_PROC:   { return parse_expr_proc(l, st); } break;
 	case TK_HASH: {
diff --git a/src/parse.h b/src/parse.h
index f33d96f..25b2675 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -25,7 +25,7 @@ typedef enum {
 
 	AK_ASSIGN, AK_AS_ADD, AK_AS_SUB, AK_AS_MUL, AK_AS_DIV, AK_AS_MOD,
 
-	AK_ID_VAR, AK_CALL, AK_INT, AK_FLT,
+	AK_ID_VAR, AK_CALL, AK_INT, AK_FLT, AK_BOOL,
 
 	AK_HASH_SYSCALL
 } ast_k;
diff --git a/src/type.c b/src/type.c
index e201182..ef7eb0c 100644
--- a/src/type.c
+++ b/src/type.c
@@ -139,6 +139,9 @@ type *type_ptrc(type *base, u64 n) {
 /* Check if a type is a pointer. */
 inline bool is_ptr(type *t) { return (t->f & TF_PTR); }
 
+/* Check if a type is a boolean. */
+inline bool is_bool(type *t) { return (t->f & TF_BOOL); }
+
 /* 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 079a41b..2dd425e 100644
--- a/src/type.h
+++ b/src/type.h
@@ -66,6 +66,7 @@ extern type_a types_a;
 extern type *type_ptrc(type *base, u64 n);
 
 extern bool is_ptr(type *t);
+extern bool is_bool(type *t);
 extern bool is_num(type *t);
 extern bool is_int(type *t);
 extern bool is_flt(type *t);