expr/operator-coalesce.go

94 lines
2.2 KiB
Go
Raw Permalink Normal View History

2024-04-03 13:15:25 +02:00
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// operator-coalesce.go
package expr
//-------- null coalesce term
func newNullCoalesceTerm(tk *Token) (inst *term) {
return &term{
2024-04-09 05:32:50 +02:00
tk: *tk,
// class: classOperator,
// kind: kindUnknown,
2024-04-03 13:15:25 +02:00
children: make([]*term, 0, 2),
position: posInfix,
priority: priCoalesce,
evalFunc: evalNullCoalesce,
}
}
func evalNullCoalesce(ctx ExprContext, self *term) (v any, err error) {
2024-04-03 13:15:25 +02:00
var rightValue any
if err = self.checkOperands(); err != nil {
return
}
leftTerm := self.children[0]
if leftTerm.tk.Sym != SymIdentifier {
err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
return
}
if leftValue, exists := ctx.GetVar(leftTerm.source()); exists {
v = leftValue
} else if rightValue, err = self.children[1].compute(ctx); err == nil {
if _, ok := rightValue.(Functor); ok {
err = errCoalesceNoFunc(self.children[1])
} else {
v = rightValue
}
}
return
}
//-------- coalesce assign term
func newCoalesceAssignTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priCoalesce,
evalFunc: evalAssignCoalesce,
}
}
func evalAssignCoalesce(ctx ExprContext, self *term) (v any, err error) {
2024-04-03 13:15:25 +02:00
var rightValue any
if err = self.checkOperands(); err != nil {
return
}
leftTerm := self.children[0]
if leftTerm.tk.Sym != SymIdentifier {
err = leftTerm.Errorf("left operand of %q must be a variable", self.tk.source)
return
}
if leftValue, exists := ctx.GetVar(leftTerm.source()); exists {
v = leftValue
} else if rightValue, err = self.children[1].compute(ctx); err == nil {
if _, ok := rightValue.(Functor); ok {
err = errCoalesceNoFunc(self.children[1])
} else {
v = rightValue
ctx.setVar(leftTerm.source(), rightValue)
2024-04-03 13:15:25 +02:00
}
}
return
}
// utils
func errCoalesceNoFunc(t *term) error {
return t.Errorf("the right operand of a coalescing operation cannot be a function definition")
}
// init
func init() {
registerTermConstructor(SymDoubleQuestion, newNullCoalesceTerm)
registerTermConstructor(SymQuestionEqual, newCoalesceAssignTerm)
}