I update type of a variable (e.g. Foo a; -> Bar b) how MPS updates x.field references to the new type? - mps

TL;DR: I know MPS 2017.2 does not update field references. The question is how to get it right, so DSL users would not have to retype all the program in case of a single "variable type change"
Here's an example for MPS's base language:
public class Foo {
public int x;
public int y;
}
public class Bar {
public long x;
public long z;
}
public void test() {
Foo a;
a.x = 1; // "x" points to the field of class Foo
a.y = 1;
}
If I update Foo with Bar in Foo a;, then the test code would look like the same
public void test() {
Bar a;
a.x = 1; // "x" still points to the field of class Foo
a.y = 1; // Of course this reference is now invalid, however MPS does not underline that
}
If I update the type of variable a to Bar, then the code in test method would still reference fields of Foo. Of course, check model identifies the broken reference, however I wonder what is the expected way to solve that kind of DSL issues in MPS?
Should "on update" scripts find all the "field usages" and update model accordingly?
Should "field type updates" be forbidden and ask user confirmation? (e.g. some sort of refactoring or whatever intention)
I'm building 61131 ST language in MPS, so I'm looking into "static typed language" kind of DSL.

In my opinion this is mostly a bug in MPS. MPS should similar to the typesystem also track the dependencies of scoping rules and the reevaluate them when something changes. MPS for some reason doesn't know that there is a dependency from you dot operation (the field access) to the operand the local variable. So when you change the type of the local variable it won't reevaluate the scope of the operation. If you press F5 it will reevaluate and show the error, but this is usually not the desired behaviour. I think this should get solved in MPS in a generic way.
Usually MPS does a good job on rebinding references based on the name if they become out of scope but the user has to press F5 to make this happen.
Other than that we are suffering the same problem as you are that these errors aren't presented to the user the type of a variable gets changed. Even baseLanguage has this problem.
I have just put up a feature request into the MPS issue tracker, feel free to vote for it and/or add your comments in there.
https://youtrack.jetbrains.com/issue/MPS-27328

Related

IntelliJ - is there an option to automatically add extra parameters to a constructor?

I am adding a 3rd parameter to this constructor (the String? memberId), does anyone know how or why IntelliJ doesn't give me the option to insert this new constructor parameter automatically? The best it can do is change the type of the next parameter, or make a second constructor, which I would have thought it should be kind of obvious to IntelliJ these are probably not useful.
The expected feature is supported in Code Completion. memberId argument is supposed in completion list with first priority. Using 'Ctrl+Space' and ',' completes the arguments. This behavior is also the same for other type of functions (not only for constructors).
Note: there is no such quick fix in case of Java:
public class Test {
private String s;
private Integer n;
Test(String s, Integer n) {
this.s = s;
this.n = n;
}
public Test foo() {
return new Test(s); // there is no quick fox to add 'n' argument but it presents in completion
}
}
FYI: There is an opposite situation when argument is added on use-site but parameter is not yet added at declaration site. Here is a ticket for supporting quick fix for that: https://youtrack.jetbrains.com/issue/KT-8478. (edited)

C# cannot implicitly convert type when types are the same

I have a generic class:
public abstract class ModelSet<T> : ObservableCollection<T>, IModelObject where T : ModelObject, new(){
public static ModelSet<T> Lookup(long pObjectId){
return (ModelObjectMap.Get(pObjectId) as ModelSet<T>);
}
}
I have the following class instantiation of the type using a class Movement defined as:
class Movement : ModelObject.
public partial class Movements : ModelSet<Movement>
The following code won't compile due to
cannot implicitly convert type ModelSet<Movement> to Movements. An explicit conversion exists.
Movements X = Movements.Lookup(12345);
Surely, they are the same. What am I doing wrong?
Surely, they are the same.
No, they're not the same. One is Movements, and the other is ModelSet<Movement>. While every Movements instance is an instance of ModelSet<Movement>, it's entirely possible to have a ModelSet<Movement> which isn't a Movements... and your method's return type only says that it will return a ModelSet<T>.
We have no idea what ModelObjectMap.Get(pObjectId) actually does, but it could definitely return a ModelSet<Movement> instance which isn't a Movements.
We don't know what you need to do with the return value, but you could certainly write:
ModelSet<Movement> X = Movements.Lookup(12345);
... although it's worth noting that the Movements class actually isn't involved in that call at all; it would actually be compiled to:
ModelSet<Movement> X = ModelSet<Movement>.Lookup(12345);

