new operator ':=', it assigns a value to a variable by deep copy
This commit is contained in:
+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) {
|
||||
var collectionValue, keyListValue, keyValue any
|
||||
var keyList *kern.ListType
|
||||
@@ -57,16 +77,19 @@ func assignCollectionItem(ctx kern.ExprContext, collectionTerm, keyListTerm *sca
|
||||
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 {
|
||||
err = assignCollectionItem(ctx, leftTerm.Children[0], leftTerm.Children[1], v)
|
||||
} else {
|
||||
if deepCopy {
|
||||
v = kern.Clone(v)
|
||||
}
|
||||
ctx.UnsafeSetVar(leftTerm.Source(), v)
|
||||
}
|
||||
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 {
|
||||
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())
|
||||
}
|
||||
} else {
|
||||
err = assignValue(ctx, leftTerm, v)
|
||||
err = assignValue(ctx, leftTerm, v, deepCopy)
|
||||
}
|
||||
} else {
|
||||
err = assignValue(ctx, leftTerm, v)
|
||||
err = assignValue(ctx, leftTerm, v, deepCopy)
|
||||
}
|
||||
}
|
||||
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())
|
||||
}
|
||||
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
|
||||
func init() {
|
||||
scan.RegisterTermConstructor(scan.SymEqual, newAssignTerm)
|
||||
scan.RegisterTermConstructor(scan.SymColonEqual, newDeepCopyAssignTerm)
|
||||
scan.RegisterTermConstructor(scan.SymPlusEqual, newOpAssignTerm)
|
||||
scan.RegisterTermConstructor(scan.SymMinusEqual, newOpAssignTerm)
|
||||
scan.RegisterTermConstructor(scan.SymStarEqual, newOpAssignTerm)
|
||||
|
||||
Reference in New Issue
Block a user