Introduce typed semantic analysis pipeline
This commit is contained in:
parent
117d188194
commit
f4cd4f4458
30 changed files with 2079 additions and 2381 deletions
|
|
@ -1096,7 +1096,7 @@ fun main() {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGenerateGoChannelsAndSelect(t *testing.T) {
|
||||
func TestGenerateGoChannelSendAndRead(t *testing.T) {
|
||||
src := `
|
||||
package demo
|
||||
|
||||
|
|
@ -1105,13 +1105,8 @@ fun writer(ch: Channel<Int>) {
|
|||
}
|
||||
|
||||
fun main() {
|
||||
val ch = Channel<Int>()
|
||||
runBlocking {
|
||||
launch { writer(ch) }
|
||||
select {
|
||||
ch -> println(it)
|
||||
}
|
||||
}
|
||||
val ch = Channel<Int>(1)
|
||||
writer(ch)
|
||||
val v = ch.read()
|
||||
println(v)
|
||||
}
|
||||
|
|
@ -1131,12 +1126,8 @@ fun main() {
|
|||
for _, want := range []string{
|
||||
`func writer(ch chan int)`,
|
||||
`ch <- 7`,
|
||||
`ch := make(chan int)`,
|
||||
`gotlinScope.Launch`,
|
||||
`ch := make(chan int, 1)`,
|
||||
`writer(ch)`,
|
||||
`select {`,
|
||||
`case it := <-ch:`,
|
||||
`fmt.Println(it)`,
|
||||
`v := <-ch`,
|
||||
`fmt.Println(v)`,
|
||||
} {
|
||||
|
|
@ -1146,138 +1137,6 @@ fun main() {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGenerateGoSelectAfterAndEvery(t *testing.T) {
|
||||
src := `
|
||||
package demo
|
||||
|
||||
fun main() {
|
||||
select {
|
||||
after(1000) -> println(it)
|
||||
every(250) -> println("tick")
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
prog, err := Parse(src)
|
||||
if err != nil {
|
||||
t.Fatalf("parse failed: %v", err)
|
||||
}
|
||||
|
||||
out, err := GenerateGo(prog)
|
||||
if err != nil {
|
||||
t.Fatalf("go generation failed: %v", err)
|
||||
}
|
||||
|
||||
code := string(out)
|
||||
for _, want := range []string{
|
||||
`"time"`,
|
||||
`func gotlinEveryMs(ms int) <-chan time.Time {`,
|
||||
`case it := <-time.After(time.Duration(1000) * time.Millisecond):`,
|
||||
`fmt.Println(it)`,
|
||||
`case <-gotlinEveryMs(250):`,
|
||||
`fmt.Println("tick")`,
|
||||
} {
|
||||
if !strings.Contains(code, want) {
|
||||
t.Fatalf("generated Go missing %q:\n%s", want, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateGoEveryRejectsNonPositiveMilliseconds(t *testing.T) {
|
||||
cases := []string{
|
||||
`every(0)`,
|
||||
`every(-1)`,
|
||||
}
|
||||
for _, timerCall := range cases {
|
||||
src := `
|
||||
package demo
|
||||
|
||||
fun main() {
|
||||
select {
|
||||
` + timerCall + ` -> println("x")
|
||||
}
|
||||
}
|
||||
`
|
||||
prog, err := Parse(src)
|
||||
if err != nil {
|
||||
t.Fatalf("parse failed: %v", err)
|
||||
}
|
||||
_, err = GenerateGo(prog)
|
||||
if err == nil {
|
||||
t.Fatalf("expected go generation error for %s", timerCall)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "every(ms) requires ms > 0") {
|
||||
t.Fatalf("unexpected error for %s: %v", timerCall, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateGoAfterEveryArityValidation(t *testing.T) {
|
||||
cases := []struct {
|
||||
call string
|
||||
want string
|
||||
}{
|
||||
{`after()`, "after(ms) expects exactly one Int argument"},
|
||||
{`after(1, 2)`, "after(ms) expects exactly one Int argument"},
|
||||
{`every()`, "every(ms) expects exactly one Int argument"},
|
||||
{`every(1, 2)`, "every(ms) expects exactly one Int argument"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
src := `
|
||||
package demo
|
||||
|
||||
fun main() {
|
||||
select {
|
||||
` + tc.call + ` -> println("x")
|
||||
}
|
||||
}
|
||||
`
|
||||
prog, err := Parse(src)
|
||||
if err != nil {
|
||||
t.Fatalf("parse failed: %v", err)
|
||||
}
|
||||
_, err = GenerateGo(prog)
|
||||
if err == nil {
|
||||
t.Fatalf("expected go generation error for %s", tc.call)
|
||||
}
|
||||
if !strings.Contains(err.Error(), tc.want) {
|
||||
t.Fatalf("unexpected error for %s: %v", tc.call, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateGoAfterEveryIntValidation(t *testing.T) {
|
||||
cases := []struct {
|
||||
call string
|
||||
want string
|
||||
}{
|
||||
{`after("1s")`, "after(ms) expects an Int argument"},
|
||||
{`every(true)`, "every(ms) expects an Int argument"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
src := `
|
||||
package demo
|
||||
|
||||
fun main() {
|
||||
select {
|
||||
` + tc.call + ` -> println("x")
|
||||
}
|
||||
}
|
||||
`
|
||||
prog, err := Parse(src)
|
||||
if err != nil {
|
||||
t.Fatalf("parse failed: %v", err)
|
||||
}
|
||||
_, err = GenerateGo(prog)
|
||||
if err == nil {
|
||||
t.Fatalf("expected go generation error for %s", tc.call)
|
||||
}
|
||||
if !strings.Contains(err.Error(), tc.want) {
|
||||
t.Fatalf("unexpected error for %s: %v", tc.call, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateGoNoTimeImportWhenUnused(t *testing.T) {
|
||||
src := `
|
||||
package demo
|
||||
|
|
@ -1300,36 +1159,6 @@ fun main() {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGenerateGoNoTickerShorthandRewrite(t *testing.T) {
|
||||
src := `
|
||||
package demo
|
||||
|
||||
import time
|
||||
|
||||
fun main() {
|
||||
val tick = time.NewTicker(time.Second)
|
||||
select {
|
||||
tick -> println("x")
|
||||
}
|
||||
}
|
||||
`
|
||||
prog, err := Parse(src)
|
||||
if err != nil {
|
||||
t.Fatalf("parse failed: %v", err)
|
||||
}
|
||||
out, err := GenerateGo(prog)
|
||||
if err != nil {
|
||||
t.Fatalf("go generation failed: %v", err)
|
||||
}
|
||||
code := string(out)
|
||||
if strings.Contains(code, "<-tick.C") {
|
||||
t.Fatalf("ticker shorthand rewrite should be removed:\n%s", code)
|
||||
}
|
||||
if !strings.Contains(code, "case <-tick:") {
|
||||
t.Fatalf("expected raw source receive in generated code:\n%s", code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateGoExplicitErrorsForBunStyleCalls(t *testing.T) {
|
||||
src := `
|
||||
package demo
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue