package eval
import (
)
type lvaluesGroup struct {
lvalues []lvalue
rest int
}
type lvalue struct {
diag.Ranging
ref *varRef
indexOps []valuesOp
ends []int
}
func ( *compiler) ( []*parse.Compound) lvaluesGroup {
:= lvaluesGroup{nil, -1}
for , := range {
if len(.Indexings) != 1 {
.errorpf(, "lvalue may not be composite expressions")
}
:= .parseIndexingLValue(.Indexings[0])
if .rest == -1 {
.lvalues = append(.lvalues, .lvalues...)
} else if .rest != -1 {
.errorpf(, "at most one rest variable is allowed")
} else {
.rest = len(.lvalues) + .rest
.lvalues = append(.lvalues, .lvalues...)
}
}
return
}
func ( *compiler) ( *parse.Indexing) lvaluesGroup {
if .Head.Type == parse.Braced {
if len(.Indicies) > 0 {
.errorpf(, "braced list may not have indices when used as lvalue")
}
return .parseCompoundLValues(.Head.Braced)
}
if !parse.ValidLHSVariable(.Head, true) {
.errorpf(.Head, "lvalue must be valid literal variable names")
}
:= .Head.Value
, := SplitSigil()
var *varRef
if len(.Indicies) == 0 {
= resolveVarRef(, , nil)
if == nil {
:= SplitQNameSegs()
if len() == 1 {
= &varRef{localScope, .thisScope().addInner([0]), nil}
} else if len() == 2 && ([0] == "local:" || [0] == ":") {
= &varRef{localScope, .thisScope().addInner([1]), nil}
} else {
.errorpf(, "cannot create variable $%s; new variables can only be created in the local scope", )
}
}
} else {
= resolveVarRef(, , )
if == nil {
.errorpf(, "cannot find variable $%s", )
}
}
:= make([]int, len(.Indicies)+1)
[0] = .Head.Range().To
for , := range .Indicies {
[+1] = .Range().To
}
:= lvalue{.Range(), , .arrayOps(.Indicies), }
:= -1
if == "@" {
= 0
}
return lvaluesGroup{[]lvalue{}, }
}
type assignOp struct {
diag.Ranging
lhs lvaluesGroup
rhs valuesOp
}
func ( *assignOp) ( *Frame) Exception {
:= make([]vars.Var, len(.lhs.lvalues))
for , := range .lhs.lvalues {
, := derefLValue(, )
if != nil {
return .errorp(, )
}
[] =
}
, := .rhs.exec()
if != nil {
return
}
if .lhs.rest == -1 {
if len() != len() {
return .errorp(, errs.ArityMismatch{
What: "assignment right-hand-side",
ValidLow: len(), ValidHigh: len(), Actual: len()})
}
for , := range {
:= .Set([])
if != nil {
return .errorp(.lhs.lvalues[], )
}
}
} else {
if len() < len()-1 {
return .errorp(, errs.ArityMismatch{
What: "assignment right-hand-side",
ValidLow: len() - 1, ValidHigh: -1, Actual: len()})
}
:= .lhs.rest
for := 0; < ; ++ {
:= [].Set([])
if != nil {
return .errorp(.lhs.lvalues[], )
}
}
:= len() - len()
:= [].Set(vals.MakeList([ : ++1]...))
if != nil {
return .errorp(.lhs.lvalues[], )
}
for := + 1; < len(); ++ {
:= [].Set([+])
if != nil {
return .errorp(.lhs.lvalues[], )
}
}
}
return nil
}
func ( string) error {
return noSuchVariableError{}
}
type noSuchVariableError struct{ name string }
func ( noSuchVariableError) () string { return "no variable $" + .name }
func ( *Frame, lvalue) (vars.Var, error) {
:= deref(, .ref)
if == nil {
return nil, NoSuchVariable(.srcMeta.Code[.From:.To])
}
if len(.indexOps) == 0 {
return , nil
}
:= make([]interface{}, len(.indexOps))
for , := range .indexOps {
, := .exec()
if != nil {
return nil,
}
if len() != 1 {
return nil, errors.New("multi indexing not implemented")
}
[] = [0]
}
, := vars.MakeElement(, )
if != nil {
:= vars.ElementErrorLevel()
if < 0 {
return nil, .errorp(, )
}
return nil, .errorp(diag.Ranging{From: .From, To: .ends[]}, )
}
return , nil
}