temperlang / temper

3 stars 0 forks source link

Need compiler error for not yet defined functions #162

Open tjpalmer opened 1 month ago

tjpalmer commented 1 month ago

We should have a compiler error for the first case here:

$ let f(): Void {
     let g(): Void { h(); }
     g();
     let h(): Void { console.log("hi"); }
   }; f()
interactive#0: fail
$ let f(): Void {
     let g(): Void { h(); }
     let h(): Void { console.log("hi"); }
     g();
   }; f()
hi
interactive#1: void

See also the test case here that I added for working on fixing this issue.

tjpalmer commented 1 month ago

Something we do check already:

$ let f(): Void { let g(): String { a }; let a = "hi"; }
1: { let g(): String { a }; let a = "hi"; }
                       ⇧
[interactive#4:1+34-35]@G: Expected subtype of String, but got Invalid
interactive#4: void
$ let f(): Void { let a = "hi"; let g(): String { a } }
interactive#5: void

Also:

$ let f(): Void { let h = g; let g(): String { "hi" } }
1: f(): Void { let h = g; let g(): String {
                       ⇧
[interactive#1:1+24-25]@T: g__3 is not initialized along branches at [:1+16]
1: let f(): Void { let h = g; let g():
                   ⇧
interactive#1: void
tjpalmer commented 1 month ago

Some additional interesting examples of current behavior:

$ let f(i: Int): Void {
    let g(): Void { h() }
    let h: fn (): Void;
    if (i == 0) {
      h = fn (): Void { console.log("hi") };
    } else {
      h = fn (): Void { console.log("ha") };
    }
  }
2: let g(): Void { h() }
                   ⇧
[interactive#2:2+18-19]@G: Expected function type, but got Invalid
interactive#2: void
$ let f(i: Int): Void {
    let g(): Void { h() }
    let h: fn (): Void = fn (): Void { console.log("hi") };
  }
2: let g(): Void { h() }
                   ⇧
[interactive#3:2+18-19]@G: Expected function type, but got Invalid
interactive#3: void
$ let f(i: Int): Void {
    let h: fn (): Void = fn (): Void { console.log("hi") };
    let g(): Void { h() }
  }
interactive#4: void
$ let f(i: Int): Void {
    let g(): Void { h() }
    let h(): Void { console.log("hi") }
  }
interactive#5: void
tjpalmer commented 1 month ago

I'm ok with restricting forward function references to the cases that work above, but we still want static errors for the fail cases, as reported in the original issue description.