1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/* static bool eval_expr_as_float(Expression *e, FloatLiteral *f) { */
/* switch (e->kind) { */
/* case EXPR_FLOAT_LITERAL: */
/* *f = e->floatl; */
/* return true; */
/* case EXPR_INT_LITERAL: */
/* *f = (FloatLiteral)e->intl; */
/* return true; */
/* } */
/* err_print(e->where, "Not implemented yet"); */
/* return false; */
/* } */
static bool eval_expr_as_int(Expression *e, Integer *i) {
/* OPTIM: cache eval'd expression values? (probably only for declarations) */
switch (e->kind) {
case EXPR_FLOAT_LITERAL:
err_print(e->where, "Expected integer, but found floating-point literal.");
return false;
case EXPR_INT_LITERAL:
if (e->intl > (UInteger)INTEGER_MAX) { /* TODO: FIXME */
err_print(e->where, "Overflow when evaluating integer.");
return false;
}
*i = (Integer)e->intl;
return true;
case EXPR_STR_LITERAL:
err_print(e->where, "Expected integer, but found string literal.");
return false;
case EXPR_UNARY_OP:
switch (e->unary.op) {
case UNARY_MINUS: {
Integer of;
if (!eval_expr_as_int(e->unary.of, &of)) return false;
*i = -of;
return true;
}
}
break;
case EXPR_BINARY_OP: {
switch (e->binary.op) {
case BINARY_PLUS:
case BINARY_MINUS: {
Integer lhs, rhs;
if (!eval_expr_as_int(e->binary.lhs, &lhs)) return false;
if (!eval_expr_as_int(e->binary.rhs, &rhs)) return false;
switch (e->binary.op) {
case BINARY_PLUS:
*i = lhs + rhs;
return true;
case BINARY_MINUS:
*i = lhs - rhs;
return true;
default: assert(0); return false;
}
}
case BINARY_SET:
case BINARY_COMMA:
err_print(e->where, "Expected operator which returns an integer, but got %s", binary_op_to_str(e->binary.op));
return false;
case BINARY_AT_INDEX:
err_print(e->where, "Cannot get index of array at compile time yet.");
return false;
}
} break;
case EXPR_IDENT: {
Identifier id = e->ident;
IdentDecl *id_decl = ident_decl(id);
if (!id_decl) {
char *id_str = ident_to_str(id);
err_print(e->where, "Undeclared identifier: %s", id_str);
free(id_str);
return false;
}
Declaration *d = id_decl->decl;
if (location_after(d->where, e->where)) {
err_print(e->where, "Use of constant before its declaration.");
info_print(d->where, "Declaration will be here.");
return false;
}
if (!(d->flags & DECL_FLAG_CONST)) {
err_print(e->where, "Use of non-constant identifier in a constant expression.");
info_print(d->where, "Declaration was here.");
return false;
}
if (d->type.kind != TYPE_BUILTIN || !type_builtin_is_integer(d->type.builtin)) {
char *type_str = type_to_str(&d->type);
err_print(e->where, "Expected integer, but identifier has type %s.", type_str);
info_print(d->where, "Declaration was here.");
free(type_str);
return false;
}
/* TODO: tuples */
eval_expr_as_int(&d->expr, i);
return true;
} break;
case EXPR_FN:
err_print(e->where, "Expected integer, but found function.");
return false;
case EXPR_CALL:
err_print(e->where, "Compile time function calling not supported yet."); /* TODO */
break;
case EXPR_DIRECT:
switch (e->direct.which) {
case DIRECT_C:
err_print(e->where, "Can't run C code at compile time.");
return false;
case DIRECT_COUNT: assert(0); break;
}
break;
}
err_print(e->where, "Not implemented yet");
return false;
}
|