expexp
Version:
The express model io and express model and data representation.
81 lines (70 loc) • 2.22 kB
JavaScript
// Provides a scope with variable names to lookup values and query whether
// a given value is by copy or by reference.
// Variable scope is hierarical, meaning that there can be a parent scope given
// on construction. That if any lookup on the current scope fails, the parent
// scope is tried for instead.
// There are two different notions about setting a value: First a value and its
// type model must be registered. This can only happen once and only for the
// current scope - not for the parent. On the other hand a value can be set
// several times and if declared as 'by reference' (proc VAR) setting can also
// affect the value in the parents scope. It is not up to this class to check
// if a value is valid to be set for a given name or type model.
export function VariableScope(parent) {
const me = {}
const c = {} // name cache
const BY_VAL = -1
const r = {} // reference index (or -1 if not a reference - mostly the case)
const setup = function() {
// nothing to do
}
// Register a value.
// If a value is by reference (onyl case: procedure var param) value is always
// an array and isRefIdx says what position the actual value has within that array.
// Like that an entites attrValues might be passed (infrastructure array) as
// value or a data arrays position.
me.regVal = function(name, value, isRefIdx = -1) {
c[name] = value
r[name] = isRefIdx
}
me.has = function(name) {
if (name in c) {
return true
} else if (parent) {
return parent.has(name)
} else {
return false
}
}
me.get = function(name) {
if (name in c) {
if (r[name] == BY_VAL) {
return c[name]
} else { // by reference (var)
return getByRef(name)
}
} else if (parent) {
return parent.get(name)
}
}
// Set an existing value. It must already be registered.
me.set = function(name, value) {
if (name in c) {
if (r[name] == BY_VAL) {
c[name] = value
} else { // by reference (var)
setByRef(name, value)
}
return true
} else if (parent) {
return parent.set(name, value)
}
}
const getByRef = function(name) {
return c[name][r[name]]
}
const setByRef = function(name, value) {
c[name][r[name]] = value
}
setup()
return me
}