fspl/generator/function_test.go

239 lines
4.4 KiB
Go

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]
[main] = [exit 1]
`)
}
func TestFunctionCall (test *testing.T) {
testString (test,
`define i64 @f() {
0:
%1 = call i64 @g(i64 5)
ret i64 %1
}
define i64 @g(i64 %x) {
0:
%1 = alloca i64
store i64 %x, ptr %1
%2 = load i64, ptr %1
%3 = call i64 @h(i64 %2)
ret i64 %3
}
define i64 @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 @f() {
0:
%1 = call i64 @g(i64 5)
call void @h()
%2 = call i64 @g(i64 6)
ret void
}
define i64 @g(i64 %x) {
0:
%1 = alloca i64
store i64 %x, ptr %1
%2 = load i64, ptr %1
ret i64 %2
}
define void @h() {
0:
ret void
}
`,
`
[f] = { [g 5] [h] [g 6] }
[g x:Int]:Int = x
[h] = { }
`)
}
func TestMethod (test *testing.T) {
testString (test,
`%Number = type i64
define i64 @main() {
0:
%1 = alloca %Number
store i64 5, ptr %1
%2 = call i64 @Number.number(ptr %1)
ret i64 %2
}
define i64 @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 TestMethodChained (test *testing.T) {
testString (test,
`%Number = type i64
define %Number @main() {
0:
%1 = alloca i64
store i64 5, ptr %1
%2 = call %Number @Number.add(ptr %1, i64 8)
%3 = alloca %Number
store %Number %2, ptr %3
%4 = call %Number @Number.mul(ptr %3, i64 3)
ret %Number %4
}
define %Number @Number.mul(ptr %this, %Number %x) {
0:
%1 = alloca ptr
store ptr %this, ptr %1
%2 = alloca %Number
store %Number %x, ptr %2
%3 = load ptr, ptr %1
%4 = load %Number, ptr %3
%5 = load %Number, ptr %2
%6 = mul %Number %4, %5
ret %Number %6
}
define %Number @Number.add(ptr %this, %Number %x) {
0:
%1 = alloca ptr
store ptr %this, ptr %1
%2 = alloca %Number
store %Number %x, ptr %2
%3 = load ptr, ptr %1
%4 = load %Number, ptr %3
%5 = load %Number, ptr %2
%6 = add %Number %4, %5
ret %Number %6
}
define %Number @Number.div(ptr %this, %Number %x) {
0:
%1 = alloca ptr
store ptr %this, ptr %1
%2 = alloca %Number
store %Number %x, ptr %2
%3 = load ptr, ptr %1
%4 = load %Number, ptr %3
%5 = load %Number, ptr %2
%6 = sdiv %Number %4, %5
ret %Number %6
}
define %Number @Number.sub(ptr %this, %Number %x) {
0:
%1 = alloca ptr
store ptr %this, ptr %1
%2 = alloca %Number
store %Number %x, ptr %2
%3 = load ptr, ptr %1
%4 = load %Number, ptr %3
%5 = load %Number, ptr %2
%6 = sub %Number %4, %5
ret %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,
`%Index = type i64
%String = type { ptr, %Index }
%Greeter = type { %String }
define void @main() {
0:
%1 = alloca %Greeter
%2 = getelementptr %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 %String, ptr %2, i32 0, i32 0
store ptr %3, ptr %10
%11 = getelementptr %String, ptr %2, i32 0, i32 1
store %Index 6, ptr %11
call void @Greeter.greet(ptr %1)
ret void
}
define void @Greeter.greet(ptr %this) {
0:
%1 = alloca ptr
store ptr %this, ptr %1
%2 = load ptr, ptr %1
%3 = getelementptr %Greeter, ptr %2, i32 0, i32 0
%4 = getelementptr %String, ptr %3, i32 0, i32 0
%5 = load ptr, ptr %4
%6 = getelementptr i8, ptr %5, i64 0
%7 = call %Index @puts(ptr %6)
ret void
}
declare %Index @puts(ptr %string)
`,
`
[puts string: *Byte]: Index
Greeter: (. message: String)
Greeter.[greet] = [puts [@[.this.message 0]]]
[main] = {
greeter: Greeter = (.
message: 'hello\0'
)
greeter.[greet]
}
`)
}