UNPKG

mlld

Version:

mlld: llm scripting language

1 lines 18.6 kB
{"version":3,"sources":["../interpreter/utils/variable-resolution.ts"],"names":["ResolutionContext","shouldPreserveVariable","context","resolveVariable","variable","env","isPipelineInput","value","isStructured","complexFlag","isComplex","evaluateDataValue","evaluatedValue","evaluatedAt","Date","now","mx","internal","wasEvaluated","isExecutableVariable","extracted","extractVariableValue","isStructuredValue","asData","asText","isPrimitive","isTextLike","arrayType","type","extractWithBehaviors","process","MLLD_DEBUG_FIX","console","error","name","valuePreview","keys","Object","isPath","resolvedPath","evaluateExecInvocation","invocation","commandRef","identifier","args","result","isImported","isComputed","isVariable","resolveValue"],"mappings":"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","file":"chunk-DUS6QZAC.mjs","sourcesContent":["/**\n * Enhanced variable resolution that preserves Variable wrappers when possible\n * Part of Phase 3: Making Variables flow through the system\n */\n\nimport type { Variable, VariableValue } from '@core/types/variable/VariableTypes';\nimport type { Environment } from '@interpreter/env/Environment';\nimport { \n isTextLike,\n isStructured,\n isPath,\n isPipelineInput,\n isExecutableVariable,\n isImported,\n isComputed,\n isPrimitive,\n isObject,\n isArray\n} from '@core/types/variable';\nimport { asData, asText, isStructuredValue } from './structured-value';\n// Import removed to avoid circular dependency - will use dynamic import if needed\n\n/**\n * Resolution context to determine when to extract values\n * \n * WHY: Different usage contexts have different requirements for Variables.\n * Some contexts need the Variable wrapper for type introspection or metadata,\n * while others need raw values for processing or display.\n */\nexport enum ResolutionContext {\n // Contexts where we should preserve Variables\n VariableAssignment = 'variable-assignment', // WHY: Target variable needs full type info\n VariableCopy = 'variable-copy', // WHY: Copying requires preserving metadata\n ArrayElement = 'array-element', // WHY: Arrays can store Variables with types\n ObjectProperty = 'object-property', // WHY: Objects can store Variables with types\n FunctionArgument = 'function-argument', // WHY: Shadow envs need type introspection (mlld.isVariable)\n DataStructure = 'data-structure', // WHY: Data structures preserve Variable types\n FieldAccess = 'field-access', // WHY: Metadata property access (@var.mx, @var.type, @items.any)\n ImportResult = 'import-result', // WHY: Imports preserve module Variable types\n \n // Contexts where we must extract values\n StringInterpolation = 'string-interpolation', // WHY: Templates need raw strings to concat\n CommandExecution = 'command-execution', // WHY: Shell commands need raw strings\n FileOutput = 'file-output', // WHY: Files contain raw content, not Variables\n Conditional = 'conditional', // WHY: Conditions evaluate raw truthy/falsy values\n Display = 'display', // WHY: Users see final content, not wrappers\n PipelineInput = 'pipeline-input', // WHY: Pipelines transform raw data, not types\n Truthiness = 'truthiness', // WHY: Truthy checks need raw values\n Equality = 'equality' // WHY: Comparison needs raw values\n}\n\n/**\n * Determines if we should preserve the Variable wrapper in this context\n * \n * WHY: Preserving Variables maintains type information and metadata that would\n * be lost if we extracted the raw value. This enables type introspection,\n * special behaviors (custom toString), and proper handling of complex types.\n * \n * @param context - The context in which the Variable is being used\n * @returns true if Variable wrapper should be preserved, false if value should be extracted\n */\nexport function shouldPreserveVariable(context: ResolutionContext): boolean {\n switch (context) {\n // Preserve Variable wrapper contexts\n case ResolutionContext.VariableAssignment:\n case ResolutionContext.VariableCopy:\n case ResolutionContext.ArrayElement:\n case ResolutionContext.ObjectProperty:\n case ResolutionContext.FunctionArgument:\n case ResolutionContext.DataStructure:\n case ResolutionContext.FieldAccess:\n case ResolutionContext.ImportResult:\n return true;\n \n // Extract raw value contexts\n case ResolutionContext.StringInterpolation:\n case ResolutionContext.CommandExecution:\n case ResolutionContext.FileOutput:\n case ResolutionContext.Conditional:\n case ResolutionContext.Display:\n case ResolutionContext.PipelineInput:\n case ResolutionContext.Truthiness:\n case ResolutionContext.Equality:\n return false;\n \n default:\n // Default to extraction for safety\n return false;\n }\n}\n\n/**\n * Enhanced variable resolution that preserves Variables when appropriate\n * \n * WHY: This function is the central decision point for Variable handling. It determines\n * whether to preserve the Variable wrapper (maintaining type info and metadata) or\n * extract the raw value based on usage context.\n * \n * GOTCHA: PipelineInput Variables always return their .value property even in\n * PipelineInput context because they're wrapper objects, not the actual input.\n * \n * CONTEXT: Called throughout the interpreter when Variables need resolution.\n * The context parameter is critical for correct behavior.\n * \n * @param variable - The Variable to resolve\n * @param env - The environment for evaluation\n * @param context - The context determining if we should preserve the Variable\n * @returns Either the Variable itself or its extracted value\n */\nexport async function resolveVariable(\n variable: Variable, \n env: Environment,\n context: ResolutionContext = ResolutionContext.Display\n): Promise<Variable | VariableValue> {\n \n /**\n * Special case: PipelineInput handling\n * WHY: PipelineInput is a wrapper Variable containing the actual pipeline data.\n * We return .value (the wrapped object) not the Variable itself because pipelines\n * work with raw data transformations, not mlld Variable types.\n */\n if (isPipelineInput(variable) && context === ResolutionContext.PipelineInput) {\n return variable.value; // Return the PipelineInput object, not the Variable wrapper\n }\n \n // If context allows preservation, return the Variable itself for most types\n if (shouldPreserveVariable(context)) {\n /**\n * Complex/lazy variable handling\n * WHY: Complex variables contain unevaluated mlld directives (like run commands).\n * We evaluate them on access but create a new Variable with the result to\n * preserve type information and track that evaluation occurred.\n * GOTCHA: The wasEvaluated metadata prevents re-evaluation of the same content.\n * WHY new Variable: Maintains immutability. Mutating would affect all references\n * to the original Variable. New Variable tracks that THIS resolution was evaluated\n * without polluting the original (different contexts may need different results).\n */\n if (isStructured(variable)) {\n const complexFlag = (variable as any).isComplex;\n if (complexFlag) {\n // Complex data needs evaluation but we can wrap result in a new Variable\n // Dynamic import to avoid circular dependency\n const { evaluateDataValue } = await import('@interpreter/eval/data-value-evaluator');\n const evaluatedValue = await evaluateDataValue(variable.value, env);\n \n const evaluatedAt = Date.now();\n // Create a new Variable with the evaluated value\n return {\n ...variable,\n value: evaluatedValue,\n mx: { ...variable.mx },\n internal: {\n ...(variable.internal ?? {}),\n wasEvaluated: true,\n evaluatedAt\n }\n } as Variable;\n }\n }\n \n // For executable variables in non-execution contexts, preserve them\n if (isExecutableVariable(variable)) {\n return variable;\n }\n \n // Most variables can be returned as-is\n return variable;\n }\n \n // Context requires extraction\n const extracted = await extractVariableValue(variable, env);\n if (!isStructuredValue(extracted)) {\n return extracted;\n }\n if (context === ResolutionContext.Equality) {\n return asData(extracted);\n }\n if (context === ResolutionContext.CommandExecution) {\n return asText(extracted);\n }\n return extracted;\n}\n\n/**\n * Extract raw value from a Variable\n * Always returns the underlying JavaScript value\n * \n * WHY: Some contexts need raw values, not Variable wrappers. This function\n * handles all Variable types and ensures proper evaluation of complex/lazy\n * variables and auto-execution of executables.\n * \n * GOTCHA: ExecutableVariables auto-execute when extracted (e.g., in pipelines\n * where @func means \"execute with piped input\").\n * \n * @param variable - The Variable to extract value from\n * @param env - The environment for evaluation\n * @returns The raw JavaScript value\n */\nexport async function extractVariableValue(\n variable: Variable, \n env: Environment\n): Promise<VariableValue> {\n \n // Type-specific resolution using type guards\n if (isPrimitive(variable)) {\n return variable.value;\n } else if (isTextLike(variable)) {\n return variable.value;\n } else if (isStructured(variable)) {\n const complexFlag = (variable as any).isComplex;\n \n if (complexFlag) {\n // Dynamic import to avoid circular dependency\n const { evaluateDataValue } = await import('@interpreter/eval/data-value-evaluator');\n const evaluatedValue = await evaluateDataValue(variable.value, env);\n return evaluatedValue;\n }\n \n // Check if this is an array with custom behaviors (load-content-result, renamed-content)\n // WHY: Special array types have behaviors (toString, content getter) that must be preserved\n // during value extraction to maintain proper output formatting\n const arrayType = variable.internal?.arrayType;\n if (\n variable.type === 'array' &&\n arrayType &&\n (arrayType === 'renamed-content' || arrayType === 'load-content-result')\n ) {\n // Use the variable-migration extractVariableValue to preserve behaviors\n const { extractVariableValue: extractWithBehaviors } = await import('./variable-migration');\n return extractWithBehaviors(variable);\n }\n \n return variable.value;\n } else if (\n (variable.type === 'object' || variable.type === 'array') &&\n (variable as any).isComplex\n ) {\n if (process.env.MLLD_DEBUG_FIX === 'true') {\n console.error('[extractVariableValue] evaluating complex collection', {\n name: (variable as any).name,\n type: variable.type,\n isComplex: (variable as any).isComplex,\n valuePreview:\n variable.value && typeof variable.value === 'object'\n ? { type: (variable.value as any).type, keys: Object.keys(variable.value || {}) }\n : typeof variable.value\n });\n }\n // Lazy-evaluate complex object/array AST nodes to plain JS values\n const { evaluateDataValue } = await import('@interpreter/eval/data-value-evaluator');\n return await evaluateDataValue((variable as any).value, env);\n } else if (isPath(variable)) {\n return variable.value.resolvedPath;\n } else if (isPipelineInput(variable)) {\n // For pipeline inputs, return the whole PipelineInput object\n // so that pipeline functions can access .json, .csv, etc.\n return variable.value;\n } else if (isExecutableVariable(variable)) {\n /**\n * Auto-execute executables when extracting\n * WHY: In extraction contexts (like pipelines), @func without parentheses\n * means \"execute with piped input\". This enables the pattern:\n * \"text\" | @uppercase | @trim where executables act as transforms.\n */\n const { evaluateExecInvocation } = await import('../eval/exec-invocation');\n const invocation = {\n type: 'ExecInvocation',\n commandRef: {\n identifier: variable.name,\n args: []\n }\n };\n const result = await evaluateExecInvocation(invocation as any, env);\n return result.value;\n } else if (isImported(variable)) {\n return variable.value;\n } else if (isComputed(variable)) {\n return variable.value;\n }\n \n // Fallback\n return variable.value;\n}\n\n/**\n * Helper to check if a value is a Variable\n */\nexport function isVariable(value: unknown): value is Variable {\n return value !== null && \n typeof value === 'object' && \n 'type' in value && \n 'name' in value && \n 'value' in value &&\n 'source' in value;\n}\n\n/**\n * Resolve a value that might be a Variable or raw value\n * Uses context to determine whether to preserve or extract\n * \n * WHY: This is a convenience wrapper that handles both Variables and raw values,\n * making it easier to work with values that might or might not be wrapped.\n * \n * CONTEXT: Used throughout the interpreter where values could be either\n * Variables (from variable references) or raw values (from literals).\n * \n * @param value - Either a Variable or raw value\n * @param env - The environment for evaluation\n * @param context - The resolution context\n * @returns Either the Variable or extracted value based on context\n */\nexport async function resolveValue(\n value: Variable | VariableValue,\n env: Environment,\n context: ResolutionContext\n): Promise<Variable | VariableValue> {\n if (isVariable(value)) {\n return resolveVariable(value, env, context);\n }\n return value;\n}\n\n// Remove legacy aliases - use extractVariableValue or resolveVariable with context\n"]}