aboutsummaryrefslogtreecommitdiff
path: root/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts')
-rw-r--r--sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts215
1 files changed, 215 insertions, 0 deletions
diff --git a/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts
new file mode 100644
index 00000000..51199229
--- /dev/null
+++ b/sandbox/testAppNevena/Front/node_modules/ajv/lib/compile/codegen/scope.ts
@@ -0,0 +1,215 @@
+import {_, nil, Code, Name} from "./code"
+
+interface NameGroup {
+ prefix: string
+ index: number
+}
+
+export interface NameValue {
+ ref: ValueReference // this is the reference to any value that can be referred to from generated code via `globals` var in the closure
+ key?: unknown // any key to identify a global to avoid duplicates, if not passed ref is used
+ code?: Code // this is the code creating the value needed for standalone code wit_out closure - can be a primitive value, function or import (`require`)
+}
+
+export type ValueReference = unknown // possibly make CodeGen parameterized type on this type
+
+class ValueError extends Error {
+ readonly value?: NameValue
+ constructor(name: ValueScopeName) {
+ super(`CodeGen: "code" for ${name} not defined`)
+ this.value = name.value
+ }
+}
+
+interface ScopeOptions {
+ prefixes?: Set<string>
+ parent?: Scope
+}
+
+interface ValueScopeOptions extends ScopeOptions {
+ scope: ScopeStore
+ es5?: boolean
+ lines?: boolean
+}
+
+export type ScopeStore = Record<string, ValueReference[] | undefined>
+
+type ScopeValues = {
+ [Prefix in string]?: Map<unknown, ValueScopeName>
+}
+
+export type ScopeValueSets = {
+ [Prefix in string]?: Set<ValueScopeName>
+}
+
+export enum UsedValueState {
+ Started,
+ Completed,
+}
+
+export type UsedScopeValues = {
+ [Prefix in string]?: Map<ValueScopeName, UsedValueState | undefined>
+}
+
+export const varKinds = {
+ const: new Name("const"),
+ let: new Name("let"),
+ var: new Name("var"),
+}
+
+export class Scope {
+ protected readonly _names: {[Prefix in string]?: NameGroup} = {}
+ protected readonly _prefixes?: Set<string>
+ protected readonly _parent?: Scope
+
+ constructor({prefixes, parent}: ScopeOptions = {}) {
+ this._prefixes = prefixes
+ this._parent = parent
+ }
+
+ toName(nameOrPrefix: Name | string): Name {
+ return nameOrPrefix instanceof Name ? nameOrPrefix : this.name(nameOrPrefix)
+ }
+
+ name(prefix: string): Name {
+ return new Name(this._newName(prefix))
+ }
+
+ protected _newName(prefix: string): string {
+ const ng = this._names[prefix] || this._nameGroup(prefix)
+ return `${prefix}${ng.index++}`
+ }
+
+ private _nameGroup(prefix: string): NameGroup {
+ if (this._parent?._prefixes?.has(prefix) || (this._prefixes && !this._prefixes.has(prefix))) {
+ throw new Error(`CodeGen: prefix "${prefix}" is not allowed in this scope`)
+ }
+ return (this._names[prefix] = {prefix, index: 0})
+ }
+}
+
+interface ScopePath {
+ property: string
+ itemIndex: number
+}
+
+export class ValueScopeName extends Name {
+ readonly prefix: string
+ value?: NameValue
+ scopePath?: Code
+
+ constructor(prefix: string, nameStr: string) {
+ super(nameStr)
+ this.prefix = prefix
+ }
+
+ setValue(value: NameValue, {property, itemIndex}: ScopePath): void {
+ this.value = value
+ this.scopePath = _`.${new Name(property)}[${itemIndex}]`
+ }
+}
+
+interface VSOptions extends ValueScopeOptions {
+ _n: Code
+}
+
+const line = _`\n`
+
+export class ValueScope extends Scope {
+ protected readonly _values: ScopeValues = {}
+ protected readonly _scope: ScopeStore
+ readonly opts: VSOptions
+
+ constructor(opts: ValueScopeOptions) {
+ super(opts)
+ this._scope = opts.scope
+ this.opts = {...opts, _n: opts.lines ? line : nil}
+ }
+
+ get(): ScopeStore {
+ return this._scope
+ }
+
+ name(prefix: string): ValueScopeName {
+ return new ValueScopeName(prefix, this._newName(prefix))
+ }
+
+ value(nameOrPrefix: ValueScopeName | string, value: NameValue): ValueScopeName {
+ if (value.ref === undefined) throw new Error("CodeGen: ref must be passed in value")
+ const name = this.toName(nameOrPrefix) as ValueScopeName
+ const {prefix} = name
+ const valueKey = value.key ?? value.ref
+ let vs = this._values[prefix]
+ if (vs) {
+ const _name = vs.get(valueKey)
+ if (_name) return _name
+ } else {
+ vs = this._values[prefix] = new Map()
+ }
+ vs.set(valueKey, name)
+
+ const s = this._scope[prefix] || (this._scope[prefix] = [])
+ const itemIndex = s.length
+ s[itemIndex] = value.ref
+ name.setValue(value, {property: prefix, itemIndex})
+ return name
+ }
+
+ getValue(prefix: string, keyOrRef: unknown): ValueScopeName | undefined {
+ const vs = this._values[prefix]
+ if (!vs) return
+ return vs.get(keyOrRef)
+ }
+
+ scopeRefs(scopeName: Name, values: ScopeValues | ScopeValueSets = this._values): Code {
+ return this._reduceValues(values, (name: ValueScopeName) => {
+ if (name.scopePath === undefined) throw new Error(`CodeGen: name "${name}" has no value`)
+ return _`${scopeName}${name.scopePath}`
+ })
+ }
+
+ scopeCode(
+ values: ScopeValues | ScopeValueSets = this._values,
+ usedValues?: UsedScopeValues,
+ getCode?: (n: ValueScopeName) => Code | undefined
+ ): Code {
+ return this._reduceValues(
+ values,
+ (name: ValueScopeName) => {
+ if (name.value === undefined) throw new Error(`CodeGen: name "${name}" has no value`)
+ return name.value.code
+ },
+ usedValues,
+ getCode
+ )
+ }
+
+ private _reduceValues(
+ values: ScopeValues | ScopeValueSets,
+ valueCode: (n: ValueScopeName) => Code | undefined,
+ usedValues: UsedScopeValues = {},
+ getCode?: (n: ValueScopeName) => Code | undefined
+ ): Code {
+ let code: Code = nil
+ for (const prefix in values) {
+ const vs = values[prefix]
+ if (!vs) continue
+ const nameSet = (usedValues[prefix] = usedValues[prefix] || new Map())
+ vs.forEach((name: ValueScopeName) => {
+ if (nameSet.has(name)) return
+ nameSet.set(name, UsedValueState.Started)
+ let c = valueCode(name)
+ if (c) {
+ const def = this.opts.es5 ? varKinds.var : varKinds.const
+ code = _`${code}${def} ${name} = ${c};${this.opts._n}`
+ } else if ((c = getCode?.(name))) {
+ code = _`${code}${c}${this.opts._n}`
+ } else {
+ throw new ValueError(name)
+ }
+ nameSet.set(name, UsedValueState.Completed)
+ })
+ }
+ return code
+ }
+}