Skip to content

Commit 4b01497

Browse files
committed
Fix interpreter/binary parity for dict extraction and SSE test timeouts
ExtractAction now extracts from pre-parsed dictionaries using result specifiers, fixing [object Object] in interpreter mode when the HTTP body is already parsed. SSE example test hints corrected from invalid type:keepalive to proper keep-alive:true with 8s timeout.
1 parent 29efd4a commit 4b01497

File tree

7 files changed

+49
-12
lines changed

7 files changed

+49
-12
lines changed

Examples/SQLiteExample/plugins/SQLitePlugin/Package.resolved

Lines changed: 0 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Examples/SSEClient/test.hint

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Test hints for SSEClient
22
# Connects to a live SSE stream; verifies startup output.
3-
type: keepalive
3+
type: console
4+
keep-alive: true
5+
timeout: 8
46
allow-error: true
57
occurrence-check: true

Examples/SSEStreamDemo/test.hint

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Test hints for SSEStreamDemo
22
# This example connects to a live SSE stream; output is non-deterministic.
33
# We only verify that the application starts and connects successfully.
4-
# The test times out after 8 seconds (SSE streams are persistent).
5-
type: keepalive
4+
type: console
5+
keep-alive: true
6+
timeout: 8
67
allow-error: true
78
occurrence-check: true

Sources/AROParser/AST.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,23 @@ public enum BinaryOperator: String, Sendable, CaseIterable {
11471147
// Collection
11481148
case contains = "contains"
11491149
case matches = "matches"
1150+
1151+
/// True for comparison/equality operators (==, !=, <, >, <=, >=, is, is not, contains, matches)
1152+
public var isComparison: Bool {
1153+
switch self {
1154+
case .equal, .notEqual, .lessThan, .greaterThan,
1155+
.lessEqual, .greaterEqual, .is, .isNot,
1156+
.contains, .matches:
1157+
return true
1158+
default:
1159+
return false
1160+
}
1161+
}
1162+
1163+
/// True for logical connectives (and, or)
1164+
public var isLogical: Bool {
1165+
self == .and || self == .or
1166+
}
11501167
}
11511168

11521169
/// Unary operators

Sources/AROParser/Parser.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,20 @@ extension Parser {
18191819
let right = try parsePrecedence(precedence)
18201820
let span = left.span.merged(with: right.span)
18211821

1822+
// Short-hand logical: `<x> = "a" or "b"` → `<x> = "a" or <x> = "b"`
1823+
// When `or`/`and` joins a comparison on the left with a bare value on the right,
1824+
// distribute the left-hand comparison's subject and operator to the right side.
1825+
if (actualOp == .or || actualOp == .and),
1826+
let leftBin = left as? BinaryExpression,
1827+
leftBin.op.isComparison,
1828+
!((right as? BinaryExpression)?.op.isComparison ?? false),
1829+
!((right as? BinaryExpression)?.op.isLogical ?? false) {
1830+
let expandedRight = BinaryExpression(
1831+
left: leftBin.left, op: leftBin.op, right: right, span: right.span
1832+
)
1833+
return BinaryExpression(left: left, op: actualOp, right: expandedRight, span: span)
1834+
}
1835+
18221836
return BinaryExpression(left: left, op: actualOp, right: right, span: span)
18231837
}
18241838
}

Sources/ARORuntime/Actions/BuiltIn/ExtractAction.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,15 @@ public struct ExtractAction: SynchronousAction {
112112
return extracted
113113
}
114114

115+
// Extract from dictionary using result specifier as key
116+
// Example: <Extract> the <message-text: message> from the <body>.
117+
// When body is already a parsed dictionary, uses "message" as key
118+
if let specifier = result.specifiers.first,
119+
let dict = resolvedSource as? [String: any Sendable],
120+
let value = dict[specifier] {
121+
return value
122+
}
123+
115124
// Use result specifier to extract from string (form data, JSON, etc.)
116125
// Example: <Extract> the <message-text: message> from the <body>.
117126
// Uses "message" as the key to extract from body string

Sources/ARORuntime/Core/ExecutionEngine.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,9 @@ public actor ExecutionEngine {
13101310
let eventData: [String: any Sendable] = ["key": event.key]
13111311
context.bind("event", value: eventData)
13121312
context.bind("event:key", value: event.key)
1313+
// Also bind plain "key" so `where <key> = "down"` works
1314+
// (consistent with binary mode which binds all payload keys)
1315+
context.bind("key", value: event.key)
13131316
}
13141317
}
13151318

0 commit comments

Comments
 (0)