diff --git a/CHANGELOG.md b/CHANGELOG.md index b2b0a450..e9e52431 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm The structure and content of this file follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [1.19.3] - 2023-09-11 +### Fixed +- asm cond condition is now evaluated correctly. + ## [1.19.2] - 2023-08-07 ### Fixed - The test tool (tt) package Panic() function should return the recovered panic and now does. diff --git a/asm/cond.go b/asm/cond.go index 3446b7ea..edd7c566 100644 --- a/asm/cond.go +++ b/asm/cond.go @@ -4,6 +4,8 @@ package asm import ( "fmt" + + "github.com/ohler55/ojg/jp" ) func init() { @@ -20,17 +22,54 @@ is returned.`, func cond(root map[string]any, at any, args ...any) any { for _, arg := range args { - v := evalArg(root, at, arg) - list, ok := v.([]any) + list, ok := arg.([]any) if !ok { - panic(fmt.Errorf("cond expects array arguments, not a %T", v)) + panic(fmt.Errorf("cond expects array arguments, not a %T", arg)) } if len(list) != 2 { panic(fmt.Errorf("cond array arguments must have two elements, not a %d", len(list))) } - if b, _ := evalArg(root, at, list[0]).(bool); b { - return list[1] + if bv, _ := evalValue(root, at, list[0]).(bool); bv { + return evalValue(root, at, list[1]) } } return nil } + +func evalValue(root map[string]any, at any, value any) (result any) { +top: + switch tv := value.(type) { + case *Fn: + result = tv.Eval(root, at, tv.Args...) + case []any: + if 0 < len(tv) { + if name, _ := tv[0].(string); 0 < len(name) { + if af := NewFn(name); af != nil { + af.Args = tv[1:] + af.compile() + value = af + goto top + } + } + } + case jp.Expr: + if 0 < len(tv) { + if _, ok := tv[0].(jp.At); ok { + result = tv.First(at) + } else { + result = tv.First(root) + } + } + case string: + if 0 < len(tv) && (tv[0] == '$' || tv[0] == '@') { + if x, err := jp.Parse([]byte(tv)); err == nil { + value = x + goto top + } + } + result = tv + default: + result = value + } + return +} diff --git a/asm/cond_test.go b/asm/cond_test.go index 6abb6fdc..9667e3e0 100644 --- a/asm/cond_test.go +++ b/asm/cond_test.go @@ -48,3 +48,24 @@ func TestCondArgElementCount(t *testing.T) { err := p.Execute(map[string]any{}) tt.NotNil(t, err) } + +func TestCondEval(t *testing.T) { + root := testPlan(t, + `[ + [set $.asm.a [cond [[get "$.src.x[1]"] [get "@.src.x[0]"]]]] + [set $.asm.b [cond ["$.src.x[1]" 2]]] + [set $.asm.c [cond [@.src.y @.src.z]]] + [set $.asm.d [cond [$.src.y abc]]] + ]`, + "{src: {x: [1 true 3], y: true, z: 4}}", + ) + opt := sopt + opt.Indent = 2 + tt.Equal(t, + `{ + a: 1 + b: 2 + c: 4 + d: abc +}`, sen.String(root["asm"], &opt)) +}