expr/operator-assign.go

102 lines
2.7 KiB
Go
Raw Normal View History

// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserightChilded.
// operator-assign.go
package expr
//-------- assign term
func newAssignTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priAssign,
evalFunc: evalAssign,
}
}
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 [%s]", keyListValue, TypeName(keyListValue))
return
}
2024-06-05 05:53:02 +02:00
if keyValue = (*keyList)[0]; keyValue == nil {
err = keyListTerm.Errorf("index/key is nil")
return
}
switch collection := collectionValue.(type) {
case *ListType:
if index, ok := keyValue.(int64); ok {
2024-06-05 05:53:02 +02:00
err = collection.setItem(index, value)
} else {
err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, TypeName(keyValue))
}
case *DictType:
2024-06-05 05:53:02 +02:00
err = 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 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 {
2024-06-05 05:53:02 +02:00
err = leftTerm.tk.Errorf("left operand of %q must be a variable or a collection's item", 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, 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)
}
}
if err != nil {
2024-06-05 05:53:02 +02:00
v = nil
}
return
}
// init
func init() {
registerTermConstructor(SymEqual, newAssignTerm)
}