gotlin/internal/lang/expression_function_test.go

86 lines
2.2 KiB
Go

package lang
import (
"strings"
"testing"
)
func TestExpressionBodiedFunctionInfersReturnType(t *testing.T) {
program, err := Parse(`package demo
fun twice(value: Int) = value * 2
fun text() = "value"`)
if err != nil {
t.Fatal(err)
}
output, err := GenerateGo(program)
if err != nil {
t.Fatal(err)
}
for _, expected := range []string{"func twice(value int) int", "return value * 2", "func text() string", `return "value"`} {
if !strings.Contains(string(output), expected) {
t.Fatalf("missing %q:\n%s", expected, output)
}
}
if got := ResolvedType(program.Functions[0].ExpressionBody).String(); got != "Int" {
t.Fatalf("return type = %s", got)
}
}
func TestExpressionBodyInferenceReachesFixedPoint(t *testing.T) {
program, err := Parse(`package demo
fun first() = second()
fun second() = third()
fun third() = 42`)
if err != nil {
t.Fatal(err)
}
semantic, err := Analyze(program)
if err != nil {
t.Fatal(err)
}
for _, name := range []string{"first", "second", "third"} {
symbol, _ := semantic.Global.Lookup(name)
if got := symbol.Type.(FunctionType).Result.String(); got != "Int" {
t.Fatalf("%s result = %s", name, got)
}
}
}
func TestWithContextExpressionBodyEstablishesBoundary(t *testing.T) {
program, err := Parse(`package demo
import http net.http
import exec os.exec
fun work() { exec.commandContext("date") }
fun handle(request: *http.Request) = withContext(request.context()) {
work()
}`)
if err != nil {
t.Fatal(err)
}
semantic, err := Analyze(program)
if err != nil {
t.Fatal(err)
}
if !semantic.FunctionEffects["work"].Has(CoroutineEffect) {
t.Fatal("work should require ambient context")
}
if semantic.FunctionEffects["handle"].Has(CoroutineEffect) {
t.Fatal("withContext should be an effect boundary")
}
output, err := GenerateGo(program)
if err != nil {
t.Fatal(err)
}
code := string(output)
for _, expected := range []string{
"func work(gotlinScope *GotlinCoroutineScope)",
`exec.CommandContext(gotlinScope.Context(), "date")`,
"func handle(request *http.Request)",
"gotlinRunWithContext(request.Context()",
"work(gotlinScope)",
} {
if !strings.Contains(code, expected) {
t.Fatalf("missing %q:\n%s", expected, code)
}
}
}