diff options
| author | Cliff Click <cliffc@acm.org> | 2025-01-12 10:54:27 -0800 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-01-15 15:07:30 -0800 |
| commit | e491c528e8d9380bdef823889f0b0a8e08a34f55 (patch) | |
| tree | 3da5efc22250cbfcab14fd175fd5f69ed9fd11f5 | |
| parent | 4cbab83ffd93831c0c9d887889bcf3ac49460d00 (diff) | |
| download | Simple-e491c528e8d9380bdef823889f0b0a8e08a34f55.tar.gz Simple-e491c528e8d9380bdef823889f0b0a8e08a34f55.zip | |
Fix deep co-recursive type check
5 files changed, 85 insertions, 22 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index a4fd9d52..649145fd 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -651,7 +651,7 @@ public class Parser { // Auto-narrow wide ints to narrow ints expr = zsMask(expr,t); // Type is sane - if( expr._type!=Type.BOTTOM && !expr._type.isa(t) ) + if( expr._type!=Type.BOTTOM && !expr._type.shallowISA(t) ) throw error("Type " + expr._type.str() + " is not of declared type " + t.str()); return expr; } @@ -835,7 +835,7 @@ public class Parser { if( !(peek(',') || peek(';')) ) return posT(old1); pos(old2); // Reset lexer to reparse - if( id==null || _scope.lookup(id)!=null ) + if( id==null ) return posT(old1); // Reset lexer to reparse // Yes a forward ref, so declare it TYPES.put(tname,t1); diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java index 95fdca74..b6757ef2 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java @@ -191,6 +191,9 @@ public class Type { // True if this "isa" t; e.g. 17 isa TypeInteger.BOT public boolean isa( Type t ) { return meet(t)==t; } + // True if this "isa" t up to named structures + public boolean shallowISA( Type t ) { return isa(t); } + public Type nonZero() { return TypePtr.NPTR; } // Make a zero version of this type, 0 for integers and null for pointers. diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java index 6dda9c39..c8a5c1f4 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java @@ -64,6 +64,18 @@ public class TypeMemPtr extends TypeNil { return _nil==3 ? this : make((byte)3,_obj); } + + // True if this "isa" t up to named structures + @Override public boolean shallowISA( Type t ) { + if( !(t instanceof TypeMemPtr that) ) return false; + if( this==that ) return true; + if( xmeet0(that)!=that._nil ) return false; + if( _obj==that._obj ) return true; + if( _obj._name.equals(that._obj._name) ) + return true; // Shallow, do not follow matching names, just assume ok + throw Utils.TODO(); // return _obj.shallowISA(that._obj); + } + @Override public TypeMemPtr glb() { return make((byte)3,_obj.glb()); } // Is forward-reference @Override public boolean isFRef() { return _obj.isFRef(); } diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java index 645c066a..6aa64bf9 100644 --- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java +++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java @@ -178,4 +178,70 @@ return p1.pi.i + 1; catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); } } + @Test + public void testCoRecur2() { + CodeGen code = new CodeGen( +""" +struct A { L? a; T? b; F? c; }; A? !a = new A; +struct B { M? a; U? b; G? c; }; B? !b = new B; +struct C { N? a; V? b; H? c; }; C? !c = new C; +struct D { O? a; W? b; I? c; }; D? !d = new D; +struct E { P? a; X? b; J? c; }; E? !e = new E; +struct F { Q? a; Y? b; K? c; }; F? !f = new F; +struct G { R? a; Z? b; L? c; }; G? !g = new G; +struct H { S? a; A? b; M? c; }; H? !h = new H; +struct I { T? a; B? b; N? c; }; I? !i = new I; +struct J { U? a; C? b; O? c; }; J? !j = new J; +struct K { V? a; D? b; P? c; }; K? !k = new K; +struct L { W? a; E? b; Q? c; }; L? !l = new L; +struct M { X? a; F? b; R? c; }; M? !m = new M; +struct N { Y? a; G? b; S? c; }; N? !n = new N; +struct O { Z? a; H? b; T? c; }; O? !o = new O; +struct P { A? a; I? b; U? c; }; P? !p = new P; +struct Q { B? a; J? b; V? c; }; Q? !q = new Q; +struct R { C? a; K? b; W? c; }; R? !r = new R; +struct S { D? a; L? b; X? c; }; S? !s = new S; +struct T { E? a; M? b; Y? c; }; T? !t = new T; +struct U { F? a; N? b; Z? c; }; U? !u = new U; +struct V { G? a; O? b; A? c; }; V? !v = new V; +struct W { H? a; P? b; B? c; }; W? !w = new W; +struct X { I? a; Q? b; C? c; }; X? !x = new X; +struct Y { J? a; R? b; D? c; }; Y? !y = new Y; +struct Z { K? a; S? b; E? c; }; Z? !z = new Z; + +a.a=l; a.b=t; a.c=f; +b.a=m; b.b=u; b.c=g; +c.a=n; c.b=v; c.c=h; +d.a=o; d.b=w; d.c=i; +e.a=p; e.b=x; e.c=j; +f.a=q; f.b=y; f.c=k; +g.a=r; g.b=z; g.c=l; +h.a=s; h.b=a; h.c=m; +i.a=t; i.b=b; i.c=n; +j.a=u; j.b=c; j.c=o; +k.a=v; k.b=d; k.c=p; +l.a=w; l.b=e; l.c=q; +m.a=x; m.b=f; m.c=r; +n.a=y; n.b=g; n.c=s; +o.a=z; o.b=h; o.c=t; +p.a=a; p.b=i; p.c=u; +q.a=b; q.b=j; q.c=v; +r.a=c; r.b=k; r.c=w; +s.a=d; s.b=l; s.c=x; +t.a=e; t.b=m; t.c=y; +u.a=f; u.b=n; u.c=z; +v.a=g; v.b=o; v.c=a; +w.a=h; w.b=p; w.c=b; +x.a=i; x.b=q; x.c=c; +y.a=j; y.b=r; y.c=d; +z.a=k; z.b=s; z.c=e; + +return a.b.c.a.b.c.a.b.c.a.b.c.a.b.c.a.b.c; + +"""); + code.parse().opto().typeCheck().GCM().localSched(); + assertEquals("return R;", code._stop.toString()); + assertEquals("R{a=C{a=N{a=Y{a=J{a=U{a=F{a=Q{a=B{a=M{a=X{a=I{a=T{a=E{a=P{a=A{a=L{a=W{a=H{a=S{a=D{a=O{a=Z{a=K{a=V{a=G{a=$cyclic,b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic}", Eval2.eval(code, 0)); + } + } diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java index 8852537b..217c6275 100644 --- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -13,27 +13,9 @@ public class Chapter18Test { """ return 0; """); - code.parse().opto().typeCheck().GCM().localSched(); - assertEquals("return 0;", code._stop.toString()); - assertEquals("0", Eval2.eval(code, 0)); - } - - @Test - public void testJig2() { - CodeGen code = new CodeGen( -""" -struct S { S? next; }; -val f = { int dep, S s -> - if (dep-- == 0) return s; - S? v = f(dep, s); - return v ? v.next : null; -}; -return f(1, new S); -"""); code.parse().opto().typeCheck().GCM(); - assertEquals("Stop[ return f( 1,S); return Phi(Region,Parm_s(f,*S {*S? !next; },S,s),Phi(Region,.next,null)); ]", code._stop.toString()); - assertEquals("null", Eval2.eval(code, 0)); - assertEquals("null", Eval2.eval(code, 1)); + assertEquals("return 0;", code._stop.toString()); + assertEquals("0", Eval2.eval(code, 1)); } @Test |
