moved a subset of source file to the kern package
This commit is contained in:
@@ -6,6 +6,8 @@ package expr
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.portale-stac.it/go-pkg/expr/kern"
|
||||
)
|
||||
|
||||
type termPriority uint32
|
||||
@@ -49,7 +51,7 @@ const (
|
||||
posMultifix
|
||||
)
|
||||
|
||||
type evalFuncType func(ctx ExprContext, self *term) (v any, err error)
|
||||
type evalFuncType func(ctx kern.ExprContext, self *term) (v any, err error)
|
||||
|
||||
type term struct {
|
||||
tk Token
|
||||
@@ -60,40 +62,40 @@ type term struct {
|
||||
evalFunc evalFuncType
|
||||
}
|
||||
|
||||
func (s *term) Clone() (d *term) {
|
||||
func (t *term) Clone() (d *term) {
|
||||
var children []*term
|
||||
if s.children != nil {
|
||||
children = make([]*term, len(s.children))
|
||||
for i, c := range s.children {
|
||||
if t.children != nil {
|
||||
children = make([]*term, len(t.children))
|
||||
for i, c := range t.children {
|
||||
children[i] = c.Clone()
|
||||
}
|
||||
}
|
||||
d = &term{
|
||||
tk: *s.tk.Clone(),
|
||||
parent: s.parent,
|
||||
tk: *t.tk.Clone(),
|
||||
parent: t.parent,
|
||||
children: children,
|
||||
position: s.position,
|
||||
priority: s.priority,
|
||||
evalFunc: s.evalFunc,
|
||||
position: t.position,
|
||||
priority: t.priority,
|
||||
evalFunc: t.evalFunc,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (term *term) String() string {
|
||||
func (t *term) String() string {
|
||||
var sb strings.Builder
|
||||
term.toString(&sb)
|
||||
t.toString(&sb)
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (term *term) toString(sb *strings.Builder) {
|
||||
if term.position == posLeaf {
|
||||
sb.WriteString(term.tk.String())
|
||||
func (t *term) toString(sb *strings.Builder) {
|
||||
if t.position == posLeaf {
|
||||
sb.WriteString(t.tk.String())
|
||||
} else {
|
||||
sb.WriteByte('[')
|
||||
sb.WriteString(term.tk.String())
|
||||
if term.children != nil {
|
||||
sb.WriteString(t.tk.String())
|
||||
if t.children != nil {
|
||||
sb.WriteByte('(')
|
||||
for i, c := range term.children {
|
||||
for i, c := range t.children {
|
||||
if i > 0 {
|
||||
sb.WriteByte(' ')
|
||||
}
|
||||
@@ -105,17 +107,17 @@ func (term *term) toString(sb *strings.Builder) {
|
||||
}
|
||||
}
|
||||
|
||||
func (term *term) getChildrenCount() (count int) {
|
||||
if term.position == posLeaf || term.children == nil {
|
||||
func (t *term) GetChildCount() (count int) {
|
||||
if t.position == posLeaf || t.children == nil {
|
||||
count = 0
|
||||
} else {
|
||||
count = len(term.children)
|
||||
count = len(t.children)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (term *term) getRoom() (room int) {
|
||||
switch term.position {
|
||||
func (t *term) getRoom() (room int) {
|
||||
switch t.position {
|
||||
case posLeaf:
|
||||
room = 0
|
||||
case posInfix:
|
||||
@@ -128,52 +130,70 @@ func (term *term) getRoom() (room int) {
|
||||
return
|
||||
}
|
||||
|
||||
func (term *term) isComplete() bool {
|
||||
return term.getChildrenCount() == term.getRoom()
|
||||
func (t *term) isComplete() bool {
|
||||
return t.GetChildCount() == t.getRoom()
|
||||
}
|
||||
|
||||
func (term *term) removeLastChild() (child *term) {
|
||||
if term.children != nil {
|
||||
child = term.children[len(term.children)-1]
|
||||
term.children = term.children[0 : len(term.children)-1]
|
||||
func (t *term) removeLastChild() (child *term) {
|
||||
if t.children != nil {
|
||||
child = t.children[len(t.children)-1]
|
||||
t.children = t.children[0 : len(t.children)-1]
|
||||
} else {
|
||||
panic("Can't get last child")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (term *term) isLeaf() bool {
|
||||
return term.position == posLeaf
|
||||
func (t *term) isLeaf() bool {
|
||||
return t.position == posLeaf
|
||||
}
|
||||
|
||||
func (term *term) getPriority() termPriority {
|
||||
return term.priority
|
||||
func (t *term) getPriority() termPriority {
|
||||
return t.priority
|
||||
}
|
||||
|
||||
func (term *term) setParent(parent *term) {
|
||||
term.parent = parent
|
||||
func (t *term) setParent(parent *term) {
|
||||
t.parent = parent
|
||||
if parent != nil && len(parent.children) < cap(parent.children) {
|
||||
parent.children = append(parent.children, term)
|
||||
parent.children = append(parent.children, t)
|
||||
}
|
||||
}
|
||||
|
||||
func (term *term) symbol() Symbol {
|
||||
return term.tk.Sym
|
||||
func (t *term) symbol() Symbol {
|
||||
return t.tk.Sym
|
||||
}
|
||||
|
||||
func (term *term) source() string {
|
||||
return term.tk.source
|
||||
func (t *term) Source() string {
|
||||
return t.tk.source
|
||||
}
|
||||
|
||||
func (term *term) value() any {
|
||||
return term.tk.Value
|
||||
func (t *term) value() any {
|
||||
return t.tk.Value
|
||||
}
|
||||
|
||||
func (term *term) compute(ctx ExprContext) (v any, err error) {
|
||||
if term.evalFunc == nil {
|
||||
err = term.Errorf("undefined eval-func for %q term", term.source())
|
||||
func (t *term) GetChild(index int) (c kern.Term) {
|
||||
if index >= 0 && index < len(t.children) {
|
||||
c = t.children[index]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *term) GetChildSource(index int) (s string) {
|
||||
if index >= 0 && index < len(t.children) {
|
||||
s = t.children[index].tk.source
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *term) IsAssign() bool {
|
||||
return t.symbol() == SymEqual
|
||||
}
|
||||
|
||||
func (t *term) Compute(ctx kern.ExprContext) (v any, err error) {
|
||||
if t.evalFunc == nil {
|
||||
err = t.Errorf("undefined eval-func for %q term", t.Source())
|
||||
} else {
|
||||
v, err = term.evalFunc(ctx, term)
|
||||
v, err = t.evalFunc(ctx, t)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -187,75 +207,81 @@ func (term *term) compute(ctx ExprContext) (v any, err error) {
|
||||
// return
|
||||
// }
|
||||
|
||||
func (term *term) errIncompatibleTypes(leftValue, rightValue any) error {
|
||||
leftType := TypeName(leftValue)
|
||||
leftText := getFormatted(leftValue, Truncate)
|
||||
rightType := TypeName(rightValue)
|
||||
rightText := getFormatted(rightValue, Truncate)
|
||||
return term.tk.Errorf(
|
||||
func (t *term) errIncompatibleTypes(leftValue, rightValue any) error {
|
||||
leftType := kern.TypeName(leftValue)
|
||||
leftText := kern.GetFormatted(leftValue, kern.Truncate)
|
||||
rightType := kern.TypeName(rightValue)
|
||||
rightText := kern.GetFormatted(rightValue, kern.Truncate)
|
||||
return t.tk.Errorf(
|
||||
"left operand '%s' [%s] and right operand '%s' [%s] are not compatible with operator %q",
|
||||
leftText, leftType,
|
||||
rightText, rightType,
|
||||
term.source())
|
||||
t.Source())
|
||||
}
|
||||
|
||||
func (term *term) errIncompatibleType(value any) error {
|
||||
return term.tk.Errorf(
|
||||
"prefix/postfix operator %q do not support operand '%v' [%s]",
|
||||
term.source(), value, TypeName(value))
|
||||
func (t *term) errIncompatibleType(value any, side string) error {
|
||||
return t.tk.Errorf(
|
||||
"operator %q does not support operand '%v' [%s] on its %s side",
|
||||
t.Source(), value, kern.TypeName(value), side)
|
||||
}
|
||||
|
||||
func (term *term) errDivisionByZero() error {
|
||||
return term.tk.Errorf("division by zero")
|
||||
func (t *term) errIncompatiblePrefixPostfixType(value any) error {
|
||||
return t.tk.Errorf(
|
||||
"prefix/postfix operator %q does not support operand '%v' [%s]",
|
||||
t.Source(), value, kern.TypeName(value))
|
||||
}
|
||||
|
||||
func (term *term) Errorf(template string, args ...any) (err error) {
|
||||
err = term.tk.Errorf(template, args...)
|
||||
func (t *term) errDivisionByZero() error {
|
||||
return t.tk.Errorf("division by zero")
|
||||
}
|
||||
|
||||
func (t *term) Errorf(template string, args ...any) (err error) {
|
||||
err = t.tk.Errorf(template, args...)
|
||||
return
|
||||
}
|
||||
|
||||
func (term *term) checkOperands() (err error) {
|
||||
switch term.position {
|
||||
func (t *term) checkOperands() (err error) {
|
||||
switch t.position {
|
||||
case posInfix:
|
||||
if term.children == nil || len(term.children) != 2 || term.anyChildrenNil() {
|
||||
err = term.tk.Errorf("infix operator %q requires two non-nil operands, got %d", term.source(), term.getChildrenCount())
|
||||
if t.children == nil || len(t.children) != 2 || t.anyChildrenNil() {
|
||||
err = t.tk.Errorf("infix operator %q requires two non-nil operands, got %d", t.Source(), t.GetChildCount())
|
||||
}
|
||||
case posPrefix:
|
||||
if term.children == nil || len(term.children) != 1 || term.children[0] == nil {
|
||||
err = term.tk.Errorf("prefix operator %q requires one non-nil operand", term.tk.String())
|
||||
if t.children == nil || len(t.children) != 1 || t.children[0] == nil {
|
||||
err = t.tk.Errorf("prefix operator %q requires one non-nil operand", t.tk.String())
|
||||
}
|
||||
case posPostfix:
|
||||
if term.children == nil || len(term.children) != 1 || term.anyChildrenNil() {
|
||||
err = term.tk.Errorf("postfix operator %q requires one non-nil operand", term.tk.String())
|
||||
if t.children == nil || len(t.children) != 1 || t.anyChildrenNil() {
|
||||
err = t.tk.Errorf("postfix operator %q requires one non-nil operand", t.tk.String())
|
||||
}
|
||||
case posMultifix:
|
||||
if term.children == nil || len(term.children) < 3 || term.anyChildrenNil() {
|
||||
err = term.tk.Errorf("infix operator %q requires at least three not operands, got %d", term.source(), term.getChildrenCount())
|
||||
if t.children == nil || len(t.children) < 3 || t.anyChildrenNil() {
|
||||
err = t.tk.Errorf("infix operator %q requires at least three not operands, got %d", t.Source(), t.GetChildCount())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (term *term) anyChildrenNil() bool {
|
||||
for _, child := range term.children {
|
||||
func (t *term) anyChildrenNil() bool {
|
||||
for _, child := range t.children {
|
||||
if child == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func (term *term) evalInfix(ctx ExprContext) (leftValue, rightValue any, err error) {
|
||||
if err = term.checkOperands(); err == nil {
|
||||
if leftValue, err = term.children[0].compute(ctx); err == nil {
|
||||
rightValue, err = term.children[1].compute(ctx)
|
||||
func (t *term) evalInfix(ctx kern.ExprContext) (leftValue, rightValue any, err error) {
|
||||
if err = t.checkOperands(); err == nil {
|
||||
if leftValue, err = t.children[0].Compute(ctx); err == nil {
|
||||
rightValue, err = t.children[1].Compute(ctx)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (term *term) evalPrefix(ctx ExprContext) (childValue any, err error) {
|
||||
if err = term.checkOperands(); err == nil {
|
||||
childValue, err = term.children[0].compute(ctx)
|
||||
func (t *term) evalPrefix(ctx kern.ExprContext) (childValue any, err error) {
|
||||
if err = t.checkOperands(); err == nil {
|
||||
childValue, err = t.children[0].Compute(ctx)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user