The assign operator '=' can now set items in ListType and DictType
This commit is contained in:
parent
f2d6d63017
commit
d96123ab02
@ -16,13 +16,93 @@ func newAssignTerm(tk *Token) (inst *term) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assignListItem(list *ListType, index int64, value any) (err error) {
|
||||||
|
return list.setItem(index, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func assignCollectionItem(ctx ExprContext, collectionTerm, keyListTerm *term, value any) (err error) {
|
||||||
|
var collectionValue, keyListValue, keyValue any
|
||||||
|
var keyList *ListType
|
||||||
|
var ok bool
|
||||||
|
|
||||||
|
if collectionValue, err = collectionTerm.compute(ctx); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if keyListValue, err = keyListTerm.compute(ctx); err != nil {
|
||||||
|
return
|
||||||
|
} else if keyList, ok = keyListValue.(*ListType); !ok || len(*keyList) != 1 {
|
||||||
|
err = keyListTerm.Errorf("index/key specification expected, got %v [%T]", keyListValue, keyListValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
keyValue = (*keyList)[0]
|
||||||
|
|
||||||
|
switch collection := collectionValue.(type) {
|
||||||
|
case *ListType:
|
||||||
|
if index, ok := keyValue.(int64); ok {
|
||||||
|
err = assignListItem(collection, index, value)
|
||||||
|
} else {
|
||||||
|
err = keyListTerm.Errorf("integer expected, got %v [%T]", keyValue, keyValue)
|
||||||
|
}
|
||||||
|
case *DictType:
|
||||||
|
collection.setItem(keyValue, value)
|
||||||
|
default:
|
||||||
|
err = collectionTerm.Errorf("collection expected")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func assignValue(ctx ExprContext, leftTerm *term, v any) (err error) {
|
||||||
|
if leftTerm.symbol() == SymIndex {
|
||||||
|
err = assignCollectionItem(ctx, leftTerm.children[0], leftTerm.children[1], v)
|
||||||
|
} else {
|
||||||
|
ctx.UnsafeSetVar(leftTerm.source(), v)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func _assignValue(ctx ExprContext, leftTerm *term, v any) (err error) {
|
||||||
|
if leftTerm.symbol() == SymIndex {
|
||||||
|
var collection, indexListAny any
|
||||||
|
var list *ListType
|
||||||
|
var index int64
|
||||||
|
if collection, err = leftTerm.children[0].compute(ctx); err != nil {
|
||||||
|
return
|
||||||
|
} else if IsList(collection) {
|
||||||
|
list, _ = collection.(*ListType)
|
||||||
|
} else {
|
||||||
|
err = leftTerm.children[0].Errorf("expected collection")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if indexListAny, err = leftTerm.children[1].compute(ctx); err != nil {
|
||||||
|
return
|
||||||
|
} else if indexList, ok := indexListAny.(*ListType); ok && len(*indexList) == 1 {
|
||||||
|
if indexAny := (*indexList)[0]; IsInteger(indexAny) {
|
||||||
|
index, _ = indexAny.(int64)
|
||||||
|
} else {
|
||||||
|
err = leftTerm.children[1].Errorf("expected integer, got %v [%T]", indexAny, indexAny)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = leftTerm.children[1].Errorf("expected index spec, got %v [%T]", indexListAny, indexListAny)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list.setItem(index, v)
|
||||||
|
} else {
|
||||||
|
ctx.UnsafeSetVar(leftTerm.source(), v)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func evalAssign(ctx ExprContext, self *term) (v any, err error) {
|
func evalAssign(ctx ExprContext, self *term) (v any, err error) {
|
||||||
if err = self.checkOperands(); err != nil {
|
if err = self.checkOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
leftTerm := self.children[0]
|
leftTerm := self.children[0]
|
||||||
if leftTerm.tk.Sym != SymVariable {
|
leftSym := leftTerm.symbol()
|
||||||
|
if leftSym != SymVariable && leftSym != SymIndex {
|
||||||
err = leftTerm.tk.Errorf("left operand of %q must be a variable", self.tk.source)
|
err = leftTerm.tk.Errorf("left operand of %q must be a variable", self.tk.source)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -49,6 +129,53 @@ func evalAssign(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func evalAssign(ctx ExprContext, self *term) (v any, err error) {
|
||||||
|
if err = self.checkOperands(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
leftTerm := self.children[0]
|
||||||
|
leftSym := leftTerm.symbol()
|
||||||
|
if leftSym != SymVariable && leftSym != SymIndex {
|
||||||
|
err = leftTerm.tk.Errorf("left operand of %q must be a variable", self.tk.source)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rightChild := self.children[1]
|
||||||
|
|
||||||
|
if v, err = rightChild.compute(ctx); err == nil {
|
||||||
|
if functor, ok := v.(Functor); ok {
|
||||||
|
if info := functor.GetFunc(); info != nil {
|
||||||
|
ctx.RegisterFunc(leftTerm.source(), info.Functor(), info.ReturnType(), info.Params())
|
||||||
|
} else if funcDef, ok := functor.(*exprFunctor); ok {
|
||||||
|
// paramSpecs := ForAll(funcDef.params, newFuncParam)
|
||||||
|
paramSpecs := ForAll(funcDef.params, func(p ExprFuncParam) ExprFuncParam { return p })
|
||||||
|
|
||||||
|
ctx.RegisterFunc(leftTerm.source(), functor, typeAny, paramSpecs)
|
||||||
|
/*
|
||||||
|
}
|
||||||
|
funcName := rightChild.source()
|
||||||
|
if info, exists, _ := GetFuncInfo(ctx, funcName); exists {
|
||||||
|
// ctx.RegisterFuncInfo(info)
|
||||||
|
ctx.RegisterFunc(leftTerm.source(), info.Functor(), info.ReturnType(), info.Params())
|
||||||
|
} else if funcDef, ok := functor.(*exprFunctor); ok {
|
||||||
|
// paramSpecs := ForAll(funcDef.params, newFuncParam)
|
||||||
|
paramSpecs := ForAll(funcDef.params, func(p ExprFuncParam) ExprFuncParam { return p })
|
||||||
|
|
||||||
|
ctx.RegisterFunc(leftTerm.source(), functor, typeAny, paramSpecs)
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
err = self.Errorf("unknown function %s()", rightChild.source())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = assignValue(ctx, leftTerm, v)
|
||||||
|
//ctx.UnsafeSetVar(leftTerm.source(), v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -52,7 +52,7 @@ func TestListParser(t *testing.T) {
|
|||||||
/* 30 */ {`2 >> 3;`, nil, errors.New(`[1:4] left operand '2' [integer] and right operand '3' [integer] are not compatible with operator ">>"`)},
|
/* 30 */ {`2 >> 3;`, nil, errors.New(`[1:4] left operand '2' [integer] and right operand '3' [integer] are not compatible with operator ">>"`)},
|
||||||
/* 31 */ {`a=[1,2]; a<<3`, []any{1, 2, 3}, nil},
|
/* 31 */ {`a=[1,2]; a<<3`, []any{1, 2, 3}, nil},
|
||||||
/* 33 */ {`a=[1,2]; 5>>a`, []any{5, 1, 2}, nil},
|
/* 33 */ {`a=[1,2]; 5>>a`, []any{5, 1, 2}, nil},
|
||||||
|
/* 34 */ {`L=[1,2]; L[0]=9; L`, newListA(int64(9),int64(2)), nil},
|
||||||
// /* 8 */ {`[int(x)|x=csv("test.csv",1,all(),1)]`, []any{int64(10), int64(40), int64(20)}, nil},
|
// /* 8 */ {`[int(x)|x=csv("test.csv",1,all(),1)]`, []any{int64(10), int64(40), int64(20)}, nil},
|
||||||
// /* 9 */ {`sum(@[int(x)|x=csv("test.csv",1,all(),1)])`, []any{int64(10), int64(40), int64(20)}, nil},
|
// /* 9 */ {`sum(@[int(x)|x=csv("test.csv",1,all(),1)])`, []any{int64(10), int64(40), int64(20)}, nil},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user