Skip to content

Commit 1a94a52

Browse files
authored
Cond eval (#139)
Fix cond condition evaluation
1 parent 51d8032 commit 1a94a52

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
44

55
The structure and content of this file follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

7+
## [1.19.3] - 2023-09-11
8+
### Fixed
9+
- asm cond condition is now evaluated correctly.
10+
711
## [1.19.2] - 2023-08-07
812
### Fixed
913
- The test tool (tt) package Panic() function should return the recovered panic and now does.

asm/cond.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ package asm
44

55
import (
66
"fmt"
7+
8+
"github.com/ohler55/ojg/jp"
79
)
810

911
func init() {
@@ -20,17 +22,54 @@ is returned.`,
2022

2123
func cond(root map[string]any, at any, args ...any) any {
2224
for _, arg := range args {
23-
v := evalArg(root, at, arg)
24-
list, ok := v.([]any)
25+
list, ok := arg.([]any)
2526
if !ok {
26-
panic(fmt.Errorf("cond expects array arguments, not a %T", v))
27+
panic(fmt.Errorf("cond expects array arguments, not a %T", arg))
2728
}
2829
if len(list) != 2 {
2930
panic(fmt.Errorf("cond array arguments must have two elements, not a %d", len(list)))
3031
}
31-
if b, _ := evalArg(root, at, list[0]).(bool); b {
32-
return list[1]
32+
if bv, _ := evalValue(root, at, list[0]).(bool); bv {
33+
return evalValue(root, at, list[1])
3334
}
3435
}
3536
return nil
3637
}
38+
39+
func evalValue(root map[string]any, at any, value any) (result any) {
40+
top:
41+
switch tv := value.(type) {
42+
case *Fn:
43+
result = tv.Eval(root, at, tv.Args...)
44+
case []any:
45+
if 0 < len(tv) {
46+
if name, _ := tv[0].(string); 0 < len(name) {
47+
if af := NewFn(name); af != nil {
48+
af.Args = tv[1:]
49+
af.compile()
50+
value = af
51+
goto top
52+
}
53+
}
54+
}
55+
case jp.Expr:
56+
if 0 < len(tv) {
57+
if _, ok := tv[0].(jp.At); ok {
58+
result = tv.First(at)
59+
} else {
60+
result = tv.First(root)
61+
}
62+
}
63+
case string:
64+
if 0 < len(tv) && (tv[0] == '$' || tv[0] == '@') {
65+
if x, err := jp.Parse([]byte(tv)); err == nil {
66+
value = x
67+
goto top
68+
}
69+
}
70+
result = tv
71+
default:
72+
result = value
73+
}
74+
return
75+
}

asm/cond_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,24 @@ func TestCondArgElementCount(t *testing.T) {
4848
err := p.Execute(map[string]any{})
4949
tt.NotNil(t, err)
5050
}
51+
52+
func TestCondEval(t *testing.T) {
53+
root := testPlan(t,
54+
`[
55+
[set $.asm.a [cond [[get "$.src.x[1]"] [get "@.src.x[0]"]]]]
56+
[set $.asm.b [cond ["$.src.x[1]" 2]]]
57+
[set $.asm.c [cond [@.src.y @.src.z]]]
58+
[set $.asm.d [cond [$.src.y abc]]]
59+
]`,
60+
"{src: {x: [1 true 3], y: true, z: 4}}",
61+
)
62+
opt := sopt
63+
opt.Indent = 2
64+
tt.Equal(t,
65+
`{
66+
a: 1
67+
b: 2
68+
c: 4
69+
d: abc
70+
}`, sen.String(root["asm"], &opt))
71+
}

0 commit comments

Comments
 (0)