64 lines
1.7 KiB
JavaScript
64 lines
1.7 KiB
JavaScript
'use strict'
|
|
|
|
const { safe } = require('./safe-format')
|
|
|
|
const caches = new WeakMap()
|
|
|
|
// Given a scope object, generates new symbol/loop/pattern/format/ref variable names,
|
|
// also stores in-scope format/ref mapping to variable names
|
|
|
|
const scopeMethods = (scope) => {
|
|
// cache meta info for known scope variables, per meta type
|
|
if (!caches.has(scope))
|
|
caches.set(scope, { sym: new Map(), ref: new Map(), format: new Map(), pattern: new Map() })
|
|
const cache = caches.get(scope)
|
|
|
|
// Generic variable names, requires a base name aka prefix
|
|
const gensym = (name) => {
|
|
if (!cache.sym.get(name)) cache.sym.set(name, 0)
|
|
const index = cache.sym.get(name)
|
|
cache.sym.set(name, index + 1)
|
|
return safe(`${name}${index}`)
|
|
}
|
|
|
|
// Regexp pattern names
|
|
const genpattern = (p) => {
|
|
if (cache.pattern.has(p)) return cache.pattern.get(p)
|
|
const n = gensym('pattern')
|
|
scope[n] = new RegExp(p, 'u')
|
|
cache.pattern.set(p, n)
|
|
return n
|
|
}
|
|
|
|
// Loop variable names
|
|
if (!cache.loop) cache.loop = 'ijklmnopqrstuvxyz'.split('')
|
|
const genloop = () => {
|
|
const v = cache.loop.shift()
|
|
cache.loop.push(`${v}${v[0]}`)
|
|
return safe(v)
|
|
}
|
|
|
|
// Reference (validator function) names
|
|
const getref = (sub) => cache.ref.get(sub)
|
|
const genref = (sub) => {
|
|
const n = gensym('ref')
|
|
cache.ref.set(sub, n)
|
|
return n
|
|
}
|
|
|
|
// Format validation function names
|
|
const genformat = (impl) => {
|
|
let n = cache.format.get(impl)
|
|
if (!n) {
|
|
n = gensym('format')
|
|
scope[n] = impl
|
|
cache.format.set(impl, n)
|
|
}
|
|
return n
|
|
}
|
|
|
|
return { gensym, genpattern, genloop, getref, genref, genformat }
|
|
}
|
|
|
|
module.exports = { scopeMethods }
|