package generator import "testing" func TestFunctionExternal (test *testing.T) { testString (test, `declare void @exit(i64 %status) define void @main() { 0: call void @exit(i64 1) ret void } `, ` [exit status:Int] 'exit' [main] 'main' = [exit 1] `) } func TestFunctionCall (test *testing.T) { testString (test, `define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::f"() { 0: %1 = call i64 @"0zNZN147MN2wzMAQ6NS2dQ==::g"(i64 5) ret i64 %1 } define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::g"(i64 %x) { 0: %1 = alloca i64 store i64 %x, ptr %1 %2 = load i64, ptr %1 %3 = call i64 @"0zNZN147MN2wzMAQ6NS2dQ==::h"(i64 %2) ret i64 %3 } define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::h"(i64 %x) { 0: %1 = alloca i64 store i64 %x, ptr %1 %2 = load i64, ptr %1 ret i64 %2 } `, ` [f ]:Int = [g 5] [g x:Int]:Int = [h x] [h x:Int]:Int = x `) } func TestFunctionCallVoid (test *testing.T) { testString (test, `define void @"0zNZN147MN2wzMAQ6NS2dQ==::f"() { 0: %1 = call i64 @"0zNZN147MN2wzMAQ6NS2dQ==::g"(i64 5) call void @"0zNZN147MN2wzMAQ6NS2dQ==::h"() %2 = call i64 @"0zNZN147MN2wzMAQ6NS2dQ==::g"(i64 6) ret void } define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::g"(i64 %x) { 0: %1 = alloca i64 store i64 %x, ptr %1 %2 = load i64, ptr %1 ret i64 %2 } define void @"0zNZN147MN2wzMAQ6NS2dQ==::h"() { 0: ret void } `, ` [f] = { [g 5] [h] [g 6] } [g x:Int]:Int = x [h] = { } `) } func TestMethod (test *testing.T) { testString (test, `%"0zNZN147MN2wzMAQ6NS2dQ==::Number" = type i64 define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::main"() { 0: %1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Number" store i64 5, ptr %1 %2 = call i64 @"0zNZN147MN2wzMAQ6NS2dQ==::Number.number"(ptr %1) ret i64 %2 } define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::Number.number"(ptr %this) { 0: %1 = alloca ptr store ptr %this, ptr %1 %2 = load ptr, ptr %1 %3 = load i64, ptr %2 ret i64 %3 } `, ` Number: Int Number.[number]: Int = [.this] [main]: Int = { num:Number = 5 num.[number] } `) } func TestMethodPtr (test *testing.T) { testString (test, `%"0zNZN147MN2wzMAQ6NS2dQ==::Number" = type i64 define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::main"() { 0: %1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Number" store i64 5, ptr %1 %2 = alloca ptr store ptr %1, ptr %2 %3 = load ptr, ptr %2 %4 = call i64 @"0zNZN147MN2wzMAQ6NS2dQ==::Number.number"(ptr %3) ret i64 %4 } define i64 @"0zNZN147MN2wzMAQ6NS2dQ==::Number.number"(ptr %this) { 0: %1 = alloca ptr store ptr %this, ptr %1 %2 = load ptr, ptr %1 %3 = load i64, ptr %2 ret i64 %3 } `, ` Number: Int Number.[number]: Int = [.this] [main]: Int = { num:Number = 5 numptr:*Number = [@num] numptr.[number] } `) } func TestMethodChained (test *testing.T) { testString (test, `%"0zNZN147MN2wzMAQ6NS2dQ==::Number" = type i64 define %"0zNZN147MN2wzMAQ6NS2dQ==::Number" @"0zNZN147MN2wzMAQ6NS2dQ==::main"() { 0: %1 = alloca i64 store i64 5, ptr %1 %2 = call %"0zNZN147MN2wzMAQ6NS2dQ==::Number" @"0zNZN147MN2wzMAQ6NS2dQ==::Number.add"(ptr %1, i64 8) %3 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Number" store %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %2, ptr %3 %4 = call %"0zNZN147MN2wzMAQ6NS2dQ==::Number" @"0zNZN147MN2wzMAQ6NS2dQ==::Number.mul"(ptr %3, i64 3) ret %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %4 } define %"0zNZN147MN2wzMAQ6NS2dQ==::Number" @"0zNZN147MN2wzMAQ6NS2dQ==::Number.mul"(ptr %this, %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %x) { 0: %1 = alloca ptr store ptr %this, ptr %1 %2 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Number" store %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %x, ptr %2 %3 = load ptr, ptr %1 %4 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Number", ptr %3 %5 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Number", ptr %2 %6 = mul %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %4, %5 ret %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %6 } define %"0zNZN147MN2wzMAQ6NS2dQ==::Number" @"0zNZN147MN2wzMAQ6NS2dQ==::Number.add"(ptr %this, %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %x) { 0: %1 = alloca ptr store ptr %this, ptr %1 %2 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Number" store %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %x, ptr %2 %3 = load ptr, ptr %1 %4 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Number", ptr %3 %5 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Number", ptr %2 %6 = add %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %4, %5 ret %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %6 } define %"0zNZN147MN2wzMAQ6NS2dQ==::Number" @"0zNZN147MN2wzMAQ6NS2dQ==::Number.div"(ptr %this, %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %x) { 0: %1 = alloca ptr store ptr %this, ptr %1 %2 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Number" store %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %x, ptr %2 %3 = load ptr, ptr %1 %4 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Number", ptr %3 %5 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Number", ptr %2 %6 = sdiv %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %4, %5 ret %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %6 } define %"0zNZN147MN2wzMAQ6NS2dQ==::Number" @"0zNZN147MN2wzMAQ6NS2dQ==::Number.sub"(ptr %this, %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %x) { 0: %1 = alloca ptr store ptr %this, ptr %1 %2 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Number" store %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %x, ptr %2 %3 = load ptr, ptr %1 %4 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Number", ptr %3 %5 = load %"0zNZN147MN2wzMAQ6NS2dQ==::Number", ptr %2 %6 = sub %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %4, %5 ret %"0zNZN147MN2wzMAQ6NS2dQ==::Number" %6 } `, ` Number: Int Number.[add x:Number]:Number = [+ [.this] x] Number.[sub x:Number]:Number = [- [.this] x] Number.[mul x:Number]:Number = [* [.this] x] Number.[div x:Number]:Number = [/ [.this] x] [main]: Number = [~Number 5].[add 8].[mul 3] `) } func TestMethodGreeter (test *testing.T) { testString (test, `%"AAAAAAAAAAAAAAAAAAAAAA==::Index" = type i64 %"AAAAAAAAAAAAAAAAAAAAAA==::String" = type { ptr, %"AAAAAAAAAAAAAAAAAAAAAA==::Index" } %"0zNZN147MN2wzMAQ6NS2dQ==::Greeter" = type { %"AAAAAAAAAAAAAAAAAAAAAA==::String" } define void @main() { 0: %1 = alloca %"0zNZN147MN2wzMAQ6NS2dQ==::Greeter" %2 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::Greeter", ptr %1, i32 0, i32 0 %3 = alloca [6 x i8] %4 = getelementptr [6 x i8], ptr %3, i32 0, i32 0 store i8 104, ptr %4 %5 = getelementptr [6 x i8], ptr %3, i32 0, i32 1 store i8 101, ptr %5 %6 = getelementptr [6 x i8], ptr %3, i32 0, i32 2 store i8 108, ptr %6 %7 = getelementptr [6 x i8], ptr %3, i32 0, i32 3 store i8 108, ptr %7 %8 = getelementptr [6 x i8], ptr %3, i32 0, i32 4 store i8 111, ptr %8 %9 = getelementptr [6 x i8], ptr %3, i32 0, i32 5 store i8 0, ptr %9 %10 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %2, i32 0, i32 0 store ptr %3, ptr %10 %11 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %2, i32 0, i32 1 store %"AAAAAAAAAAAAAAAAAAAAAA==::Index" 6, ptr %11 call void @"0zNZN147MN2wzMAQ6NS2dQ==::Greeter.greet"(ptr %1) ret void } define void @"0zNZN147MN2wzMAQ6NS2dQ==::Greeter.greet"(ptr %this) { 0: %1 = alloca ptr store ptr %this, ptr %1 %2 = load ptr, ptr %1 %3 = getelementptr %"0zNZN147MN2wzMAQ6NS2dQ==::Greeter", ptr %2, i32 0, i32 0 %4 = getelementptr %"AAAAAAAAAAAAAAAAAAAAAA==::String", ptr %3, i32 0, i32 0 %5 = load ptr, ptr %4 %6 = getelementptr i8, ptr %5, i64 0 %7 = call %"AAAAAAAAAAAAAAAAAAAAAA==::Index" @puts(ptr %6) ret void } declare %"AAAAAAAAAAAAAAAAAAAAAA==::Index" @puts(ptr %string) `, ` [puts string: *Byte]: Index 'puts' Greeter: (. message: String) Greeter.[greet] = [puts [@[.this.message 0]]] [main] 'main' = { greeter: Greeter = (. message: 'hello\0' ) greeter.[greet] } `) }