-
Notifications
You must be signed in to change notification settings - Fork 16
Development Design Changing the Language
This is simply a guide based on previous cases where we needed to change the language. Tries to be a checklist of common errors and tasks you might need to do. Since the language uses multiple dispatch and visitor pattern there are some tasks that don't naturally arise by compilation errors when you add a new element to the language. Therefore you need to know which places you need to extend to implement certain concerns for your new element.
- Grammar: of course!
- WollokInterpreterEvaluator: which has the runtime logic to be executed when the element is evaluated.
- AbstractVisitor: to avoid an exception. This class navigates all elements in the model. If your element has nested element, then you must visit
- TESTS: of course !! See Testing
- WollokTemplateProposalProvider: to contribute a template proposal for your element (autocomplete). See [Template Proposals] (Development - Template Proposals)
Lets see it in an example: adding a while statement to the language
Edit the grammar file
org.uqbar.project.wollok/src/org/uqbar/project/wollok/WollokDsl.xtext
Add the new rule:
WWhile:
'while' '(' condition=WExpression ')'
then=WBlockOrExpression
;
Then use it in some other rule (last line option)
WPrimaryExpression returns WExpression:
WVariableReference |
WLiteral |
WConstructorCall |
WParenthesizedExpression |
WSuperInvocation |
WIfExpression |
WTry |
WReturnExpression |
WThrow |
WWhile
;
Then add a new dispatch method for your new rule to org.uqbar.project.wollok.interpreter.WollokInterpreterEvaluator
def dispatch evaluate(WWhile it) {
while(checkCondition) {
then.eval
}
theVoid
}
def getTheVoid(EObject it) { getVoid(interpreter, it) }
def checkCondition(WWhile it) {
val cond = condition.eval
if (cond == null) {
throw newWollokExceptionAsJava('''Cannot use null in 'while' condition''')
}
if (!(cond.isWBoolean))
throw new WollokInterpreterException('''Condition in 'if' must evaluate to a boolean. Instead got: «cond» («cond?.class.name»)''', it)
cond == trueObject
}
Edit org.uqbar.project.wollok.visitors.AbstractVisitor and add a new dispatch method for visiting all child elements
def dispatch void visit(WWhile it) {
condition.doVisit
then.doVisit
}
Edit WollokTemplateProposalProvider and add a new template there
< WWhile >>
'''while (${condition}) {
${then}
}'''