Add set index in list, and update lib+examples+tests
This commit is contained in:
parent
09ac16a42d
commit
3bccc227ba
12 changed files with 117 additions and 60 deletions
|
|
@ -977,6 +977,41 @@ func (c *Compiler) compileAssignFromStack(to Node, sig TypeSignature, declare bo
|
|||
}
|
||||
|
||||
return sig, nil
|
||||
case IndexNodeType:
|
||||
if declare {
|
||||
return nil, c.error(fmt.Sprintf("cannot declare an indexed item"), to)
|
||||
}
|
||||
|
||||
n := to.(*IndexNode)
|
||||
|
||||
ssig, err := c.compile(n.source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isig, err := c.compile(n.index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isig.Type() != TypeInteger {
|
||||
return nil, c.error(fmt.Sprintf("cannot index into list with non-integer (%s)", isig), n.index)
|
||||
}
|
||||
|
||||
switch ssig.Type() {
|
||||
case TypeList:
|
||||
lsig := ssig.(*ListSignature)
|
||||
if !c.typeMatches(sig, lsig.Contents) {
|
||||
return nil, c.error(fmt.Sprintf("cannot assign value of type %s to list with items of type %s", sig, lsig.Contents), to)
|
||||
}
|
||||
|
||||
c.add(InstructionSetIndexList)
|
||||
default:
|
||||
return nil, c.error(fmt.Sprintf("cannot set index of %s", ssig.Type()), n.source)
|
||||
}
|
||||
|
||||
return sig, nil
|
||||
|
||||
default:
|
||||
return nil, c.error(fmt.Sprintf("cannot assign to %s", to.Type()), to)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,8 +117,12 @@ type Value interface {
|
|||
// Get a member from the value. An error is returned if the member does not exist
|
||||
Get(string) (Value, error)
|
||||
|
||||
// Clone create a clone of the value. The returned value is a pointer to a new value of the same type as the value.
|
||||
Clone() Value
|
||||
// Copy create a copy of the value. A copy is a direct copy for small data (numbers) and a copy of pointer
|
||||
// for bigger data (lists, tuples, dicts)
|
||||
Copy() Value
|
||||
|
||||
// Clone create a clone of the value. A clone is new data for all data.
|
||||
//Clone() Value
|
||||
}
|
||||
|
||||
type NilValue struct{}
|
||||
|
|
@ -143,7 +147,7 @@ func (v *NilValue) Get(_ string) (Value, error) {
|
|||
return nil, errors.New("nil has no properties")
|
||||
}
|
||||
|
||||
func (v *NilValue) Clone() Value {
|
||||
func (v *NilValue) Copy() Value {
|
||||
return &NilValue{}
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +179,7 @@ func (v *BoolValue) Get(_ string) (Value, error) {
|
|||
return nil, errors.New("booleans have no properties")
|
||||
}
|
||||
|
||||
func (v *BoolValue) Clone() Value {
|
||||
func (v *BoolValue) Copy() Value {
|
||||
return &BoolValue{
|
||||
v.Boolean,
|
||||
}
|
||||
|
|
@ -258,11 +262,11 @@ func (v *ObjectValue) Get(key string) (Value, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (v *ObjectValue) Clone() Value {
|
||||
func (v *ObjectValue) Copy() Value {
|
||||
m := make(map[string]Value, len(v.Members))
|
||||
|
||||
for name, mem := range v.Members {
|
||||
m[name] = mem.Clone()
|
||||
m[name] = mem.Copy()
|
||||
}
|
||||
|
||||
return &ObjectValue{
|
||||
|
|
@ -303,7 +307,7 @@ func (v *FloatValue) Get(_ string) (Value, error) {
|
|||
return nil, errors.New("numbers have no properties")
|
||||
}
|
||||
|
||||
func (v *FloatValue) Clone() Value {
|
||||
func (v *FloatValue) Copy() Value {
|
||||
return &FloatValue{
|
||||
v.Number,
|
||||
}
|
||||
|
|
@ -334,7 +338,7 @@ func (v *IntegerValue) Get(_ string) (Value, error) {
|
|||
return nil, errors.New("numbers have no properties")
|
||||
}
|
||||
|
||||
func (v *IntegerValue) Clone() Value {
|
||||
func (v *IntegerValue) Copy() Value {
|
||||
return &IntegerValue{
|
||||
new(big.Int).Set(v.Number),
|
||||
}
|
||||
|
|
@ -427,7 +431,7 @@ func (v *StringValue) Get(key string) (Value, error) {
|
|||
return nil, errors.New(fmt.Sprintf("string has no property \"%s\"", key))
|
||||
}
|
||||
|
||||
func (v *StringValue) Clone() Value {
|
||||
func (v *StringValue) Copy() Value {
|
||||
return &StringValue{
|
||||
v.Text,
|
||||
}
|
||||
|
|
@ -594,15 +598,9 @@ func (v *ListValue) Get(key string) (Value, error) {
|
|||
return nil, errors.New(fmt.Sprintf("list has no property \"%s\"", key))
|
||||
}
|
||||
|
||||
func (v *ListValue) Clone() Value {
|
||||
n := make([]Value, len(v.Items))
|
||||
|
||||
for i, item := range v.Items {
|
||||
n[i] = item.Clone()
|
||||
}
|
||||
|
||||
func (v *ListValue) Copy() Value {
|
||||
return &ListValue{
|
||||
n,
|
||||
v.Items,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -635,13 +633,9 @@ func (v *TupleValue) DebugString() string {
|
|||
return v.String()
|
||||
}
|
||||
|
||||
func (v *TupleValue) Clone() Value {
|
||||
n := make([]Value, len(v.Items))
|
||||
for i, item := range v.Items {
|
||||
n[i] = item.Clone()
|
||||
}
|
||||
func (v *TupleValue) Copy() Value {
|
||||
return &TupleValue{
|
||||
n,
|
||||
v.Items,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -718,7 +712,7 @@ func (v *FunctionValue) Get(_ string) (Value, error) {
|
|||
return nil, errors.New("functions have no properties")
|
||||
}
|
||||
|
||||
func (v *FunctionValue) Clone() Value {
|
||||
func (v *FunctionValue) Copy() Value {
|
||||
return &FunctionValue{
|
||||
v.Name,
|
||||
v.Params,
|
||||
|
|
@ -758,7 +752,7 @@ func (v *BuiltinFunctionValue) Get(_ string) (Value, error) {
|
|||
return nil, errors.New("functions have no properties")
|
||||
}
|
||||
|
||||
func (v *BuiltinFunctionValue) Clone() Value {
|
||||
func (v *BuiltinFunctionValue) Copy() Value {
|
||||
return &BuiltinFunctionValue{
|
||||
v.Name,
|
||||
v.Signature,
|
||||
|
|
@ -807,7 +801,7 @@ func (v *RecordValue) DebugString() string {
|
|||
return v.String()
|
||||
}
|
||||
|
||||
func (v *RecordValue) Clone() Value {
|
||||
func (v *RecordValue) Copy() Value {
|
||||
return &RecordValue{
|
||||
v.Entries,
|
||||
}
|
||||
|
|
|
|||
34
core/vm.go
34
core/vm.go
|
|
@ -152,10 +152,14 @@ const (
|
|||
// is the index. [..., container, index] -> [..., item]
|
||||
InstructionIndexTuple
|
||||
// InstructionIndexString index into a string. The lower item is the container, and the top item
|
||||
// is the index. [..., container, index] -> [..., item]. Produces a new string with the character
|
||||
// at the position
|
||||
// is the index. [..., container, index] -> [..., item]. Produces a new string with only the character
|
||||
// at the indexed position
|
||||
InstructionIndexString
|
||||
|
||||
// InstructionSetIndexList set the item at a given index in a list.
|
||||
// [..., item, container, index] -> [..., item]
|
||||
InstructionSetIndexList
|
||||
|
||||
// InstructionBreakpoint for debugging purposes
|
||||
InstructionBreakpoint
|
||||
)
|
||||
|
|
@ -638,7 +642,7 @@ var DefaultGlobals = map[string]Value{
|
|||
n, _ := v.Number.Float64()
|
||||
return &FloatValue{n}, nil
|
||||
case *FloatValue:
|
||||
return v.Clone(), nil
|
||||
return v.Copy(), nil
|
||||
case *StringValue:
|
||||
num, err := strconv.ParseFloat(v.Text, FloatSize)
|
||||
if err != nil {
|
||||
|
|
@ -978,7 +982,7 @@ func (vm *VM) Next() bool {
|
|||
vm.Stack.Push(v)
|
||||
|
||||
case InstructionSetLocal:
|
||||
value := vm.Stack.Peek().Clone()
|
||||
value := vm.Stack.Peek().Copy()
|
||||
name := vm.GetConstant(vm.NextByte()).(*StringValue).Text
|
||||
|
||||
vm.setVar(name, value)
|
||||
|
|
@ -986,7 +990,7 @@ func (vm *VM) Next() bool {
|
|||
case InstructionDeclareLocal:
|
||||
vm.addVar(
|
||||
vm.GetConstant(vm.NextByte()).(*StringValue).Text,
|
||||
vm.Stack.Peek().Clone(),
|
||||
vm.Stack.Peek().Copy(),
|
||||
)
|
||||
|
||||
case InstructionGetGlobal:
|
||||
|
|
@ -1070,7 +1074,7 @@ func (vm *VM) Next() bool {
|
|||
vm.Stack.Push(r, l)
|
||||
|
||||
case InstructionDuplicate:
|
||||
vm.Stack.Push(vm.Stack.Peek().Clone())
|
||||
vm.Stack.Push(vm.Stack.Peek().Copy())
|
||||
|
||||
case InstructionAccessProperty:
|
||||
source := vm.Stack.Pop()
|
||||
|
|
@ -1112,7 +1116,7 @@ func (vm *VM) Next() bool {
|
|||
vm.error(fmt.Sprintf("index %d out of bounds", n))
|
||||
}
|
||||
|
||||
vm.Stack.Push(l.Items[n].Clone())
|
||||
vm.Stack.Push(l.Items[n].Copy())
|
||||
|
||||
case InstructionIndexTuple:
|
||||
i := vm.Stack.Pop().(*IntegerValue)
|
||||
|
|
@ -1124,7 +1128,7 @@ func (vm *VM) Next() bool {
|
|||
vm.error(fmt.Sprintf("index %d out of bounds", n))
|
||||
}
|
||||
|
||||
vm.Stack.Push(t.Items[n].Clone())
|
||||
vm.Stack.Push(t.Items[n].Copy())
|
||||
|
||||
case InstructionIndexString:
|
||||
i := vm.Stack.Pop().(*IntegerValue)
|
||||
|
|
@ -1138,6 +1142,18 @@ func (vm *VM) Next() bool {
|
|||
|
||||
vm.Stack.Push(&StringValue{string(s.Text[n])})
|
||||
|
||||
case InstructionSetIndexList:
|
||||
n := vm.Stack.Pop().(*IntegerValue)
|
||||
l := vm.Stack.Pop().(*ListValue)
|
||||
|
||||
i := n.Number.Int64()
|
||||
|
||||
if i < 0 || int64(len(l.Items)) <= i {
|
||||
vm.error(fmt.Sprintf("index %d out of bounds", i))
|
||||
}
|
||||
|
||||
l.Items[i] = vm.Stack.Peek().Copy()
|
||||
|
||||
case InstructionBreakpoint:
|
||||
/*
|
||||
// I'm keeping this
|
||||
|
|
@ -1284,7 +1300,7 @@ func (vm *VM) HasNext() bool {
|
|||
}
|
||||
|
||||
func (vm *VM) GetConstant(id Bytecode) Value {
|
||||
return vm.chunk.Constants[id].Clone()
|
||||
return vm.chunk.Constants[id].Copy()
|
||||
}
|
||||
|
||||
func (vm *VM) ReadConstant() Value {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue