@@ -304,6 +304,9 @@ fn (mut g Parser) parse_function() ! {
304304 // result type. Reject them until the direct parser tracks the required type.
305305 return g.unsupported ('narrow integer function types' )
306306 }
307+ if name == 'main' && params.len == 0 && return_type != 'void' {
308+ return g.unsupported ('main function returning `${return_type }`' )
309+ }
307310 g.expect (.lcbr)!
308311 is_main := name == 'main' && params.len == 0
309312 if is_main {
@@ -564,9 +567,14 @@ fn (mut g Parser) parse_for() !bool {
564567 }
565568 g.next ()
566569 start := g.read_expression ([token.Token.dotdot])!
567- start_type := fastc_normalize_inferred_type ( g.last_expression_type)
570+ start_expression_type := g.last_expression_type
568571 g.expect (.dotdot)!
569572 end := g.read_expression ([token.Token.lcbr])!
573+ end_expression_type := g.last_expression_type
574+ if ! fastc_is_integer_expression_type (start_expression_type)
575+ || ! fastc_is_integer_expression_type (end_expression_type) {
576+ return g.unsupported ('range bounds of types `${start_expression_type }` and `${end_expression_type }` must both be integers' )
577+ }
570578 g.expect (.lcbr)!
571579 start_name := g.temporary_name ('range_start' )
572580 end_name := g.temporary_name ('range_end' )
@@ -575,7 +583,7 @@ fn (mut g Parser) parse_for() !bool {
575583 g.write_line ('__typeof__((${end })) ${end_name } = (${end });' )
576584 g.write_line ('for (__typeof__((${start_name })) ${name } = (${start_name }); ${name } < (${end_name }); ${name }++) {' )
577585 g.locals[name] = FastcLocal{
578- typ: start_type
586+ typ: fastc_normalize_inferred_type (start_expression_type)
579587 }
580588 g.indent++
581589 _ = g.parse_block_body ()!
@@ -716,6 +724,10 @@ fn (mut g Parser) parse_simple_statement() ! {
716724 if ! fastc_call_types_are_compatible (actual_type, expected_type) {
717725 return g.unsupported ('assignment of type `${actual_type }` to `${name }` of type `${expected_type }`' )
718726 }
727+ if operator != .assign && (! fastc_is_numeric_expression_type (actual_type)
728+ || ! fastc_is_numeric_expression_type (expected_type)) {
729+ return g.unsupported ('arithmetic assignment `${operator .str ()}` on non-numeric type `${expected_type }`' )
730+ }
719731 g.consume_statement_end ()
720732 g.write_line ('${name }${operator .str ()}${value };' )
721733 return
@@ -887,7 +899,7 @@ fn (mut g Parser) read_expression_with_prefix(prefix string, stops []token.Token
887899 return g.unsupported ('unbalanced expression' )
888900 }
889901 g.validate_expression_calls (expression_tokens)!
890- g.last_expression_type = g.infer_expression_type (expression_tokens)
902+ g.last_expression_type = g.infer_expression_type (expression_tokens)!
891903 return result.str ().trim_space ()
892904}
893905
@@ -954,7 +966,7 @@ fn (g &Parser) validate_expression_calls(tokens []FastcExpressionToken) ! {
954966 return g.unsupported ('function `${name }` call with ${call_args .len } arguments instead of ${signature .parameter_types .len }' )
955967 }
956968 for argument_index, argument in call_args {
957- actual_type := g.infer_expression_type (argument)
969+ actual_type := g.infer_expression_type (argument)!
958970 expected_type := signature.parameter_types[argument_index]
959971 if actual_type.len == 0 {
960972 return g.unsupported ('unverifiable argument ${argument_index + 1 } to function `${name }`' )
@@ -967,6 +979,7 @@ fn (g &Parser) validate_expression_calls(tokens []FastcExpressionToken) ! {
967979 if call_args.len != 1 {
968980 return g.unsupported ('function `${name }` call with ${call_args .len } arguments' )
969981 }
982+ _ = g.infer_expression_type (call_args[0 ])!
970983 } else if _ := fastc_primitive_c_type (name) {
971984 if call_args.len != 1 {
972985 return g.unsupported ('cast `${name }` with ${call_args .len } arguments' )
@@ -1031,7 +1044,7 @@ fn fastc_call_arguments(tokens []FastcExpressionToken, open int, close int) ![][
10311044 return call_args
10321045}
10331046
1034- fn (g &Parser) infer_expression_type (tokens []FastcExpressionToken) string {
1047+ fn (g &Parser) infer_expression_type (tokens []FastcExpressionToken) ! string {
10351048 if tokens.len == 0 {
10361049 return ''
10371050 }
@@ -1090,10 +1103,18 @@ fn (g &Parser) infer_expression_type(tokens []FastcExpressionToken) string {
10901103 }
10911104 }
10921105 if tokens[start].tok in [.plus, .minus] {
1093- return g.infer_expression_type (tokens[start + 1 ..end])
1106+ operand_type := g.infer_expression_type (tokens[start + 1 ..end])!
1107+ if ! fastc_is_numeric_expression_type (operand_type) {
1108+ return g.unsupported ('arithmetic `${tokens [start ].tok .str ()}` on non-numeric type `${operand_type }`' )
1109+ }
1110+ return operand_type
10941111 }
10951112 if tokens[end - 1 ].tok in [.inc, .dec] {
1096- return g.infer_expression_type (tokens[start..end - 1 ])
1113+ operand_type := g.infer_expression_type (tokens[start..end - 1 ])!
1114+ if ! fastc_is_numeric_expression_type (operand_type) {
1115+ return g.unsupported ('arithmetic `${tokens [end - 1 ].tok .str ()}` on non-numeric type `${operand_type }`' )
1116+ }
1117+ return operand_type
10971118 }
10981119 mut depth := 0
10991120 for i in start .. end {
@@ -1106,12 +1127,16 @@ fn (g &Parser) infer_expression_type(tokens []FastcExpressionToken) string {
11061127 continue
11071128 }
11081129 if tokens[i].tok.is_assignment () {
1109- return g.infer_expression_type (tokens[start..i])
1130+ return g.infer_expression_type (tokens[start..i])!
11101131 }
11111132 if tokens[i].tok in [.plus, .minus, .mul, .amp, .pipe, .xor] && i > start {
1112- left_type := g.infer_expression_type (tokens[start..i])
1113- right_type := g.infer_expression_type (tokens[i + 1 ..end])
1114- return fastc_common_arithmetic_type (left_type, right_type)
1133+ left_type := g.infer_expression_type (tokens[start..i])!
1134+ right_type := g.infer_expression_type (tokens[i + 1 ..end])!
1135+ common_type := fastc_common_arithmetic_type (left_type, right_type)
1136+ if common_type.len == 0 {
1137+ return g.unsupported ('arithmetic `${tokens [i ].tok .str ()}` operands of types `${left_type }` and `${right_type }`' )
1138+ }
1139+ return common_type
11151140 }
11161141 }
11171142 return ''
@@ -1127,7 +1152,7 @@ fn fastc_number_expression_type(literal string) string {
11271152}
11281153
11291154fn fastc_common_arithmetic_type (left string , right string ) string {
1130- if left == right {
1155+ if left == right && fastc_is_numeric_expression_type (left) {
11311156 return left
11321157 }
11331158 if left == 'integer literal' && fastc_is_integer_type (right) {
@@ -1145,6 +1170,14 @@ fn fastc_common_arithmetic_type(left string, right string) string {
11451170 return ''
11461171}
11471172
1173+ fn fastc_is_numeric_expression_type (typ string ) bool {
1174+ return typ in ['integer literal' , 'float literal' , 'f32' , 'f64' ] || fastc_is_integer_type (typ)
1175+ }
1176+
1177+ fn fastc_is_integer_expression_type (typ string ) bool {
1178+ return typ == 'integer literal' || fastc_is_integer_type (typ)
1179+ }
1180+
11481181fn fastc_call_types_are_compatible (actual string , expected string ) bool {
11491182 if actual == expected {
11501183 return true
0 commit comments