add float constraint type
This commit is contained in:
+208
-5
@@ -5136,6 +5136,209 @@ main :: func() void {
|
||||
testing.expect(t, found_value_i16)
|
||||
}
|
||||
|
||||
float_local_type :: proc(hir_module: ^hir.Module, symbols: ^symbol.Table, function_name, local_name: string) -> (types.Type, bool) {
|
||||
fn_symbol := symbol.intern(symbols, function_name)
|
||||
loc_symbol := symbol.intern(symbols, local_name)
|
||||
for function in hir_module.functions {
|
||||
if function.name != fn_symbol {
|
||||
continue
|
||||
}
|
||||
for local in function.locals {
|
||||
if local.name == loc_symbol {
|
||||
return local.type, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return types.INVALID, false
|
||||
}
|
||||
|
||||
float_result_type :: proc(hir_module: ^hir.Module, symbols: ^symbol.Table, function_name: string) -> (types.Type, bool) {
|
||||
fn_symbol := symbol.intern(symbols, function_name)
|
||||
for function in hir_module.functions {
|
||||
if function.name == fn_symbol {
|
||||
return function.result, true
|
||||
}
|
||||
}
|
||||
return types.INVALID, false
|
||||
}
|
||||
|
||||
@(test)
|
||||
float_constraint_resolves_to_f64 :: proc(t: ^testing.T) {
|
||||
text := `make :: func() float {
|
||||
pi float = 3.14
|
||||
return pi
|
||||
}
|
||||
main :: func() void {
|
||||
_ = make()
|
||||
}
|
||||
`
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
diagnostics := source.init_diagnostics(&source_file)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
stream := lexer.lex(&source_file, &diagnostics, &symbols)
|
||||
defer delete(stream.items)
|
||||
ast_module := parser.parse(&stream, &source_file, &diagnostics)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
pi_type, found := float_local_type(&hir_module, &symbols, "make", "pi")
|
||||
result_type, _ := float_result_type(&hir_module, &symbols, "make")
|
||||
|
||||
testing.expect_value(t, len(diagnostics.items), 0)
|
||||
testing.expect(t, found)
|
||||
testing.expect_value(t, pi_type, types.F64)
|
||||
testing.expect_value(t, result_type, types.F64)
|
||||
}
|
||||
|
||||
@(test)
|
||||
float_constraint_accepts_integer_literal :: proc(t: ^testing.T) {
|
||||
text := `make :: func() float {
|
||||
pi float = 3
|
||||
return pi
|
||||
}
|
||||
main :: func() void {
|
||||
_ = make()
|
||||
}
|
||||
`
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
diagnostics := source.init_diagnostics(&source_file)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
stream := lexer.lex(&source_file, &diagnostics, &symbols)
|
||||
defer delete(stream.items)
|
||||
ast_module := parser.parse(&stream, &source_file, &diagnostics)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
pi_type, found := float_local_type(&hir_module, &symbols, "make", "pi")
|
||||
|
||||
testing.expect_value(t, len(diagnostics.items), 0)
|
||||
testing.expect(t, found)
|
||||
testing.expect_value(t, pi_type, types.F64)
|
||||
}
|
||||
|
||||
@(test)
|
||||
float_constraint_result_resolves_to_f64 :: proc(t: ^testing.T) {
|
||||
text := `make :: func() float {
|
||||
return 3.0
|
||||
}
|
||||
main :: func() void {
|
||||
_ = make()
|
||||
}
|
||||
`
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
diagnostics := source.init_diagnostics(&source_file)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
stream := lexer.lex(&source_file, &diagnostics, &symbols)
|
||||
defer delete(stream.items)
|
||||
ast_module := parser.parse(&stream, &source_file, &diagnostics)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
result_type, found := float_result_type(&hir_module, &symbols, "make")
|
||||
|
||||
testing.expect_value(t, len(diagnostics.items), 0)
|
||||
testing.expect(t, found)
|
||||
testing.expect_value(t, result_type, types.F64)
|
||||
}
|
||||
|
||||
@(test)
|
||||
float_constraint_widens_f32_to_f64 :: proc(t: ^testing.T) {
|
||||
text := `wide :: func(a f32, b f64) float {
|
||||
x float = a
|
||||
x = b
|
||||
return x
|
||||
}
|
||||
main :: func() void {
|
||||
_ = wide(1.0, 2.0)
|
||||
}
|
||||
`
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
diagnostics := source.init_diagnostics(&source_file)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
stream := lexer.lex(&source_file, &diagnostics, &symbols)
|
||||
defer delete(stream.items)
|
||||
ast_module := parser.parse(&stream, &source_file, &diagnostics)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
x_type, found := float_local_type(&hir_module, &symbols, "wide", "x")
|
||||
result_type, _ := float_result_type(&hir_module, &symbols, "wide")
|
||||
|
||||
testing.expect_value(t, len(diagnostics.items), 0)
|
||||
testing.expect(t, found)
|
||||
testing.expect_value(t, x_type, types.F64)
|
||||
testing.expect_value(t, result_type, types.F64)
|
||||
}
|
||||
|
||||
@(test)
|
||||
int_constraint_rejects_float_initializer :: proc(t: ^testing.T) {
|
||||
text := `main :: func() void {
|
||||
x int = 1.0
|
||||
}
|
||||
`
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
diagnostics := source.init_diagnostics(&source_file)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
stream := lexer.lex(&source_file, &diagnostics, &symbols)
|
||||
defer delete(stream.items)
|
||||
ast_module := parser.parse(&stream, &source_file, &diagnostics)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
found_constraint_error := false
|
||||
for diagnostic in diagnostics.items {
|
||||
found_constraint_error = found_constraint_error ||
|
||||
strings.contains(diagnostic.message, "could not resolve the 'int' constraint for local 'x'")
|
||||
}
|
||||
|
||||
testing.expect(t, found_constraint_error)
|
||||
}
|
||||
|
||||
@(test)
|
||||
float_constraint_rejects_runtime_integer :: proc(t: ^testing.T) {
|
||||
text := `take :: func(n i32) void {
|
||||
x float = n
|
||||
}
|
||||
main :: func() void {
|
||||
take(7)
|
||||
}
|
||||
`
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
diagnostics := source.init_diagnostics(&source_file)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
stream := lexer.lex(&source_file, &diagnostics, &symbols)
|
||||
defer delete(stream.items)
|
||||
ast_module := parser.parse(&stream, &source_file, &diagnostics)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
found_convert_error := false
|
||||
for diagnostic in diagnostics.items {
|
||||
found_convert_error = found_convert_error ||
|
||||
strings.contains(diagnostic.message, "cannot implicitly convert i32 to f64")
|
||||
}
|
||||
|
||||
testing.expect(t, found_convert_error)
|
||||
}
|
||||
|
||||
@(test)
|
||||
undefined_accepts_concrete_runtime_annotations :: proc(t: ^testing.T) {
|
||||
text := `Point :: struct {
|
||||
@@ -5423,11 +5626,11 @@ compound_assignment_preserves_checked_numeric_operations :: proc(t: ^testing.T)
|
||||
unsigned -= 2
|
||||
unsigned *= 3
|
||||
unsigned /= 4
|
||||
float f64 = 24.0
|
||||
float += 6.0
|
||||
float -= 2.0
|
||||
float *= 3.0
|
||||
float /= 4.0
|
||||
real f64 = 24.0
|
||||
real += 6.0
|
||||
real -= 2.0
|
||||
real *= 3.0
|
||||
real /= 4.0
|
||||
return signed
|
||||
}
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user