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) } } } func TestLambdaReturnsFinalExpression(t *testing.T) { program, err := Parse(`package demo fun transform(value: T, block: (T) -> R): R = block(value) fun answer(): Int = transform(21) { value -> value * 2 }`) if err != nil { t.Fatal(err) } output, err := GenerateGo(program) if err != nil { t.Fatal(err) } code := string(output) for _, expected := range []string{"func(value int) int", "return value * 2", "func answer() int"} { if !strings.Contains(code, expected) { t.Fatalf("missing %q:\n%s", expected, code) } } } func TestGoCallbackReturnsFinalExpression(t *testing.T) { program, err := Parse(`package demo import sort fun order(values: MutableList) { sort.slice(values) { left, right -> values[left] < values[right] } }`) if err != nil { t.Fatal(err) } output, err := GenerateGo(program) if err != nil { t.Fatal(err) } code := string(output) for _, expected := range []string{"func(left int, right int) bool", "return values[left] < values[right]"} { if !strings.Contains(code, expected) { t.Fatalf("missing %q:\n%s", expected, code) } } } func TestUnitLambdaKeepsFinalExpressionAsStatement(t *testing.T) { program, err := Parse(`package demo fun execute(block: () -> Unit) = block() fun start() = execute { println("started") }`) if err != nil { t.Fatal(err) } output, err := GenerateGo(program) if err != nil { t.Fatal(err) } if strings.Contains(string(output), `return fmt.Println("started")`) { t.Fatalf("Unit lambda returned final expression:\n%s", output) } }