Author | Jakob Wakeling <[email protected]> |
Date | 2023-06-21 10:05:21 |
Commit | e91c41c67b91e52b496da535c5e020965e7c19b5 |
Parent | 74972c29942d72717c2d02e107d1d035fbc75494 |
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);