import { BaseNode } from './BaseNode.js'; /** * AST node for evidence definitions * Represents: evidence canRead(user: User, doc: Document) { ... } PROVIDES string */ export class EvidenceNode extends BaseNode { constructor(name, location = null) { super('Evidence', location); this.name = name; this.parameters = []; this.returnType = null; this.body = null; // EvidenceBodyNode this.provides = null; // Return type specification } /** * Add a parameter to the evidence * @param {ParameterNode} parameter - Parameter to add */ addParameter(parameter) { this.parameters.push(parameter); this.addChild(parameter); } /** * Set the body of the evidence * @param {EvidenceBodyNode} body - Evidence body */ setBody(body) { this.body = body; this.addChild(body); } /** * Set the return type for this evidence * @param {string} returnType - Return type */ setReturnType(returnType) { this.returnType = returnType; this.provides = returnType; } /** * Get the parameter names as an array * @returns {string[]} Array of parameter names */ getParameterNames() { return this.parameters.map(param => param.name); } /** * Get the parameter types as an array * @returns {string[]} Array of parameter types */ getParameterTypes() { return this.parameters.map(param => param.type); } /** * Find a parameter by name * @param {string} name - Parameter name to find * @returns {ParameterNode|null} Found parameter or null */ getParameter(name) { return this.parameters.find(param => param.name === name) || null; } /** * Get the signature string for this evidence * @returns {string} Evidence signature */ getSignature() { const paramStr = this.parameters.map(param => `${param.name}: ${param.type}`).join(', '); return `${this.name}(${paramStr})`; } /** * Check if this evidence has a return type * @returns {boolean} True if has return type */ hasReturnType() { return this.returnType !== null; } /** * Validate the evidence * @returns {string[]} Array of error messages */ validate() { const errors = []; // Validate evidence name if (!this.name || typeof this.name !== 'string') { errors.push(`Invalid evidence name: ${this.name}`); } // Validate parameters this.parameters.forEach((param, index) => { const paramErrors = param.validate ? param.validate() : []; errors.push(...paramErrors.map(err => `Parameter ${index + 1}: ${err}`)); }); // Validate body if (this.body) { const bodyErrors = this.body.validate ? this.body.validate() : []; errors.push(...bodyErrors); } return errors; } toString() { const providesStr = this.returnType ? ` PROVIDES ${this.returnType}` : ''; return `Evidence(${this.getSignature()}${providesStr})`; } }