This commit is contained in:
2024-05-14 12:10:58 +02:00
parent a9bb79b01c
commit 59911aebb9
645 changed files with 263320 additions and 0 deletions

221
vendor/github.com/glycerine/zygomys/zygo/arrayutils.go generated vendored Normal file
View File

@@ -0,0 +1,221 @@
package zygo
import "fmt"
func MapArray(env *Zlisp, fun *SexpFunction, arr *SexpArray) (Sexp, error) {
result := make([]Sexp, len(arr.Val))
var err error
var firstTyp *RegisteredType
for i := range arr.Val {
result[i], err = env.Apply(fun, arr.Val[i:i+1])
if err != nil {
return &SexpArray{Val: result, Typ: firstTyp, Env: env}, err
}
if firstTyp == nil {
firstTyp = result[i].Type()
}
}
return &SexpArray{Val: result, Typ: firstTyp, Env: env}, nil
}
func ConcatArray(arr *SexpArray, rest []Sexp) (Sexp, error) {
if arr == nil {
return SexpNull, fmt.Errorf("ConcatArray called with nil arr")
}
var res SexpArray
res.Val = arr.Val
for i, x := range rest {
switch t := x.(type) {
case *SexpArray:
res.Val = append(res.Val, t.Val...)
default:
return &res, fmt.Errorf("ConcatArray error: %d-th argument "+
"(0-based) is not an array", i)
}
}
return &res, nil
}
// (arrayidx ar [0 1])
func ArrayIndexFunction(env *Zlisp, name string, args []Sexp) (Sexp, error) {
Q("in ArrayIndexFunction, args = '%#v'", args)
narg := len(args)
if narg != 2 {
return SexpNull, WrongNargs
}
var err error
args, err = env.ResolveDotSym(args)
if err != nil {
return SexpNull, err
}
var ar *SexpArray
switch ar2 := args[0].(type) {
case *SexpArraySelector:
x, err := ar2.RHS(env)
if err != nil {
return SexpNull, err
}
switch xArr := x.(type) {
case *SexpArray:
ar = xArr
case *SexpHash:
return HashIndexFunction(env, name, []Sexp{xArr, args[1]})
default:
return SexpNull, fmt.Errorf("bad (arrayidx ar index) call: ar as arrayidx, but that did not resolve to an array, instead '%s'/type %T", x.SexpString(nil), x)
}
case *SexpArray:
ar = ar2
case *SexpHash:
return HashIndexFunction(env, name, args)
case *SexpHashSelector:
Q("ArrayIndexFunction sees args[0] is a hashSelector")
return HashIndexFunction(env, name, args)
default:
return SexpNull, fmt.Errorf("bad (arrayidx ar index) call: ar was not an array, instead '%s'/type %T",
args[0].SexpString(nil), args[0])
}
var idx *SexpArray
switch idx2 := args[1].(type) {
case *SexpArray:
idx = idx2
default:
return SexpNull, fmt.Errorf("bad (arrayidx ar index) call: index was not an array, instead '%s'/type %T",
args[1].SexpString(nil), args[1])
}
ret := SexpArraySelector{
Select: idx,
Container: ar,
}
return &ret, nil
}
// IndexBy subsets one array (possibly multidimensional) by another.
// e.g. if arr is [a b c] and idx is [0], we'll return a.
func (arr *SexpArray) IndexBy(idx *SexpArray) (Sexp, error) {
nIdx := len(idx.Val)
nTarget := arr.NumDim()
if nIdx > nTarget {
return SexpNull, fmt.Errorf("bad (arrayidx ar index) call: index requested %d dimensions, only have %d",
nIdx, nTarget)
}
if len(idx.Val) == 0 {
return SexpNull, fmt.Errorf("bad (arrayidx ar index) call: no index supplied")
}
if len(idx.Val) != 1 {
return SexpNull, fmt.Errorf("bad (arrayidx ar index) call: we only support a single index value atm")
}
i := 0
myInt, isInt := idx.Val[i].(*SexpInt)
if !isInt {
return SexpNull, fmt.Errorf("bad (arrayidx ar index) call: index with non-integer '%v'",
idx.Val[i].SexpString(nil))
}
k := myInt.Val
pos := k % int64(len(arr.Val))
if k < 0 {
mk := -k
mod := mk % int64(len(arr.Val))
pos = int64(len(arr.Val)) - mod
}
//Q("return pos %v", pos)
return arr.Val[pos], nil
}
func (arr *SexpArray) NumDim() int {
return 1
}
// SexpSelector: select a subset of an array:
// can be multidimensional index/slice
// and hence know its container and its position(s),
// and thus be able to read and write that position as
// need be.
type SexpArraySelector struct {
Select *SexpArray
Container *SexpArray
}
func (si *SexpArraySelector) SexpString(ps *PrintState) string {
Q("in SexpArraySelector.SexpString(), si.Container.Env = %p", si.Container.Env)
rhs, err := si.RHS(si.Container.Env)
if err != nil {
return fmt.Sprintf("(arraySelector %v %v)", si.Container.SexpString(ps), si.Select.SexpString(ps))
}
Q("in SexpArraySelector.SexpString(), rhs = %v", rhs.SexpString(ps))
Q("in SexpArraySelector.SexpString(), si.Container = %v", si.Container.SexpString(ps))
Q("in SexpArraySelector.SexpString(), si.Select = %v", si.Select.SexpString(ps))
return fmt.Sprintf("%v /*(arraySelector %v %v)*/", rhs.SexpString(ps), si.Container.SexpString(ps), si.Select.SexpString(ps))
}
// Type returns the type of the value.
func (si *SexpArraySelector) Type() *RegisteredType {
return GoStructRegistry.Lookup("arraySelector")
}
// RHS applies the selector to the contain and returns
// the value obtained.
func (x *SexpArraySelector) RHS(env *Zlisp) (Sexp, error) {
if len(x.Select.Val) != 1 {
return SexpNull, fmt.Errorf("SexpArraySelector: only " +
"size 1 selectors implemented")
}
var i int64
switch asInt := x.Select.Val[0].(type) {
case *SexpInt:
i = asInt.Val
default:
return SexpNull, fmt.Errorf("SexpArraySelector: int "+
"selector required; we saw %T", x.Select.Val[0])
}
if i < 0 {
return SexpNull, fmt.Errorf("SexpArraySelector: negative "+
"indexes not supported; we saw %v", i)
}
if i >= int64(len(x.Container.Val)) {
return SexpNull, fmt.Errorf("SexpArraySelector: index "+
"%v is out-of-bounds; length is %v", i, len(x.Container.Val))
}
ret := x.Container.Val[i]
Q("arraySelector returning ret = %#v", ret)
return ret, nil
}
// Selector stores indexing information that isn't
// yet materialized for getting or setting.
//
type Selector interface {
// RHS (right-hand-side) is used to dereference
// the pointer-like Selector, yielding a value suitable for the
// right-hand-side of an assignment statement.
//
RHS(env *Zlisp) (Sexp, error)
// AssignToSelection sets the selection to rhs
// The selected elements are the left-hand-side of the
// assignment *lhs = rhs
AssignToSelection(env *Zlisp, rhs Sexp) error
}
func (x *SexpArraySelector) AssignToSelection(env *Zlisp, rhs Sexp) error {
_, err := x.RHS(x.Container.Env) // check for errors
if err != nil {
return err
}
x.Container.Val[x.Select.Val[0].(*SexpInt).Val] = rhs
return nil
}
func (env *Zlisp) NewSexpArray(arr []Sexp) *SexpArray {
return &SexpArray{Val: arr, Env: env}
}