various typing fixes

This commit is contained in:
pommicket 2022-01-14 22:16:57 -05:00
parent 27a6d0eb2d
commit 2ec0cd4ae3
3 changed files with 160 additions and 66 deletions

View file

@ -1 +1,6 @@
"hi"[33] << 8 /* +*"hello" */
/* *"hello"+3 */
/* +*"hello" */
/* 3+4+5 */
/* 3+=4+=5*=6>>=7 */
"hello"+=7

View file

@ -1,4 +1,7 @@
; @TODO: fix 5 * *x being interpreted as (5*) * x function type_create_pointer
argument type
byte 0xcc ; @TODO
function parse_expression function parse_expression
argument tokens argument tokens
argument tokens_end argument tokens_end
@ -14,6 +17,7 @@ function parse_expression
local best_precedence local best_precedence
local depth local depth
local value local value
local first_token
:parse_expression_top :parse_expression_top
;print_tokens(tokens, tokens_end) ;print_tokens(tokens, tokens_end)
@ -55,23 +59,30 @@ function parse_expression
; look for the operator with the lowest precedence not in brackets ; look for the operator with the lowest precedence not in brackets
depth = 0 ; paren/square bracket depth depth = 0 ; paren/square bracket depth
b = 1 ; first token? -- i.e. is this operator unary first_token = 1
p = tokens p = tokens
best = 0 best = 0
best_precedence = 1000 best_precedence = 1000
goto expr_find_operator_loop_first goto expr_find_operator_loop_first
:expr_find_operator_loop :expr_find_operator_loop
b = 0 first_token = 0
:expr_find_operator_loop_first :expr_find_operator_loop_first
if p >= tokens_end goto expr_find_operator_loop_end if p >= tokens_end goto expr_find_operator_loop_end
n = p
c = *1p c = *1p
p += 16 p += 16
if depth > 0 goto expr_findop_not_new_best if depth > 0 goto expr_findop_not_new_best
if depth < 0 goto expr_too_many_closing_brackets if depth < 0 goto expr_too_many_closing_brackets
n = p - 16 a = operator_precedence(n, first_token)
a = operator_precedence(n, b)
n = a n = a
n -= operator_right_associative(c) ; ensure that the leftmost += / -= / etc. is processed first if a == 0xe0 goto select_leftmost ; ensure that the leftmost unary operator is processed first
b = operator_right_associative(c)
if b != 0 goto select_leftmost ; ensure that the leftmost += / -= / etc. is processed first
goto select_rightmost
:select_leftmost
n += 1
; fallthrough
:select_rightmost
if n > best_precedence goto expr_findop_not_new_best if n > best_precedence goto expr_findop_not_new_best
; new best! ; new best!
best = p - 16 best = p - 16
@ -91,8 +102,11 @@ function parse_expression
goto expr_find_operator_loop goto expr_find_operator_loop
:expr_find_operator_loop_end :expr_find_operator_loop_end
if best == 0 goto unrecognized_expression if best == 0 goto unrecognized_expression
n = best - tokens
c = *1best c = *1best
if best == tokens goto parse_expr_unary if best == tokens goto parse_expr_unary
@ -102,50 +116,52 @@ function parse_expression
if c == SYMBOL_MINUS_MINUS goto parse_postdecrement if c == SYMBOL_MINUS_MINUS goto parse_postdecrement
if c == SYMBOL_QUESTION goto parse_conditional if c == SYMBOL_QUESTION goto parse_conditional
*1out = binop_symbol_to_expression_type(c) *1out = binop_symbol_to_expression_type(c)
c = *1out
out += 8 out += 8
if c == SYMBOL_DOT goto parse_expr_member if c == EXPRESSION_DOT goto parse_expr_member
if c == SYMBOL_ARROW goto parse_expr_member if c == EXPRESSION_ARROW goto parse_expr_member
a = out + 4 ; type of first operand a = out + 4 ; type of first operand
out = parse_expression(tokens, best, out) ; first operand out = parse_expression(tokens, best, out) ; first operand
p = best + 16 p = best + 16
b = out + 4 ; type of second operand b = out + 4 ; type of second operand
if c != SYMBOL_LSQUARE goto binary_not_subscript if c != EXPRESSION_SUBSCRIPT goto binary_not_subscript
tokens_end -= 16 tokens_end -= 16
if *1tokens_end != SYMBOL_RSQUARE goto unrecognized_expression if *1tokens_end != SYMBOL_RSQUARE goto unrecognized_expression
:binary_not_subscript :binary_not_subscript
out = parse_expression(p, tokens_end, out) ; second operand out = parse_expression(p, tokens_end, out) ; second operand
if c == SYMBOL_LSHIFT goto type_binary_left_promote if c == EXPRESSION_LSHIFT goto type_shift
if c == SYMBOL_RSHIFT goto type_binary_left_promote if c == EXPRESSION_RSHIFT goto type_shift
if c == SYMBOL_LSQUARE goto type_subscript if c == EXPRESSION_SUBSCRIPT goto type_subscript
if c == SYMBOL_EQ_EQ goto type_binary_int if c == EXPRESSION_EQ goto type_int
if c == SYMBOL_NOT_EQ goto type_binary_int if c == EXPRESSION_NEQ goto type_int
if c == SYMBOL_LT_EQ goto type_binary_int if c == EXPRESSION_LEQ goto type_int
if c == SYMBOL_GT_EQ goto type_binary_int if c == EXPRESSION_GEQ goto type_int
if c == SYMBOL_LT goto type_binary_int if c == EXPRESSION_LT goto type_int
if c == SYMBOL_GT goto type_binary_int if c == EXPRESSION_GT goto type_int
if c == SYMBOL_COMMA goto type_binary_right if c == EXPRESSION_COMMA goto type_binary_right
if c == SYMBOL_EQ goto type_binary_left if c == EXPRESSION_EQ goto type_binary_left
if c == SYMBOL_PLUS_EQ goto type_binary_left if c == EXPRESSION_ASSIGN_ADD goto type_binary_left
if c == SYMBOL_MINUS_EQ goto type_binary_left if c == EXPRESSION_ASSIGN_SUB goto type_binary_left
if c == SYMBOL_TIMES_EQ goto type_binary_left if c == EXPRESSION_ASSIGN_MUL goto type_binary_left
if c == SYMBOL_DIV_EQ goto type_binary_left if c == EXPRESSION_ASSIGN_DIV goto type_binary_left
if c == SYMBOL_PERCENT_EQ goto type_binary_left if c == EXPRESSION_ASSIGN_REMAINDER goto type_binary_left
if c == SYMBOL_AND_EQ goto type_binary_left_int if c == EXPRESSION_ASSIGN_AND goto type_binary_left_integer
if c == SYMBOL_XOR_EQ goto type_binary_left_int if c == EXPRESSION_ASSIGN_XOR goto type_binary_left_integer
if c == SYMBOL_OR_EQ goto type_binary_left_int if c == EXPRESSION_ASSIGN_OR goto type_binary_left_integer
if c == SYMBOL_LSHIFT_EQ goto type_binary_left_int if c == EXPRESSION_ASSIGN_LSHIFT goto type_binary_left_integer
if c == SYMBOL_RSHIFT_EQ goto type_binary_left_int if c == EXPRESSION_ASSIGN_RSHIFT goto type_binary_left_integer
if c == SYMBOL_OR_OR goto type_binary_int if c == EXPRESSION_LOGICAL_OR goto type_int
if c == SYMBOL_AND_AND goto type_binary_int if c == EXPRESSION_LOGICAL_AND goto type_int
if c == SYMBOL_AND goto type_binary_usual_int if c == EXPRESSION_BITWISE_AND goto type_binary_usual_integer
if c == SYMBOL_XOR goto type_binary_usual_int if c == EXPRESSION_BITWISE_XOR goto type_binary_usual_integer
if c == SYMBOL_OR goto type_binary_usual_int if c == EXPRESSION_BITWISE_OR goto type_binary_usual_integer
if c == SYMBOL_PLUS goto type_plus if c == EXPRESSION_ADD goto type_plus
if c == SYMBOL_MINUS goto type_minus if c == EXPRESSION_SUB goto type_minus
if c == SYMBOL_TIMES goto type_binary_usual if c == EXPRESSION_MUL goto type_binary_usual
if c == SYMBOL_DIV goto type_binary_usual if c == EXPRESSION_DIV goto type_binary_usual
if c == SYMBOL_PERCENT goto type_binary_usual_int if c == EXPRESSION_REMAINDER goto type_binary_usual_integer
fputs(2, .str_binop_this_shouldnt_happen) fputs(2, .str_binop_this_shouldnt_happen)
exit(1) exit(1)
@ -155,9 +171,19 @@ function parse_expression
byte 0 byte 0
:type_plus :type_plus
byte 0xcc ; @TODO p = types + *4a
if *1p == TYPE_POINTER goto type_binary_left ; pointer plus integer
p = types + *4b
if *1p == TYPE_POINTER goto type_binary_right ; integer plus pointer
goto type_binary_usual
:type_minus :type_minus
byte 0xcc ; @TODO p = types + *4a
if *1p == TYPE_POINTER goto type_minus_left_ptr
goto type_binary_usual
:type_minus_left_ptr
p = types + *4b
if *1p == TYPE_POINTER goto type_long ; pointer difference
goto type_binary_left ; pointer minus integer
:type_subscript :type_subscript
p = types + *4a p = types + *4a
if *1p == TYPE_POINTER goto type_subscript_pointer if *1p == TYPE_POINTER goto type_subscript_pointer
@ -174,20 +200,21 @@ function parse_expression
:str_subscript_bad_type :str_subscript_bad_type
string Subscript of non-pointer type. string Subscript of non-pointer type.
byte 0 byte 0
; apply the "usual conversions"
:type_binary_usual :type_binary_usual
*4type = expr_binary_type_usual_conversions(tokens, *4a, *4b) *4type = expr_binary_type_usual_conversions(tokens, *4a, *4b)
return out return out
:type_binary_usual_int ; like type_binary_usual, but the operands must be integers
:type_binary_usual_integer
*4type = expr_binary_type_usual_conversions(tokens, *4a, *4b) *4type = expr_binary_type_usual_conversions(tokens, *4a, *4b)
p = types + *4type p = types + *4type
if *1p >= TYPE_FLOAT goto expr_binary_bad_types if *1p >= TYPE_FLOAT goto expr_binary_bad_types
return out return out
:type_binary_int :type_binary_left_integer
*4type = TYPE_INT
return out
:type_binary_left_int
p = types + *4a p = types + *4a
if *1p >= TYPE_FLOAT goto expr_binary_bad_types if *1p >= TYPE_FLOAT goto expr_binary_bad_types
p = types + *4b
if *1p >= TYPE_FLOAT goto expr_binary_bad_types
goto type_binary_left goto type_binary_left
:type_binary_left :type_binary_left
*4type = *4a *4type = *4a
@ -195,9 +222,20 @@ function parse_expression
:type_binary_right :type_binary_right
*4type = *4b *4type = *4b
return out return out
:type_binary_left_promote :type_shift
p = types + *4a
if *1p >= TYPE_FLOAT goto expr_binary_bad_types
p = types + *4b
if *1p >= TYPE_FLOAT goto expr_binary_bad_types
*4type = type_promotion(*4a) *4type = type_promotion(*4a)
return out return out
; the type here is just int
:type_int
*4type = TYPE_INT
return out
:type_long
*4type = TYPE_LONG
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 ;@TODO: casts
@ -206,10 +244,53 @@ function parse_expression
:parse_expr_unary :parse_expr_unary
if c == KEYWORD_SIZEOF goto parse_expr_sizeof if c == KEYWORD_SIZEOF goto parse_expr_sizeof
*1out = unary_op_to_expression_type(c) *1out = unary_op_to_expression_type(c)
c = *1out
out += 8 out += 8
a = out + 4 ; type of operand
p = tokens + 16 p = tokens + 16
out = parse_expression(p, tokens_end, out) out = parse_expression(p, tokens_end, out)
p = types + *4a
if c == EXPRESSION_BITWISE_NOT goto unary_type_integral
if c == EXPRESSION_UNARY_PLUS goto unary_type_promote
if c == EXPRESSION_UNARY_MINUS goto unary_type_promote
if c == EXPRESSION_LOGICAL_NOT goto unary_type_logical_not
if c == EXPRESSION_ADDRESS_OF goto unary_address_of
if c == EXPRESSION_DEREFERENCE goto unary_dereference
fputs(2, .str_unop_this_shouldnt_happen)
exit(1)
:str_unop_this_shouldnt_happen
string Bad unary symbol (this shouldn't happen).
byte 10
byte 0
:unary_address_of
*4type = type_create_pointer(*4a)
return out return out
:unary_dereference
if *1p != TYPE_POINTER goto unary_bad_type
*4type = *4a + 1
return out
:unary_type_logical_not
if *1p > TYPE_POINTER goto unary_bad_type
*4type = TYPE_INT
return out
:unary_type_integral
if *1p >= TYPE_FLOAT goto unary_bad_type
goto unary_type_promote
:unary_type_promote
if *1p > TYPE_DOUBLE goto unary_bad_type
*4type = type_promotion(*4a)
return out
:unary_bad_type
fprint_token_location(1, tokens)
puts(.str_unary_bad_type)
print_type(*4a)
putc(10)
exit(1)
:str_unary_bad_type
string : Bad type for unary operator:
byte 32
byte 0
:parse_expr_sizeof :parse_expr_sizeof
byte 0xcc ; @TODO byte 0xcc ; @TODO
@ -223,6 +304,7 @@ function parse_expression
if p != tokens_end goto bad_expression ; e.g. foo->bar hello if p != tokens_end goto bad_expression ; e.g. foo->bar hello
out += 8 out += 8
out = parse_expression(tokens, best, out) out = parse_expression(tokens, best, out)
; @TODO: typing
return out return out
@ -351,6 +433,8 @@ function expr_binary_type_usual_conversions
local ptype1 local ptype1
local ptype2 local ptype2
local kind1
local kind2
if type1 == 0 goto return_0 if type1 == 0 goto return_0
if type2 == 0 goto return_0 if type2 == 0 goto return_0
@ -358,24 +442,27 @@ function expr_binary_type_usual_conversions
ptype1 = types + type1 ptype1 = types + type1
ptype2 = types + type2 ptype2 = types + type2
if type1 > TYPE_DOUBLE goto usual_bad_types_to_operator kind1 = *1ptype1
if type2 > TYPE_DOUBLE goto usual_bad_types_to_operator kind2 = *1ptype2
if kind1 > TYPE_DOUBLE goto usual_bad_types_to_operator
if kind2 > TYPE_DOUBLE goto usual_bad_types_to_operator
; "if either operand has type double, the other operand is converted to double" ; "if either operand has type double, the other operand is converted to double"
if type1 == TYPE_DOUBLE goto return_type_double if kind1 == TYPE_DOUBLE goto return_type_double
if type2 == TYPE_DOUBLE goto return_type_double if kind2 == TYPE_DOUBLE goto return_type_double
; "if either operand has type float, the other operand is converted to float" ; "if either operand has type float, the other operand is converted to float"
if type1 == TYPE_FLOAT goto return_type_float if kind1 == TYPE_FLOAT goto return_type_float
if type2 == TYPE_FLOAT goto return_type_float if kind2 == TYPE_FLOAT goto return_type_float
; "If either operand has type unsigned long int, the other operand is converted to unsigned long int" ; "If either operand has type unsigned long int, the other operand is converted to unsigned long int"
if type1 == TYPE_UNSIGNED_LONG goto return_type_unsigned_long if kind1 == TYPE_UNSIGNED_LONG goto return_type_unsigned_long
if type2 == TYPE_UNSIGNED_LONG goto return_type_unsigned_long if kind2 == TYPE_UNSIGNED_LONG goto return_type_unsigned_long
; "if either operand has type long int, the other operand is converted to long int" ; "if either operand has type long int, the other operand is converted to long int"
if type1 == TYPE_LONG goto return_type_long if kind1 == TYPE_LONG goto return_type_long
if type2 == TYPE_LONG goto return_type_long if kind2 == TYPE_LONG goto return_type_long
; "if either operand has type unsigned int, the other operand is converted to unsigned int." ; "if either operand has type unsigned int, the other operand is converted to unsigned int."
if type1 == TYPE_UNSIGNED_INT goto return_type_unsigned_int if kind1 == TYPE_UNSIGNED_INT goto return_type_unsigned_int
if type2 == TYPE_UNSIGNED_INT goto return_type_unsigned_int if kind2 == TYPE_UNSIGNED_INT goto return_type_unsigned_int
; "Otherwise, both operands have type int." ; "Otherwise, both operands have type int."
goto return_type_int goto return_type_int
@ -391,10 +478,10 @@ function bad_types_to_operator
argument type1 argument type1
argument type2 argument type2
fprint_token_location(2, token) fprint_token_location(1, token)
fputs(2, .str_bad_types_to_operator) puts(.str_bad_types_to_operator)
print_type(type1) print_type(type1)
fputs(2, .str_space_and_space) puts(.str_space_and_space)
print_type(type2) print_type(type2)
putc(10) putc(10)
exit(1) exit(1)
@ -405,8 +492,9 @@ function bad_types_to_operator
function type_promotion function type_promotion
argument type argument type
type = types + type local p
if *1type < TYPE_INT goto return_type_int p = types + type
if *1p < TYPE_INT goto return_type_int
return type return type
; return precedence of given operator token, or 0xffff if not an operator ; return precedence of given operator token, or 0xffff if not an operator

View file

@ -339,6 +339,7 @@ function tokenize
out += 1 out += 1
; suffix ; suffix
*1out = read_number_suffix(file, line_number, &in) *1out = read_number_suffix(file, line_number, &in)
pptoken_skip(&in)
out += 1 out += 1
goto token_output goto token_output
:float_exponent :float_exponent