I have the following grammar:
Model: declarations += Declaration* statements += Statement*;
Declaration: 'Declare' name=ID;
Statement: 'Execute' what=[Declaration];
With that I can write simple scripts like:
Declare step_forward
Declare turn_right
Declare turn_left
Execute step_forward
Execute turn_left
Execute step_forward
Now I want that the java program provides all declarations, so that the script only contains the Execute statements. I read about IGlobalScopeProvider which seems to be the right tool for the job, but I have no idea how to add my data to it, and how to make Xtext use it.
So, how can I provide declarations from external to my grammar?
Update
My goal was somewhat unclear, so I try to make it more concrete. I want to keep the declarations as simple java objects, for instance:
List<Move> declarations = Arrays.asList(
new Move("step_forward"),
new Move("turn_right"),
new Move("turn_left"));
and the script should be:
Execute step_forward
Execute turn_left
Execute step_forward
I'm not really sure what you are asking for. After thinking about it, I cand derive th following possible questions:
1.) You want to split your script into two files. File a will only contain your declarations and File b then will only contain Statements. But any 'what' attribute will hold a reference to the declarations of File a.
This works out of the box with your grammar.
2.) You have any Java source code which provides a class which defines, for example a 'Declare Interface', and you want the 'what' attribute to reference to this interface or to classes which implement this interface.
Updated answer You should use Xbase within your language. There you can define that your 'what' attribute references to any Java type using the Xtypes rule 'JvmTypeReference'. The modifications you have to within your grammar are not that difficult, I think it could look this:
// Grammar now inherits from the Xbase grammar
// instead of the common terminals grammar
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Model:
declarator=Declarator?
statements+=Statement*;
Declarator:
'Declare' name=ID;
Statement:
'Execute' what=JvmTypeReference;
The, you can refer to any Java type (Java API, any linked API, user-defined types) by adressing them with their qualified name. It would look like this:
Referring to JVM types look like this in an Xtext language. (Screenshot)
You can also validate whether the referenced JVM type is valid, e.g. implements a desired interface which I would define with one single, optional declarator in the model.
Referenced JVM type is checked whether it is a valid type. (Screenshot)
With Xbase it is very easy to infer a Java interface for this model element. Use the generated stub '...mydsl.MyDslJvmModelInferrer':
class MyDslJvmModelInferrer extends AbstractModelInferrer {
#Inject extension JvmTypesBuilder
#Inject extension TypeReferences
def dispatch void infer(Model element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
acceptor.accept(
element.declaration.toInterface('declarator.' + element.declaration.name) [
members += it.toMethod("execute", TypesFactory.eINSTANCE.createJvmVoid.createTypeRef)[]
])
}
}
It derives a single interface, named individually with only one method 'execute()'.
Then, implement static checks like this, you should use the generated stub '...mydsl.validation.MyDslValidator' In my example it is very quick and dirty, but you should get the idea of it:
class MyDslValidator extends AbstractMyDslValidator {
#Check
def checkReferredType(Statement s) {
val declarator = (s.eContainer as Model).declaration.name
for (st : (s.what.type as JvmDeclaredType).superTypes) {
if (st.qualifiedName.equals('declarator.' + declarator)) {
return
}
}
(s.what.simpleName + " doesn't implement the declarator interface " + declarator).
warning(MyDslPackage.eINSTANCE.statement_What)
}
}
(I used the preferred Xtend programming language to implement the static checking!) The static check determines if the given JvmTypeReference (which is a Java class from your project) implements the declared interface. Otherwise it will introduce a warning to your dsl document.
Hopefully this will answer your question.
Next update: Your idea will not work that well! You could simply write a template with Xtend for that without using Xbase, but I cannot imagine how to use it in a good way. The problem is, I assume, you don't to generate the hole class 'Move' and the hole execution process. I have played around a little bit trying to generate usable code and seems to be hacky! Neverthess, here is my solution:
Xtext generated the stub '...mydsl.generator.MyDslGenerator' for you with the method 'void doGenerate'. You have to fill this method. My idea is the following: First, you generate an abstract and generic Executor class with two generic parameters T and U. My executor class then has an abstract method 'executeMoves()' with the return value T. If this should be void use the non-primitive 'Void' class. It holds your List, but of the generic type u which is defined as a subclass of a Move class.
The Move class will be generated, too, but only with a field to store the String. It then has to be derived. My 'MyDslGenerator' looks like that:
class MyDslGenerator implements IGenerator {
static var cnt = 0
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
cnt = 0
resource.allContents.filter(typeof(Model)).forEach [ m |
fsa.generateFile('mydsl/execution/Move.java', generateMove)
fsa.generateFile('mydsl/execution/Executor' + cnt++ + '.java', m.generateExecutor)
]
}
def generateMove() '''
package mydsl.execution;
public class Move {
protected String s;
public Move(String s) {
this.s = s;
}
}
'''
def generateExecutor(Model m) '''
package mydsl.execution;
import java.util.List;
import java.util.Arrays;
/**
* The class Executor is abstract because the execution has to implemented somewhere else.
* The class Executor is generic because one does not know if the execution has a return
* value. If it has no return value, use the not primitive type 'Void':
* public class MyExecutor extends Executor_i<Void> {...}
*/
public abstract class Executor«cnt - 1»<T, U extends Move> {
#SuppressWarnings("unchecked")
private List<U> declarations = Arrays.<U>asList(
«FOR Statement s : m.statements»
(U) new Move("«s.what.name»")«IF !m.statements.get(m.statements.size - 1).equals(s)»,«ENDIF»
«ENDFOR»
);
/**
* This method return list of moves.
*/
public List<U> getMoves() {
return declarations;
}
/**
* The executor class has to be extended and the extending class has to implement this
* method.
*/
public abstract T executeMoves();
}'''
}
Related
This is a followup question after reading this Q&A:
Generic Sorting function accepts T, but want to ensure T is comparable
I have a class like so:
class BinarySearchTree<E extends Comparable> { ... }
so I can create an instance like this:
final tree = BinarySearchTree<int>();
My question is about using Comparable vs Comparable<E>. When I do this:
class BinarySearchTree<E extends Comparable> { ... }
then the type defaults to E extends Comparable<dynamic>. I normally try to avoid dynamic, so in order to be more explicit about the type that is being compared, it seems like I should write it this:
class BinarySearchTree<E extends Comparable<E>> { ... }
But in that case I get an error here:
final tree = BinarySearchTree<int>();
// 'int' doesn't conform to the bound 'Comparable<int>' of the type parameter 'E'.
// Try using a type that is or is a subclass of 'Comparable<int>'.
This demonstrates my lack of understanding of generics. What am I missing?
In Dart, a class cannot implement 2 different concrete instances of a generic interface:
abstract class Foo<T> {}
// error: Foo can only be implemented once
class Bar implements Foo<String>, Foo<int> {}
num implements Comparable<num>, because it would be slightly absurd for the built-in number types to not be comparable. However, since int is a subtype of num (and therefore inherits Comparable<num>, it cannot have Comparable<int>.
This leads to the slightly weird consequence that int does not implement Comparable<int>.
The problem you're facing is that from the language's point of view, there are 2 types involved: the type of the elements being compared, and the type of the elements they are being compared to.
As such, your type will need 2 type parameters:
class Tree<T extends Comparable<S>, S> {
T get foo;
}
final intTree = Tree<int, num>();
final foo = intTree.foo; // returns an int
Admittedly, this isn't a super clean solution, but if you're using Dart 2.13 or higher, you can use typedefs to make it a bit nicer:
typedef IntTree = Tree<int, num>;
typedef RegularTree<T> = Tree<T, T>;
final intTree = IntTree();
final stringTree = RegularTree<String>();
intTree.foo // is an int
stringTree.foo // is a String
There is another option, which is to just drop some type safety and use Comparable<dynamic>, but personally I'd recommend against it. BTW, if you want to avoid accidentally missing type parameters you can disable implicit-dynamic as described here: https://dart.dev/guides/language/analysis-options#enabling-additional-type-checks
This will give an error any time the type dynamic is inferred from context without the programmer actually typing the word dynamic
Should I get the following error:
class.dart:11:11: Error: The getter '_privateID' isn't defined for the class 'Y'.
- 'Y' is from 'class.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named '_privateID'.
From the following code?
mixin.dart:
class Mixin {
static int _nextID = 0;
int publicID = _nextID++; // I only need one of these lines
int _privateID = _nextID++; // but this variable is inaccessible
}
class.dart:
import 'mixin.dart';
class X with Mixin {
void run() {
print(publicID); // no error here
}
}
class Y with Mixin {
void run() {
print(_privateID); // Error: _privateID not defined
}
}
void main() {
Y().run();
}
Or is this a bug? If it's not a bug, I'd like to understand why this behavior is reasonable.
When I instead define the mixin in the same file as the above classes, I get no error.
(Dart SDK 2.4.1.)
It is not a bug.
The private field is inherited, but you cannot access it because its name is private to a different library.
Dart's notion of "privacy" is library private names.
The name _privateID in the mixin.dart library introduces a library private name. This name is special in that it can only be written inside the same library.
If someone writes _privateID in a different library, it is a different name, one unique to that library instead.
It is as if private names includes the library URI of the library it is written in, so what you really declare is a name _privateID#mixin.dart.
When you try to read that field in class.dart, you write ._privateID, but because it is in a different library, what you really write is ._privateID#class.dart, a completely different name, and the classs does not have any declarations with that name.
So, if one class needs to access a private member of another class (or mixin, or anything), then the two needs to be declared in the same library, because otherwise they cannot even write the name of that variable.
That is why the code works if you write the mixin in the same library.
If you want to move the mixin to a separate file, but not necessarily a separate library, you can use a part file.
Consider the following Java code:
import java.util.LinkedList;
import java.util.List;
class Library {
List<String> loans = new LinkedList<>();
public List<String> searchUser(String name) {
List<String> usersFound = new LinkedList<>();
return loans;
}
}
and the following Rascal module:
module Mwe
import lang::java::flow::JavaToObjectFlow;
import lang::java::jdt::m3::AST;
import IO;
void m() {
ast = createAstFromEclipseFile(|project://test/src/test.java|, true);
fp = createOFG({ast});
print(fp);
}
The resulting flow program will be:
flowProgram({
attribute(|java+field:///Library/loans|),
method(|java+method:///Library/searchUser(java.lang.String)|,[|java+parameter:///Library/searchUser(java.lang.String)/scope(name)/scope(0)/name|]),
constructor(|java+constructor:///Library/Library()|,[])
},{
assign(|java+method:///Library/searchUser(java.lang.String)/return|,|id:///|,|java+field:///Library/loans|),
newAssign(|java+variable:///Library/searchUser(java.lang.String)/usersFound|,|java+class:///java/util/LinkedList|,|java+constructor:///java/util/LinkedList/LinkedList()|,[])
})
So, there is a new assignment of LinkedList to usersFound, but nothing comparable for loans. Why would that happen? Is that the intended behaviour?
Just checked the implementation, the field initializers are not included in the getStatements function (see lang::java::flow::JavaToObjectFlow on line 169). Similarly the static initializers of a class are ignored.
The best way forward would be to either report it as a bug, or fix it and turn it into a pull-request. (pull request is the quickest way to getting it fixed on unstable)
As a possible, yet work intensive workaround you rewrite the AST to put the field initializers inside all existing constructors (or add a constructor if there is none).
I am newbie for Guice and seeking help for the following use case :
I have developed one package say (PCKG) where the entry class of that package depends on other class like:
A : Entry point class --> #Inject A(B b) {}
B in turn is dependent on C and D like --> #Inject B(C c, D d) {}
In my binding module I am doing :
bind(BInterface).to(Bimpl);
bind(CInterface).to(CImpl);
...
Note I am not providing binding information for A as i want to provide its binding by its consumer class. (this is how the design is so my request is to keep the discussion on main problem rather than design).
Now my consumer class is doing like:
AModule extends PrivateModule {
protected void configure() {
bind(AInterface.class).annotatedWith(AImpl.class);
}
}
Also in my consumer package:
.(new PCKGModule(), new AModule())
Q1. Am i doing the bindings correctly in consumer class. I am confused because when i am doing some internal testing as below in my consumer package:
class testModule {
bind(BInterface).to(Bimpl);
bind(CInterface).to(CImpl)...
}
class TestApp {
public static void main(..) {
Guice.createInstance(new testModule());
Injector inj = Guice.createInstance(new AModule());
A obj = inj.getInstance(A.class);
}
}
It is throwing Guice creation exception.Please help me get rid of this situation.
Also one of my friend who is also naive to Guice was suggesting that I need to create B's instance in AModule using Provides annotation. But i really didn't get his point.
Your main method should look like this:
class TestApp {
public static void main(..) {
Injector injector = Guice.createInjector(new TestModule(), new AModule());
A obj = injector.getInstance(A.class);
}
Note that the Java convention is for class names to have the first letter capitalised.
I'm pretty sure your implementation of AModule isn't doing what you think it's doing either, but it's hard to be certain based on the information you've provided. Most likely, you mean to do this:
bind(AInterface.class).to(AImpl.class)`
There's no need to do anything "special" with A's binding. Guice resolves all the recursion for you. That's part of its "magic".
annotatedWith() is used together with to() or toInstance(), like this:
bind(AInterface.class).to(AImpl.class).annotatedWIth(Foo.class);
bind(AInterface.class).to(ZImpl.class).annotatedWIth(Bar.class);
Then you can inject different implementations by annotating your injection points, e.g.:
#Inject
MyInjectionPoint(#Foo AInterface getsAImpl, #Bar AInterface getsZImpl) {
....
}
It's worth also pointing out that you can potentially save yourself some boilerplate by not bothering with the binding modules (depending how your code is arranged) and using JIT bindings:
#ImplementedBy(AImpl.class)
public interface AInterface {
....
}
These effectively act as "defaults" which are overridden by explicit bindings, if they exist.
Dart does not support true mixin composition like Scala does.
library some_lib;
// mixin A
abstract class A {
String get a => 'A';
}
// mixin B
abstract class B extends Object with A {
String get b => a + 'B';
}
Client usage
import 'some_lib.dart';
// client usage
class Client extends Object with B {
String get c => b + 'C';
}
void main(){
print(new Client().c); // should print ABC
}
Dart analyzer complains saying "The class 'B' cannot be used as a mixin because it extends a class other than Object"
I know you would reply that the following works fine:
class C extends Object with A, B {
String get c => a + b;
}
But I'm designing a library that will export some mixins that share some common functionality (provided by a base mixin), witch is relevant to their behavior, but irrelevant to my library clients.
I would even want to make this base mixin private if possible.
Any thoughts on that?
The specs for this are still evolving. I think they intend to implement full mixin based inheritance in the future releases.
That is what I gleaned from Gilad Bracha's (the brains behind the dart specs) talk here (fast forwarded to the appropriate section): http://youtu.be/yXY5bGlhxlw?t=18m42s