summaryrefslogtreecommitdiff
path: root/05
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-01-24 18:27:09 -0500
committerpommicket <pommicket@gmail.com>2022-01-24 18:27:09 -0500
commit150fbb9dd8d29199427e5f0318c11f21e713a5f7 (patch)
treeffe1ff501a2e2aba9127293ecd61afd385456c74 /05
parent466de9358310c4d291c480577efc972705df787d (diff)
casts
Diffstat (limited to '05')
-rw-r--r--05/constants.b1
-rw-r--r--05/main.c8
-rw-r--r--05/parse.b152
-rw-r--r--05/util.b2
4 files changed, 99 insertions, 64 deletions
diff --git a/05/constants.b b/05/constants.b
index fa2d0f4..a9f7774 100644
--- a/05/constants.b
+++ b/05/constants.b
@@ -132,6 +132,7 @@
; - for constant floats, the 64-bit double value (even if expression has type float)
; - for string literals, a 64-bit pointer to the string (for the executable, not for the compiler)
; - for unary operators, the operand
+; - for casts, the operand (type is given by type member)
; - for binary operators, the first operand followed by the second
; - for the operators . and ->, the first argument is a 64-bit pointer to the name of the member and the second is the left hand side of the . / ->
; - for the ternary operator ? :, the first followed by the second followed by the third
diff --git a/05/main.c b/05/main.c
index 09707e4..fd2f3cd 100644
--- a/05/main.c
+++ b/05/main.c
@@ -3,10 +3,4 @@
long double d;
} (*x)(void);
*/
-#if 5+FLURGE==5
-typedef long int unsigned Foo[sizeof"hello"+sizeof(double[sizeof(int) * sizeof 3])];
-typedef int (*x)(Foo);
-#else
-typedef aaa x;
-#endif
-/* */
+typedef int Foo[(char)((unsigned char)0xff + (unsigned char)0xf02)];
diff --git a/05/parse.b b/05/parse.b
index 2df9db1..c424ee5 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -288,6 +288,15 @@ function parse_type_to
prefix_end = p
goto parse_type_loop
:parse_array_type
+ local prev_types
+ local prev_types_bytes_used
+ ; little hack to avoid screwing up types like double[sizeof(int)]
+ ; temporarily switch out types array to parse the cast's type
+ prev_types = types
+ prev_types_bytes_used = types_bytes_used
+ types = malloc(4000)
+ types_init(types, &types_bytes_used)
+
local expr
expr = malloc(4000)
*1out = TYPE_ARRAY
@@ -296,11 +305,16 @@ function parse_type_to
token_skip_to_matching_rsquare(&p)
suffix += 16 ; skip [
parse_expression(suffix, p, expr)
- evaluate_constant_expression(expr, &n)
+ print_expression(expr)
+ putc(10)
+ evaluate_constant_expression(*8p_token, expr, &n)
if n < 0 goto bad_array_size
*8out = n
out += 8
free(expr)
+ free(types)
+ types = prev_types
+ types_bytes_used = prev_types_bytes_used
suffix = p + 16
goto parse_type_loop
:bad_array_size
@@ -782,13 +796,13 @@ function parse_expression
return out
:expr_binary_bad_types
bad_types_to_operator(tokens, *4a, *4b)
- ;@TODO: casts
:parse_expr_unary
if c == KEYWORD_SIZEOF goto parse_sizeof
*1out = unary_op_to_expression_type(c)
c = *1out
+ if c == EXPRESSION_CAST goto parse_cast
out += 8
a = out + 4 ; type of operand
p = tokens + 16
@@ -808,6 +822,22 @@ function parse_expression
string Bad unary symbol (this shouldn't happen).
byte 10
byte 0
+ :parse_cast
+ p = best + 16
+ a = parse_type(&p, &c)
+ if c != 0 goto bad_cast ; e.g. (int x)5
+ if *1p != SYMBOL_RPAREN goto bad_cast ; e.g. (int ,)5
+ out += 4
+ *4out = a
+ out += 4
+ p += 16
+ out = parse_expression(p, tokens_end, out)
+ return out
+ :bad_cast
+ token_error(tokens, .str_bad_cast)
+ :str_bad_cast
+ string Bad cast.
+ byte 0
:unary_address_of
*4type = type_create_pointer(*4a)
return out
@@ -842,14 +872,6 @@ function parse_expression
byte 0
:parse_sizeof
- ; little hack to avoid screwing up types like double[sizeof(int)]
- ; temporarily switch out types array to parse the sizeof's type
- local prev_types
- local prev_types_bytes_used
- prev_types = types
- prev_types_bytes_used = types_bytes_used
- types = malloc(4000)
- types_init(types, &types_bytes_used)
*1out = EXPRESSION_CONSTANT_INT
out += 4
*1out = TYPE_UNSIGNED_LONG
@@ -874,9 +896,6 @@ function parse_expression
*8out = type_sizeof(*4p)
free(temp)
:parse_sizeof_finish
- free(types)
- types = prev_types
- types_bytes_used = prev_types_bytes_used
out += 8
return out
@@ -1094,8 +1113,10 @@ function type_sizeof
; @NONSTANDARD: doesn't handle floats, but really why would you use floats in an array size
; e.g. SomeType x[(int)3.3];
; this is also used for #if evaluation
+; tokens is used for error messages (e.g. if this "constant" expression is *x or something)
; NOTE: this returns the end of the expression, not the value (which is stored in *8p_value)
function evaluate_constant_expression
+ argument token
argument expr
argument p_value
local a
@@ -1116,7 +1137,7 @@ function evaluate_constant_expression
if c == EXPRESSION_UNARY_MINUS goto eval_unary_minus
if c == EXPRESSION_BITWISE_NOT goto eval_bitwise_not
if c == EXPRESSION_LOGICAL_NOT goto eval_logical_not
- if c == EXPRESSION_CAST goto eval_todo ; @TODO
+ if c == EXPRESSION_CAST goto eval_cast
if c == EXPRESSION_ADD goto eval_add
if c == EXPRESSION_SUB goto eval_sub
if c == EXPRESSION_MUL goto eval_mul
@@ -1137,16 +1158,25 @@ function evaluate_constant_expression
if c == EXPRESSION_LOGICAL_OR goto eval_logical_or
if c == EXPRESSION_CONDITIONAL goto eval_conditional
- byte 0xcc
- :eval_todo
- fputs(2, .str_eval_todo)
- exit(1)
- :str_eval_todo
- string evaluate_constant_expression does not support this kind of expression yet (see @TODOs).
- byte 10
+ token_error(token, .str_eval_bad_exprtype)
+
+ :str_eval_bad_exprtype
+ string Can't evaluate constant expression.
byte 0
-
+ :eval_cast
+ p = types + type
+ if *1p == TYPE_VOID goto eval_cast_bad_type
+ if *1p > TYPE_UNSIGNED_LONG goto eval_cast_bad_type
+ expr += 8
+ ; @NONSTANDARD: we don't support, for example, int x[(int)(float)5];
+ expr = evaluate_constant_expression(token, expr, p_value)
+ goto eval_fit_to_type
+ :eval_cast_bad_type
+ token_error(token, .str_eval_cast_bad_type)
+ :str_eval_cast_bad_type
+ string Bad type for constant cast (note: floating-point casts are not supported even though they are standard).
+ byte 0
:eval_constant_identifier
; @TODO: enum values
fputs(2, .str_constant_identifier)
@@ -1162,45 +1192,45 @@ function evaluate_constant_expression
return expr
:eval_unary_plus
expr += 8
- expr = evaluate_constant_expression(expr, p_value)
+ expr = evaluate_constant_expression(token, expr, p_value)
return expr
:eval_unary_minus
expr += 8
- expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(token, expr, &a)
*8p_value = 0 - a
goto eval_fit_to_type
:eval_bitwise_not
expr += 8
- expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(token, expr, &a)
*8p_value = ~a
goto eval_fit_to_type
:eval_logical_not
expr += 8
- expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(token, expr, &a)
if a == 0 goto eval_value_1
goto eval_value_0
:eval_add
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a + b
goto eval_fit_to_type
:eval_sub
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a - b
goto eval_fit_to_type
:eval_mul
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a * b
goto eval_fit_to_type
:eval_div
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
if *1p == TYPE_UNSIGNED_LONG goto eval_div_unsigned
; division is signed or uses a small type, so we can use 64-bit signed division
*8p_value = a / b
@@ -1211,8 +1241,8 @@ function evaluate_constant_expression
goto eval_fit_to_type
:eval_remainder
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
p = types + type
if *1p == TYPE_UNSIGNED_LONG goto eval_rem_unsigned
*8p_value = a % b
@@ -1222,14 +1252,14 @@ function evaluate_constant_expression
goto eval_fit_to_type
:eval_lshift
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a < b
goto eval_fit_to_type
:eval_rshift
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
p = types + type
p = *1p
p &= 1 ; signed types are odd
@@ -1275,8 +1305,8 @@ function evaluate_constant_expression
goto eval_comparison
:eval_comparison
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
p = types + type
p = *1p
@@ -1309,41 +1339,41 @@ function evaluate_constant_expression
goto eval_value_0
:eval_bitwise_and
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a & b
goto eval_fit_to_type
:eval_bitwise_or
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a | b
goto eval_fit_to_type
:eval_bitwise_xor
expr += 8
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a ^ b
goto eval_fit_to_type
:eval_logical_and
expr += 8
- expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(token, expr, &a)
if a == 0 goto eval_value_0
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &b)
if b == 0 goto eval_value_0
goto eval_value_1
:eval_logical_or
expr += 8
- expr = evaluate_constant_expression(expr, &a)
+ expr = evaluate_constant_expression(token, expr, &a)
if a != 0 goto eval_value_1
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &b)
if b != 0 goto eval_value_1
goto eval_value_0
:eval_conditional
expr += 8
- expr = evaluate_constant_expression(expr, &mask)
- expr = evaluate_constant_expression(expr, &a)
- expr = evaluate_constant_expression(expr, &b)
+ expr = evaluate_constant_expression(token, expr, &mask)
+ expr = evaluate_constant_expression(token, expr, &a)
+ expr = evaluate_constant_expression(token, expr, &b)
if mask == 0 goto eval_conditional_b
*8p_value = a
goto eval_fit_to_type
@@ -1557,6 +1587,7 @@ function operator_precedence
if op == SYMBOL_MINUS goto return_0xe0
if op == SYMBOL_TILDE goto return_0xe0
if op == SYMBOL_NOT goto return_0xe0
+ if op == SYMBOL_LPAREN goto return_0xe8 ; casts
return 0xffff
@@ -1570,6 +1601,7 @@ function unary_op_to_expression_type
if op == SYMBOL_MINUS goto return_EXPRESSION_UNARY_MINUS
if op == SYMBOL_TILDE goto return_EXPRESSION_BITWISE_NOT
if op == SYMBOL_NOT goto return_EXPRESSION_LOGICAL_NOT
+ if op == SYMBOL_LPAREN goto return_EXPRESSION_CAST
return 0
:return_EXPRESSION_PRE_INCREMENT
@@ -1588,7 +1620,8 @@ function unary_op_to_expression_type
return EXPRESSION_BITWISE_NOT
:return_EXPRESSION_LOGICAL_NOT
return EXPRESSION_LOGICAL_NOT
-
+:return_EXPRESSION_CAST
+ return EXPRESSION_CAST
; is this operator right-associative? most C operators are left associative,
; but += / -= / etc. are not
@@ -1755,6 +1788,7 @@ function print_expression
if c == EXPRESSION_UNARY_MINUS goto print_unary_minus
if c == EXPRESSION_BITWISE_NOT goto print_bitwise_not
if c == EXPRESSION_LOGICAL_NOT goto print_logical_not
+ if c == EXPRESSION_CAST goto print_cast
b = binop_expression_type_to_symbol(c)
if b != 0 goto print_expr_binop
@@ -1766,7 +1800,11 @@ function print_expression
string Bad expression passed to print_expression.
byte 10
byte 0
-
+ :print_cast
+ ; we've already printed the type
+ expression += 8
+ expression = print_expression(expression)
+ return expression
:print_expr_int
expression += 8
putn(*8expression)
diff --git a/05/util.b b/05/util.b
index 9f8aee6..bdafeb1 100644
--- a/05/util.b
+++ b/05/util.b
@@ -711,6 +711,8 @@ function leftmost_1bit
return 0xd0
:return_0xe0
return 0xe0
+:return_0xe8
+ return 0xe8
:return_0xf0
return 0xf0