@atomic-ehr/fhirpath 0.0.1-canary.0c6931e.20250727185306

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +473 -0
  2. package/dist/index.d.ts +462 -0
  3. package/dist/index.js +10307 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +58 -0
  6. package/src/analyzer/analyzer.ts +499 -0
  7. package/src/analyzer/model-provider.ts +244 -0
  8. package/src/analyzer/schemas/index.ts +2 -0
  9. package/src/analyzer/schemas/types.ts +40 -0
  10. package/src/analyzer/types.ts +142 -0
  11. package/src/api/builder.ts +157 -0
  12. package/src/api/errors.ts +145 -0
  13. package/src/api/expression.ts +156 -0
  14. package/src/api/index.ts +122 -0
  15. package/src/api/inspect.ts +99 -0
  16. package/src/api/registry.ts +128 -0
  17. package/src/api/types.ts +210 -0
  18. package/src/compiler/compiler.ts +546 -0
  19. package/src/compiler/index.ts +2 -0
  20. package/src/compiler/prototype-context-adapter.ts +99 -0
  21. package/src/compiler/types.ts +24 -0
  22. package/src/index.ts +107 -0
  23. package/src/interpreter/README.md +78 -0
  24. package/src/interpreter/interpreter.ts +475 -0
  25. package/src/interpreter/types.ts +108 -0
  26. package/src/lexer/char-tables.ts +37 -0
  27. package/src/lexer/errors.ts +31 -0
  28. package/src/lexer/index.ts +5 -0
  29. package/src/lexer/lexer.ts +745 -0
  30. package/src/lexer/token.ts +104 -0
  31. package/src/lexer2/index.md +232 -0
  32. package/src/lexer2/index.perf.test.ts +68 -0
  33. package/src/lexer2/index.test.ts +549 -0
  34. package/src/lexer2/index.ts +1251 -0
  35. package/src/lexer2/notes.md +173 -0
  36. package/src/lexer2/optimization-summary.md +718 -0
  37. package/src/parser/ast-factory.ts +220 -0
  38. package/src/parser/ast.ts +144 -0
  39. package/src/parser/collection-parser.ts +89 -0
  40. package/src/parser/diagnostic-messages.ts +216 -0
  41. package/src/parser/diagnostics.ts +85 -0
  42. package/src/parser/error-reporter.ts +230 -0
  43. package/src/parser/index.ts +3 -0
  44. package/src/parser/literal-parser.ts +103 -0
  45. package/src/parser/parse-error.ts +16 -0
  46. package/src/parser/parser-error-factory.ts +141 -0
  47. package/src/parser/parser-state.ts +134 -0
  48. package/src/parser/parser.ts +1272 -0
  49. package/src/parser/pprint.ts +169 -0
  50. package/src/parser/precedence-manager.ts +64 -0
  51. package/src/parser/source-mapper.ts +248 -0
  52. package/src/parser/special-constructs.ts +142 -0
  53. package/src/parser/token-navigator.ts +110 -0
  54. package/src/parser/types.ts +60 -0
  55. package/src/parser2/index.md +177 -0
  56. package/src/parser2/index.perf.test.ts +184 -0
  57. package/src/parser2/index.test.ts +305 -0
  58. package/src/parser2/index.ts +578 -0
  59. package/src/parser2/optimization-summary.md +176 -0
  60. package/src/registry/default-analyzers.ts +257 -0
  61. package/src/registry/default-compilers.ts +31 -0
  62. package/src/registry/index.ts +96 -0
  63. package/src/registry/operations/arithmetic.ts +506 -0
  64. package/src/registry/operations/collection.ts +425 -0
  65. package/src/registry/operations/comparison.ts +432 -0
  66. package/src/registry/operations/existence.ts +703 -0
  67. package/src/registry/operations/filtering.ts +358 -0
  68. package/src/registry/operations/literals.ts +341 -0
  69. package/src/registry/operations/logical.ts +439 -0
  70. package/src/registry/operations/math.ts +128 -0
  71. package/src/registry/operations/membership.ts +132 -0
  72. package/src/registry/operations/navigation.ts +52 -0
  73. package/src/registry/operations/string.ts +507 -0
  74. package/src/registry/operations/subsetting.ts +174 -0
  75. package/src/registry/operations/type-checking.ts +162 -0
  76. package/src/registry/operations/type-conversion.ts +404 -0
  77. package/src/registry/operations/type-operators.ts +308 -0
  78. package/src/registry/operations/utility.ts +644 -0
  79. package/src/registry/registry.ts +146 -0
  80. package/src/registry/types.ts +161 -0
  81. package/src/registry/utils/evaluation-helpers.ts +93 -0
  82. package/src/registry/utils/index.ts +3 -0
  83. package/src/registry/utils/type-system.ts +173 -0
  84. package/src/runtime/context.ts +158 -0
  85. package/src/runtime/debug-context.ts +135 -0
