Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » DSL template functions (specialization)
DSL template functions (specialization) [message #1786440] Thu, 03 May 2018 09:36 Go to next message
Goruk Chogall is currently offline Goruk ChogallFriend
Messages: 2
Registered: May 2018
Junior Member
Hello,

I am currently working on a DSL that is basically a functional language.
We want to add a "specialization" feature which will allow us to have template functions.
The main idea is to have a template function which call one or more other functions.
These other functions can then be overridden in other files without rewriting the template function.

To illustrate the purpose, here is an example.

File Parent.mydsl
Parent 1.0.0

function suffix {
	return "Parent"
}

function myTemplateFunction : string as input {
	return input + call suffix
}


File Child.mydsl
Child 1.0.0
specializes Parent

specialized function suffix {
	return "Child"
}


File Main.mydsl
Main 1.0.0

function main {
	var string as parent = call Parent.myTemplateFunction("test") // => "testParent"
	var string as child = call Child.myTemplateFunction("test")   // => "testChild"
}


The problem I am facing is that Child.myTemplateFunction is not resolved.
This is normal because it is not defined in Child.mydsl.
I tried adding the EObjectDescription via the a custom ResourceDescriptionStrategy#createEObjectDescriptions to do as if Child contained a function named "myTemplateFunction", but it didn't work.


The grammar and the MWS2 file I used are in the attached files.

I would be very grateful if anyone can help me on this issue.
Re: DSL template functions (specialization) [message #1786513 is a reply to message #1786440] Fri, 04 May 2018 20:39 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
there are multiple problems with that and no easy solution

(1) objects are only indexed where they are defined => nothing index under name Child.myTemplateFunction
(2) indexing is does without having references => dont know that there is a myTemplateFunction in parent when indexing children

idea:

split up function=[FunctionDefinition|FQN] up in packageThingy=[CommonInstance|ID] "." function=[FunctionDefinition|ID]

and scope the function thing manually by asking the packageThingy/CommonInstance for its functions and its specialized functions


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: DSL template functions (specialization) [message #1786572 is a reply to message #1786513] Mon, 07 May 2018 14:54 Go to previous message
Goruk Chogall is currently offline Goruk ChogallFriend
Messages: 2
Registered: May 2018
Junior Member
Hello,

Thanks for your answer.

We came up with another but somewhat similar solution because we also had to handle imports such as import "Parent-1.0.0.mydsl" for which we must also take care of the version.

I did not mention this point in the original post for simplicity's sake.

So, I'm posting this solution but with a simpler import statement, such as import Parent.

The grammar is modified as follows:
CommonInstance:
	name=ID  version=VERSION
	('import' imports+=ImportDeclaration (',' imports+=ImportDeclaration)*)?
	(specialization=Specialization)?
	functions+=FunctionDefinition*;
	
ImportDeclaration:
	referenced=[CommonInstance|ID];
...



Then, in MyDslScopeProvider (see attached MyDslScopeProvider.xtend file), we basically restrict the scope to limit to all functions belonging the imports and the file itself (this is done in the inner class DelegatingScope).

Then when we have function definition, we look for the parents and import their functions as is. This allows us to use parent's functions without the prefix Parent. in the specialized file.

Example:

Parent-1.0.0.mydsl
Parent 1.0.0

function suffix {
	return "Parent"
}

function myTemplateFunction : string as input {
	return input + call suffix
}

function parentHelperMethod : string as input {
	return input + "Helper"
}


Child-1.0.0.mydsl
Child 1.0.0
specializes Parent

specialized function suffix {
	return call parentHelperMethod("Child")
} 



Then we look if any of the imported file is a specialized file. If yes, then we add its functions and its parent's functions in the scope while taking care to adjust the qualified name. The piece of code doing this is:
                    var parentScope = Scopes::scopeFor(
                    	defs,
                    	[QualifiedName.create(imported.get(it.eContainer as CommonInstance).name, it.name)],
                    	new DelegatingScope(super.getScope(context, reference), root)
                    )


[QualifiedName.create(imported.get(it.eContainer as CommonInstance).name, it.name)] is doing the trick.

See the entire MyDslScopeProvider.xtend file for all the code.


The the Main.mydsl becomes:
Main 1.0.0
import Parent, Child 

function main { 
	var string as parent = call Parent.myTemplateFunction("test") // => "testParent"
	var string as child = call Child.myTemplateFunction("test")   // => "testChildHelper"
} 



Thanks for your support!
Cheers.


Previous Topic:How to change lexer to copy tokens from other files
Next Topic:Xtext Lexer and Parser
Goto Forum:
  


Current Time: Fri Apr 19 09:43:25 GMT 2024

Powered by FUDForum. Page generated in 0.03728 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top