-
-
Notifications
You must be signed in to change notification settings - Fork 0
env EnvMap
This class is an alternative implementation of an environment object based on Map stacks. It is a sibling of Env and conforms to the same EnvLike contract; either can be passed to unify() and they are interchangeable.
EnvMap is defined in env-map.js and can be accessed like that:
import {EnvMap} from 'deep6/env-map.js';Both implementations satisfy the same contract, but they have different performance profiles depending on workload shape:
-
EnvMap(Map-stack) is the default and is used internally whenunify()is called without an explicit environment. It is faster on workloads with many distinct variable names per frame — particularly the alias-binding hot path and accumulating-symbol scenarios. The internalMap-of-name→value lookup avoids the dict-mode-deopt pressure that the proto-chain version pays once enough symbol-named bindings accumulate. - Env (proto-chain) is the opt-in sibling. It is fast for small environments and shallow nesting.
For solver-style consumers (e.g., yopl) where the binding count is large, EnvMap measures 4–8× faster on synthetic aggregate benchmarks. For occasional equal() / match() calls with small inputs, the difference between the implementations is negligible.
unify() accepts any EnvLike instance as its third argument:
import {unify, variable} from 'deep6/unify.js';
import {EnvMap} from 'deep6/env-map.js';
const x = variable('x'),
y = variable('y'),
env = new EnvMap();
const result = unify({a: x, b: y}, {a: 1, b: 2}, env);
result === env; // true
x.get(env); // 1
y.get(env); // 2Variable and Unifier instances are environment-agnostic — they work identically against either implementation through the EnvLike method API.
This class defines objects with the following public properties:
-
depth— an integer value of the depth, the current generation number. The initial value is 0. -
options— a plain object holding the behavioural flags read byunify(). Initially empty.
The class defines exactly the methods specified by EnvLike: push(), pop(), revert(depth), bindVar(name1, name2), bindVal(name, value), isBound(name), isAlias(name1, name2), get(name), getAllValues(). Their behavioural semantics match Env — only the underlying storage differs.
Internally EnvMap keeps two parallel stacks indexed by depth:
-
valuesStack: Map[]— per-frameMapfrom variable name to bound value. -
variablesStack: Map[]— per-frameMapfrom variable name to the aliasSetit belongs to.
Frames are lazily allocated — pushing a generation does not allocate a Map until the first write at that depth. Lookups (get(), isBound(), isAlias()) walk the stack top→bottom and stop at the first hit, giving the expected shadowing semantics.
bindVar() merges alias Sets by union; bindVal() propagates a binding to every member of the alias Set in the top frame.
Core functions
Environments and variables
Unification
Traverse
Unifiers
Utilities