This commit is contained in:
pommicket 2022-01-24 18:27:09 -05:00
parent 466de93583
commit 150fbb9dd8
4 changed files with 99 additions and 64 deletions

View file

@ -132,6 +132,7 @@
; - for constant floats, the 64-bit double value (even if expression has type float) ; - 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 string literals, a 64-bit pointer to the string (for the executable, not for the compiler)
; - for unary operators, the operand ; - 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 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 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 ; - for the ternary operator ? :, the first followed by the second followed by the third

View file

@ -3,10 +3,4 @@
long double d; long double d;
} (*x)(void); } (*x)(void);
*/ */
#if 5+FLURGE==5 typedef int Foo[(char)((unsigned char)0xff + (unsigned char)0xf02)];
typedef long int unsigned Foo[sizeof"hello"+sizeof(double[sizeof(int) * sizeof 3])];
typedef int (*x)(Foo);
#else
typedef aaa x;
#endif
/* */

View file

@ -288,6 +288,15 @@ function parse_type_to
prefix_end = p prefix_end = p
goto parse_type_loop goto parse_type_loop
:parse_array_type :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 local expr
expr = malloc(4000) expr = malloc(4000)
*1out = TYPE_ARRAY *1out = TYPE_ARRAY
@ -296,11 +305,16 @@ function parse_type_to
token_skip_to_matching_rsquare(&p) token_skip_to_matching_rsquare(&p)
suffix += 16 ; skip [ suffix += 16 ; skip [
parse_expression(suffix, p, expr) 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 if n < 0 goto bad_array_size
*8out = n *8out = n
out += 8 out += 8
free(expr) free(expr)
free(types)
types = prev_types
types_bytes_used = prev_types_bytes_used
suffix = p + 16 suffix = p + 16
goto parse_type_loop goto parse_type_loop
:bad_array_size :bad_array_size
@ -782,13 +796,13 @@ function parse_expression
return out return out
:expr_binary_bad_types :expr_binary_bad_types
bad_types_to_operator(tokens, *4a, *4b) bad_types_to_operator(tokens, *4a, *4b)
;@TODO: casts
:parse_expr_unary :parse_expr_unary
if c == KEYWORD_SIZEOF goto parse_sizeof if c == KEYWORD_SIZEOF goto parse_sizeof
*1out = unary_op_to_expression_type(c) *1out = unary_op_to_expression_type(c)
c = *1out c = *1out
if c == EXPRESSION_CAST goto parse_cast
out += 8 out += 8
a = out + 4 ; type of operand a = out + 4 ; type of operand
p = tokens + 16 p = tokens + 16
@ -808,6 +822,22 @@ function parse_expression
string Bad unary symbol (this shouldn't happen). string Bad unary symbol (this shouldn't happen).
byte 10 byte 10
byte 0 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 :unary_address_of
*4type = type_create_pointer(*4a) *4type = type_create_pointer(*4a)
return out return out
@ -842,14 +872,6 @@ function parse_expression
byte 0 byte 0
:parse_sizeof :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 *1out = EXPRESSION_CONSTANT_INT
out += 4 out += 4
*1out = TYPE_UNSIGNED_LONG *1out = TYPE_UNSIGNED_LONG
@ -874,9 +896,6 @@ function parse_expression
*8out = type_sizeof(*4p) *8out = type_sizeof(*4p)
free(temp) free(temp)
:parse_sizeof_finish :parse_sizeof_finish
free(types)
types = prev_types
types_bytes_used = prev_types_bytes_used
out += 8 out += 8
return out 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 ; @NONSTANDARD: doesn't handle floats, but really why would you use floats in an array size
; e.g. SomeType x[(int)3.3]; ; e.g. SomeType x[(int)3.3];
; this is also used for #if evaluation ; 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) ; NOTE: this returns the end of the expression, not the value (which is stored in *8p_value)
function evaluate_constant_expression function evaluate_constant_expression
argument token
argument expr argument expr
argument p_value argument p_value
local a local a
@ -1116,7 +1137,7 @@ function evaluate_constant_expression
if c == EXPRESSION_UNARY_MINUS goto eval_unary_minus if c == EXPRESSION_UNARY_MINUS goto eval_unary_minus
if c == EXPRESSION_BITWISE_NOT goto eval_bitwise_not if c == EXPRESSION_BITWISE_NOT goto eval_bitwise_not
if c == EXPRESSION_LOGICAL_NOT goto eval_logical_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_ADD goto eval_add
if c == EXPRESSION_SUB goto eval_sub if c == EXPRESSION_SUB goto eval_sub
if c == EXPRESSION_MUL goto eval_mul 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_LOGICAL_OR goto eval_logical_or
if c == EXPRESSION_CONDITIONAL goto eval_conditional if c == EXPRESSION_CONDITIONAL goto eval_conditional
byte 0xcc
:eval_todo token_error(token, .str_eval_bad_exprtype)
fputs(2, .str_eval_todo)
exit(1) :str_eval_bad_exprtype
:str_eval_todo string Can't evaluate constant expression.
string evaluate_constant_expression does not support this kind of expression yet (see @TODOs).
byte 10
byte 0 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 :eval_constant_identifier
; @TODO: enum values ; @TODO: enum values
fputs(2, .str_constant_identifier) fputs(2, .str_constant_identifier)
@ -1162,45 +1192,45 @@ function evaluate_constant_expression
return expr return expr
:eval_unary_plus :eval_unary_plus
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, p_value) expr = evaluate_constant_expression(token, expr, p_value)
return expr return expr
:eval_unary_minus :eval_unary_minus
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
*8p_value = 0 - a *8p_value = 0 - a
goto eval_fit_to_type goto eval_fit_to_type
:eval_bitwise_not :eval_bitwise_not
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
*8p_value = ~a *8p_value = ~a
goto eval_fit_to_type goto eval_fit_to_type
:eval_logical_not :eval_logical_not
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
if a == 0 goto eval_value_1 if a == 0 goto eval_value_1
goto eval_value_0 goto eval_value_0
:eval_add :eval_add
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a + b *8p_value = a + b
goto eval_fit_to_type goto eval_fit_to_type
:eval_sub :eval_sub
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a - b *8p_value = a - b
goto eval_fit_to_type goto eval_fit_to_type
:eval_mul :eval_mul
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a * b *8p_value = a * b
goto eval_fit_to_type goto eval_fit_to_type
:eval_div :eval_div
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
if *1p == TYPE_UNSIGNED_LONG goto eval_div_unsigned 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 ; division is signed or uses a small type, so we can use 64-bit signed division
*8p_value = a / b *8p_value = a / b
@ -1211,8 +1241,8 @@ function evaluate_constant_expression
goto eval_fit_to_type goto eval_fit_to_type
:eval_remainder :eval_remainder
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
p = types + type p = types + type
if *1p == TYPE_UNSIGNED_LONG goto eval_rem_unsigned if *1p == TYPE_UNSIGNED_LONG goto eval_rem_unsigned
*8p_value = a % b *8p_value = a % b
@ -1222,14 +1252,14 @@ function evaluate_constant_expression
goto eval_fit_to_type goto eval_fit_to_type
:eval_lshift :eval_lshift
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a < b *8p_value = a < b
goto eval_fit_to_type goto eval_fit_to_type
:eval_rshift :eval_rshift
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
p = types + type p = types + type
p = *1p p = *1p
p &= 1 ; signed types are odd p &= 1 ; signed types are odd
@ -1275,8 +1305,8 @@ function evaluate_constant_expression
goto eval_comparison goto eval_comparison
:eval_comparison :eval_comparison
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
p = types + type p = types + type
p = *1p p = *1p
@ -1309,41 +1339,41 @@ function evaluate_constant_expression
goto eval_value_0 goto eval_value_0
:eval_bitwise_and :eval_bitwise_and
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a & b *8p_value = a & b
goto eval_fit_to_type goto eval_fit_to_type
:eval_bitwise_or :eval_bitwise_or
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a | b *8p_value = a | b
goto eval_fit_to_type goto eval_fit_to_type
:eval_bitwise_xor :eval_bitwise_xor
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
*8p_value = a ^ b *8p_value = a ^ b
goto eval_fit_to_type goto eval_fit_to_type
:eval_logical_and :eval_logical_and
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
if a == 0 goto eval_value_0 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 if b == 0 goto eval_value_0
goto eval_value_1 goto eval_value_1
:eval_logical_or :eval_logical_or
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
if a != 0 goto eval_value_1 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 if b != 0 goto eval_value_1
goto eval_value_0 goto eval_value_0
:eval_conditional :eval_conditional
expr += 8 expr += 8
expr = evaluate_constant_expression(expr, &mask) expr = evaluate_constant_expression(token, expr, &mask)
expr = evaluate_constant_expression(expr, &a) expr = evaluate_constant_expression(token, expr, &a)
expr = evaluate_constant_expression(expr, &b) expr = evaluate_constant_expression(token, expr, &b)
if mask == 0 goto eval_conditional_b if mask == 0 goto eval_conditional_b
*8p_value = a *8p_value = a
goto eval_fit_to_type goto eval_fit_to_type
@ -1557,6 +1587,7 @@ function operator_precedence
if op == SYMBOL_MINUS goto return_0xe0 if op == SYMBOL_MINUS goto return_0xe0
if op == SYMBOL_TILDE goto return_0xe0 if op == SYMBOL_TILDE goto return_0xe0
if op == SYMBOL_NOT goto return_0xe0 if op == SYMBOL_NOT goto return_0xe0
if op == SYMBOL_LPAREN goto return_0xe8 ; casts
return 0xffff return 0xffff
@ -1570,6 +1601,7 @@ function unary_op_to_expression_type
if op == SYMBOL_MINUS goto return_EXPRESSION_UNARY_MINUS if op == SYMBOL_MINUS goto return_EXPRESSION_UNARY_MINUS
if op == SYMBOL_TILDE goto return_EXPRESSION_BITWISE_NOT if op == SYMBOL_TILDE goto return_EXPRESSION_BITWISE_NOT
if op == SYMBOL_NOT goto return_EXPRESSION_LOGICAL_NOT if op == SYMBOL_NOT goto return_EXPRESSION_LOGICAL_NOT
if op == SYMBOL_LPAREN goto return_EXPRESSION_CAST
return 0 return 0
:return_EXPRESSION_PRE_INCREMENT :return_EXPRESSION_PRE_INCREMENT
@ -1588,7 +1620,8 @@ function unary_op_to_expression_type
return EXPRESSION_BITWISE_NOT return EXPRESSION_BITWISE_NOT
:return_EXPRESSION_LOGICAL_NOT :return_EXPRESSION_LOGICAL_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, ; is this operator right-associative? most C operators are left associative,
; but += / -= / etc. are not ; but += / -= / etc. are not
@ -1755,6 +1788,7 @@ function print_expression
if c == EXPRESSION_UNARY_MINUS goto print_unary_minus if c == EXPRESSION_UNARY_MINUS goto print_unary_minus
if c == EXPRESSION_BITWISE_NOT goto print_bitwise_not if c == EXPRESSION_BITWISE_NOT goto print_bitwise_not
if c == EXPRESSION_LOGICAL_NOT goto print_logical_not if c == EXPRESSION_LOGICAL_NOT goto print_logical_not
if c == EXPRESSION_CAST goto print_cast
b = binop_expression_type_to_symbol(c) b = binop_expression_type_to_symbol(c)
if b != 0 goto print_expr_binop if b != 0 goto print_expr_binop
@ -1766,7 +1800,11 @@ function print_expression
string Bad expression passed to print_expression. string Bad expression passed to print_expression.
byte 10 byte 10
byte 0 byte 0
:print_cast
; we've already printed the type
expression += 8
expression = print_expression(expression)
return expression
:print_expr_int :print_expr_int
expression += 8 expression += 8
putn(*8expression) putn(*8expression)

View file

@ -711,6 +711,8 @@ function leftmost_1bit
return 0xd0 return 0xd0
:return_0xe0 :return_0xe0
return 0xe0 return 0xe0
:return_0xe8
return 0xe8
:return_0xf0 :return_0xf0
return 0xf0 return 0xf0