70 likes | 218 Views
let x. initExpr. in. collect( j |...)->any(true). select( i |...). source. body. source. body. self.f. j.e. x.a .d. let y. in. initExpr. if. y.b > i.c+x.a. cond. then. else. x.a > i.c. let z. self .g >3. initExpr. in. i.c -2. z+i.c. let x. initExpr. in.
E N D
let x initExpr in collect(j|...)->any(true) select(i|...) source body source body self.f j.e x.a.d let y in initExpr if y.b>i.c+x.a cond then else x.a>i.c let z self.g>3 initExpr in i.c-2 z+i.c
let x initExpr in collect(j|...)->any(true) select(i|...) source body source body self.f j.e x.a.d let y in initExpr if y.b>i.c+x.a cond then else x.a>i.c let z self.g>3 initExpr in i.c-2 z+i.c
let y in initExpr self let z initExpr in y.h.k y+z traceback on y.h; unused for y.h; unused for y.h.k; unused for z in y+z; unused for y+z in y+z (=false) traceback on y (after reverse-traversal across y.h); unused for y; unused for y.h (cached=false) --> on to initExpr for let-variable y: traceback(no-unused) on self
let x • traceback for i.b, unused for i.b-->i.b.c-->i.b.c+x.g--> z in z, unused for let z, [[i.a>2]] with unknown i • traceback for i; resolves [[i.a>2]], unused for i-->i.b (cached) • traceback for x.a.d leaving select body (let y) scope; unused for x.a.d--> select-->let x (false) • traceback for x.a; unused for x.a-->x.a.d (cached) • traceback for x; unused for x-->x.a (cached) • traceback(cache: unused(self.f)=false) for self.f • traceback for self; unused for self-->self.f (cached: false) initExpr in self.f select(i|...) source body x.a.d let y in initExpr if y.b>i.c+x.a cond then else i.a>2 let z self.g>3 initExpr in i.b.c + x.g z
traceback for x.z in d(...) infers x, branch: • traces back to self.d(x,y) and infers x, traces back to self.b(x, y) and infers x --> [[x.z>y.z]] for unknown y@0 • traces back to self.d(y,x) and infers y, traces back to self.c(x, y) and infers y@1; does not trigger [[x.z>y.z]] because dynamic scope y@0<>y@1. • Problem: actually, the dynamic scopes would have been the same a(x:T, y:T):Integer body: if x.z > y.z then self.b(x, y) + self.c(x, y) else ... endif b(x:T, y:T):Integer body: self.d(x, y) c(x:T, y:T):Integer body: self.d(y, x) d(x:T, y:T):Integer body: x.z + y.z
let y initExpr in self select(i|...) source body x.a.d let z initExpr in y.h.k z+i traceback on y.h; unused for y.h; unused for y.h.k; unused for z in z+i; unused for z+i in z+i (=false) traceback on y (after reverse-traversal across y.h); unused for y; unused for y.h (cached=false) --> on to initExpr for let-variable y: traceback on self (insert into cache: unused(self)=false); unused for self (cached: false)
iterate(result=self; i|...) • traceback for result, entering result value for current dynamic scope #n; unused for result--> result.c--> [[self.a.d]] with unknown self--> iterate (false) • branch: • traceback for self, infers one of potentially several values for self; unused for self--> iterate (false) • traceback for result.c, entering new dynamic scope for result.c (n++); unused for result.c but in different dynamic scope than the one cached-->[[self.a.d]] with yet unknown self (self values inferred on the other branch don't count in this branch) source body self.a.d result.c If a value is inferred for self, this triggers the [[self.a.d]] callback