Xtext, Xbase: infer questions - code-generation

I'm going to write an inferrer for my dsl and I have some questions that I could not solve with only the help of documentation.
First one:
I need to create static void main() from a feature: how can I add static with .toMethod()?
Second one:
Suppose I have a rule in my dsl like this:
Sequence:
'SEQ' name=ID '{'
statements+=Statement*
'}'
;
Where Statement:
Statement:
Sequence | others...
;
Sequence must be mapped to a void method and the body of that method is composed from the traslation of statements.
But the problem is this: when inside a Sequence I'll find another Sequence I have to create a method for the new sequence and add a call in super sequence.
For example:
SEQ first {
instructions...
SEQ second {
other instructions....
}
instructions...
}
Must generate:
void first(){
instructions(translated)...
second();
instructions(translated)...
}
void second(){
other instructions(translated)...
}
Is it possible to realize it?

First question:
ctx.toMethod('main', ctx.newTypeRef(Void.Type)) [
static = true
….
]
Second question:
Implying that with 'instructions' you mean instances of 'XExpression', you need to trick a bit, as it is currently not possible to compose new expressions during inference.
What you coudl basically do is to make your Sequence a subtype of XExpression. Then during JvmModelInference you need to walk over your expression tree (Statement) and create methods for Sequences. you need to override the XbaseTypeComputer as well as the XbaseCompiler and add type computation and compile strategies for your expressions. The latter would be a call to the method created during inference.

Related

How to create a newtype operation in Q#?

I am working with Q# on a generic grover search implementation and I wanted to define a custom Oracle type
newtype ModelOracle = ((Qubit[], Qubit[], Int[], Qubit) => Unit);
// ...
function GroverMaxMatchingOracle(search_set: (Int,Int)[], vertices: Int[], marked_pts: Bool[]): ModelOracle {
return ModelOracle(ApplyMaxMatchingOracle(_,_,_,_,search_set, vertices, marked_pts));
}
that will fit into my model. But when I try to use it (kind of in the same way as they use StateOracle in the DatabaseSearch sample), I get an error saying that the new type ModelOracle is not a valid operation
fail: Microsoft.Quantum.IQSharp.Workspace[0]
QS5021: The type of the expression must be a function or operation type. The given expression is of type OracleHelper.ModelOracle.
What am I getting wrong about the types here?
It looks like you have defined things ok, so it might be that you have to unwrap the user defined type first with the ! operator.
So where you are using it you may have to do something like GroverMaxMatchingOracle!(...)
Another approach could be to name the tuple in your UDT:
newtype ModelOracle = (Apply: (Qubit[], Qubit[], Int[], Qubit) => Unit);
Then wherever you want to use it you can directly used the named item Apply like this: GroverMaxMatchingOracle::Apply(...)
If its helpful, there is a section on user defined types (8.2) in the book #cgranade and I are working on, Learn Quantum Computing with Python and Q#

Adding classes to micropython module

