Skip to content

Development Design Changing the Language

javierfernandes edited this page Jul 13, 2016 · 5 revisions

Intro

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.

Required changes

  • 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

Optional elements

  • WollokTemplateProposalProvider: to contribute a template proposal for your element (autocomplete). See [Template Proposals] (Development - Template Proposals)

Example: While

Lets see it in an example: adding a while statement to the language

Grammar

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
;

Interpreter Evaluator

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
 	}

Visitor

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
 	}

Template Proposal

Edit WollokTemplateProposalProvider and add a new template there

< WWhile >>
 '''while (${condition}) {
 	${then}
 }'''
Clone this wiki locally