new operator ':=', it assigns a value to a variable by deep copy
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||||
|
// All rights reserved.
|
||||||
|
|
||||||
|
// clone-value.go
|
||||||
|
package kern
|
||||||
|
|
||||||
|
func Clone(v any) (c any) {
|
||||||
|
if v == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch unboxed := v.(type) {
|
||||||
|
case int64:
|
||||||
|
c = unboxed
|
||||||
|
case float64:
|
||||||
|
c = unboxed
|
||||||
|
case string:
|
||||||
|
c = unboxed
|
||||||
|
case bool:
|
||||||
|
c = unboxed
|
||||||
|
case *ListType:
|
||||||
|
c = unboxed.Clone()
|
||||||
|
case *DictType:
|
||||||
|
c = unboxed.Clone()
|
||||||
|
default:
|
||||||
|
c = v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
+1
-1
@@ -155,7 +155,7 @@ func (dict *DictType) GetItem(key any) (value any, exists bool) {
|
|||||||
func (dict *DictType) Clone() (c *DictType) {
|
func (dict *DictType) Clone() (c *DictType) {
|
||||||
c = newDict(nil)
|
c = newDict(nil)
|
||||||
for k, v := range *dict {
|
for k, v := range *dict {
|
||||||
(*c)[k] = v
|
(*c)[k] = Clone(v)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,15 @@ func (ls1 *ListType) Equals(ls2 ListType) (answer bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ls1 *ListType) Clone() (ls2 *ListType) {
|
||||||
|
ls := make(ListType, len(*ls1))
|
||||||
|
for i, item := range *ls1 {
|
||||||
|
ls[i] = Clone(item)
|
||||||
|
}
|
||||||
|
ls2 = &ls
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (dict *ListType) IndexDeepSameCmp(target any) (index int) {
|
func (dict *ListType) IndexDeepSameCmp(target any) (index int) {
|
||||||
var eq bool
|
var eq bool
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
+29
-5
@@ -22,6 +22,26 @@ func newAssignTerm(tk *scan.Token) (inst *scan.Term) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func evalAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
|
v, err = generalEvalAssign(ctx, opTerm, false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDeepCopyAssignTerm(tk *scan.Token) (inst *scan.Term) {
|
||||||
|
return &scan.Term{
|
||||||
|
Tk: *tk,
|
||||||
|
Children: make([]*scan.Term, 0, 2),
|
||||||
|
Position: scan.PosInfix,
|
||||||
|
Priority: scan.PriAssign,
|
||||||
|
EvalFunc: evalDeepCopyAssign,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func evalDeepCopyAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
||||||
|
v, err = generalEvalAssign(ctx, opTerm, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *scan.Term, value any) (err error) {
|
func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *scan.Term, value any) (err error) {
|
||||||
var collectionValue, keyListValue, keyValue any
|
var collectionValue, keyListValue, keyValue any
|
||||||
var keyList *kern.ListType
|
var keyList *kern.ListType
|
||||||
@@ -57,16 +77,19 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *sca
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func assignValue(ctx kern.ExprContext, leftTerm *scan.Term, v any) (err error) {
|
func assignValue(ctx kern.ExprContext, leftTerm *scan.Term, v any, deepCopy bool) (err error) {
|
||||||
if leftTerm.Symbol() == scan.SymIndex {
|
if leftTerm.Symbol() == scan.SymIndex {
|
||||||
err = assignCollectionItem(ctx, leftTerm.Children[0], leftTerm.Children[1], v)
|
err = assignCollectionItem(ctx, leftTerm.Children[0], leftTerm.Children[1], v)
|
||||||
} else {
|
} else {
|
||||||
|
if deepCopy {
|
||||||
|
v = kern.Clone(v)
|
||||||
|
}
|
||||||
ctx.UnsafeSetVar(leftTerm.Source(), v)
|
ctx.UnsafeSetVar(leftTerm.Source(), v)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
func generalEvalAssign(ctx kern.ExprContext, opTerm *scan.Term, deepCopy bool) (v any, err error) {
|
||||||
if err = opTerm.CheckOperands(); err != nil {
|
if err = opTerm.CheckOperands(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -93,10 +116,10 @@ func evalAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
err = opTerm.Errorf("unknown function %s()", rightChild.Source())
|
err = opTerm.Errorf("unknown function %s()", rightChild.Source())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = assignValue(ctx, leftTerm, v)
|
err = assignValue(ctx, leftTerm, v, deepCopy)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = assignValue(ctx, leftTerm, v)
|
err = assignValue(ctx, leftTerm, v, deepCopy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -203,7 +226,7 @@ func evalOpAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
err = opTerm.Errorf("unsupported assign operator %q", opTerm.Source())
|
err = opTerm.Errorf("unsupported assign operator %q", opTerm.Source())
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = assignValue(ctx, leftTerm, v)
|
err = assignValue(ctx, leftTerm, v, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,6 +236,7 @@ func evalOpAssign(ctx kern.ExprContext, opTerm *scan.Term) (v any, err error) {
|
|||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
scan.RegisterTermConstructor(scan.SymEqual, newAssignTerm)
|
scan.RegisterTermConstructor(scan.SymEqual, newAssignTerm)
|
||||||
|
scan.RegisterTermConstructor(scan.SymColonEqual, newDeepCopyAssignTerm)
|
||||||
scan.RegisterTermConstructor(scan.SymPlusEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymPlusEqual, newOpAssignTerm)
|
||||||
scan.RegisterTermConstructor(scan.SymMinusEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymMinusEqual, newOpAssignTerm)
|
||||||
scan.RegisterTermConstructor(scan.SymStarEqual, newOpAssignTerm)
|
scan.RegisterTermConstructor(scan.SymStarEqual, newOpAssignTerm)
|
||||||
|
|||||||
@@ -192,6 +192,8 @@ func (scanner *Scanner) fetchNextToken() (tk *Token) {
|
|||||||
case ':':
|
case ':':
|
||||||
if next, _ := scanner.peek(); next == ':' {
|
if next, _ := scanner.peek(); next == ':' {
|
||||||
tk = scanner.moveOn(SymDoubleColon, ch, next)
|
tk = scanner.moveOn(SymDoubleColon, ch, next)
|
||||||
|
} else if next == '=' {
|
||||||
|
tk = scanner.moveOn(SymColonEqual, ch, next)
|
||||||
} else {
|
} else {
|
||||||
tk = scanner.MakeToken(SymColon, ch)
|
tk = scanner.MakeToken(SymColon, ch)
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-41
@@ -64,47 +64,48 @@ func init() {
|
|||||||
SymAt: {"@", SymClassOperator, PosPrefix}, // 28: '@'
|
SymAt: {"@", SymClassOperator, PosPrefix}, // 28: '@'
|
||||||
SymUndescore: {"_", SymClassIdentifier, PosLeaf}, // 29: '_'
|
SymUndescore: {"_", SymClassIdentifier, PosLeaf}, // 29: '_'
|
||||||
SymEqual: {"=", SymClassOperator, PosInfix}, // 30: '='
|
SymEqual: {"=", SymClassOperator, PosInfix}, // 30: '='
|
||||||
SymDoubleEqual: {"==", SymClassOperator, PosInfix}, // 31: '=='
|
SymColonEqual: {":=", SymClassOperator, PosInfix}, // 31: ':='
|
||||||
SymLess: {"<", SymClassOperator, PosInfix}, // 32: '<'
|
SymDoubleEqual: {"==", SymClassOperator, PosInfix}, // 32: '=='
|
||||||
SymLessOrEqual: {"<=", SymClassOperator, PosInfix}, // 33: '<='
|
SymLess: {"<", SymClassOperator, PosInfix}, // 33: '<'
|
||||||
SymGreater: {">", SymClassOperator, PosInfix}, // 34: '>'
|
SymLessOrEqual: {"<=", SymClassOperator, PosInfix}, // 34: '<='
|
||||||
SymGreaterOrEqual: {">=", SymClassOperator, PosInfix}, // 35: '>='
|
SymGreater: {">", SymClassOperator, PosInfix}, // 35: '>'
|
||||||
SymLessGreater: {"<>", SymClassOperator, PosInfix}, // 36: '<>'
|
SymGreaterOrEqual: {">=", SymClassOperator, PosInfix}, // 36: '>='
|
||||||
SymNotEqual: {"!=", SymClassOperator, PosInfix}, // 37: '!='
|
SymLessGreater: {"<>", SymClassOperator, PosInfix}, // 37: '<>'
|
||||||
SymDollar: {"$", SymClassOperator, PosPrefix}, // 38: '$'
|
SymNotEqual: {"!=", SymClassOperator, PosInfix}, // 38: '!='
|
||||||
SymHash: {"#", SymClassOperator, PosPrefix}, // 39: '#'
|
SymDollar: {"$", SymClassOperator, PosPrefix}, // 39: '$'
|
||||||
SymOpenRound: {"(", SymClassParenthesis, PosPrefix}, // 40: '('
|
SymHash: {"#", SymClassOperator, PosPrefix}, // 40: '#'
|
||||||
SymClosedRound: {")", SymClassParenthesis, PosPostfix}, // 41: ')'
|
SymOpenRound: {"(", SymClassParenthesis, PosPrefix}, // 41: '('
|
||||||
SymOpenSquare: {"[", SymClassParenthesis, PosPrefix}, // 42: '['
|
SymClosedRound: {")", SymClassParenthesis, PosPostfix}, // 42: ')'
|
||||||
SymClosedSquare: {"]", SymClassParenthesis, PosPostfix}, // 43: ']'
|
SymOpenSquare: {"[", SymClassParenthesis, PosPrefix}, // 43: '['
|
||||||
SymOpenBrace: {"{", SymClassParenthesis, PosPrefix}, // 44: '{'
|
SymClosedSquare: {"]", SymClassParenthesis, PosPostfix}, // 44: ']'
|
||||||
SymClosedBrace: {"}", SymClassParenthesis, PosPostfix}, // 45: '}'
|
SymOpenBrace: {"{", SymClassParenthesis, PosPrefix}, // 45: '{'
|
||||||
SymTilde: {"~", SymClassOperator, PosPrefix}, // 46: '~'
|
SymClosedBrace: {"}", SymClassParenthesis, PosPostfix}, // 46: '}'
|
||||||
SymDoubleQuestion: {"??", SymClassOperator, PosInfix}, // 47: '??'
|
SymTilde: {"~", SymClassOperator, PosPrefix}, // 47: '~'
|
||||||
SymQuestionEqual: {"?=", SymClassOperator, PosInfix}, // 48: '?='
|
SymDoubleQuestion: {"??", SymClassOperator, PosInfix}, // 48: '??'
|
||||||
SymQuestionExclam: {"?!", SymClassOperator, PosInfix}, // 49: '?!'
|
SymQuestionEqual: {"?=", SymClassOperator, PosInfix}, // 49: '?='
|
||||||
SymDoubleAt: {"@@", SymClassCommand, PosLeaf}, // 50: '@@'
|
SymQuestionExclam: {"?!", SymClassOperator, PosInfix}, // 50: '?!'
|
||||||
SymDoubleColon: {"::", SymClassOperator, PosInfix}, // 51: '::'
|
SymDoubleAt: {"@@", SymClassCommand, PosLeaf}, // 51: '@@'
|
||||||
SymDoubleGreater: {">>", SymClassOperator, PosInfix}, // 52: '>>'
|
SymDoubleColon: {"::", SymClassOperator, PosInfix}, // 52: '::'
|
||||||
SymDoubleLess: {"<<", SymClassOperator, PosInfix}, // 53: '<<'
|
SymDoubleGreater: {">>", SymClassOperator, PosInfix}, // 53: '>>'
|
||||||
SymCaret: {"^", SymClassOperator, PosInfix}, // 54: '^'
|
SymDoubleLess: {"<<", SymClassOperator, PosInfix}, // 54: '<<'
|
||||||
SymDollarRound: {"$(", SymClassOperator, PosPrefix}, // 55: '$('
|
SymCaret: {"^", SymClassOperator, PosInfix}, // 55: '^'
|
||||||
SymOpenClosedRound: {"()", SymClassOperator, PosPostfix}, // 56: '()'
|
SymDollarRound: {"$(", SymClassOperator, PosPrefix}, // 56: '$('
|
||||||
SymDoubleDollar: {"$$", SymClassCommand, PosLeaf}, // 57: '$$'
|
SymOpenClosedRound: {"()", SymClassOperator, PosPostfix}, // 57: '()'
|
||||||
SymDoubleDot: {"..", SymClassOperator, PosInfix}, // 58: '..'
|
SymDoubleDollar: {"$$", SymClassCommand, PosLeaf}, // 58: '$$'
|
||||||
SymTripleDot: {"...", SymClassOperator, PosPostfix}, // 59: '...'
|
SymDoubleDot: {"..", SymClassOperator, PosInfix}, // 59: '..'
|
||||||
SymStarEqual: {"*=", SymClassOperator, PosInfix}, // 60: '*='
|
SymTripleDot: {"...", SymClassOperator, PosPostfix}, // 60: '...'
|
||||||
SymSlashEqual: {"/=", SymClassOperator, PosInfix}, // 61: '/='
|
SymStarEqual: {"*=", SymClassOperator, PosInfix}, // 61: '*='
|
||||||
SymPercEqual: {"%=", SymClassOperator, PosInfix}, // 62: '%='
|
SymSlashEqual: {"/=", SymClassOperator, PosInfix}, // 62: '/='
|
||||||
SymDoubleLessEqual: {"<<=", SymClassOperator, PosInfix}, // 63: '<<='
|
SymPercEqual: {"%=", SymClassOperator, PosInfix}, // 63: '%='
|
||||||
SymDoubleGreaterEqual: {">>=", SymClassOperator, PosInfix}, // 64: '>>='
|
SymDoubleLessEqual: {"<<=", SymClassOperator, PosInfix}, // 64: '<<='
|
||||||
SymAmpersandEqual: {"&=", SymClassOperator, PosInfix}, // 65: '&='
|
SymDoubleGreaterEqual: {">>=", SymClassOperator, PosInfix}, // 65: '>>='
|
||||||
SymVertBarEqual: {"|=", SymClassOperator, PosInfix}, // 65: '|='
|
SymAmpersandEqual: {"&=", SymClassOperator, PosInfix}, // 66: '&='
|
||||||
SymCaretEqual: {"^=", SymClassOperator, PosInfix}, // 66: '^='
|
SymVertBarEqual: {"|=", SymClassOperator, PosInfix}, // 67: '|='
|
||||||
SymPlusGreater: {"+>", SymClassOperator, PosInfix}, // 67: '+>'
|
SymCaretEqual: {"^=", SymClassOperator, PosInfix}, // 68: '^='
|
||||||
SymLessPlus: {"<+", SymClassOperator, PosInfix}, // 68: '<+'
|
SymPlusGreater: {"+>", SymClassOperator, PosInfix}, // 69: '+>'
|
||||||
SymPreInc: {"++", SymClassOperator, PosPrefix}, // : '++'
|
SymLessPlus: {"<+", SymClassOperator, PosInfix}, // 70: '<+'
|
||||||
SymPreDec: {"--", SymClassOperator, PosPrefix}, // : '--'
|
SymPreInc: {"++", SymClassOperator, PosPrefix}, // 71: '++'
|
||||||
|
SymPreDec: {"--", SymClassOperator, PosPrefix}, // 72: '--'
|
||||||
// SymChangeSign
|
// SymChangeSign
|
||||||
// SymUnchangeSign
|
// SymUnchangeSign
|
||||||
// SymIdentifier
|
// SymIdentifier
|
||||||
|
|||||||
+67
-66
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// Symbol.go
|
// symbol.go
|
||||||
package scan
|
package scan
|
||||||
|
|
||||||
type Symbol int16
|
type Symbol int16
|
||||||
@@ -39,71 +39,72 @@ const (
|
|||||||
SymAt // 28: '@'
|
SymAt // 28: '@'
|
||||||
SymUndescore // 29: '_'
|
SymUndescore // 29: '_'
|
||||||
SymEqual // 30: '='
|
SymEqual // 30: '='
|
||||||
SymDoubleEqual // 31: '=='
|
SymColonEqual // 31: ':='
|
||||||
SymLess // 32: '<'
|
SymDoubleEqual // 32: '=='
|
||||||
SymLessOrEqual // 33: '<='
|
SymLess // 33: '<'
|
||||||
SymGreater // 34: '>'
|
SymLessOrEqual // 34: '<='
|
||||||
SymGreaterOrEqual // 35: '>='
|
SymGreater // 35: '>'
|
||||||
SymLessGreater // 36: '<>'
|
SymGreaterOrEqual // 36: '>='
|
||||||
SymNotEqual // 37: '!='
|
SymLessGreater // 37: '<>'
|
||||||
SymDollar // 38: '$'
|
SymNotEqual // 38: '!='
|
||||||
SymHash // 39: '#'
|
SymDollar // 39: '$'
|
||||||
SymOpenRound // 40: '('
|
SymHash // 40: '#'
|
||||||
SymClosedRound // 41: ')'
|
SymOpenRound // 41: '('
|
||||||
SymOpenSquare // 42: '['
|
SymClosedRound // 42: ')'
|
||||||
SymClosedSquare // 43: ']'
|
SymOpenSquare // 43: '['
|
||||||
SymOpenBrace // 44: '{'
|
SymClosedSquare // 44: ']'
|
||||||
SymClosedBrace // 45: '}'
|
SymOpenBrace // 45: '{'
|
||||||
SymTilde // 46: '~'
|
SymClosedBrace // 46: '}'
|
||||||
SymDoubleQuestion // 47: '??'
|
SymTilde // 47: '~'
|
||||||
SymQuestionEqual // 48: '?='
|
SymDoubleQuestion // 48: '??'
|
||||||
SymQuestionExclam // 49: '?!'
|
SymQuestionEqual // 49: '?='
|
||||||
SymDoubleAt // 50: '@@'
|
SymQuestionExclam // 50: '?!'
|
||||||
SymDoubleColon // 51: '::'
|
SymDoubleAt // 51: '@@'
|
||||||
SymDoubleGreater // 52: '>>'
|
SymDoubleColon // 52: '::'
|
||||||
SymDoubleLess // 53: '<<'
|
SymDoubleGreater // 53: '>>'
|
||||||
SymCaret // 54: '^'
|
SymDoubleLess // 54: '<<'
|
||||||
SymDollarRound // 55: '$('
|
SymCaret // 55: '^'
|
||||||
SymOpenClosedRound // 56: '()'
|
SymDollarRound // 56: '$('
|
||||||
SymDoubleDollar // 57: '$$'
|
SymOpenClosedRound // 57: '()'
|
||||||
SymDoubleDot // 58: '..'
|
SymDoubleDollar // 58: '$$'
|
||||||
SymTripleDot // 59: '...'
|
SymDoubleDot // 59: '..'
|
||||||
SymStarEqual // 60: '*='
|
SymTripleDot // 60: '...'
|
||||||
SymSlashEqual // 61: '/='
|
SymStarEqual // 61: '*='
|
||||||
SymPercEqual // 62: '%='
|
SymSlashEqual // 62: '/='
|
||||||
SymDoubleLessEqual // 63: '<<='
|
SymPercEqual // 63: '%='
|
||||||
SymDoubleGreaterEqual // 64: '>>='
|
SymDoubleLessEqual // 64: '<<='
|
||||||
SymAmpersandEqual // 65: '&='
|
SymDoubleGreaterEqual // 65: '>>='
|
||||||
SymVertBarEqual // 65: '|='
|
SymAmpersandEqual // 66: '&='
|
||||||
SymCaretEqual // 66: '^='
|
SymVertBarEqual // 67: '|='
|
||||||
SymPlusGreater // 67: '+>'
|
SymCaretEqual // 68: '^='
|
||||||
SymLessPlus // 68: '<+'
|
SymPlusGreater // 69: '+>'
|
||||||
SymChangeSign
|
SymLessPlus // 70: '<+'
|
||||||
SymUnchangeSign
|
SymChangeSign // 71: '-'
|
||||||
SymDereference
|
SymUnchangeSign // 72: '+''
|
||||||
SymPreInc
|
SymDereference // 73: '*'
|
||||||
SymPreDec
|
SymPreInc // 74: '++'
|
||||||
SymIdentifier
|
SymPreDec // 75: '--'
|
||||||
SymBool
|
SymIdentifier // 76: identifier
|
||||||
SymInteger
|
SymBool // 77: boolean
|
||||||
SymVariable
|
SymInteger // 78: integer
|
||||||
SymFloat
|
SymVariable // 79: variable
|
||||||
SymFraction
|
SymFloat // 80: float
|
||||||
SymString
|
SymFraction // 81: fraction
|
||||||
SymIterator
|
SymString // 82: string
|
||||||
SymOr
|
SymIterator // 83: iterator
|
||||||
SymAnd
|
SymOr // 84: 'or'
|
||||||
SymNot
|
SymAnd // 85: 'and'
|
||||||
SymComment
|
SymNot // 86: 'not'
|
||||||
SymFuncCall
|
SymComment // 87: comment
|
||||||
SymFuncDef
|
SymFuncCall // 88: function call
|
||||||
SymList
|
SymFuncDef // 89: function definition
|
||||||
SymDict
|
SymList // 90: list
|
||||||
SymIndex
|
SymDict // 91: dict
|
||||||
SymRange // [index : index]
|
SymIndex // 92: index
|
||||||
SymExpression
|
SymRange // 93: range [index : index]
|
||||||
SymSelector // <selector> ::= <expr> "?" <selector-case> {":" <selector-case>} ["::" <default-selector-case>]
|
SymExpression // 94: expression
|
||||||
SymSelectorCase // <selector-case> ::= [<list>] "{" <multi-expr> "}"
|
SymSelector // 95: selector <selector> ::= <expr> "?" <selector-case> {":" <selector-case>} ["::" <default-selector-case>]
|
||||||
|
SymSelectorCase // 96: <selector-case> ::= [<list>] "{" <multi-expr> "}"
|
||||||
// SymOpenComment // 0: '/*'
|
// SymOpenComment // 0: '/*'
|
||||||
// SymClosedComment // 0: '*/'
|
// SymClosedComment // 0: '*/'
|
||||||
// SymOneLineComment // 0: '//'
|
// SymOneLineComment // 0: '//'
|
||||||
|
|||||||
+9
-84
@@ -7,7 +7,6 @@ package expr
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.portale-stac.it/go-pkg/expr/kern"
|
"git.portale-stac.it/go-pkg/expr/kern"
|
||||||
@@ -17,105 +16,31 @@ import (
|
|||||||
func TestDictParser(t *testing.T) {
|
func TestDictParser(t *testing.T) {
|
||||||
section := "Dict"
|
section := "Dict"
|
||||||
|
|
||||||
type inputType struct {
|
|
||||||
source string
|
|
||||||
wantResult any
|
|
||||||
wantErr error
|
|
||||||
}
|
|
||||||
|
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
/* 1 */ {`{}`, map[any]any{}, nil},
|
/* 1 */ {`{}`, kern.NewDict(nil), nil},
|
||||||
/* 2 */ {`{123}`, nil, errors.New("[1:6] expected `:`, got `}`")},
|
/* 2 */ {`{123}`, nil, errors.New("[1:6] expected `:`, got `}`")},
|
||||||
/* 3 */ {`{1:"one",2:"two",3:"three"}`, map[int64]any{int64(1): "one", int64(2): "two", int64(3): "three"}, nil},
|
/* 3 */ {`{1:"one",2:"two",3:"three"}`, kern.NewDict(map[any]any{int64(1): "one", int64(2): "two", int64(3): "three"}), nil},
|
||||||
/* 4 */ {`{1:"one",2:"two",3:"three"}[3]`, "three", nil},
|
/* 4 */ {`{1:"one",2:"two",3:"three"}[3]`, "three", nil},
|
||||||
/* 5 */ {`#{1:"one",2:"two",3:"three"}`, int64(3), nil},
|
/* 5 */ {`#{1:"one",2:"two",3:"three"}`, int64(3), nil},
|
||||||
/* 6 */ {`{1:"one"} + {2:"two"}`, map[any]any{1: "one", 2: "two"}, nil},
|
/* 6 */ {`{1:"one"} + {2:"two"}`, kern.NewDict(map[any]any{int64(1): "one", int64(2): "two"}), nil},
|
||||||
/* 7 */ {`2 in {1:"one", 2:"two"}`, true, nil},
|
/* 7 */ {`2 in {1:"one", 2:"two"}`, true, nil},
|
||||||
/* 8 */ {`D={"a":1, "b":2}; D["a"]=9; D`, map[any]any{"a": 9, "b": 2}, nil},
|
/* 8 */ {`D={"a":1, "b":2}; D["a"]=9; D`, kern.NewDict(map[any]any{"a": int64(9), "b": int64(2)}), nil},
|
||||||
/* 9 */ {`D={"a":1, "b":2}; D["z"]=9; D`, map[any]any{"z": 9, "a": 1, "b": 2}, nil},
|
/* 9 */ {`D={"a":1, "b":2}; D["z"]=9; D`, kern.NewDict(map[any]any{"z": int64(9), "a": int64(1), "b": int64(2)}), nil},
|
||||||
/* 10 */ {`D={"a":1, "b":2}; D[nil]=9`, nil, errors.New(`[1:21] index/key is nil`)},
|
/* 10 */ {`D={"a":1, "b":2}; D[nil]=9`, nil, errors.New(`[1:21] index/key is nil`)},
|
||||||
/* 11 */ {`D={"a":1, "b":2}; D["a"]`, int64(1), nil},
|
/* 11 */ {`D={"a":1, "b":2}; D["a"]`, int64(1), nil},
|
||||||
/* 12 */ {`m={
|
/* 12 */ {`m={
|
||||||
"a":1,
|
"a":1,
|
||||||
//"b":2,
|
//"b":2,
|
||||||
"c":3
|
"c":3
|
||||||
}`, map[any]any{"a": 1, "c": 3}, nil},
|
}`, kern.NewDict(map[any]any{"a": int64(1), "c": int64(3)}), nil},
|
||||||
/* 13 */ {`D={"a":1, "b":2}; D."a"`, int64(1), nil},
|
/* 13 */ {`D={"a":1, "b":2}; D."a"`, int64(1), nil},
|
||||||
/* 14 */ {`D={"a":1, "b":2}; D.a`, int64(1), nil},
|
/* 14 */ {`D={"a":1, "b":2}; D.a`, int64(1), nil},
|
||||||
/* 15 */ {`D={1:"a", 2:"b", 3:"c"}; D.(1+2)`, "c", nil},
|
/* 15 */ {`D={1:"a", 2:"b", 3:"c"}; D.(1+2)`, "c", nil},
|
||||||
|
/* 16 */ {`D={"a":1, "b":2}; D.a`, int64(1), nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
succeeded := 0
|
runTestSuiteSpec(t, section, inputs, 16)
|
||||||
failed := 0
|
// runTestSuite(t, section, inputs)
|
||||||
|
|
||||||
// inputs1 := []inputType{
|
|
||||||
// /* 7 */ {`add([1,4,3,2])`, int64(10), nil},
|
|
||||||
// }
|
|
||||||
|
|
||||||
for i, input := range inputs {
|
|
||||||
var expr *scan.Ast
|
|
||||||
var gotResult any
|
|
||||||
var gotErr error
|
|
||||||
|
|
||||||
ctx := NewSimpleStoreWithoutGlobalContext()
|
|
||||||
ctx.SetVar("var1", int64(123))
|
|
||||||
ctx.SetVar("var2", "abc")
|
|
||||||
ImportMathFuncs(ctx)
|
|
||||||
parser := NewParser()
|
|
||||||
|
|
||||||
logTest(t, i+1, "Dict", input.source, input.wantResult, input.wantErr)
|
|
||||||
|
|
||||||
r := strings.NewReader(input.source)
|
|
||||||
scanner := scan.NewScanner(r, scan.DefaultTranslations())
|
|
||||||
|
|
||||||
good := true
|
|
||||||
if expr, gotErr = parser.Parse(scanner); gotErr == nil {
|
|
||||||
gotResult, gotErr = expr.Eval(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gotResult == nil && input.wantResult != nil) || (gotResult != nil && input.wantResult == nil) {
|
|
||||||
t.Errorf("%d: %q -> result = %v [%T], want %v [%T]", i+1, input.source, gotResult, gotResult, input.wantResult, input.wantResult)
|
|
||||||
good = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if gotList, okGot := gotResult.([]any); okGot {
|
|
||||||
if wantList, okWant := input.wantResult.([]any); okWant {
|
|
||||||
if (gotList == nil && wantList != nil) || (gotList != nil && wantList == nil) {
|
|
||||||
t.Errorf("%d: %q -> result = %v [%T], want %v [%T]", i+1, input.source, gotResult, gotResult, input.wantResult, input.wantResult)
|
|
||||||
good = false
|
|
||||||
} else {
|
|
||||||
equal := len(gotList) == len(wantList)
|
|
||||||
if equal {
|
|
||||||
for i, gotItem := range gotList {
|
|
||||||
wantItem := wantList[i]
|
|
||||||
equal = gotItem == wantItem
|
|
||||||
if !equal {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !equal {
|
|
||||||
t.Errorf("%d: %q -> result = %v [%T], want %v [%T]", i+1, input.source, gotResult, gotResult, input.wantResult, input.wantResult)
|
|
||||||
good = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if gotErr != input.wantErr {
|
|
||||||
if input.wantErr == nil || gotErr == nil || (gotErr.Error() != input.wantErr.Error()) {
|
|
||||||
t.Errorf("%d: %q -> err = <%v>, want <%v>", i+1, input.source, gotErr, input.wantErr)
|
|
||||||
good = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if good {
|
|
||||||
succeeded++
|
|
||||||
} else {
|
|
||||||
failed++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t.Logf("%s -- test count: %d, succeeded: %d, failed: %d", section, len(inputs), succeeded, failed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDictToStringMultiLine(t *testing.T) {
|
func TestDictToStringMultiLine(t *testing.T) {
|
||||||
|
|||||||
+14
-1
@@ -54,7 +54,7 @@ func TestOperatorInsert(t *testing.T) {
|
|||||||
/* 6 */ {`[] >> ["a", "b"]`, kern.NewListA("a", "b"), nil},
|
/* 6 */ {`[] >> ["a", "b"]`, kern.NewListA("a", "b"), nil},
|
||||||
/* 7 */ {`["a", "b"] << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil},
|
/* 7 */ {`["a", "b"] << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||||
/* 8 */ {`L=["a", "b"]; L << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil},
|
/* 8 */ {`L=["a", "b"]; L << $([1,2,3])`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil},
|
||||||
/* 9 */ {`L=["a", "b"]; L << $([1,2,3]); L`, kern.NewListA("a", "b", int64(1), int64(2), int64(3)), nil},
|
/* 9 */ {`L=["a", "b"]; L << $([1,2,3]); L`, kern.NewListA("a", "b"), nil},
|
||||||
/* 10 */ {`L << $([1,2,3])`, nil, `undefined variable or function "L"`},
|
/* 10 */ {`L << $([1,2,3])`, nil, `undefined variable or function "L"`},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +62,19 @@ func TestOperatorInsert(t *testing.T) {
|
|||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOperatorDeepAssign(t *testing.T) {
|
||||||
|
section := "Operator-DeepAssign"
|
||||||
|
inputs := []inputType{
|
||||||
|
/* 1 */ {`DD={"uno": 1, "due": 2}; D=DD; D["uno"]=11; DD`, kern.NewDict(map[any]any{"uno": int64(11), "due": int64(2)}), nil},
|
||||||
|
/* 2 */ {`DD={"uno": 1, "due": 2}; D:=DD; D["uno"]=11; DD`, kern.NewDict(map[any]any{"uno": int64(1), "due": int64(2)}), nil},
|
||||||
|
/* 3 */ {`LL=["a", "b"]; L=LL; L[0]="x"; LL`, kern.NewListA("x", "b"), nil},
|
||||||
|
/* 4 */ {`LL=["a", "b"]; L:=LL; L[0]="x"; LL`, kern.NewListA("a", "b"), nil},
|
||||||
|
}
|
||||||
|
|
||||||
|
// runTestSuiteSpec(t, section, inputs, 4)
|
||||||
|
runTestSuite(t, section, inputs)
|
||||||
|
}
|
||||||
|
|
||||||
func TestOperatorDigest(t *testing.T) {
|
func TestOperatorDigest(t *testing.T) {
|
||||||
section := "Operator-Digest"
|
section := "Operator-Digest"
|
||||||
inputs := []inputType{
|
inputs := []inputType{
|
||||||
|
|||||||
Reference in New Issue
Block a user