@o-lang/olang 1.0.11 → 1.0.13

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/parser.js +71 -36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o-lang/olang",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "author": "Olalekan Ogundipe <info@workfily.com>",
5
5
  "description": "O-Lang: A governance language for user-directed, rule-enforced agent workflows",
6
6
  "main": "./src/index.js",
package/src/parser.js CHANGED
@@ -1,7 +1,6 @@
1
1
  // src/parser.js
2
2
 
3
3
  function parse(code, fileName = null) {
4
- // --- Enforce .ol extension if filename provided ---
5
4
  if (fileName && !fileName.endsWith(".ol")) {
6
5
  throw new Error(`Expected .ol workflow, got: ${fileName}`);
7
6
  }
@@ -19,7 +18,6 @@ function parse(code, fileName = null) {
19
18
  returnValues: [],
20
19
  allowedResolvers: [],
21
20
 
22
- // --- NEW: formal resolver policy ---
23
21
  resolverPolicy: {
24
22
  declared: [],
25
23
  autoInjected: [],
@@ -27,10 +25,7 @@ function parse(code, fileName = null) {
27
25
  warnings: []
28
26
  },
29
27
 
30
- // --- NEW: parser warnings (non-fatal) ---
31
28
  __warnings: [],
32
-
33
- // --- NEW: feature detection flags ---
34
29
  __requiresMath: false
35
30
  };
36
31
 
@@ -39,9 +34,6 @@ function parse(code, fileName = null) {
39
34
  while (i < lines.length) {
40
35
  let line = lines[i];
41
36
 
42
- // ---------------------------
43
- // Resolver policy declaration
44
- // ---------------------------
45
37
  const allowMatch = line.match(/^Allow resolvers\s*:\s*$/i);
46
38
  if (allowMatch) {
47
39
  i++;
@@ -56,9 +48,6 @@ function parse(code, fileName = null) {
56
48
  continue;
57
49
  }
58
50
 
59
- // ============================
60
- // Math operations (detected)
61
- // ============================
62
51
  let mathAdd = line.match(/^Add\s+\{(.+?)\}\s+and\s+\{(.+?)\}\s+Save as\s+(.+)$/i);
63
52
  if (mathAdd) {
64
53
  workflow.__requiresMath = true;
@@ -107,9 +96,6 @@ function parse(code, fileName = null) {
107
96
  continue;
108
97
  }
109
98
 
110
- // ---------------------------
111
- // Workflow definition
112
- // ---------------------------
113
99
  const wfMatch = line.match(/^Workflow\s+"([^"]+)"(?:\s+with\s+(.+))?/i);
114
100
  if (wfMatch) {
115
101
  workflow.name = wfMatch[1];
@@ -120,25 +106,82 @@ function parse(code, fileName = null) {
120
106
  continue;
121
107
  }
122
108
 
109
+ // ---------------------------
110
+ // Return statement (updated: auto-detect math)
111
+ // ---------------------------
112
+ const returnMatch = line.match(/^Return\s+(.+)$/i);
113
+ if (returnMatch) {
114
+ const returns = returnMatch[1].split(',').map(v => v.trim());
115
+ workflow.returnValues = returns;
116
+
117
+ // --- Check if any return vars come from math steps ---
118
+ for (const retVar of returns) {
119
+ const producedByMath = workflow.steps.some(
120
+ s => s.saveAs === retVar && s.type === 'calculate'
121
+ );
122
+ if (producedByMath) workflow.__requiresMath = true;
123
+ }
124
+
125
+ i++;
126
+ continue;
127
+ }
128
+
129
+
123
130
  // ---------------------------
124
- // Steps
125
- // ---------------------------
126
- const stepMatch = line.match(/^Step\s+(\d+)\s*:\s*(.+)$/i);
127
- if (stepMatch) {
128
- workflow.steps.push({
129
- type: 'action',
130
- stepNumber: parseInt(stepMatch[1], 10),
131
- actionRaw: stepMatch[2].trim(),
132
- saveAs: null,
133
- constraints: {}
134
- });
135
- i++;
136
- continue;
131
+ // Steps (updated: auto-detect math + saveAs)
132
+ // ---------------------------
133
+ const stepMatch = line.match(/^Step\s+(\d+)\s*:\s*(.+)$/i);
134
+ if (stepMatch) {
135
+ const stepNum = parseInt(stepMatch[1], 10);
136
+ const raw = stepMatch[2].trim();
137
+
138
+ // --- Detect math inside Step ---
139
+ let mathDetected = null;
140
+ let expr = '';
141
+ let saveVar = null;
142
+
143
+ const mathOps = [
144
+ { re: /^Add\s+\{(.+?)\}\s+and\s+\{(.+?)\}\s+Save as\s+(.+)$/i, fn: 'add' },
145
+ { re: /^Subtract\s+\{(.+?)\}\s+from\s+\{(.+?)\}\s+Save as\s+(.+)$/i, fn: 'subtract' },
146
+ { re: /^Multiply\s+\{(.+?)\}\s+and\s+\{(.+?)\}\s+Save as\s+(.+)$/i, fn: 'multiply' },
147
+ { re: /^Divide\s+\{(.+?)\}\s+by\s+\{(.+?)\}\s+Save as\s+(.+)$/i, fn: 'divide' }
148
+ ];
149
+
150
+ for (const op of mathOps) {
151
+ const m = raw.match(op.re);
152
+ if (m) {
153
+ mathDetected = op.fn;
154
+ saveVar = m[3].trim();
155
+ if (op.fn === 'subtract') expr = `subtract({${m[2]}}, {${m[1]}})`;
156
+ else expr = `${op.fn}({${m[1]}}, {${m[2]}})`;
157
+ break;
137
158
  }
159
+ }
160
+
161
+ if (mathDetected) workflow.__requiresMath = true;
162
+
163
+ workflow.steps.push({
164
+ type: mathDetected ? 'calculate' : 'action',
165
+ stepNumber: stepNum,
166
+ actionRaw: mathDetected ? null : raw,
167
+ expression: mathDetected ? expr : undefined,
168
+ saveAs: saveVar,
169
+ constraints: {}
170
+ });
171
+
172
+ i++;
173
+ continue;
174
+ }
138
175
 
139
176
  const saveMatch = line.match(/^Save as\s+(.+)$/i);
140
177
  if (saveMatch && workflow.steps.length > 0) {
141
- workflow.steps[workflow.steps.length - 1].saveAs = saveMatch[1].trim();
178
+ const lastStep = workflow.steps[workflow.steps.length - 1];
179
+ lastStep.saveAs = saveMatch[1].trim();
180
+
181
+ if (lastStep.saveAs.match(/[A-Z][A-Za-z0-9_]*/)) {
182
+ workflow.__requiresMath = true;
183
+ }
184
+
142
185
  i++;
143
186
  continue;
144
187
  }
@@ -169,26 +212,18 @@ function parse(code, fileName = null) {
169
212
  continue;
170
213
  }
171
214
 
172
- // ---------------------------
173
- // (ALL remaining blocks unchanged)
174
- // If, Parallel, Connect, Agent, Debrief, Evolve,
175
- // Prompt, Persist, Emit, Return, Use, Ask
176
- // ---------------------------
177
-
178
215
  i++;
179
216
  }
180
217
 
181
218
  // ============================
182
219
  // LINT & POLICY FINALIZATION
183
220
  // ============================
184
-
185
221
  if (workflow.__requiresMath) {
186
222
  workflow.resolverPolicy.used.push('builtInMathResolver');
187
223
 
188
224
  if (!workflow.resolverPolicy.declared.includes('builtInMathResolver')) {
189
225
  workflow.resolverPolicy.autoInjected.push('builtInMathResolver');
190
226
  workflow.allowedResolvers.unshift('builtInMathResolver');
191
-
192
227
  workflow.__warnings.push(
193
228
  'Math operations detected. builtInMathResolver auto-injected.'
194
229
  );