Skip to content

Commit 3d92e90

Browse files
committed
compiler: refactor anytype '#' handling
struct Type now has a property 'bool is_anytype' to represent the anytype. Anytype can be used to override the typechecker. For example, calling a memory allocation function returns a pointer, which can be a used as a pointer to any other type, whatever is put there. Anytype should have the highest native width of the architecture which is targeted, so 8 bytes for x86-64, and 2 bytes for AVR.
1 parent b804e68 commit 3d92e90

File tree

14 files changed

+65
-18
lines changed

14 files changed

+65
-18
lines changed

ast/ast/ast_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ struct Type {
6969
struct TypeParam* type_param;
7070
struct ArrayType* array_type;
7171
struct PointerType* pointer_type;
72+
73+
// '#', stands for anything,
74+
// always has highest native width of the architecture,
75+
// e.g. x86: 8 bytes, avr: 2 bytes
76+
bool is_anytype;
7277
};
7378

7479
struct TypeParam {

ast/test/test_str_ast.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ void test_ast_str_expr() {
104104

105105
char* s = str_expr(&e);
106106

107-
assert(strcmp(s, "-45*-45") == 0);
107+
assert(strcmp(s, "-45 * -45") == 0);
108108

109109
free_un_op_term(u2);
110110
free(s);

ast/util/copy_ast.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ struct Type* copy_type(struct Type* t) {
179179
res->type_param = NULL;
180180
res->array_type = NULL;
181181
res->pointer_type = NULL;
182+
res->is_anytype = t->is_anytype;
182183

183184
if (t->basic_type != NULL) { res->basic_type = copy_basic_type(t->basic_type); }
184185
if (t->type_param != NULL) { res->type_param = copy_type_param(t->type_param); }

ast/util/equals_ast.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ bool eq_type(struct Type* a, struct Type* b) {
1717

1818
if (a->pointer_type != NULL) { return eq_pointertype(a->pointer_type, b->pointer_type); }
1919

20+
if (a->is_anytype && b->is_anytype) {
21+
return true;
22+
}
23+
2024
return false;
2125
}
2226

ast/util/str_ast.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,10 @@ char* str_type(struct Type* t) {
293293

294294
if (t->pointer_type != NULL) { return str_pointer_type(t->pointer_type); }
295295

296+
if (t->is_anytype) {
297+
return strdup("#");
298+
}
299+
296300
error("str_type");
297301
return NULL;
298302
}
@@ -494,15 +498,15 @@ char* str_expr(struct Expr* e) {
494498
return NULL;
495499
}
496500

497-
uint16_t l = strlen(strTerm1) + strlen(strO) + strlen(strTerm2) + 1;
501+
uint16_t l = strlen(strTerm1) + strlen(strO) + strlen(strTerm2) + 3;
498502

499503
char* res = malloc(sizeof(char) * l);
500504

501505
if (!res) {
502506
return NULL;
503507
}
504508

505-
sprintf(res, "%s%s%s", strTerm1, strO, strTerm2);
509+
sprintf(res, "%s %s %s", strTerm1, strO, strTerm2);
506510

507511
free(strTerm1);
508512

@@ -512,6 +516,7 @@ char* str_expr(struct Expr* e) {
512516
return res;
513517
}
514518

519+
// @returns NULL on error
515520
char* str_op(enum OP o) {
516521

517522
char* res = malloc(sizeof(char) * 16);
@@ -533,8 +538,18 @@ char* str_op(enum OP o) {
533538
case OP_OR: str = "|"; break;
534539
case OP_XOR: str = "^"; break;
535540

541+
// relational
542+
case OP_EQ: str = "=="; break;
543+
case OP_NEQ: str = "!="; break;
544+
case OP_GE: str = ">="; break;
545+
case OP_GT: str = ">"; break;
546+
case OP_LE: str = "<="; break;
547+
case OP_LT: str = "<"; break;
548+
536549
//should not happen
537-
default: str = "fix str_op"; break;
550+
default:
551+
free(res);
552+
return NULL;
538553
}
539554

540555
sprintf(res, "%s", str);

compiler/main/typechecker/tc_ifstmt.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ bool tc_ifstmt(struct IfStmt* i, struct TCCtx* tcctx) {
3535

3636
error_snippet(tcctx, msg, TC_ERR_CONDITION_REQUIRES_BOOL);
3737

38+
char* s2 = str_type(type);
39+
40+
fprintf(stderr, "actual type: %s\n\n", s2);
41+
42+
free(s2);
43+
3844
free(msg);
3945

4046
return false;

compiler/main/typechecker/tc_retstmt.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
//Typechecker Includes
1313
#include "_tc.h"
14+
#include "typechecker/type_contains/tc_type_contains.h"
1415
#include "typechecker/util/tc_errors.h"
1516
#include "typechecker/util/tc_utils.h"
1617
#include "tcctx.h"
@@ -31,7 +32,7 @@ bool tc_retstmt(struct RetStmt* r, struct TCCtx* tcctx) {
3132

3233
if (is_integer_type(returnType) && is_integer_type(returnedType)) { return true; }
3334

34-
if (!eq_type(returnType, returnedType)) {
35+
if (!tc_type_contains(returnType, returnedType)) {
3536

3637
char* s1 = str_type(returnType);
3738
char* s2 = str_type(returnedType);

compiler/main/typechecker/type_contains/tc_pointertype_contains.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ bool tc_pointer_type_contains(struct PointerType* expect, struct Type* actual) {
2222
struct PointerType* apt = actual->pointer_type;
2323

2424
// pointers of same underlying type can be assigned to each other
25-
return eq_type(expect->element_type, apt->element_type);
25+
return tc_type_contains(expect->element_type, apt->element_type);
2626
}

compiler/main/typechecker/type_contains/tc_type_contains.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99

1010
bool tc_type_contains(struct Type* expect, struct Type* actual) {
1111

12+
if (expect->is_anytype || actual->is_anytype) {
13+
return true;
14+
}
15+
1216
if (expect->pointer_type != NULL) {
1317

1418
return tc_pointer_type_contains(expect->pointer_type, actual);

compiler/main/typeinference/typeinfer_expr.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static struct Type* infer_type_expr_primitive(struct ST* st, struct Expr2Types*
2121

2222
static struct Type* infer_type_expr_both_tparam(struct ST* st, struct TypeParam* tp1, enum OP op, struct TypeParam* tp2);
2323

24-
static struct Type* infer_type_expr_ptr_arithmetic(struct ST* st, struct Type* t1, struct Type* t2);
24+
static struct Type* infer_type_expr_ptr_arithmetic(struct ST* st, struct Type* t1, struct Type* t2, enum OP op);
2525

2626
static void typeinfer_err_fatal(char* opt_str) {
2727
fprintf(stderr, "%s\n", opt_str);
@@ -44,10 +44,10 @@ struct Type* infer_type_expr(struct ST* st, struct Expr* expr) {
4444
}
4545

4646
if (type1->pointer_type) {
47-
return infer_type_expr_ptr_arithmetic(st, type1, type2);
47+
return infer_type_expr_ptr_arithmetic(st, type1, type2, op);
4848
}
4949
if (type2->pointer_type) {
50-
return infer_type_expr_ptr_arithmetic(st, type2, type1);
50+
return infer_type_expr_ptr_arithmetic(st, type2, type1, op);
5151
}
5252

5353
struct BasicType* btw1 = type1->basic_type;
@@ -82,7 +82,7 @@ struct Type* infer_type_expr(struct ST* st, struct Expr* expr) {
8282
return infer_type_expr_primitive(st, &e2t);
8383
}
8484

85-
static struct Type* infer_type_expr_ptr_arithmetic(struct ST* st, struct Type* t1, struct Type* t2) {
85+
static struct Type* infer_type_expr_ptr_arithmetic(struct ST* st, struct Type* t1, struct Type* t2, enum OP op) {
8686

8787
struct PointerType* pt = t1->pointer_type;
8888

@@ -92,9 +92,15 @@ static struct Type* infer_type_expr_ptr_arithmetic(struct ST* st, struct Type* t
9292
}
9393

9494
if (t2->basic_type && t2->basic_type->simple_type) {
95-
struct SimpleType* st = t2->basic_type->simple_type;
95+
struct SimpleType* stype = t2->basic_type->simple_type;
96+
97+
if (stype->primitive_type && stype->primitive_type->is_int_type) {
98+
99+
if (op == OP_EQ || op == OP_NEQ || op == OP_GE || op == OP_GT || op == OP_LE || op == OP_LT) {
100+
101+
return typeFromStrPrimitive(st, "bool");
102+
}
96103

97-
if (st->primitive_type && st->primitive_type->is_int_type) {
98104
return t1;
99105
}
100106
}

0 commit comments

Comments
 (0)