Open cubranic opened 8 years ago
A minimal example capturing some of the ideas from the Blang DSL: repo
Example DSL source file:
model {
task {
val x = 2*5;
Math.pow(2, x)
}
}
This should compile to:
import java.util.Collection;
@SuppressWarnings("all")
public class MyFile {
public Collection<Runnable> tasks() {
ArrayList<Runnable> tasks = new ArrayList<>();
tasks.add(getTask0());
return tasks;
}
public static Runnable getTask0() {
Runnable _runnable = new Runnable() {
public void run() {
final int x = (2 * 5);
Math.pow(2, x);
}
}
return _runnable;
}
}
Should the contents of the task be valid Xbase? Then I think int x = 2*5;
should be var int x = 2*5;
or just var x = 2*5
Sorry, that was a typo on my part.
But I can't just say:
model {
task {
1+1
}
}
because it is compiled to:
... new Runnable() {
public void run() {
/* ( 1+1 ) */
}
}
In this case, because 1+1
is a NumberLiteral
, which toJavaStatement
compiles to its commented-out translation. But doing it as with toJavaExpression
would work (in this case). š
The answer from SO is to stay in the āmodel inferrerā world if possible and just use multiple methods:
public static Runnable getTask0() {
Runnable _runnable = new Runnable() {
public void run() {
doRun();
}
}
return _runnable;
}
public static void doRun() {
final int x = (2 * 5);
Math.pow(2, x);
}
Related discussion on Eclipse forums They give the same suggestion:
from your source eobject derive 2 methods 1.
body = thing.bodyexpression
2.
body = ''' try { <<namefrom1>>(....); } .... '''
This also spawned a feature request on Eclipseās Bugzilla bug 471992
Interesting! Ok, I have voted for that bug.
I think the workaround will have some trickiness in our case, because of the arguments to pass in. If we pass everything, this will defy the dependency inference trick I was telling you about on your board the other day. I can see at least a couple of directions from here:
Exactly. I added a comment on the suggestion to say why I really want to go the anonymous subclass route.
Maybe in the short term we should just create the static inner class using the inferrer with the dumb way of including all dependencies and take the performance hit. Then if we make get more help on using the approach with the custom compiler & type computer, we can switch to that.
If we don't get any further help on this topic, we can always add smarts to the anonymous inner class generation by only creating fields for dependencies that appear as free variables in the block. There are some existing "validators" that check for duplicate names and/or only referring to already-existing names, so maybe they could be repurposed because they also work by walking the expression tree.
Sounds gold!
We're getting somewhere:
import blang.core.Model;
import blang.core.ModelComponent;
import blang.prototype3.Real;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Supplier;
@SuppressWarnings("all")
public class MyFile implements Model {
public final Real mu;
public final Real y;
public MyFile(final Real mu, final Real y) {
this.mu = mu;
this.y = y;
}
public Collection<ModelComponent> components() {
ArrayList<ModelComponent> components = new ArrayList();
components.add(new blang.prototype3.Normal(
y,
new $Generated_SupplierSubModel0Param0(mu),
new $Generated_SupplierSubModel0Param1(mu))
);
return components;
}
public static class $Generated_SupplierSubModel0Param0 implements Supplier<Real> {
private Real mean;
public $Generated_SupplierSubModel0Param0(final Real mean) {
this.mean = mean;
}
@Override
public Real get() {
return mean;
}
}
public static class $Generated_SupplierSubModel0Param1 implements Supplier<Real> {
private Real mean;
public $Generated_SupplierSubModel0Param1(final Real mean) {
this.mean = mean;
}
@Override
public Real get() {
final Real _function = new Real() {
public double doubleValue() {
double _doubleValue = $Generated_SupplierSubModel0Param1.this.mean.doubleValue();
return Math.pow(_doubleValue, 2);
}
};
return _function;
}
}
}
A little wordy, and the closure is compiled kind of funny, but I think it's the right thing.
Adding the key work enhancement, as the static inner class method may create un-needed dependencies. This has no effect on correctness, but may have large performance penalties in certain cases.
The main enhancement left here is to reduce the scope of the __generated..(..)
methods to pass in only what is actually used inside the XExpression.
http://stackoverflow.com/q/34434562