Programmatic code evaluation

To evaluate an expression programmatically a developer should use GtPharoSnippetCoder GtPharoSourceCoder subclass: #GtPharoSnippetCoder instanceVariableNames: 'behavior' classVariableNames: '' package: 'GToolkit-Pharo-Coder-Method-Coder' . A snippet coder provides developers with a good control over execution parameters and assists them with retrieving an evaluation result value or an exception.

Context-free expressions

A context-free expression is an expression the evaluation result of which does not depend on a runtime context. Such expressions do not reference self, and do not depend on external variables. In this simple case we can directly evaluate an expression, for example:

coder := GtPharoSnippetCoder forSource: '2 + 2'.
coder doItAll
  
coder := GtPharoSnippetCoder forSource: 'Object new'.
coder doItAll
  

Context-sensitive expressions

To evaluate any context-sensitive expression a developer should first create an evaluation context. That evaluation context can be parametries with runtime values. Once the context is setup it can be used to evaluate an expression.

coder := GtPharoSnippetCoder forSource: '2 + 2'.
context := coder evaluationContext.
coder doItInContext: context
  
Expressions with input variables

Sometimes it is desired to provide an expression with an input variable. The following snippet shows how we can provide a value for a local variable that will be used during evaluation (GtLocalVariablesBindings Object subclass: #GtLocalVariablesBindings uses: TGtVariablesBindings instanceVariableNames: 'bindings' classVariableNames: '' package: 'GToolkit-VariableBindings-Bindings' ):

coder := GtPharoSnippetCoder forSource: 'number * 2'.
context := coder evaluationContext.
context addBindings: (GtLocalVariablesBindings new
	localAt: #number put: 42).
coder doItInContext: context
  
Expressions with a bound self object

By default, special reserved variables such as self, super and thisContext are not bound to anything. In order to use self within the expression it is neccessary to setup a receiver object and declare reserved variables bindings (GtReservedVariablesBindings Object subclass: #GtReservedVariablesBindings uses: TGtVariablesBindings instanceVariableNames: '' classVariableNames: '' package: 'GToolkit-VariableBindings-Bindings' ):

coder := GtPharoSnippetCoder forSource: 'self * 2'.
context := coder evaluationContext.
context receiverObject: 42.
context addBindings: GtReservedVariablesBindings new.
coder doItInContext: context
  
Expressions that use slots of a bound object

If a context-sensitive expression uses slots (or instance variables) of a bound object it is required to specify an additional set of bindings designed to read the value from the slots of an object (GtSlotVariablesBindings Object subclass: #GtSlotVariablesBindings uses: TGtVariablesBindings instanceVariableNames: 'object' classVariableNames: '' package: 'GToolkit-VariableBindings-Bindings' ):

coder := GtPharoSnippetCoder forSource: 'bounds class'.
context := coder evaluationContext.
context receiverObject: BlElement new.
context addBindings: (GtSlotVariablesBindings new object: context receiverObject).
coder doItInContext: context