In reference to adding module in micropython, I was trying to create a class which has a local method. In the documentation it is given how to add local methods and that the first argument should be of mp_obj_t type which is the data struct itself. However, I was asking how can I pass extra parameters like other methods? I tried using mp_obj_t * args as second argument but STATIC MP_DEFINE_CONST_FUN_OBJ_1 gives error. I tried the same with STATIC MP_DEFINE_CONST_FUN_OBJ_VAR but it does not support passing mp_obt_t as first argument as STATIC MP_DEFINE_CONST_FUN_OBJ_VAR needs an int. I am quite new, so I was asking how to add methods to classes which can accept arguments?
You need MP_DEFINE_CONST_FUN_OBJ_2, since you have 2 arguments.
Something like
STATIC mp_obj_t my_class_func(mp_obj_t self, mp_obj_t arg) {
if (MP_OBJ_IS_SMALL_INT(lhs)) {
const mp_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(arg);
//...
} else {
//oops, not an int
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(my_class_func_obj, my_class_func);
The best source of samples like this is the source code btw.
To eleaborate on #stijn answer ~ when creating a class, all the MP_DEFINE_CONST_FUN_OBJ_XXXXXX defines work the exact same as they would if you weren't creating a class. The only difference is the first argument of ACTUAL arguments will always refer to self
Here's an example:
mp_obj_t Class_method(mp_uint_t n_args, const mp_obj_t *args) { ... }
That is the standard candidate for:
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(Class_method_obj, 1, 3, Class_method);
However, in this case args[0] will be self.
Let's have another example.
mp_obj_t Class_method(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { ... }
That's a prime candidate for this define
MP_DEFINE_CONST_FUN_OBJ_KW(Class_method_obj, 2, Class_method);
The only difference in this case is that the first index of allowed_args needs to automatically be handled as self. Nothing about how you do these things changes, except now the first ACTUAL argument (ie not including n_args or any other "helper" argument) needs to automatically be considered as self. That being said, you will NEVER use MP_DEFINE_CONST_FUN_OBJ_0 with a class method. '_0' means "zero arguments" and a class method will never have zero arguments because it will ALWAYS at least have self. This also means that you have to add one to however many expected arguments you have on the python end. If your python version accepts 3 arguments ~
(red, green, blue)
then your C_MODULE define has to start at 4 because it's going to get
(self, red, green, blue)

How to bind parameters in replaced expression nodes in Entity Framework on the fly

I'm trying to replace a function call like (simplified) Utility.GetString(MyEntity.SomePropertyWithRelatedEntity)=="abc" with an expression visitor into something like p => p.SubRelatedEntities.FirstOrDefault(sre => sre.SomeFlag==true).SomePropertyWithRelatedEntity.
It means, the datamodel goes like:
MyEntity -> RelatedEntity -> SubRelatedEntity
I'm trying to return a string value from the SubRelatedEntity, based on some rules in the RelatedEntity, so I don't have to re-write / copy/paste the whole filtering rules in every usage; that's why I put inside a "call-signature", so my expression visitor can identify it and replace the fake-call to Utility.GetString to some complicated lambda expressions.
My expression visitor contains something like:
public override Expression Visit(Expression node)
{
if (node == null)
return null;
Expression result = null;
if (node.NodeType == ExpressionType.Call)
{
MethodCallExpression mce = node as MethodCallExpression;
if (mce.Method.DeclaringType == typeof(Utility) && mce.Method.Name == "GetString")
{
Expression<Func<RelatedEntity, string>> exp = re => re.SubRelatedEntities.FirstOrDefault(sre => sre.SomeFlag == true).SomeStringValue;
result = exp.Body;
}
else
result = base.Visit(node);
}
else
result = base.Visit(node);
return result;
}
Now, the problem is, the "sre" parameter is not bound when called the injected lambda expression. After much research, I see the lambda parameters should be replaced with another expression visitor, specifically searching for the new parameters and replacing them with the old ones. In my situation, however, I don't have an "old parameter" - I have the expression MyEntity.SomePropertyWithRelatedEntity (e.g. an property filled with the related entities) which I need to insert somehow in the generated lambda.
I hope my problem is understandable. Thank you for any insights!
After getting no answers for long time and trying hard to find a solution, I've solved it at the end :o)! It goes like this:
The newly injected lambda expression gets an ParameterExpression - well, this is a 'helper', used when directly calling the lambda, what I don't want (hence, 'parameter not bound' exception when ToEnumerable is called). So, the clue is to make a specialized ExpressionVisitor, which replaces this helper with the original expression, which is of course available in the Arguments[] for the method call, which I try to replace.
Works like a charm, like this you can reuse the same LINQ expressions, something like reusable sub-queries, instead of writing all the same LINQ stuff all time. Notice as well, that expression calling a method is not allowed in EF, in Linq2Sql it worked. Also, all the proposed web articles only replace the parameter instances, when constructing/merging more LINQ expressions together - here, I needed to replace a parameter with an faked-method-call argument, e.g. the method should not be called, it only stands for a code-marker, where I need to put my LINQ sub-query.
Hope this helps somebody, at the end it's pretty simple and logical, when one knows how the expression trees are constructed ;-).
Bye,
Andrej

Entity Framework and Nested Lambda Expressions

I've just started using Lambda expressions, and really like the shortcut. I also like the fact that I have scope within the lambda of the encompassing method. One thing I am having trouble with is nesting lambdas. Here is what I am trying to do:
public void DoSomeWork()
{
MyContext context = new MyDomainContext();
context.GetDocumentTypeCount(ci.CustomerId, io =>
{
if (io.HasError)
{
// Handle error
}
// Do some work here
// ...
// make DB call to get data
EntityQuery<AppliedGlobalFilter> query =
from a in context.GetAppliedGlobalFiltersQuery()
where a.CustomerId == ci.CustomerId && a.FilterId == 1
select a;
context.Load<AppliedGlobalFilter>(query, lo =>
{
if (lo.HasError)
{
}
**// Do more work in this nested lambda.
// Get compile time error here**
}
}, null);
}, null);
}
The second lambda is where I get the following compile time error:
Cannot convert Lambda expression to type 'System.ServiceModel.DomainService.Client.LoadBehavior' because it is not a delegate type
The compiler is choosing the wrong overload for the Load method even though I am using the same override I did in the previous Lambda.
Is this because I am trying to nest? Or do I have something else wrong?
Thanks,
-Scott
Found the problem as described in my comment above. I'll head back to work now - red face and all....
I realize this is not the answer you want, but I suggest caution about lengthy and/or nested lambdas. They work, but they often make code harder to read / maintain by other developers. I try to limit my lambdas in length to three statements, with no nesting.

; expected but <place your favourite keyword here> found

I'm trying to write a class for a scala project and I get this error in multiple places with keywords such as class, def, while.
It happens in places like this:
var continue = true
while (continue) {
[..]
}
And I'm sure the error is not there since when I isolate that code in another class it doesn't give me any error.
Could you please give me a rule of thumb for such errors? Where should I find them? are there some common syntactic errors elsewhere when this happens?
It sounds like you're using reserved keywords as variable names. "Continue", for instance, is a Java keyword.
You probably don't have parentheses or braces matched somewhere, and the compiler can't tell until it hits a structure that looks like the one you showed.
The other possibility is that Scala sometimes has trouble distinguishing between the end of a statement with a new one on the next line, and a multi-line statement. In that case, just drop the ; at the end of the first line and see if the compiler's happy. (This doesn't seem like it fits your case, as Scala should be able to tell that nothing should come after true, and that you're done assigning a variable.)
Can you let us know what this code is inside? Scala expects "expressions" i.e. things that resolve to a particular value/type. In the case of "var continue = true", this does not evaluate to a value, so it cannot be at the end of an expression (i.e. inside an if-expression or match-expression or function block).
i.e.
def foo() = {
var continue = true
while (continue) {
[..]
}
}
This is a problem, as the function block is an expression and needs to have an (ignored?) return value, i.e.
def foo() = {
var continue = true
while (continue) {
[..]
}
()
}
() => a value representing the "Unit" type.
I get this error when I forget to put an = sign after a function definition:
def function(val: String):Boolean {
// Some stuff
}