UNPKG

mlld

Version:

mlld: a modular prompt scripting language

1 lines 15.9 kB
{"version":3,"sources":["../interpreter/utils/variable-resolution.ts"],"names":["ResolutionContext","shouldPreserveVariable","context","resolveVariable","variable","env","isPipelineInput","value","isStructured","complexFlag","isComplex","evaluateDataValue","evaluatedValue","metadata","wasEvaluated","evaluatedAt","Date","now","isExecutableVariable","extractVariableValue","isPrimitive","isTextLike","type","arrayType","extractWithBehaviors","isPath","resolvedPath","evaluateExecInvocation","invocation","commandRef","identifier","name","args","result","isImported","isComputed","isVariable","resolveValue"],"mappings":"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","file":"chunk-7ASO6AZA.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';\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: TODO - Why preserve for field access?\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 * TODO: Why create new Variable instead of caching in the original?\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 // Create a new Variable with the evaluated value\n return {\n ...variable,\n value: evaluatedValue,\n metadata: {\n ...variable.metadata,\n wasEvaluated: true,\n evaluatedAt: Date.now()\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 return extractVariableValue(variable, env);\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 (LoadContentResultArray, RenamedContentArray)\n // WHY: Special array types have behaviors (toString, content getter) that must be preserved\n // during value extraction to maintain proper output formatting\n if (variable.type === 'array' && variable.metadata?.arrayType && \n (variable.metadata.arrayType === 'renamed-content' || \n variable.metadata.arrayType === 'load-content-result')) {\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 (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"]}