Meaning of 'private' keyword in Alloy? Meaning of 'enum' declaration?

The Alloy 4 grammar allows signature declarations (and some other things) to carry a private keyword. It also allows Allow specifications to contain enumeration declarations of the form
enum nephews { hughie, louis, dewey }
enum ducks { donald, daisy, scrooge, nephews }
The language reference doesn't (as far as I can tell) describe the meaning of either the private keyword or the enum construct.
Is there documentation available? Or are they in the grammar as constructs that are reserved for future specification?
This is my unofficial understanding of those two keywords.
enum nephews { hughie, louis, dewey }
is semantically equivalent to
open util/ordering[nephews] as nephewsOrd
abstract sig nephews {}
one sig hughie extends nephews {}
one sig louis extends nephews {}
one sig dewey extends nephews {}
fact {
nephewsOrd/first = hughie
nephewsOrd/next = hughie -> louis + louis -> dewey
}
The private keyword means that if a sig has the private attribute, its label is private within the same module. The same applies for private fields and private functions.
In addition to the previous accepted answer, I'd like to add some useful insights coming from a one-week experience with Alloy on enums, in particular on the main differences with standard sig.
If you use abstract sig + extend, you'll come up with a model in which there are many sets corresponding to the same concept. Maybe an example could clarify it better.
Suppose somthing like
sig Car {
dameges: set Damage
}
You have the choice to use
abstract sig Damage {}
sig MajorDamage, MinorDamage extends Damage {}
vs
enum Damage {
MajorDamage, MinorDamage
}
In the first case we can come up wiht a model with different MinorDamage atoms (MinorDamage0, MinorDamage1, ...) associatet to Cars, while in the second case you always have only one MinorDamage to which different Cars can refer.
It could have some sense in this case to use an abstract sig + extend form (because you can decide to track different MinorDamage or MajorDamage elements).
On the other hand, if you want to have a currentState: set State, it could be better to use an
enum State {Damaged, Parked, Driven}
to map the concept, in order to have exactly three State to which each Car can refer to. In this way, in the Visualizer, you can decide to project your model on exactly one of the states and it will highlight all the Cars associated to this state. You can't do that with the abstract + extend construct, of course, because projecting over MajorDamage0 will highlight only the Car associated to that Damage and nothing else.
So, in conclusion, it really depends on what you have to do.
Also, keep in mind that if you have an enum composed by X elements and execute
run some_predicate for Y
where Y < X, Alloy produces no instance at all.
So, in our last example, we can't have a Y < 3.
As a last note, enums don't always appear in the Visualizer if you use the Magic Layout button, but as I said previously you can "project" your model over the enum and switch between the different elements of the enum.

dot operators on functions

