diff options
| author | Cliff Click <cliffc@acm.org> | 2024-12-29 21:29:31 -0800 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-01-15 15:07:30 -0800 |
| commit | 5fe11b24e49c0a7bb84eeb76f724133e3298a1a9 (patch) | |
| tree | 7f6058ed0404d241a6988c69c1aa452ab52ebf13 /chapter18/src/main/java/com/seaofnodes | |
| parent | 5400096ec10da839cf2006a8a02e11ffeff521dd (diff) | |
| download | Simple-5fe11b24e49c0a7bb84eeb76f724133e3298a1a9.tar.gz Simple-5fe11b24e49c0a7bb84eeb76f724133e3298a1a9.zip | |
More getting errors reliable
...with and without peeps. Float moves out of the TypeNil set.
Eval2 picks up the FLT compares.
Diffstat (limited to 'chapter18/src/main/java/com/seaofnodes')
8 files changed, 64 insertions, 60 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index 235d2414..6267c09d 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -648,7 +648,7 @@ public class Parser { } private Node widenInt( Node expr, Type t ) { - return expr._type instanceof TypeInteger && t instanceof TypeFloat + return (expr._type instanceof TypeInteger || expr._type==Type.NIL) && t instanceof TypeFloat ? peep(new ToFloatNode(expr)) : expr; } @@ -706,7 +706,7 @@ public class Parser { // Bottom signals type inference: they must be initialized in // the constructor and that's when we'll discover the type. // Otherwise, its an Integer and use 0. - : (t==Type.BOTTOM ? con(t) : ZERO); + : (t==Type.BOTTOM ? con(t) : (t instanceof TypeInteger ? ZERO : con(TypeFloat.FZERO))); } // Lift expression, based on type @@ -1203,11 +1203,11 @@ public class Parser { // Happens when parsing known dead code, which often has other typing // issues. Since the code is dead, possibly due to inlining, lets not // spoil the user experience with error messages. - if( ctrl()._type==Type.XCONTROL ) { - if( expr.isUnused() ) expr.kill(); // Losing last use of expr - // Exit out via parsing the trailing expression - return matchOpx( '=', '=' ) ? parseAsgn() : parsePostfix( con( Type.TOP ) ); - } + //if( ctrl()._type==Type.XCONTROL ) { + // if( expr.isUnused() ) expr.kill(); // Losing last use of expr + // // Exit out via parsing the trailing expression + // return matchOpx( '=', '=' ) ? parseAsgn() : parsePostfix( con( Type.TOP ) ); + //} // if( expr._type==Type.NIL ) diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/LogicalNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/LogicalNode.java index 7f959ff3..094f2bf1 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/LogicalNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/LogicalNode.java @@ -18,8 +18,8 @@ public abstract class LogicalNode extends Node { @Override public String err() { if( in(1)._type.isHigh() || in(2)._type.isHigh() ) return null; - if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '"+op()+"' " + in(1)._type; - if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '"+op()+"' " + in(2)._type; + if( !(in(1)._type instanceof TypeInteger) ) return "Cannot '"+op()+"' " + in(1)._type.glb(); + if( !(in(2)._type instanceof TypeInteger) ) return "Cannot '"+op()+"' " + in(2)._type.glb(); return null; } } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java b/chapter18/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java index 8311405d..44d3a587 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/RoundF32Node.java @@ -30,7 +30,7 @@ public class RoundF32Node extends Node { Type t1 = lhs._type; // RoundF32 of float - if( t1 instanceof TypeFloat tf && tf._f32 ) + if( t1 instanceof TypeFloat tf && tf._sz==32 ) return lhs; return null; diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java index 4557a29e..0661ac2c 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java @@ -20,8 +20,9 @@ public class ToFloatNode extends Node { @Override public Type compute() { + if( in(1)._type == Type.NIL ) return TypeFloat.FZERO; if (in(1)._type instanceof TypeInteger i0 && i0.isConstant() ) - return i0.value()==0 ? Type.NIL : TypeFloat.constant(i0.value()); + return TypeFloat.constant(i0.value()); return TypeFloat.F64; } 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 9f9f688a..cb51a847 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/Type.java @@ -195,7 +195,7 @@ public class Type { public Type makeZero() { return Type.NIL; } /** Compute greatest lower bound in the lattice */ - public Type glb() { return Type.NIL; } + public Type glb() { return Type.BOTTOM; } // Is forward-reference public boolean isFRef() { return false; } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java index 143adbcd..df99b630 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java @@ -1,95 +1,92 @@ package com.seaofnodes.simple.type; import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.Utils; import java.util.ArrayList; /** * Float Type */ -public class TypeFloat extends TypeNil { +public class TypeFloat extends Type { - public final static TypeFloat ONE = constant(1.0); - public final static TypeFloat F32 = make((byte)3, true, 0); - public final static TypeFloat NF64 = make((byte)2,false, 0); - public final static TypeFloat F64 = make((byte)3,false, 0); + public final static TypeFloat ONE = constant(1.0); + public final static TypeFloat FZERO = constant(0.0); + public final static TypeFloat F32 = make(32, 0); + public final static TypeFloat F64 = make(64, 0); - // true for 32bits, false for 64bits - public final boolean _f32; + // - high -64, high -32, con 0, low +32, low +64 + public final byte _sz; /** * The constant value or 0 */ public final double _con; - private TypeFloat(byte nil, boolean f32, double con) { - super(TFLT,nil); - assert !isConstant() || ((float)con == con) == f32; - _f32 = f32; + private TypeFloat(byte sz, double con) { + super(TFLT); + _sz = sz; _con = con; } - private static TypeFloat make(byte nil, boolean f32, double con) { - return new TypeFloat(nil,f32,con).intern(); - } - @Override public TypeFloat makeFrom(byte nil) { - return nil==_nil ? this : make(nil,_f32,_con); + private static TypeFloat make(int sz, double con) { + return new TypeFloat((byte)sz,con).intern(); } - public static TypeFloat constant(double con) { assert con!=0; return make((byte)2,((float)con)==con, con); } + public static TypeFloat constant(double con) { return make(0, con); } public static void gather(ArrayList<Type> ts) { ts.add(F64); ts.add(F32); ts.add(constant(3.141592653589793)); } @Override public String str() { - if( isConstant() ) - return ""+_con+(_f32 ? "f" : ""); - String s = ""; - if( isHigh() ) s = "~"; - if( 1 <= _nil && _nil <= 2 ) // Disallow nil? - s += "n"; - s += "f"; - s += _f32 ? "32" : "lt"; - return s; + return switch( _sz ) { + case -64 -> "~flt"; + case -32 -> "~f32"; + case 0 -> ""+_con+((float)_con==_con ? "f" : ""); + case 32 -> "f32"; + case 64 -> "flt"; + default -> throw Utils.TODO(); + }; } + private boolean isF32() { return ((float)_con)==_con; } - @Override public boolean isConstant() { return _con!=0; } - @Override public int log_size() { return _f32 ? 2 : 3; } + @Override public boolean isConstant() { return _sz==0; } + @Override public int log_size() { return _sz==32 || _sz==-32 ? 2 : 3; } public double value() { return _con; } @Override public TypeFloat xmeet(Type other) { + TypeFloat f = (TypeFloat)other; // Invariant from caller: 'this' != 'other' and same class (TypeFloat). TypeFloat i = (TypeFloat)other; // Contract - if( isConstant() && i.isHigh() ) return i._f32 && ! _f32 ? NF64 : this; - if( i.isConstant() && isHigh() ) return _f32 && !i._f32 ? NF64 : i ; - - - // From online Karnaugh map; if both values are small the result is - // small, otherwise the result is small if the otherside is high. - boolean f32 = (_f32&i._f32) | (i.isHigh()&_f32) | (isHigh()&i._f32); - return make(xmeet0(i), f32, 0); + // Larger size in i1, smaller in i0 + TypeFloat i0 = _sz < i._sz ? this : i; + TypeFloat i1 = _sz < i._sz ? i : this; + + if( i1._sz== 64 ) return F64; + if( i0._sz==-64 ) return i1; + if( i1._sz== 32 ) + return i0._sz==0 && !i0.isF32() ? F64 : F32; + if( i1._sz!= 0 ) return i1; + // i1 is a constant + if( i0._sz==-32 ) + return i1.isF32() ? i1 : F64; + // Since both are constants, and are never equals (contract) unequals + // constants fall to bottom + return i0.isF32() && i1.isF32() ? F32 : F64; } @Override public Type dual() { - if( isConstant() ) return this; // Constants are a self-dual - return make(dual0(),_f32,0); + return isConstant() ? this : make(-_sz,0); // Constants are a self-dual } - // RHS is NIL - @Override Type meet0() { - // From high, falling to the least Float that contains a zero - return isHigh() || _f32 ? F32 : F64; - } - - @Override public Type glb() { return F64; } @Override - int hash() { return (int)(Double.hashCode(_con) ^ (_f32 ? 2048 : 0) ^ super.hash()); } + int hash() { return (int)(Double.hashCode(_con) ^ _sz ^ (1<<17)); } @Override public boolean eq( Type t ) { TypeFloat i = (TypeFloat)t; // Contract - return _con==i._con && _f32==i._f32 && super.eq(i); + return _con==i._con && _sz==i._sz; } } diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java index 9438abe2..9ed4c7a8 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMem.java @@ -19,7 +19,12 @@ public class TypeMem extends Type { public final int _alias; public final Type _t; // Memory contents, some scalar type - private TypeMem(int alias, Type t) { super(TMEM); _alias = alias; _t = t; } + private TypeMem(int alias, Type t) { + super(TMEM); + assert alias!=0 || (t==Type.TOP || t==Type.BOTTOM); + _alias = alias; + _t = t; + } public static TypeMem make(int alias, Type t) { return new TypeMem(alias,t).intern(); } public static final TypeMem TOP = make(0, Type.TOP ); diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java index 03c67ce9..aee623ba 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeNil.java @@ -48,6 +48,7 @@ public abstract class TypeNil extends Type { @Override public boolean isConstant () { return false; } @Override public boolean isHighOrConst() { return isHigh() || isConstant(); } + @Override public Type glb() { return Type.NIL; } public boolean notNull() { return _nil==1 || _nil==2; } public boolean nullable() { return _nil==3; } |
