Skip to content

Commit

Permalink
map->ordermap
Browse files Browse the repository at this point in the history
  • Loading branch information
王广裕 committed May 31, 2023
1 parent fc49fbe commit 7d9ac54
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 46 deletions.
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}"
}
]
}
5 changes: 3 additions & 2 deletions builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ func builtinLen(args ...Object) (Object, error) {
case *Bytes:
return &Int{Value: int64(len(arg.Value))}, nil
case *Map:
return &Int{Value: int64(len(arg.Value))}, nil
return &Int{Value: int64(len(arg.Value.Keys()))}, nil
case *ImmutableMap:
return &Int{Value: int64(len(arg.Value))}, nil
default:
Expand Down Expand Up @@ -589,7 +589,8 @@ func builtinDelete(args ...Object) (Object, error) {
switch arg := args[0].(type) {
case *Map:
if key, ok := args[1].(*String); ok {
delete(arg.Value, key.Value)
arg.Value.Delete(key.Value)
// delete(arg.Value, key.Value)
return UndefinedValue, nil
}
return nil, ErrInvalidArgumentType{
Expand Down
7 changes: 5 additions & 2 deletions bytecode.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,15 @@ func fixDecodedObject(
o.Value[i] = fv
}
case *Map:
for k, v := range o.Value {
for _, k := range o.Value.Keys() {
ov, _ := o.Value.Get(k)
v, _ := FromInterface(ov)
fv, err := fixDecodedObject(v, modules)
if err != nil {
return nil, err
}
o.Value[k] = fv
o.Value.Set(k, fv)
// o.Value[k] = fv
}
case *ImmutableMap:
modName := inferModuleName(o)
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/macheal/tengo/v2

go 1.13

require github.com/iancoleman/orderedmap v0.2.0 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA=
github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
62 changes: 60 additions & 2 deletions iterator.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package tengo

import "github.com/iancoleman/orderedmap"

// Iterator represents an iterator for underlying data type.
type Iterator interface {
Object
Expand Down Expand Up @@ -107,10 +109,64 @@ func (i *BytesIterator) Value() Object {
return &Int{Value: int64(i.v[i.i-1])}
}

// ImmutableMapIterator represents an iterator for the map.
type ImmutableMapIterator struct {
ObjectImpl
v map[string]Object
k []string
i int
l int
}

// TypeName returns the name of the type.
func (i *ImmutableMapIterator) TypeName() string {
return "map-iterator"
}

func (i *ImmutableMapIterator) String() string {
return "<map-iterator>"
}

// IsFalsy returns true if the value of the type is falsy.
func (i *ImmutableMapIterator) IsFalsy() bool {
return true
}

// Equals returns true if the value of the type is equal to the value of
// another object.
func (i *ImmutableMapIterator) Equals(Object) bool {
return false
}

// Copy returns a copy of the type.
func (i *ImmutableMapIterator) Copy() Object {
return &ImmutableMapIterator{v: i.v, k: i.k, i: i.i, l: i.l}
}

// Next returns true if there are more elements to iterate.
func (i *ImmutableMapIterator) Next() bool {
i.i++
return i.i <= i.l
}

// Key returns the key or index value of the current element.
func (i *ImmutableMapIterator) Key() Object {
k := i.k[i.i-1]
return &String{Value: k}
}

// Value returns the value of the current element.
func (i *ImmutableMapIterator) Value() Object {
k := i.k[i.i-1]
tmp, _ := i.v[k]
r, _ := FromInterface(tmp)
return r
}

// MapIterator represents an iterator for the map.
type MapIterator struct {
ObjectImpl
v map[string]Object
v orderedmap.OrderedMap //map[string]Object
k []string
i int
l int
Expand Down Expand Up @@ -156,7 +212,9 @@ func (i *MapIterator) Key() Object {
// Value returns the value of the current element.
func (i *MapIterator) Value() Object {
k := i.k[i.i-1]
return i.v[k]
tmp, _ := i.v.Get(k) //[k]
r, _ := FromInterface(tmp)
return r
}

// StringIterator represents an iterator for a string.
Expand Down
64 changes: 41 additions & 23 deletions objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"time"

"github.com/iancoleman/orderedmap"
"github.com/macheal/tengo/v2/parser"
"github.com/macheal/tengo/v2/token"
)
Expand Down Expand Up @@ -923,7 +924,7 @@ func (o *ImmutableMap) Copy() Object {
for k, v := range o.Value {
c[k] = v.Copy()
}
return &Map{Value: c}
return &ImmutableMap{Value: c}
}

// IsFalsy returns true if the value of the type is falsy.
Expand All @@ -950,8 +951,8 @@ func (o *ImmutableMap) IndexGet(index Object) (res Object, err error) {
func (o *ImmutableMap) Equals(x Object) bool {
var xVal map[string]Object
switch x := x.(type) {
case *Map:
xVal = x.Value
// case *Map:
// xVal = x.Value
case *ImmutableMap:
xVal = x.Value
default:
Expand All @@ -975,7 +976,7 @@ func (o *ImmutableMap) Iterate() Iterator {
for k := range o.Value {
keys = append(keys, k)
}
return &MapIterator{
return &ImmutableMapIterator{
v: o.Value,
k: keys,
l: len(keys),
Expand Down Expand Up @@ -1180,7 +1181,8 @@ func (o *Int) Equals(x Object) bool {
// Map represents a map of objects.
type Map struct {
ObjectImpl
Value map[string]Object
Value orderedmap.OrderedMap
// Value map[string]Object
}

// TypeName returns the name of the type.
Expand All @@ -1190,46 +1192,61 @@ func (o *Map) TypeName() string {

func (o *Map) String() string {
var pairs []string
for k, v := range o.Value {
pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String()))
for _, k := range o.Value.Keys() {
// for k, v := range o.Value {
v, _ := o.Value.Get(k)
pairs = append(pairs, fmt.Sprintf("%s: %s", k, v))
}
return fmt.Sprintf("{%s}", strings.Join(pairs, ", "))
}

// Copy returns a copy of the type.
func (o *Map) Copy() Object {
c := make(map[string]Object)
for k, v := range o.Value {
c[k] = v.Copy()
c := orderedmap.New() // make(map[string]Object)
for _, k := range o.Value.Keys() {
// c[k] = o.Value[k].Copy()
v, _ := o.Value.Get(k)
c.Set(k, v)
}
return &Map{Value: c}
return &Map{Value: *c}
}

// IsFalsy returns true if the value of the type is falsy.
func (o *Map) IsFalsy() bool {
return len(o.Value) == 0
return len(o.Value.Keys()) == 0
}

// Equals returns true if the value of the type is equal to the value of
// another object.
func (o *Map) Equals(x Object) bool {
var xVal map[string]Object
var xVal orderedmap.OrderedMap //map[string]Object
switch x := x.(type) {
case *Map:
xVal = x.Value
case *ImmutableMap:
xVal = x.Value
// case *ImmutableMap:
// xVal = x.Value
default:
return false
}
if len(o.Value) != len(xVal) {
if len(o.Value.Keys()) != len(xVal.Keys()) {
return false
}
for k, v := range o.Value {
tv := xVal[k]
if !v.Equals(tv) {
for _, k := range o.Value.Keys() {
// for k, v := range o.Value {
v, _ := o.Value.Get(k)
tv, found := xVal.Get(k)
if !found {
return false
}
if v != tv {
return false
}
// if !reflect.DeepEqual(v, tv) {
// return false
// }
// if !v.Equals(tv) {
// return false
// }
}
return true
}
Expand All @@ -1241,11 +1258,12 @@ func (o *Map) IndexGet(index Object) (res Object, err error) {
err = ErrInvalidIndexType
return
}
res, ok = o.Value[strIdx]
r, ok := o.Value.Get(strIdx)
if !ok {
res = UndefinedValue
}
return
return FromInterface(r)
// return ToInterface(r), nil
}

// IndexSet sets the value for the given key.
Expand All @@ -1255,14 +1273,14 @@ func (o *Map) IndexSet(index, value Object) (err error) {
err = ErrInvalidIndexType
return
}
o.Value[strIdx] = value
o.Value.Set(strIdx, value) // [strIdx] = value
return nil
}

// Iterate creates a map iterator.
func (o *Map) Iterate() Iterator {
var keys []string
for k := range o.Value {
for _, k := range o.Value.Keys() {
keys = append(keys, k)
}
return &MapIterator{
Expand Down
53 changes: 40 additions & 13 deletions tengo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"strconv"
"time"

"github.com/iancoleman/orderedmap"
)

var (
Expand Down Expand Up @@ -49,8 +51,10 @@ func CountObjects(o Object) (c int) {
c += CountObjects(v)
}
case *Map:
for _, v := range o.Value {
c += CountObjects(v)
for _, k := range o.Value.Keys() {
v, _ := o.Value.Get(k)
x, _ := FromInterface(v)
c += CountObjects(x)
}
case *ImmutableMap:
for _, v := range o.Value {
Expand Down Expand Up @@ -221,15 +225,25 @@ func ToInterface(o Object) (res interface{}) {
res.([]interface{})[i] = ToInterface(val)
}
case *Map:
res = make(map[string]interface{})
for key, v := range o.Value {
res.(map[string]interface{})[key] = ToInterface(v)
res = orderedmap.New()
for _, key := range o.Value.Keys() {
v, _ := o.Value.Get(key)
res.(*orderedmap.OrderedMap).Set(key, v)
}
// res = make(map[string]interface{})
// for key, v := range o.Value {
// res.(map[string]interface{})[key] = ToInterface(v)
// }
case *ImmutableMap:
res = make(map[string]interface{})
res = orderedmap.New()
for key, v := range o.Value {
res.(map[string]interface{})[key] = ToInterface(v)
println(key)
res.(*orderedmap.OrderedMap).Set(key, ToInterface(v))
}
// res = make(map[string]interface{})
// for key, v := range o.Value {
// res.(map[string]interface{})[key] = ToInterface(v)
// }
case *Time:
res = o.Value
case *Error:
Expand Down Expand Up @@ -275,17 +289,30 @@ func FromInterface(v interface{}) (Object, error) {
case error:
return &Error{Value: &String{Value: v.Error()}}, nil
case map[string]Object:
return &Map{Value: v}, nil
m := Map{}
for key, value := range v {
m.Value.Set(key, value)
}
return &m, nil
case map[string]interface{}:
kv := make(map[string]Object)
for vk, vv := range v {
vo, err := FromInterface(vv)
m := Map{}
for key, value := range v {
vo, err := FromInterface(value)
if err != nil {
return nil, err
}
kv[vk] = vo
m.Value.Set(key, vo)
}
return &Map{Value: kv}, nil
return &m, nil
// kv := make(map[string]Object)
// for vk, vv := range v {
// vo, err := FromInterface(vv)
// if err != nil {
// return nil, err
// }
// kv[vk] = vo
// }
// return &Map{Value: kv}, nil
case []Object:
return &Array{Value: v}, nil
case []interface{}:
Expand Down
Loading

0 comments on commit 7d9ac54

Please sign in to comment.