UNPKG

@prism-lang/core

Version:

A programming language for uncertainty

293 lines 8.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultContextManager = exports.ContextAwareBase = exports.ContextManager = exports.ContextValidator = exports.ContextTransition = exports.ContextStack = exports.ContextScope = exports.Context = exports.ContextError = void 0; exports.createContext = createContext; exports.withContext = withContext; class ContextError extends Error { code; constructor(message, code) { super(message); this.code = code; this.name = 'ContextError'; } } exports.ContextError = ContextError; class Context { name; properties; parent; scopes = []; constructor(name, properties = {}, parent) { this.name = name; this.properties = properties; this.parent = parent; } // Property inheritance from parent contexts getInheritedProperty(key) { if (key in this.properties) { return this.properties[key]; } if (this.parent) { return this.parent.getInheritedProperty(key); } return undefined; } // Context compatibility checking isCompatibleWith(other) { // Basic compatibility: same domain or related contexts const thisDomain = this.getInheritedProperty('domain'); const otherDomain = other.getInheritedProperty('domain'); if (thisDomain && otherDomain) { return thisDomain === otherDomain; } // If no domain specified, contexts are compatible return true; } // Create a new scope within this context createScope(variables = {}) { const scope = new ContextScope(this, variables); this.scopes.push(scope); return scope; } // Get all scopes in this context getScopes() { return [...this.scopes]; } // Remove a scope removeScope(scope) { const index = this.scopes.indexOf(scope); if (index >= 0) { this.scopes.splice(index, 1); return true; } return false; } toString() { const parentPath = this.parent ? `${this.parent.toString()}.` : ''; return `${parentPath}${this.name}`; } } exports.Context = Context; class ContextScope { context; variables; constructor(context, variables = {}) { this.context = context; this.variables = variables; } getVariable(name) { return this.variables[name]; } setVariable(name, value) { this.variables[name] = value; } hasVariable(name) { return name in this.variables; } getAllVariables() { return { ...this.variables }; } } exports.ContextScope = ContextScope; class ContextStack { stack = []; push(context) { this.stack.push(context); } pop() { const context = this.stack.pop(); if (!context) { throw new ContextError('Cannot pop from empty context stack', 'STACK_UNDERFLOW'); } return context; } current() { return this.stack[this.stack.length - 1]; } depth() { return this.stack.length; } isEmpty() { return this.stack.length === 0; } findContext(name) { return this.stack.find(ctx => ctx.name === name); } getContextPath() { return this.stack.map(ctx => ctx.name); } clear() { this.stack.length = 0; } } exports.ContextStack = ContextStack; class ContextTransition { from; to; options; constructor(from, to, options = {}) { this.from = from; this.to = to; this.options = options; } isValid() { // Basic validation: check context compatibility return this.from.isCompatibleWith(this.to); } execute() { if (!this.isValid()) { return { success: false, error: `Invalid transition from ${this.from.name} to ${this.to.name}`, }; } const result = { success: true, newContext: this.to, }; // Preserve state if requested if (this.options.preserveState) { const scopes = this.from.getScopes(); if (scopes.length > 0) { const preservedState = {}; scopes.forEach(scope => { Object.assign(preservedState, scope.getAllVariables()); }); result.preservedState = preservedState; } } return result; } } exports.ContextTransition = ContextTransition; class ContextValidator { rules; constructor(rules = []) { this.rules = rules; } addRule(rule) { this.rules.push(rule); } validateTransition(from, to) { for (const rule of this.rules) { if (!rule(from, to)) { throw new ContextError(`Context transition validation failed: ${from?.name} -> ${to?.name}`, 'VALIDATION_FAILED'); } } } removeRule(rule) { const index = this.rules.indexOf(rule); if (index >= 0) { this.rules.splice(index, 1); return true; } return false; } } exports.ContextValidator = ContextValidator; class ContextManager { contexts = new Map(); stack = new ContextStack(); validator; registerContext(context) { this.contexts.set(context.name, context); } getContext(name) { return this.contexts.get(name); } getAllContexts() { return Array.from(this.contexts.values()); } getCurrentContext() { return this.stack.current(); } enterContext(name) { const context = this.getContext(name); if (!context) { throw new ContextError(`Context '${name}' not found`, 'CONTEXT_NOT_FOUND'); } const current = this.getCurrentContext(); if (this.validator) { this.validator.validateTransition(current, context); } this.stack.push(context); } exitContext() { if (this.stack.isEmpty()) { return undefined; } return this.stack.pop(); } switchContext(name) { const context = this.getContext(name); if (!context) { throw new ContextError(`Context '${name}' not found`, 'CONTEXT_NOT_FOUND'); } const current = this.getCurrentContext(); if (this.validator) { this.validator.validateTransition(current, context); } if (!this.stack.isEmpty()) { this.stack.pop(); } this.stack.push(context); } executeInContext(contextName, operation) { const context = this.getContext(contextName); if (!context) { throw new ContextError(`Context '${contextName}' not found`, 'CONTEXT_NOT_FOUND'); } const wasInContext = !this.stack.isEmpty(); this.enterContext(contextName); try { return operation(); } finally { this.exitContext(); if (!wasInContext && !this.stack.isEmpty()) { this.stack.clear(); } } } setValidator(validator) { this.validator = validator; } getValidator() { return this.validator; } getContextStack() { return this.stack; } } exports.ContextManager = ContextManager; // Utility functions function createContext(name, properties = {}) { return new Context(name, properties); } function withContext(context, operation) { return operation(context); } // Context-aware base class class ContextAwareBase { currentContext; getCurrentContext() { return this.currentContext; } setContext(context) { this.currentContext = context; } inContext(context, operation) { const previous = this.currentContext; this.currentContext = context; try { return operation(); } finally { this.currentContext = previous; } } } exports.ContextAwareBase = ContextAwareBase; // Default context manager instance exports.defaultContextManager = new ContextManager(); //# sourceMappingURL=context.js.map