@@ -0,0 +1,158 @@
1
+
2
+ /**
3
+ * Unified runtime context that works with both interpreter and compiler.
4
+ * Uses prototype-based inheritance for efficient context copying.
5
+ *
6
+ * Variable Storage Convention:
7
+ * - Special variables: $this, $index, $total (prefixed with $)
8
+ * - Environment variables: %context, %resource, %rootResource (stored with % prefix)
9
+ * - User-defined variables: stored with % prefix (e.g., %x, %y)
10
+ */
11
+ export interface RuntimeContext {
12
+ input: any[];
13
+ focus: any[];
14
+ variables: Record<string, any>;
15
+ }
16
+
17
+ /**
18
+ * Runtime context manager that provides efficient prototype-based context operations
19
+ * for both interpreter and compiler.
20
+ */
21
+ export class RuntimeContextManager {
22
+ /**
23
+ * Create a new runtime context
24
+ */
25
+ static create(input: any[], initialVariables?: Record<string, any>): RuntimeContext {
26
+ const context = Object.create(null) as RuntimeContext;
27
+
28
+ context.input = input;
29
+ context.focus = input;
30
+
31
+ // Create variables object with null prototype to avoid pollution
32
+ context.variables = Object.create(null);
33
+
34
+ // Set root context variables with % prefix
35
+ context.variables['%context'] = input;
36
+ context.variables['%resource'] = input;
37
+ context.variables['%rootResource'] = input;
38
+
39
+ // Add any initial variables (with % prefix for user-defined)
40
+ if (initialVariables) {
41
+ for (const [key, value] of Object.entries(initialVariables)) {
42
+ // Add % prefix if not already present and not a special variable
43
+ const varKey = key.startsWith('$') || key.startsWith('%') ? key : `%${key}`;
44
+ context.variables[varKey] = value;
45
+ }
46
+ }
47
+
48
+ return context;
49
+ }
50
+
51
+ /**
52
+ * Create a child context using prototype inheritance
53
+ * O(1) operation - no copying needed
54
+ */
55
+ static copy(context: RuntimeContext): RuntimeContext {
56
+ // Create child context with parent as prototype
57
+ const newContext = Object.create(context) as RuntimeContext;
58
+
59
+ // Create child variables that inherit from parent's variables
60
+ newContext.variables = Object.create(context.variables);
61
+
62
+ // input and focus are inherited through prototype chain
63
+ // Only set them if they need to change
64
+
65
+ return newContext;
66
+ }
67
+
68
+ /**
69
+ * Create a new context with updated input/focus
70
+ */
71
+ static withInput(context: RuntimeContext, input: any[], focus?: any[]): RuntimeContext {
72
+ const newContext = this.copy(context);
73
+ newContext.input = input;
74
+ newContext.focus = focus ?? input;
75
+ return newContext;
76
+ }
77
+
78
+ /**
79
+ * Set special variable ($this, $index, $total)
80
+ */
81
+ static setSpecialVariable(context: RuntimeContext, name: string, value: any): RuntimeContext {
82
+ const newContext = this.copy(context);
83
+ const varKey = `$${name}`;
84
+ newContext.variables[varKey] = value;
85
+
86
+ // Update input/focus for $this
87
+ if (name === 'this' && Array.isArray(value) && value.length === 1) {
88
+ newContext.input = value;
89
+ newContext.focus = value;
90
+ }
91
+
92
+ return newContext;
93
+ }
94
+
95
+ /**
96
+ * Set iterator context ($this, $index)
97
+ */
98
+ static withIterator(
99
+ context: RuntimeContext,
100
+ item: any,
101
+ index: number
102
+ ): RuntimeContext {
103
+ let newContext = this.setSpecialVariable(context, 'this', [item]);
104
+ newContext = this.setSpecialVariable(newContext, 'index', index);
105
+ return newContext;
106
+ }
107
+
108
+ /**
109
+ * Set a user-defined variable in the context
110
+ */
111
+ static setVariable(context: RuntimeContext, name: string, value: any[], allowRedefinition: boolean = false): RuntimeContext {
112
+ // Check for system variables
113
+ const systemVariables = ['context', 'resource', 'rootResource', 'ucum', 'sct', 'loinc'];
114
+ if (systemVariables.includes(name)) {
115
+ // Silently return original context for system variable redefinition
116
+ return context;
117
+ }
118
+
119
+ // Add % prefix for user-defined variables
120
+ const varKey = name.startsWith('%') ? name : `%${name}`;
121
+
122
+ // Check if variable already exists (unless redefinition is allowed)
123
+ if (!allowRedefinition && context.variables && Object.prototype.hasOwnProperty.call(context.variables, varKey)) {
124
+ // Silently return original context for variable redefinition
125
+ return context;
126
+ }
127
+
128
+ const newContext = this.copy(context);
129
+ newContext.variables[varKey] = value;
130
+ return newContext;
131
+ }
132
+
133
+ /**
134
+ * Get a variable from context
135
+ */
136
+ static getVariable(context: RuntimeContext, name: string): any | undefined {
137
+ // Handle special cases
138
+ if (name === '$this' || name === '$index' || name === '$total') {
139
+ return context.variables[name];
140
+ }
141
+
142
+ // Handle environment variables (with or without % prefix)
143
+ if (name === 'context' || name === '%context') {
144
+ return context.variables['%context'];
145
+ }
146
+ if (name === 'resource' || name === '%resource') {
147
+ return context.variables['%resource'];
148
+ }
149
+ if (name === 'rootResource' || name === '%rootResource') {
150
+ return context.variables['%rootResource'];
151
+ }
152
+
153
+ // Handle user-defined variables (add % prefix if not present)
154
+ const varKey = name.startsWith('%') ? name : `%${name}`;
155
+ return context.variables[varKey];
156
+ }
157
+
158
+ }
@@ -0,0 +1,135 @@
1
+ import type { RuntimeContext } from './context';
2
+ import type { TraceEntry, EvaluationStep, InspectOptions } from '../api/types';
3
+
4
+ /**
5
+ * Debug-enabled runtime context that extends RuntimeContext
6
+ * with debugging capabilities for inspect() function
7
+ */
8
+ export interface DebugRuntimeContext extends RuntimeContext {
9
+ debugMode: true;
10
+ traces: TraceEntry[];
11
+ steps?: EvaluationStep[];
12
+ startTime: number;
13
+ callStack: CallStackEntry[];
14
+ inspectOptions?: InspectOptions;
15
+ }
16
+
17
+ interface CallStackEntry {
18
+ expression: string;
19
+ nodeType: string;
20
+ timestamp: number;
21
+ }
22
+
23
+ /**
24
+ * Check if a context is a debug context
25
+ */
26
+ export function isDebugContext(context: RuntimeContext): context is DebugRuntimeContext {
27
+ return 'debugMode' in context && context.debugMode === true;
28
+ }
29
+
30
+ /**
31
+ * Create a debug context from a regular context
32
+ */
33
+ export function createDebugContext(
34
+ context: RuntimeContext,
35
+ options?: InspectOptions
36
+ ): DebugRuntimeContext {
37
+ const debugContext = Object.create(context) as DebugRuntimeContext;
38
+ debugContext.debugMode = true;
39
+ debugContext.traces = [];
40
+ debugContext.startTime = performance.now();
41
+ debugContext.callStack = [];
42
+ debugContext.inspectOptions = options;
43
+
44
+ if (options?.recordSteps) {
45
+ debugContext.steps = [];
46
+ }
47
+
48
+ return debugContext;
49
+ }
50
+
51
+ /**
52
+ * Add a trace entry to the debug context
53
+ */
54
+ export function addTrace(
55
+ context: DebugRuntimeContext,
56
+ name: string,
57
+ values: any[]
58
+ ): void {
59
+ // Check trace limit
60
+ if (context.inspectOptions?.maxTraces &&
61
+ context.traces.length >= context.inspectOptions.maxTraces) {
62
+ return;
63
+ }
64
+
65
+ const trace: TraceEntry = {
66
+ name,
67
+ values,
68
+ timestamp: performance.now() - context.startTime,
69
+ depth: context.callStack.length
70
+ };
71
+
72
+ context.traces.push(trace);
73
+ }
74
+
75
+ /**
76
+ * Record an evaluation step
77
+ */
78
+ export function recordStep(
79
+ context: DebugRuntimeContext,
80
+ nodeType: string,
81
+ expression: string,
82
+ input: any[],
83
+ output: any[]
84
+ ): void {
85
+ if (!context.steps) return;
86
+
87
+ // Check step limit
88
+ if (context.inspectOptions?.maxSteps &&
89
+ context.steps.length >= context.inspectOptions.maxSteps) {
90
+ return;
91
+ }
92
+
93
+ const stepStart = performance.now();
94
+
95
+ const step: EvaluationStep = {
96
+ nodeType,
97
+ expression,
98
+ input,
99
+ output,
100
+ variables: { ...context.variables }, // Snapshot current variables
101
+ timestamp: stepStart - context.startTime,
102
+ duration: 0 // Will be calculated when step completes
103
+ };
104
+
105
+ context.steps.push(step);
106
+ }
107
+
108
+ /**
109
+ * Push an entry onto the call stack
110
+ */
111
+ export function pushCallStack(
112
+ context: DebugRuntimeContext,
113
+ expression: string,
114
+ nodeType: string
115
+ ): void {
116
+ context.callStack.push({
117
+ expression,
118
+ nodeType,
119
+ timestamp: performance.now() - context.startTime
120
+ });
121
+ }
122
+
123
+ /**
124
+ * Pop an entry from the call stack
125
+ */
126
+ export function popCallStack(context: DebugRuntimeContext): void {
127
+ context.callStack.pop();
128
+ }
129
+
130
+ /**
131
+ * Get the current call stack depth
132
+ */
133
+ export function getCallDepth(context: DebugRuntimeContext): number {
134
+ return context.callStack.length;
135
+ }