Advanced Scripting Framework (ASF)
Modern scripting power inside classic VBA. Fast to adopt (No COM dependencies) โ impossible to ignore due its incredible power. Turn VBA into a full-featured script host. ASF brings modern scripting ergonomics (first-class functions, closures, arrays & objects, method chaining, builtin helpers like
map/filter/reduce, and even VBExpressions) to classic VBA projects โ without leaving the Office ecosystem.
ASF is an embeddable scripting engine written in plain VBA that brings modern language features โ first-class functions, anonymous closures, array & object literals, and safe interop with your existing VBA code โ to legacy Office apps.
This project provides a production-proven compiler and VM plus a complete test-suite vaโฆ
Advanced Scripting Framework (ASF)
Modern scripting power inside classic VBA. Fast to adopt (No COM dependencies) โ impossible to ignore due its incredible power. Turn VBA into a full-featured script host. ASF brings modern scripting ergonomics (first-class functions, closures, arrays & objects, method chaining, builtin helpers like
map/filter/reduce, and even VBExpressions) to classic VBA projects โ without leaving the Office ecosystem.
ASF is an embeddable scripting engine written in plain VBA that brings modern language features โ first-class functions, anonymous closures, array & object literals, and safe interop with your existing VBA code โ to legacy Office apps.
This project provides a production-proven compiler and VM plus a complete test-suite validating semantics and runtime behavior.
Why ASF?
- Seamless bridge between VBA codebases and modern scripting paradigms.
- No external runtime โ runs on top of VBA using a compact AST interpreter.
- Powerful features not found in any other VBA tool: shared-write closures, expression-level anonymous functions, nested arrays & objects, array helpers, VBExpressions integration, method chaining, and more.
- Native regex engine a pure VBA class module that supports lookarounds, multiline, atomic groups, back reference replace method with placeholders, non-capturing groups and more!.
- Tested โ the comprehensive Rubberduck test-suite passes across arithmetic, flow control, functions, closures, array/object manipulation and builtin methods.
- Unmatched expressiveness: Implement complex logic with concise scripts and enrich them with heavyweight VBA code.
- Safe interoperability: Delegate numeric and domain-specific work to your existing VBA functions via
@(...), we already have VBA-expressions embedded! - Readable, debuggable AST-first design. The Compiler emits Map-based ASTs (human-inspectable). The VM executes those ASTs directly so you can step through behavior and trace problems โ no opaque bytecode black box.
- Closure semantics you actually expect. Shared-write closure capture (like JavaScript/Python) keeps behavior intuitive.
- Designed for real engineering work. Robust array/object handling, VB-expression passthrough (
@(...)), and a small host-wrapper for easy integration.
Highlights / Features
- Full expression language: arithmetic, boolean, ternary, short-circuit logic.
- Arrays, objects (Map-like), member access, strings manipulation and indexing.
- First-class functions + anonymous functions + closures.
- Control flow:
if/elseif/else,for,while,switch,try/catch,break/continue. - Map / Filter / Reduce / Slice / Push / Pop as array methods
- indexOf / Pad* / Repeat / Replace / Match and many more string object methods
- Builtin helpers:
range,flatten,clone,IsArray,IsNumeric, etc. - Method chaining:
a.filter(...).reduce(...) print(...)convenience for quick debugging.- Pretty-printing for arrays/objects with cycle-safety
- VBA expressions passthrough (
@(...)) to call into native user defined functions where needed. - Compact wrapper (
ASFclass) โCompile+Runare one-liners from host code.
Quick Start
- Import canonical modules into your VBA project (recommended list below).
- Optionally initialize globals to register UDFs and share evaluators.
- Compile and run scripts from your host code.
Recommended module list: ASF.cls, ASF_Compiler.cls, ASF_VM.cls, ASF_Globals.cls, ASF_ScopeStack.cls, ASF_Parser.cls, ASF_Map.cls, UDFunctions.cls, VBAcallBack.cls, VBAexpressions.cls, VBAexpressionsScope.cls.
Examples
Map & nested arrays:
Dim engine As ASF
Set engine = New ASF
Dim idx As Long
idx = engine.Compile("a = [1,'x',[2,'y',[3]]];" & _
"b = a.map(fun(x){" & _
"if (IsArray(x)) { return x }" & _
"elseif (IsNumeric(x)) { return x*3 }" & _
"else { return x }" & _
"});" & _
"print(b);")
engine.Run idx '// => [ 3, 'x', [ 6, 'y', [ 9 ] ] ]
Chained helpers:
a=[1,2,3,4,5]; return(a.filter(fun(x){ return x > 2 }).reduce(fun(acc,x){ return acc + x }, 0)); // => 12
String templates:
a=[1,2]; return(`arr:${a[1] + a[2]} sum two items`); // => 'arr:3 sum two items'
String manipulation:
welcome=fun(string){return string.concat('!')}; return('Hello world'.replace('world', welcome('VBA'))); // => 'Hello VBA!'
Features & Capabilities
- Full AST-based compiler and VM implemented in VBA.
- Function literals (anonymous), named top-level functions, recursion.
- Arrays, objects and strings with literal syntax and methods helpers.
- Member access, nested indexing, and LValue semantics for assignments.
- Short-circuit logical operators, ternary operator, compound assignments.
- VB-expression embedding: reuse your VBA libraries seamlessly.
Language sugar
typeof operator
The typeof operator returns a string describing the runtime type of a value. Example:
f = fun(a) { a = a + 1; return a };
print(typeof f); // -> 'function'
print(typeof f(1)); // -> 'number'
for-in and for-of loops
ASF supports both for-in and for-of loops.
for (i in a) { ... } โ iterates over keys/indices of the iterable a.
- For arrays, indices reflect the current
Option Base(1 or 0). - For maps/objects, keys are iterated in insertion order when the map preserves insertion order; otherwise iteration may be in sorted or implementation-defined order.
for (v of a) { ... } โ iterates over values of the iterable a.
- For arrays, yields each element value in index order.
- For maps/objects, yields values in the same ordering as
for-inover keys.
Examples and expected behavior:
- for-in array (indices reflect option base)
// if Option Base = 1
a=[10,20]; out=[]; for (i in a) { out.push(i) }; print(out);
// expect: [1,2]
- for-of array (values)
a=[1,2,3]; sum=0; for (v of a) { sum=sum+v }; return(sum);
// expect: 6
- for-in map (insertion order or sorted if insertion order not exposed)
m = {a:1, b:2, c:3}; out=[]; for (k in m) { out.push(k) }; print(out);
// expect: ['a','b','c'] (in insertion order or sorted if map doesn't expose insertion order)
- for-of map (values)
m = {a:1, b:2}; vals=[]; for (v of m) { vals.push(v) }; print(vals);
// expect: [1,2]
- Regex replace with helper function
fun replacer(match, p1, p2, p3, offset, string)
{return [p1, p2, p3].join(' - ');
};
newString = 'abc12345#$*%'.replace(`/(\D*)(\d*)(\W*)/`, replacer);
print(newString); // --> 'abc - 12345 - #$*%'
Examples & Patterns
Explore examples/ (suggested) with scripts converting rules, workflows, or automation into ASF scripts. The test-suite provides dozens of ready-to-run scenarios.
Running the Test Suite
- Import
tests/TestRunner.basRubberduck test module, or open theASF v1.0.6.xlsmworkbook. - Ensure Rubberduck add-in is available.
- Run the test module โ all canonical tests should pass.
Contributing & Roadmap
- Report bugs or propose features via Issues.
- PRs must include tests covering behavior changes.
- Roadmap: improved diagnostics, optional sandboxing primitives, richer standard library for arrays/strings.
License
MIT โ see LICENSE.
For enterprise or integration help, reach out with a short description of your environment and goals โ ASF is intentionally lightweight so it adapts quickly to complex legacy codebases.