Concept functions allow language designers to leave hooks for their language users, through which the users can provide code to leverage in the generated code. For example, most of the languages that MPS offers for language design, such as Editor, Constraints or Intentions, leverage Concept functions:
You can also discover their usages down in the Inspector window:
Concept functions are defined in jetbrains.mps.baselanguage and they contain BaseLanguage code, which upon generation becomes part of the generated Java code. This option can give your DSLs enormous flexibility.
We'll use the Robot Kaja sample project to experiment with Concept functions. The goal is to allow the Script authors to provide a function that will customize the Trace messages, which are reported to the user through the trace command:
The user will be able to customize the trace messages through a function that receives the original message as a parameter and returns a string that should be displayed instead:
Define the concept function concept
First, a sub-concept of ConceptFunction must be created:
The behavior aspect overrides a few methods inherited from ConceptFunction:
getExpectedReturnType() - declares what type should be returned from the function
getParameterConcepts() - lists the concepts that will represent parameters to this function
showName() - indicates, whether the name of the function should be displayed in the editor alongside the parameter list and the return type
getName() - the name of the function to display in the editor. As it defaults to the concept alias, you will usually only want to override this if needing a dynamic name
Since MyFunction requires an argument to hold the original trace message value, we also need to create a concept to represent that parameter, which extends the ConceptFunctionParameter concept and specifies its type through an overriden getType() behavior method:
Add MyFunction to Script
Once defined, the MyFunction concept can be added to Script:
This will allow us to edit the function in the Script editor:
When you hit enter, the editor will display the signature of the concept function and you will be able to edit its body:
Notice that the Inspector shows the description messages for the function as well as its parameters, when you place the cursor on the concept function signature.
The last step that remains is to alter the generator so that the trace message customization can happen. We first need to modify the KajaFrame class, which is a super-class for all the classes that get generated from Robot Kaja Scripts:
The trace() method needs to call the new customizeMessage() method in order to have the original trace message customized. The default implementation of customizeMessage() method returns the message without any alteration.
The generator template that defines how a class generated for a Script should look like, now has to generate a extra method that will override the customizeMessage() method in KajaFrame:
The overriding method only gets generated when the concept function exists in the Script. The generator uses the body of myFunction as a body of the generated customizeMessage() method.
Now the concept function for customizing trace messages should be fully functional: