I can't force to work examples from GraalVM javadoc for method public Value asValue(Object hostValue)
Basic Examples: The following assertion statements always hold:
Context context = Context.create();
assert context.asValue(null).isNull();
assert context.asValue(42).isNumber();
assert context.asValue("42").isString();
assert context.asValue('c').isString();
assert context.asValue(new String[0]).hasArrayElements();
assert context.asValue(new ArrayList<>()).isHostObject();
assert context.asValue(new ArrayList<>()).hasArrayElements();
assert context.asValue((Supplier) () -> 42).execute().asInt() == 42;
because some asserts are failed (hasArrayElements() and Functional Interface):
My java class:
$ cat Test.java
import java.util.ArrayList;
import java.util.function.Supplier;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
public class Test {
public static void main( String[] args ) {
try ( Context context = Context.create() ) {
assert context.asValue(null).isNull();
assert context.asValue(42).isNumber();
assert context.asValue("42").isString();
assert context.asValue('c').isString();
assert context.asValue(new String[0]).hasArrayElements() : "String[].hasArrayElements() failed";
assert context.asValue(new ArrayList<>()).isHostObject();
assert context.asValue(new ArrayList<>()).hasArrayElements();
assert context.asValue((Supplier) () -> 42).execute().asInt() == 42;
}
}
}
result:
$ /opt/graalvm-ce-java11-20.0.0/bin/javac Test.java; /opt/graalvm-ce-java11-20.0.0/bin/java -ea Test
Exception in thread "main" java.lang.AssertionError: String[].hasArrayElements() failed
at Test.main(Test.java:14)
What am I doing wrong ?..
At best, the documentation is out of date, at worst, this is a bug. You should file an issue for Truffle: https://github.com/oracle/graal/issues
Related
I need to create a Script from a String and execute it in the context of the current test class. Here's my simplified code:
import spock.lang.Specification
class MyTestSpec extends Specification {
Integer getOne() { return 1 }
Integer getTwo() { return 2 }
void 'call script with local methods'() {
given:
GroovyShell shell = new GroovyShell()
Script script = shell.parse("getOne() + getTwo()")
when:
def result = script.run()
then:
result == 3
}
}
This gives me the following error:
No signature of method: Script1.getOne() is applicable for argument types: () values: []
I see that to set variables one can use shell.setProperty but how do I pass the method's implementation to the script?
Of course, as soon as I posted this, I found my answer.
import org.codehaus.groovy.control.CompilerConfiguration
import spock.lang.Specification
class MyTestSpec extends Specification {
Integer getOne() { return 1 }
Integer getTwo() { return 2 }
void 'call script with local methods'() {
given:
CompilerConfiguration cc = new CompilerConfiguration()
cc.setScriptBaseClass(DelegatingScript.name)
GroovyShell sh = new GroovyShell(this.class.classLoader, new Binding(), cc)
DelegatingScript script = (DelegatingScript) sh.parse("getOne() + getTwo()")
script.setDelegate(this)
when:
def result = script.run()
then:
result == 3
}
}
I have a class (with more properties than the example, of course).
How to write the following simple test? I know that equality in Dart is by object instance. How to compare the full object state? I tested with the same matcher as well, with no luck.
import 'package:test/test.dart';
class UnderTesting {
var a;
var b;
UnderTesting({this.a, this.b});
}
void main() {
test("compare objects", () {
final obj1 = UnderTesting(a:1, b:2);
final obj2 = UnderTesting(a:1, b:2);
// Next will fail because it is checking if it is the same instance
expect(obj1, equals(obj2));
} );
}
You need to override the == operator (and should therefore also override hashCode) for UnderTesting. The documentation for equals tells us how to does test for equality:
If [expected] is a [Matcher], then it matches using that. Otherwise it tests for equality using == on the expected value.
So you code should be something like this:
import 'package:test/test.dart';
import 'package:quiver/core.dart';
class UnderTesting {
int a;
int b;
UnderTesting({this.a, this.b});
#override
bool operator ==(Object other) =>
(other is UnderTesting) ? (a == other.a && b == other.b) : false;
#override
int get hashCode => hash2(a, b);
}
void main() {
test("compare objects", () {
final obj1 = UnderTesting(a: 1, b: 2);
final obj2 = UnderTesting(a: 1, b: 2);
expect(obj1, equals(obj2)); // All tests passed!
});
}
I can recommend the quiver package for making easy hashCode implementations: https://pub.dev/documentation/quiver/latest/quiver.core/quiver.core-library.html
I am trying to write unit test for addition of 2 numbers which is calling Service class add method() and there is one more class HelperAdd which is called from add() method
Here in unit test case my expected result is different from what is hardcoded in unit test class, How to solve this. Am i doing something wrong in code.
Unit Test Class--
class ControllerTest extends Specification {
Service src
HelperAdd hd
def setup() {
hd = Mock()
src = new Service(
hd: hd
)
}
def "Add 2 numbers"() {
AddModel request = new AddModel()
given: "input"
request.setA(2)
request.setB(3)
when:
src.add(request)
then:
1 * hd.add(_) >> 2
expect:"4"
}
}
Service class --
class Service {
#Autowired
HelperAdd hd
#PostMapping(value="/getdocuments")
def add(#RequestBody AddModel request) {
int a = request.a
int b = request.b
int d = hd.add(a)
int c = a+d
return c
}
}
HelperAdd class--
class HelperAdd {
def add(int a)
{
int k = a+4
return k
}
}
Model class --
#Canonical
class AddModel {
int a
int b
}
I do not understand your problem. The test passes. Your test syntax is weird, though. How about this?
def "Add 2 numbers"() {
given: "input"
def request = new AddModel(a: 2, b: 3)
when:
def result = src.add(request)
then:
1 * hd.add(_) >> 2
result == 4
}
I have sample code as below
import org.codehaus.groovy.control.CompilerConfiguration
abstract class MyClass extends Script {
void testMethod(Integer x) {
println "x = $x"
}
}
public static void main(String[] args) {
compilerConfiguration = new CompilerConfiguration();
compilerConfiguration.setScriptBaseClass("MyClass");
GroovyShell shell = new GroovyShell(new Binding(), compilerConfiguration);
shell.evaluate("testMethod 1")
}
When I run this class it prints x = 1
now if I change the "testMethod 1" to "testMethod -1" it fails with
Caught: groovy.lang.MissingPropertyException: No such property: testMethod for class: Script1
groovy.lang.MissingPropertyException: No such property: testMethod for class: Script1
at Script1.run(Script1.groovy:1)
at Test.run(Test.groovy:15)
Now I change "testMethod -1" to "testMethod (-1)". It again works and printed x = -1
What I need to understand is why Groovy is asking for the parentheses for negative numbers.
Because without parentheses, it is assuming you are trying to subtract 1 from a property called testMethod (ie: testMethod - 1)
You need the parentheses to inform the parser that this is a method call rather than a subtraction operation
Edit
I came up with a horrible way to get this to work:
import java.lang.reflect.Method
import org.codehaus.groovy.control.CompilerConfiguration
abstract class MyClass extends Script {
private methods = [:]
class MinusableMethod {
Script declarer
Method method
MinusableMethod( Script d, Method m ) {
this.declarer = d
this.method = m
}
def minus( amount ) {
method.invoke( declarer, -amount )
}
}
public MyClass() {
super()
methods = MyClass.getDeclaredMethods().grep {
it.name != 'propertyMissing' && !it.synthetic
}.collectEntries {
[ (it.name): new MinusableMethod( this, it ) ]
}
}
def propertyMissing( String name ) {
methods[ name ]
}
void testMethod(Integer x) {
println "x = $x"
}
}
static main( args ) {
def compilerConfiguration = new CompilerConfiguration();
compilerConfiguration.setScriptBaseClass( 'MyClass' );
GroovyShell shell = new GroovyShell(new Binding(), compilerConfiguration);
shell.evaluate("testMethod - 1")
}
But this will probably break under other conditions
In the long run, getting people to write valid scripts is probably the better route to take...
I would really appreciate if someone could give me advice,or point me to tutorial, or sample implementation, anything that could help me implement basic goto statement in ANTLR?
Thanks for any help
edit. ver2 of question:
Say I have this tree structure:
(BLOCK (PRINT 1) (PRINT 2) (PRINT 3) (PRINT 4) )
Now, I'm interested to know is there a way to
select, say, node (PRINT 2) and all nodes that follow
that node ((PRINT 2) (PRINT 3) (PRINT 4)) ?
I'm asking this because I'm trying to implement
basic goto mechanism.
I have print statement like this:
i=LABEL print
{interpreter.store($i.text, $print.tree);} //stores in hash table
-> print
However $print.tree just ignores later nodes,
so in input:
label: print 1
print 2
goto label
would print 121!
(What I would like is infinite loop 1212...)
I've also tried taking token
address of print statement with
getTokenStartIndex() and setting
roots node with setTokenStartIndex
but that just looped whatever was first node over and over.
My question is, how does one implement goto statement in antlr ?
Maybe my approach is wrong, as I have overlooked something?
I would really appreciate any help.
ps. even more detail, it is related to pattern 25 - Language Implementation patterns, I'm trying to add on to examples from that pattern.
Also, I've searched quite a bit on the web, looks like it is very hard to find goto example
... anything that could help me implement basic goto statement in ANTLR?
Note that it isn't ANTLR that implements this. With ANTLR you merely describe the language you want to parse to get a lexer, parser and possibly a tree-walker. After that, it's up to you to manipulate the tree and evaluate it.
Here's a possible way. Please don't look too closely at the code. It's a quick hack: there's a bit of code-duplication and I'm am passing package protected variables around which isn't as it should be done. The grammar also dictates you to start your input source with a label, but this is just a small demo of how you could solve it.
You need the following files:
Goto.g - the combined grammar file
GotoWalker.g - the tree walker grammar file
Main.java - the main class including the Node-model classes of the language
test.goto - the test input source file
antlr-3.3.jar - the ANTLR JAR (could also be another 3.x version)
Goto.g
grammar Goto;
options {
output=AST;
ASTLabelType=CommonTree;
}
tokens {
FILE;
BLOCK;
}
#members {
java.util.Map<String, CommonTree[]> labels = new java.util.HashMap<String, CommonTree[]>();
}
parse
: block EOF -> block
;
block
: ID ':' stats b=block? {labels.put($ID.text, new CommonTree[]{$stats.tree, $b.tree});} -> ^(BLOCK stats $b?)
;
stats
: stat*
;
stat
: Print Number -> ^(Print Number)
| Goto ID -> ^(Goto ID)
;
Goto : 'goto';
Print : 'print';
Number : '0'..'9'+;
ID : ('a'..'z' | 'A'..'Z')+;
Space : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
GotoWalker.g
tree grammar GotoWalker;
options {
tokenVocab=Goto;
ASTLabelType=CommonTree;
}
tokens {
FILE;
BLOCK;
}
#members {
java.util.Map<String, CommonTree[]> labels = new java.util.HashMap<String, CommonTree[]>();
}
walk returns [Node n]
: block {$n = $block.n;}
;
block returns [Node n]
: ^(BLOCK stats b=block?) {$n = new BlockNode($stats.n, $b.n);}
;
stats returns [Node n]
#init{List<Node> nodes = new ArrayList<Node>();}
: (stat {nodes.add($stat.n);})* {$n = new StatsNode(nodes);}
;
stat returns [Node n]
: ^(Print Number) {$n = new PrintNode($Number.text);}
| ^(Goto ID) {$n = new GotoNode($ID.text, labels);}
;
Main.java
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
GotoLexer lexer = new GotoLexer(new ANTLRFileStream("test.goto"));
GotoParser parser = new GotoParser(new CommonTokenStream(lexer));
CommonTree tree = (CommonTree)parser.parse().getTree();
GotoWalker walker = new GotoWalker(new CommonTreeNodeStream(tree));
walker.labels = parser.labels;
Node root = walker.walk();
root.eval();
}
}
interface Node {
public static final Node VOID = new Node(){public Object eval(){throw new RuntimeException("VOID.eval()");}};
public static final Node BREAK = new Node(){public Object eval(){throw new RuntimeException("VOID.eval()");}};
Object eval();
}
class BlockNode implements Node {
Node stats;
Node child;
BlockNode(Node ns, Node ch) {
stats = ns;
child = ch;
}
public Object eval() {
Object o = stats.eval();
if(o != VOID) {
return o;
}
if(child != null) {
o = child.eval();
if(o != VOID) {
return o;
}
}
return VOID;
}
}
class StatsNode implements Node {
List<Node> nodes;
StatsNode(List<Node> ns) {
nodes = ns;
}
public Object eval() {
for(Node n : nodes) {
Object o = n.eval();
if(o != VOID) {
return o;
}
}
return VOID;
}
}
class PrintNode implements Node {
String text;
PrintNode(String txt) {
text = txt;
}
public Object eval() {
System.out.println(text);
return VOID;
}
}
class GotoNode implements Node {
String label;
Map<String, CommonTree[]> labels;
GotoNode(String lbl, Map<String, CommonTree[]> lbls) {
label = lbl;
labels = lbls;
}
public Object eval() {
CommonTree[] toExecute = labels.get(label);
try {
Thread.sleep(1000L);
GotoWalker walker = new GotoWalker(new CommonTreeNodeStream(toExecute[0]));
walker.labels = this.labels;
Node root = walker.stats();
Object o = root.eval();
if(o != VOID) {
return o;
}
walker = new GotoWalker(new CommonTreeNodeStream(toExecute[1]));
walker.labels = this.labels;
root = walker.block();
o = root.eval();
if(o != VOID) {
return o;
}
} catch(Exception e) {
e.printStackTrace();
}
return BREAK;
}
}
test.goto
root:
print 1
A:
print 2
B:
print 3
goto A
C:
print 4
To run the demo, do the following:
*nix/MacOS
java -cp antlr-3.3.jar org.antlr.Tool Goto.g
java -cp antlr-3.3.jar org.antlr.Tool GotoWalker.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main
or:
Windows
java -cp antlr-3.3.jar org.antlr.Tool Goto.g
java -cp antlr-3.3.jar org.antlr.Tool GotoWalker.g
javac -cp antlr-3.3.jar *.java
java -cp .;antlr-3.3.jar Main
which will print:
1
2
3
2
3
2
3
2
3
...
Note that the 2 and 3 are repeated until you terminate the app manually.