# HG changeset patch # User Matthias Grimmer # Date 1449843627 -3600 # Node ID aeba89e1d8da74a1800be2bf11f1e3688a77a849 # Parent 28227895fa3577a7eaee3f8c2087a4798e995792 Add ComplexNumber sequence tests diff -r 28227895fa35 -r aeba89e1d8da truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java --- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java Thu Dec 10 15:00:16 2015 +0100 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java Fri Dec 11 15:20:27 2015 +0100 @@ -44,8 +44,11 @@ import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.sl.test.instrument.InstrumentationTestMode; import com.oracle.truffle.tck.TruffleTCK; + import org.junit.After; + import static org.junit.Assert.assertTrue; + import org.junit.Before; import org.junit.Test; @@ -220,4 +223,32 @@ public void testPrimitiveidentityFloat() throws Exception { } + @Override + public void testSumRealOfComplexNumbersA() throws Exception { + } + + @Override + public void testSumRealOfComplexNumbersB() throws Exception { + } + + @Override + public void testSumRealOfComplexNumbersAsStructuredDataColumnBased() throws Exception { + } + + @Override + public void testSumRealOfComplexNumbersAsStructuredDataRowBased() throws Exception { + } + + @Override + public void testCopyComplexNumbersA() throws Exception { + } + + @Override + public void testCopyComplexNumbersB() throws Exception { + } + + @Override + public void testCopyStructuredComplexToComplexNumbersA() throws Exception { + } + } diff -r 28227895fa35 -r aeba89e1d8da truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/ComplexNumber.java --- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/ComplexNumber.java Thu Dec 10 15:00:16 2015 +0100 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/ComplexNumber.java Fri Dec 11 15:20:27 2015 +0100 @@ -33,39 +33,45 @@ import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.RootNode; -public class ComplexNumber implements TruffleObject { +public final class ComplexNumber implements TruffleObject { public static final String REAL_IDENTIFIER = "real"; public static final String IMAGINARY_IDENTIFIER = "imaginary"; - private final double[] data = new double[2]; + private double real; + private double imag; public ComplexNumber(double real, double imaginary) { - data[0] = real; - data[1] = imaginary; + this.real = real; + this.imag = imaginary; } public ForeignAccess getForeignAccess() { return ForeignAccess.create(new ComplexForeignAccessFactory()); } - private static int identifierToIndex(String identifier) { + public void set(String identifier, double value) { switch (identifier) { case REAL_IDENTIFIER: - return 0; + this.real = value; + break; case IMAGINARY_IDENTIFIER: - return 1; + this.imag = value; + break; default: throw new IllegalArgumentException(); } } - public void set(String identifier, double value) { - data[identifierToIndex(identifier)] = value; - } - public double get(String identifier) { - return data[identifierToIndex(identifier)]; + switch (identifier) { + case REAL_IDENTIFIER: + return this.real; + case IMAGINARY_IDENTIFIER: + return this.imag; + default: + throw new IllegalArgumentException(); + } } private static class ComplexForeignAccessFactory implements Factory { diff -r 28227895fa35 -r aeba89e1d8da truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/ComplexNumbersA.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/ComplexNumbersA.java Fri Dec 11 15:20:27 2015 +0100 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tck; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.ForeignAccess.Factory; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; + +public final class ComplexNumbersA implements TruffleObject { + + private final double[] data; + + public ComplexNumbersA(double[] data) { + assert data.length % 2 == 0; + this.data = data; + } + + public double[] getData() { + return data; + } + + public ForeignAccess getForeignAccess() { + return ForeignAccess.create(new ComplexNumbersAForeignAccessFactory()); + } + + private static class ComplexNumbersAForeignAccessFactory implements Factory { + + public boolean canHandle(TruffleObject obj) { + return obj instanceof ComplexNumbersA; + } + + public CallTarget accessMessage(Message tree) { + if (Message.IS_NULL.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_EXECUTABLE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_BOXED.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.HAS_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(true)); + } else if (Message.READ.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersAReadNode()); + } else if (Message.WRITE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersAWriteNode()); + } else if (Message.GET_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersASizeNode()); + } else { + throw new IllegalArgumentException(tree.toString() + " not supported"); + } + } + } + + private static class ComplexNumbersAWriteNode extends RootNode { + protected ComplexNumbersAWriteNode() { + super(TckLanguage.class, null, null); + } + + @Child private Node readReal; + @Child private Node readImag; + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumbersA complexNumbers = (ComplexNumbersA) ForeignAccess.getReceiver(frame); + Number index = (Number) ForeignAccess.getArguments(frame).get(0); + TruffleObject value = (TruffleObject) ForeignAccess.getArguments(frame).get(1); + if (readReal == null || readImag == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + this.readReal = insert(Message.READ.createNode()); + this.readImag = insert(Message.READ.createNode()); + } + Number realPart = (Number) ForeignAccess.execute(readReal, frame, value, new Object[]{ComplexNumber.REAL_IDENTIFIER}); + Number imagPart = (Number) ForeignAccess.execute(readImag, frame, value, new Object[]{ComplexNumber.IMAGINARY_IDENTIFIER}); + + complexNumbers.data[index.intValue() * 2] = realPart.doubleValue(); + complexNumbers.data[index.intValue() * 2 + 1] = imagPart.doubleValue(); + return value; + } + } + + private static class ComplexNumbersAReadNode extends RootNode { + protected ComplexNumbersAReadNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumbersA complexNumbers = (ComplexNumbersA) ForeignAccess.getReceiver(frame); + Number index = (Number) ForeignAccess.getArguments(frame).get(0); + return new ComplexNumberAEntry(complexNumbers, index.intValue()); + } + } + + private static class ComplexNumbersASizeNode extends RootNode { + protected ComplexNumbersASizeNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumbersA complexNumbers = (ComplexNumbersA) ForeignAccess.getReceiver(frame); + return complexNumbers.data.length / 2; + } + + } + + private static class ComplexNumberAEntry implements TruffleObject { + + private final ComplexNumbersA numbers; + private final int index; + + public ComplexNumberAEntry(ComplexNumbersA numbers, int index) { + this.numbers = numbers; + this.index = index; + } + + public ForeignAccess getForeignAccess() { + return ForeignAccess.create(new ComplexNumberAEntryForeignAccessFactory()); + } + + private static class ComplexNumberAEntryForeignAccessFactory implements Factory { + + public boolean canHandle(TruffleObject obj) { + return obj instanceof ComplexNumberAEntry; + } + + public CallTarget accessMessage(Message tree) { + if (Message.IS_NULL.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_EXECUTABLE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_BOXED.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.HAS_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.READ.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersAEntryReadNode()); + } else if (Message.WRITE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersAEntryWriteNode()); + } else { + throw new IllegalArgumentException(tree.toString() + " not supported"); + } + } + + private static class ComplexNumbersAEntryReadNode extends RootNode { + protected ComplexNumbersAEntryReadNode() { + super(TckLanguage.class, null, null); + } + + @Child private Node readReal; + @Child private Node readImag; + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumberAEntry complexNumber = (ComplexNumberAEntry) ForeignAccess.getReceiver(frame); + String name = (String) ForeignAccess.getArguments(frame).get(0); + if (name.equals(ComplexNumber.IMAGINARY_IDENTIFIER)) { + return complexNumber.numbers.data[complexNumber.index * 2 + 1]; + } else if (name.equals(ComplexNumber.REAL_IDENTIFIER)) { + return complexNumber.numbers.data[complexNumber.index * 2]; + } else { + throw new IllegalArgumentException(); + } + } + } + + private static class ComplexNumbersAEntryWriteNode extends RootNode { + protected ComplexNumbersAEntryWriteNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumberAEntry complexNumber = (ComplexNumberAEntry) ForeignAccess.getReceiver(frame); + String name = (String) ForeignAccess.getArguments(frame).get(0); + Number value = (Number) ForeignAccess.getArguments(frame).get(1); + if (name.equals(ComplexNumber.IMAGINARY_IDENTIFIER)) { + complexNumber.numbers.data[complexNumber.index * 2 + 1] = value.doubleValue(); + } else if (name.equals(ComplexNumber.REAL_IDENTIFIER)) { + complexNumber.numbers.data[complexNumber.index * 2] = value.doubleValue(); + } else { + throw new IllegalArgumentException(); + } + return value; + } + + } + } + + } +} diff -r 28227895fa35 -r aeba89e1d8da truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/ComplexNumbersB.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/ComplexNumbersB.java Fri Dec 11 15:20:27 2015 +0100 @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tck; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.ForeignAccess.Factory; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; + +public class ComplexNumbersB implements TruffleObject { + + private final double[] reals; + private final double[] imags; + + public ComplexNumbersB(double[] reals, double[] imags) { + assert reals.length == imags.length; + this.reals = reals; + this.imags = imags; + } + + public double[] getData() { + double[] data = new double[reals.length * 2]; + for (int i = 0; i < reals.length; i++) { + data[i * 2] = reals[i]; + data[i * 2 + 1] = imags[i]; + } + return data; + } + + public ForeignAccess getForeignAccess() { + return ForeignAccess.create(new ComplexNumbersBForeignAccessFactory()); + } + + private static class ComplexNumbersBForeignAccessFactory implements Factory { + + public boolean canHandle(TruffleObject obj) { + return obj instanceof ComplexNumbersB; + } + + public CallTarget accessMessage(Message tree) { + if (Message.IS_NULL.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_EXECUTABLE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_BOXED.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.HAS_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(true)); + } else if (Message.READ.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersBReadNode()); + } else if (Message.WRITE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersBWriteNode()); + } else if (Message.GET_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersBSizeNode()); + } else { + throw new IllegalArgumentException(tree.toString() + " not supported"); + } + } + } + + private static class ComplexNumbersBWriteNode extends RootNode { + protected ComplexNumbersBWriteNode() { + super(TckLanguage.class, null, null); + } + + @Child private Node readReal; + @Child private Node readImag; + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumbersB complexNumbers = (ComplexNumbersB) ForeignAccess.getReceiver(frame); + Number index = (Number) ForeignAccess.getArguments(frame).get(0); + TruffleObject value = (TruffleObject) ForeignAccess.getArguments(frame).get(1); + if (readReal == null || readImag == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + this.readReal = insert(Message.READ.createNode()); + this.readImag = insert(Message.READ.createNode()); + } + Number realPart = (Number) ForeignAccess.execute(readReal, frame, value, new Object[]{ComplexNumber.REAL_IDENTIFIER}); + Number imagPart = (Number) ForeignAccess.execute(readImag, frame, value, new Object[]{ComplexNumber.IMAGINARY_IDENTIFIER}); + + complexNumbers.reals[index.intValue()] = realPart.doubleValue(); + complexNumbers.imags[index.intValue()] = imagPart.doubleValue(); + return value; + } + } + + private static class ComplexNumbersBReadNode extends RootNode { + protected ComplexNumbersBReadNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumbersB complexNumbers = (ComplexNumbersB) ForeignAccess.getReceiver(frame); + Number index = (Number) ForeignAccess.getArguments(frame).get(0); + return new ComplexNumberBEntry(complexNumbers, index.intValue()); + } + + } + + private static class ComplexNumbersBSizeNode extends RootNode { + protected ComplexNumbersBSizeNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumbersB complexNumbers = (ComplexNumbersB) ForeignAccess.getReceiver(frame); + assert complexNumbers.reals.length == complexNumbers.imags.length; + return complexNumbers.reals.length; + } + + } + + private static class ComplexNumberBEntry implements TruffleObject { + + private final ComplexNumbersB numbers; + private final int index; + + public ComplexNumberBEntry(ComplexNumbersB numbers, int index) { + this.numbers = numbers; + this.index = index; + } + + public ForeignAccess getForeignAccess() { + return ForeignAccess.create(new ComplexNumberBEntryForeignAccessFactory()); + } + + private static class ComplexNumberBEntryForeignAccessFactory implements Factory { + + public boolean canHandle(TruffleObject obj) { + return obj instanceof ComplexNumberBEntry; + } + + public CallTarget accessMessage(Message tree) { + if (Message.IS_NULL.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_EXECUTABLE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_BOXED.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.HAS_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.READ.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersAEntryReadNode()); + } else if (Message.WRITE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new ComplexNumbersAEntryWriteNode()); + } else { + throw new IllegalArgumentException(tree.toString() + " not supported"); + } + } + + private static class ComplexNumbersAEntryReadNode extends RootNode { + protected ComplexNumbersAEntryReadNode() { + super(TckLanguage.class, null, null); + } + + @Child private Node readReal; + @Child private Node readImag; + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumberBEntry complexNumber = (ComplexNumberBEntry) ForeignAccess.getReceiver(frame); + String name = (String) ForeignAccess.getArguments(frame).get(0); + if (name.equals(ComplexNumber.IMAGINARY_IDENTIFIER)) { + return complexNumber.numbers.imags[complexNumber.index]; + } else if (name.equals(ComplexNumber.REAL_IDENTIFIER)) { + return complexNumber.numbers.reals[complexNumber.index]; + } else { + throw new IllegalArgumentException(); + } + } + } + + private static class ComplexNumbersAEntryWriteNode extends RootNode { + protected ComplexNumbersAEntryWriteNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + ComplexNumberBEntry complexNumber = (ComplexNumberBEntry) ForeignAccess.getReceiver(frame); + String name = (String) ForeignAccess.getArguments(frame).get(0); + Number value = (Number) ForeignAccess.getArguments(frame).get(1); + if (name.equals(ComplexNumber.IMAGINARY_IDENTIFIER)) { + complexNumber.numbers.imags[complexNumber.index] = value.doubleValue(); + } else if (name.equals(ComplexNumber.REAL_IDENTIFIER)) { + complexNumber.numbers.reals[complexNumber.index] = value.doubleValue(); + } else { + throw new IllegalArgumentException(); + } + return value; + } + + } + } + + } + +} diff -r 28227895fa35 -r aeba89e1d8da truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/MapTruffleObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/MapTruffleObject.java Fri Dec 11 15:20:27 2015 +0100 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tck; + +import java.util.Map; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.ForeignAccess.Factory; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.RootNode; + +@SuppressWarnings({"rawtypes", "unchecked"}) +public final class MapTruffleObject implements TruffleObject { + + private final Map map; + + public MapTruffleObject(Map map) { + this.map = map; + } + + public ForeignAccess getForeignAccess() { + return ForeignAccess.create(new MapForeignAccessFactory()); + } + + private static class MapForeignAccessFactory implements Factory { + + public boolean canHandle(TruffleObject obj) { + return obj instanceof MapTruffleObject; + } + + public CallTarget accessMessage(Message tree) { + if (Message.IS_NULL.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_EXECUTABLE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_BOXED.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.HAS_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(true)); + } else if (Message.READ.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new MapReadNode()); + } else if (Message.WRITE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new MapWriteNode()); + } else if (Message.GET_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new MapSizeNode()); + } else { + throw new IllegalArgumentException(tree.toString() + " not supported"); + } + } + } + + private static class MapWriteNode extends RootNode { + protected MapWriteNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + MapTruffleObject map = (MapTruffleObject) ForeignAccess.getReceiver(frame); + Object key = ForeignAccess.getArguments(frame).get(0); + Object value = ForeignAccess.getArguments(frame).get(1); + map.map.put(key, value); + return value; + } + } + + private static class MapReadNode extends RootNode { + protected MapReadNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + MapTruffleObject map = (MapTruffleObject) ForeignAccess.getReceiver(frame); + Object key = ForeignAccess.getArguments(frame).get(0); + return map.map.get(key); + } + + } + + private static class MapSizeNode extends RootNode { + protected MapSizeNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + MapTruffleObject map = (MapTruffleObject) ForeignAccess.getReceiver(frame); + return map.map.size(); + } + + } + +} diff -r 28227895fa35 -r aeba89e1d8da truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/Schema.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/Schema.java Fri Dec 11 15:20:27 2015 +0100 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tck; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public final class Schema { + + public enum Type { + DOUBLE(Double.SIZE / Byte.SIZE), + INT(Integer.SIZE / Byte.SIZE); + + private final int size; + + private Type(int size) { + this.size = size; + } + } + + private final int size; + private final boolean rowBased; + private final List names; + private final List types; + + public Schema(int size, boolean rowBased, List names, List types) { + this.size = size; + this.rowBased = rowBased; + this.names = names; + this.types = types; + } + + public int length() { + return size; + } + + // for simplicity: structured data is read-only + + public Map getEntry(byte[] buffer, int index) { + Map entry = new HashMap<>(); + for (int i = 0; i < names.size(); i++) { + String name = names.get(i); + Object value = get(buffer, index, name); + entry.put(name, value); + } + return entry; + } + + private Object get(byte[] buffer, int index, String name) { + assert names.contains(name); + int offset = rowBased ? getRowOffset(name, index) : getColumnOffset(name, index); + if (types.get(names.indexOf(name)) == Type.DOUBLE) { + byte[] b = new byte[Type.DOUBLE.size]; + for (int i = 0; i < Type.DOUBLE.size; i++) { + b[i] = buffer[offset + i]; + } + return ByteBuffer.wrap(b).getDouble(); + } else if (types.get(names.indexOf(name)) == Type.INT) { + byte[] b = new byte[Type.INT.size]; + for (int i = 0; i < Type.INT.size; i++) { + b[i] = buffer[offset + i]; + } + return ByteBuffer.wrap(b).getInt(); + } + throw new IllegalStateException(); + } + + private int getRowSize() { + assert rowBased; + int rowSize = 0; + for (Type t : types) { + rowSize += t.size; + } + return rowSize; + } + + private int getRowOffset(String name, int index) { + assert rowBased; + if (names.contains(name)) { + int offset = 0; + for (int i = 0; i < names.size(); i++) { + if (names.get(i).equals(name)) { + return index * getRowSize() + offset; + } else { + offset += types.get(i).size; + } + } + } else { + throw new IllegalArgumentException(); + } + throw new IllegalStateException(); + } + + private int getColumnOffset(String name, int index) { + assert !rowBased; + if (names.contains(name)) { + int offset = 0; + for (int i = 0; i < names.size(); i++) { + if (names.get(i).equals(name)) { + return offset + index * types.get(i).size; + } else { + offset += types.get(i).size * size; + } + } + } else { + throw new IllegalArgumentException(); + } + throw new IllegalStateException(); + } +} diff -r 28227895fa35 -r aeba89e1d8da truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/StructuredData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/StructuredData.java Fri Dec 11 15:20:27 2015 +0100 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tck; + +import java.util.Map; + +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.ForeignAccess.Factory; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.RootNode; + +public final class StructuredData implements TruffleObject { + + private final byte[] buffer; + private final Schema schema; + + public StructuredData(byte[] buffer, Schema schema) { + this.buffer = buffer; + this.schema = schema; + } + + public Map getEntry(int index) { + return schema.getEntry(buffer, index); + } + + public ForeignAccess getForeignAccess() { + return ForeignAccess.create(new StructuredDataForeignAccessFactory()); + } + + private static class StructuredDataForeignAccessFactory implements Factory { + + public boolean canHandle(TruffleObject obj) { + return obj instanceof StructuredData; + } + + public CallTarget accessMessage(Message tree) { + // for simplicity: this StructuredData is read-only + if (Message.IS_NULL.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_EXECUTABLE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.IS_BOXED.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(false)); + } else if (Message.HAS_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(RootNode.createConstantNode(true)); + } else if (Message.READ.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new StructuredDataReadNode()); + } else if (Message.GET_SIZE.equals(tree)) { + return Truffle.getRuntime().createCallTarget(new StructuredDataSizeNode()); + } else { + throw new IllegalArgumentException(tree.toString() + " not supported"); + } + } + } + + private static class StructuredDataReadNode extends RootNode { + protected StructuredDataReadNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + StructuredData data = (StructuredData) ForeignAccess.getReceiver(frame); + Number index = (Number) ForeignAccess.getArguments(frame).get(0); + return new MapTruffleObject(data.getEntry(index.intValue())); + } + + } + + private static class StructuredDataSizeNode extends RootNode { + protected StructuredDataSizeNode() { + super(TckLanguage.class, null, null); + } + + @Override + public Object execute(VirtualFrame frame) { + StructuredData data = (StructuredData) ForeignAccess.getReceiver(frame); + return data.schema.length(); + } + + } +} \ No newline at end of file diff -r 28227895fa35 -r aeba89e1d8da truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java --- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Thu Dec 10 15:00:16 2015 +0100 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Fri Dec 11 15:20:27 2015 +0100 @@ -24,16 +24,6 @@ */ package com.oracle.truffle.tck; -import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.api.interop.TruffleObject; -import com.oracle.truffle.api.interop.java.JavaInterop; -import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.vm.PolyglotEngine; -import com.oracle.truffle.api.vm.PolyglotEngine.Language; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.Random; -import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; @@ -42,6 +32,23 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Random; + +import org.junit.Assert; +import org.junit.Test; + +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.java.JavaInterop; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.api.vm.PolyglotEngine.Language; +import com.oracle.truffle.tck.Schema.Type; + /** * A collection of tests that can certify language implementation to be compliant with most recent * requirements of the Truffle infrastructure and tooling. Subclass, implement abstract methods and @@ -156,6 +163,29 @@ } /** + * Name of a function that adds up the real part of complex numbers. The function accepts one + * argument and provides the sum of all real parts. The argument is an array/buffer of complex + * numbers. + * + * @return name of globally exported symbol + */ + protected String complexSumReal() { + throw new UnsupportedOperationException("complexSumReal() method not implemented"); + } + + /** + * Name of a function that copies a list of complex numbers. The function accepts two arguments + * and provides no return value. The arguments are two lists of complex numbers with members + * called real and imaginary. The first argument is the destination, the second argument is the + * source. + * + * @return name of globally exported symbol + */ + protected String complexCopy() { + throw new UnsupportedOperationException("complexCopy() method not implemented"); + } + + /** * Name of a function to return global object. The function can be executed without providing * any arguments and should return global object of the language, if the language supports it. * Global object is the one accessible via @@ -796,6 +826,133 @@ assertEquals(42.0, a.get(ComplexNumber.IMAGINARY_IDENTIFIER), 0.1); } + @Test + public void testSumRealOfComplexNumbersA() throws Exception { + String id = complexSumReal(); + if (id == null) { + return; + } + PolyglotEngine.Value apply = findGlobalSymbol(id); + + ComplexNumbersA numbers = new ComplexNumbersA(new double[]{2, -1, 30, -1, 10, -1}); + + Number n = (Number) apply.execute(numbers).get(); + assertEquals("The same value returned", 42.0, n.doubleValue(), 0.01); + } + + @Test + public void testSumRealOfComplexNumbersB() throws Exception { + String id = complexSumReal(); + if (id == null) { + return; + } + PolyglotEngine.Value apply = findGlobalSymbol(id); + + ComplexNumbersB numbers = new ComplexNumbersB(new double[]{2, 30, 10}, new double[]{-1, -1, -1}); + + Number n = (Number) apply.execute(numbers).get(); + assertEquals("The same value returned", 42.0, n.doubleValue(), 0.01); + } + + @Test + public void testSumRealOfComplexNumbersAsStructuredDataRowBased() throws Exception { + String id = complexSumReal(); + if (id == null) { + return; + } + PolyglotEngine.Value apply = findGlobalSymbol(id); + + Schema schema = new Schema(3, true, Arrays.asList(ComplexNumber.REAL_IDENTIFIER, ComplexNumber.IMAGINARY_IDENTIFIER), Arrays.asList(Type.DOUBLE, Type.DOUBLE)); + byte[] buffer = new byte[(6 * Double.SIZE / Byte.SIZE)]; + putDoubles(buffer, new double[]{2, -1, 30, -1, 10, -1}); + StructuredData numbers = new StructuredData(buffer, schema); + + Number n = (Number) apply.execute(numbers).get(); + assertEquals("The same value returned", 42.0, n.doubleValue(), 0.01); + } + + @Test + public void testSumRealOfComplexNumbersAsStructuredDataColumnBased() throws Exception { + String id = complexSumReal(); + if (id == null) { + return; + } + PolyglotEngine.Value apply = findGlobalSymbol(id); + + Schema schema = new Schema(3, false, Arrays.asList(ComplexNumber.REAL_IDENTIFIER, ComplexNumber.IMAGINARY_IDENTIFIER), Arrays.asList(Type.DOUBLE, Type.DOUBLE)); + byte[] buffer = new byte[6 * Double.SIZE / Byte.SIZE]; + putDoubles(buffer, new double[]{2, 30, 10, -1, -1, -1}); + + StructuredData numbers = new StructuredData(buffer, schema); + + Number n = (Number) apply.execute(numbers).get(); + assertEquals("The same value returned", 42.0, n.doubleValue(), 0.01); + } + + @Test + public void testCopyComplexNumbersA() throws Exception { + String id = complexCopy(); + if (id == null) { + return; + } + PolyglotEngine.Value apply = findGlobalSymbol(id); + + ComplexNumbersA a = new ComplexNumbersA(new double[]{-1, -1, -1, -1, -1, -1}); + ComplexNumbersA b = new ComplexNumbersA(new double[]{41, 42, 43, 44, 45, 46}); + + apply.execute(a, b); + + Assert.assertArrayEquals(new double[]{41, 42, 43, 44, 45, 46}, a.getData(), 0.1); + } + + @Test + public void testCopyComplexNumbersB() throws Exception { + String id = complexCopy(); + if (id == null) { + return; + } + PolyglotEngine.Value apply = findGlobalSymbol(id); + + ComplexNumbersB a = new ComplexNumbersB(new double[]{-1, -1, -1}, new double[]{-1, -1, -1}); + ComplexNumbersB b = new ComplexNumbersB(new double[]{41, 43, 45}, new double[]{42, 44, 46}); + + apply.execute(a, b); + + Assert.assertArrayEquals(new double[]{41, 42, 43, 44, 45, 46}, a.getData(), 0.1); + } + + @Test + public void testCopyStructuredComplexToComplexNumbersA() throws Exception { + String id = complexCopy(); + if (id == null) { + return; + } + PolyglotEngine.Value apply = findGlobalSymbol(id); + + ComplexNumbersA a = new ComplexNumbersA(new double[]{-1, -1, -1, -1, -1, -1}); + + Schema schema = new Schema(3, true, Arrays.asList(ComplexNumber.REAL_IDENTIFIER, ComplexNumber.IMAGINARY_IDENTIFIER), Arrays.asList(Type.DOUBLE, Type.DOUBLE)); + byte[] buffer = new byte[6 * Double.SIZE / Byte.SIZE]; + putDoubles(buffer, new double[]{41, 42, 43, 44, 45, 46}); + + StructuredData b = new StructuredData(buffer, schema); + + apply.execute(a, b); + + Assert.assertArrayEquals(new double[]{41, 42, 43, 44, 45, 46}, a.getData(), 0.1); + } + + private static void putDoubles(byte[] buffer, double[] values) { + for (int index = 0; index < values.length; index++) { + int doubleSize = Double.SIZE / Byte.SIZE; + byte[] bytes = new byte[doubleSize]; + ByteBuffer.wrap(bytes).putDouble(values[index]); + for (int i = 0; i < doubleSize; i++) { + buffer[index * doubleSize + i] = bytes[i]; + } + } + } + private PolyglotEngine.Value findGlobalSymbol(String name) throws Exception { PolyglotEngine.Value s = vm().findGlobalSymbol(name); assert s != null : "Symbol " + name + " is not found!";