JetBrains / MPS-extensions

MPS-extensions aims to ease language development within MPS.
https://jetbrains.github.io/MPS-extensions/
Apache License 2.0
82 stars 51 forks source link

Enable property macros on grammar.flag #941

Open Abrissbirne66 opened 1 month ago

Abrissbirne66 commented 1 month ago

When writing a generator that targets a language that uses grammar.flag, it woud be really nice to be able to set the status of the flag using a property macro, just like you would when using the boolean value in the editor itself. Because as it is now, you have to create an IF/ELSE macro with two versions of the node which introduces duplication and clutter.

alexanderpann commented 1 month ago

Can you show the if/else macro that you are currently using? I am a bit confused on what you are trying to achieve.

Abrissbirne66 commented 1 month ago

@alexanderpann For example, imagine you want to generate something like a Lisp Unquote that has a boolean splice property. To display whether or not it is a splice unquote, a grammar flag with the text @ is used. So it either looks like ,x or ,@x. What I imagine is applying a property macro to the splice flag like so: ,$[@]$COPY_SRC[expr] and define the condition in the inspector:

property value                                                      

comment : <none>                                                    
value : (templateValue, genContext, node)->boolean { 
  // code that determines whether it should be spliced or not
}

Since this is not possible, on can use an IF/ELSE macro:

$IF$[,$COPY_SRC$[expr]] /         
$ELSE$[<T  ,@$COPY_SRC$[expr]  T>

and define the condition in the inspector for the IF/ELSE macro. This has disadvantages:

alexanderpann commented 1 month ago

I still don't understand why go can't just set the boolean value, so I can just give some hints. If you want to automatically set the value, you could have a listener that changes the value automatically. I could also change the code so that not the raw property value is used but also the getter of the property is evaluated. Then you can derive the value by a condition. If you want to prevent users from typing the flag in certain situations, you can set the substitute and side transformation condition in the flag cell. An alternative would be also to have a separate concept e.g. SpliceExpression with an editor like [- @ wrap(expr) % -] where you just have to type "@" to convert the Expression into a SpliceExpression. You can generate those nested nodes easily in the generator instead of using flags.

Abrissbirne66 commented 1 month ago

I'm not sure if you understood what I meant, because you are writing about a listener to change a value and side transformations and I guess these things ar about when you want to change a value based on an event, in this case, when a user uses the editor. But I'm talking about the programmatic setting of the value during generation, where the language using the grammar.flag is the generation target. Without grammarcells, properties are usually set using a property macro but it is apparently not possible to create a property macro around a grammar.flag, therefore I am suggesting to add this possibility, just for convenience. I don't think that evaluating the getter instead of the raw value would help because I'm just trying to set the value in a generation reduction rule and don't need the flexibility of a custom getter. Yes, the two seperate concepts would be another workaround, but probably not better than the IF/ELSE macro, it has the same disadvantages. Anyway, this is just a feature suggestion, because I thought it would be nice if one could use grammar.flag with the same convenience as the regular boolean properties.