TbExpressionService class

TbExpressionService is twinBASIC’s runtime expression engine: a way to take twinBASIC-syntax expressions supplied as ordinary strings and compile and evaluate them on the fly, without going through a separate build step. It powers calculators, formula columns in reports, scriptable property bindings, and any other feature that needs to turn user-supplied text into a value.

It is exposed as one class and two interfaces:

Compiling and evaluating an expression

Create a TbExpressionService, register at least one binder, then call Compile to get back an ITbExpression. The same compiled expression can be evaluated as many times as needed, so reuse it whenever the source text doesn’t change.

Sub Demo()
    Dim Service As TbExpressionService = New TbExpressionService
    Service.AddStdLibraryBinder()                       ' enable Sin, Sqr, Len, ...

    Dim Expr As ITbExpression = Service.Compile("2 * (Sqr(2) + 1)")
    Debug.Print Expr.Evaluate()                         ' 4.82842712474619
End Sub

Binding to your own objects

Anything beyond the standard library — application objects, configuration values, helper functions, recordset fields — has to be made visible to the engine through a binder.

The simplest form is AddCustomBinderObject, which takes a name and an object and exposes the object’s public members under that name. Pass the IsAppObject flag to make the object behave like an Office host’s Application: its members become reachable both qualified (Report.Title) and unqualified (Title).

Sub UseCustomObject()
    Dim Service As TbExpressionService = New TbExpressionService
    Service.AddStdLibraryBinder()
    Service.AddCustomBinderObject "Report", Me, IsAppObject

    Debug.Print Service.Compile("Report.Title").Evaluate()  ' qualified
    Debug.Print Service.Compile("Title").Evaluate()         ' unqualified — IsAppObject in effect
End Sub

For full control over symbol resolution — for example, to look up names dynamically against a recordset, virtualize a name into something other than a member access, or fall through to a custom default — implement ITbCustomBinder and register it with AddCustomBinder. Multiple binders can coexist; the engine consults them in registration order until one returns a non-Nothing result.

TbExpressionService class

New TbExpressionService returns the default interface, ITbExpressionService. Multiple services can coexist; each carries its own list of binders and is independent of the others.

Members

  • Compile – parses an expression string and returns it as an executable ITbExpression
  • AddStdLibraryBinder – registers the built-in binder for the standard runtime library (Sin, Sqr, Len, CStr, …)
  • AddCustomBinderObject – exposes a live object’s members under a chosen name, optionally as an unqualified application object
  • AddCustomBinder – registers a user-supplied ITbCustomBinder implementation

ExpressionEngineBinderFlags

Flags accepted by AddCustomBinderObject:

Constant Value Description
IsAppObject 1 Members of the bound object are reachable without the qualifying name, the way an Office host’s Application members are.

ITbExpression interface

A handle to a compiled expression. Returned by Compile and by an ITbCustomBinder.Bind implementation. Calling Evaluate runs the expression against the current state of its bindings and returns the result; the same instance can be evaluated as many times as needed.

Members

  • Evaluate – runs the compiled expression and returns its result

ITbCustomBinder interface

Implement this interface to register a fully custom resolver with AddCustomBinder. The engine calls Bind during compilation for each unresolved symbol it encounters in the expression source, supplying the symbol name and the number of arguments at the call site, and expects an ITbExpression that produces the value when Evaluate is called — or Nothing to defer to the next binder.

Members

  • Bind – resolves a symbol reference to an ITbExpression, or returns Nothing to defer to the next binder