diff options
Diffstat (limited to 'chapter15')
5 files changed, 47 insertions, 2 deletions
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java index a0c15ae3..81291326 100644 --- a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java @@ -834,6 +834,8 @@ public class Parser { // zero/sign extend. "i" is limited to either classic unsigned (min==0) or // classic signed (min=minus-power-of-2); max=power-of-2-minus-1. private Node zsMask(Node val, Type t ) { + if( val._type instanceof TypeFloat && t instanceof TypeInteger ) + val = new ToIntegerNode(val).peephole(); if( !(val._type instanceof TypeInteger tval && t instanceof TypeInteger t0 && !tval.isa(t0)) ) { if( !(val._type instanceof TypeFloat tval && t instanceof TypeFloat t0 && !tval.isa(t0)) ) return val; diff --git a/chapter15/src/main/java/com/seaofnodes/simple/node/ToIntegerNode.java b/chapter15/src/main/java/com/seaofnodes/simple/node/ToIntegerNode.java new file mode 100644 index 00000000..df740202 --- /dev/null +++ b/chapter15/src/main/java/com/seaofnodes/simple/node/ToIntegerNode.java @@ -0,0 +1,23 @@ +package com.seaofnodes.simple.node; + +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeFloat; +import com.seaofnodes.simple.type.TypeInteger; + +// Truncate toward zero, saturating overflow; NaN converts to zero. +public class ToIntegerNode extends Node { + public ToIntegerNode(Node lhs) { super(null,lhs); } + @Override public String label() { return "ToInteger"; } + @Override protected String format() { return "(int)%1"; } + + @Override public Type compute() { + Type t = in(1)._type; + if( t.isHigh() ) return TypeInteger.TOP; + if( t instanceof TypeFloat tf && tf.isConstant() ) + return TypeInteger.constant((long)tf.value()); + return TypeInteger.BOT; + } + + @Override public Node idealize() { return null; } + @Override Node copy(Node lhs, Node rhs) { return new ToIntegerNode(lhs); } +} diff --git a/chapter15/src/test/java/com/seaofnodes/simple/Chapter12Test.java b/chapter15/src/test/java/com/seaofnodes/simple/Chapter12Test.java index e885deb3..813dd757 100644 --- a/chapter15/src/test/java/com/seaofnodes/simple/Chapter12Test.java +++ b/chapter15/src/test/java/com/seaofnodes/simple/Chapter12Test.java @@ -126,8 +126,7 @@ N n = new N; n.i = 3.14; return n.i; """); - try { parser.parse().iterate(); fail(); } - catch( Exception e ) { assertEquals("Cannot store 3.14 into field int i",e.getMessage()); } + assertEquals("3",com.seaofnodes.simple.evaluator.Evaluator.evaluate(parser.parse().iterate(),0).toString()); } @Test diff --git a/chapter15/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java b/chapter15/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java index f4323fe0..fd71ad5f 100644 --- a/chapter15/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java +++ b/chapter15/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java @@ -8,6 +8,25 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class Chapter14FloatTest { + @Test public void testNumericAssignments() { + String[][] tests = { + {"int rounded=17.3/2.5; return rounded;", "6", "6"}, + {"int rounded=arg/2.5; return rounded;", "6", "-6"}, + {"int rounded=0; rounded=arg/2.5; return rounded;", "6", "-6"}, + {"i8 rounded=arg*16.0; return rounded;", "16", "-16"}, + {"int rounded=1e100; return rounded;", "9223372036854775807", "9223372036854775807"}, + {"int rounded=-1e100; return rounded;", "-9223372036854775808", "-9223372036854775808"}, + {"int rounded=1e300*1e300-1e300*1e300; return rounded;", "0", "0"}, + {"f32 rounded=arg+16777216.0; return rounded;", "1.6777232E7", "1.6777199E7"} + }; + for( String[] test : tests ) { + var stop = new Parser(test[0]).parse().iterate(); + assertEquals(test[0],test[1],Evaluator.evaluate(stop,17).toString()); + assertEquals(test[0],test[2],Evaluator.evaluate(stop,-17).toString()); + } + } + + @Test public void testSubZeroFloat() { var stop = new Parser("flt x = arg; return 0-x;").parse().iterate(); // Compare strings so +0.0 and -0.0 remain distinct. diff --git a/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java b/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java index 9eed23de..485f73c5 100644 --- a/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java +++ b/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java @@ -305,6 +305,8 @@ public class Evaluator { case OrNode or -> vall(or .in(1)) | vall(or .in(2)); case XorNode xor -> vall(xor.in(1)) ^ vall(xor.in(2)); case CastNode cast -> val(cast.in(1)); + case RoundF32Node rnd -> (double)(float)vald(rnd.in(1)); + case ToIntegerNode cvt -> (long)vald(cvt.in(1)); case ToFloatNode cast -> (double)vall(cast.in(1)); case LoadNode load -> load(load); case StoreNode store -> store(store); |