I don't know if this is possible, but are there any languages where you can use a dot operator on a function per se. I'll give an example.
function blah returns type2
type 2 looks like this
{
data
number
}
when I call blah are there any languages that support blah.number, so that when it makes the function call and gets the type2, it then grabs number and returns that. I'm sorry if this is an obvious answer, but I couldn't even think of a good way to word it to google it.
I just ran into a situation that would be convienient to have that, rather then make an intermediate variable you just make sure you return the type.
I know that I could add a "get" function that would get the specific number variable from that type, but that's an additional function someone would have to add so I am excluding that as a option (as I can just return the type and access using a variable there isn't really a dire need for a new function).
EDIT: I feel like an idiot.....
EDIT # 2: For some reason I had it in my head that you couldn't do dot operations on functions, (I don't care about the parentheses I was just trying to give an example)
Edit # 3: Is there a name for this or is it still just a dot operation?
Well this works in C if the function returns a struct like this:
struct retval {
char * data;
int number;
};
retval foo() {
// do something and then return an instance of retval
}
// call
int a = foo().number;
I would like to know if there is any language that does not support something like this.
About Edit #3
The name would generally be member access, since all you do is to access a member of the return value. This could differ across languages though.
In most languages you can do Blah().Member ... the typing of a pair of parentheses won't kill you, will it? These languages include C, C++, Java, C# etc.
Yep, to the best of my knowledge, most modern languages (if not most languages in general) support this.
Maybe I misunderstand you, but in most languages, you can already do that.
in java for example, if you have a function get_foo() returning an object of type foo, and foo is defined as
Class Foo{
public int bar;
public double baz;
}
you can do get_foo().bar returning bar
Any language that allows a function to return an object/struct will support that... And languages like Ruby (where the () are optional) will make it exactly like you tiped (blah.number instead of blah().number).
Another way of avoiding the parentheses is using a property or an equivalent idiom... So C#, VB.NET and Python would also allow that.
If you want to make a new function out of an existing one, it's possible with lambda expressions. In C#, for example, it'd be var fooblah = (x => foo(x).blah); Obviously, if there's an overloading available in the language, you can't do it without giving a list of arguments.
Er...you mean, like a returning a class or a struct?
In C#
private class Blah
{
public string Data {get; set;}
public int Number {get; set;}
}
public Blah DoSomething()
{
return new Blah{Data="Data",Number=1};
}

C# 4.0, Methods on the fly?

With the introduction of things like duck typing, I would love it if I compose object methods on the fly, besides extension methods. Anybody know if this is possible? I know that MS is worried about composing framework on the fly, but they seem to be dipping their toes in the water.
Update: Thanks to Pavel for clarifying. For example, say I return a new dynamic object from LINQ and would like to add some methods to it on the fly.
In light of the updated answer, you're actually not looking for "dynamic methods", so much so as "dynamic objects" - such that you may add new properties and methods to them at runtime. If that is correct, then in .NET 4.0, you can use ExpandoObject in conjunction with dynamic:
dynamic foo = new ExpandoObject();
foo.Bar = 123; // creates a new property on the fly
int x = foo.Bar; // 123
// add a new method (well, a delegate property, but it's callable as method)
foo.Baz = (Func<int, int, int>)
delegate(int x, int y)
{
return x + y;
};
foo.Baz(1, 2); // 3
You can have "dynamic methods" too, with expression trees, and once you obtain a delegate for such a method, you can also create a callable method-like property out of it on an ExpandoObject.
For use in LINQ queries, unfortunately, you cannot use object initializers with ExpandoObject; in the simplest case, the following will not compile:
var foo = new ExpandoObject { Bar = 123; }
The reason is that Bar in this case will be looked up statically as a property of ExpandoObject. You need the receiver to be dynamic for this feature to kick in, and there's no way to make it that inside an object initializer. As a workaround for use in LINQ, consider this helper extension method:
public static dynamic With(this ExpandoObject o, Action<dynamic> init)
{
init(o);
return o;
}
Now you can use it thus:
from x in xs
select new ExpandoObject().With(o => {
o.Foo = x;
o.Bar = (Func<int, int>)delegate(int y) { return x + y; };
});
Yes, there is: Generating Dynamic Methods with Expression Trees in Visual Studio 2010
This was already possible with the aid of DynamicMethod and/or MethodBuilder. Not sure if that counts for being "worried", as it has been around for a while now, though it requires a dynamic assembly in most scenarios (DynamicMethod can be used without, though).

Resources