2016-02-19 05:52:05 +08:00
|
|
|
package eval
|
|
|
|
|
2016-03-10 23:36:35 +08:00
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
)
|
2016-02-19 05:52:05 +08:00
|
|
|
|
|
|
|
// Map is a map from string to Value.
|
|
|
|
type Map struct {
|
|
|
|
inner *map[Value]Value
|
|
|
|
}
|
|
|
|
|
2016-03-20 23:18:08 +08:00
|
|
|
type HasKeyer interface {
|
|
|
|
HasKey(k Value) bool
|
|
|
|
}
|
|
|
|
|
2016-02-19 19:21:55 +08:00
|
|
|
type MapLike interface {
|
|
|
|
Lener
|
|
|
|
IndexOneer
|
2016-03-20 23:18:08 +08:00
|
|
|
HasKeyer
|
2016-02-19 19:21:55 +08:00
|
|
|
}
|
|
|
|
|
2016-03-20 23:18:08 +08:00
|
|
|
var _ MapLike = Map{}
|
|
|
|
|
2016-02-19 05:52:05 +08:00
|
|
|
// NewMap creates a new Map.
|
|
|
|
func NewMap(inner map[Value]Value) Map {
|
|
|
|
return Map{&inner}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (Map) Kind() string {
|
|
|
|
return "map"
|
|
|
|
}
|
|
|
|
|
2016-03-10 23:36:35 +08:00
|
|
|
func (m Map) MarshalJSON() ([]byte, error) {
|
|
|
|
// XXX Not the most efficient way.
|
|
|
|
mm := map[string]Value{}
|
|
|
|
for k, v := range *m.inner {
|
|
|
|
mm[ToString(k)] = v
|
|
|
|
}
|
|
|
|
return json.Marshal(mm)
|
|
|
|
}
|
|
|
|
|
2016-02-20 03:11:31 +08:00
|
|
|
func (m Map) Repr(indent int) string {
|
2016-02-19 05:52:05 +08:00
|
|
|
var builder MapReprBuilder
|
2016-02-20 03:11:31 +08:00
|
|
|
builder.Indent = indent
|
2016-02-19 05:52:05 +08:00
|
|
|
for k, v := range *m.inner {
|
2016-02-20 03:31:54 +08:00
|
|
|
builder.WritePair(k.Repr(indent+1), v.Repr(indent+1))
|
2016-02-19 05:52:05 +08:00
|
|
|
}
|
|
|
|
return builder.String()
|
|
|
|
}
|
|
|
|
|
2016-02-19 18:49:19 +08:00
|
|
|
func (m Map) Len() int {
|
|
|
|
return len(*m.inner)
|
|
|
|
}
|
|
|
|
|
2016-02-19 05:52:05 +08:00
|
|
|
func (m Map) IndexOne(idx Value) Value {
|
|
|
|
v, ok := (*m.inner)[idx]
|
|
|
|
if !ok {
|
2016-02-20 03:31:54 +08:00
|
|
|
throw(errors.New("no such key: " + idx.Repr(NoPretty)))
|
2016-02-19 05:52:05 +08:00
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2016-03-20 23:18:08 +08:00
|
|
|
func (m Map) HasKey(k Value) bool {
|
|
|
|
_, ok := (*m.inner)[k]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2016-02-19 05:52:05 +08:00
|
|
|
func (m Map) IndexSet(idx Value, v Value) {
|
|
|
|
(*m.inner)[idx] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
// MapReprBuilder helps building the Repr of a Map. It is also useful for
|
|
|
|
// implementing other Map-like values. The zero value of a MapReprBuilder is
|
|
|
|
// ready to use.
|
|
|
|
type MapReprBuilder struct {
|
2016-02-20 03:11:31 +08:00
|
|
|
ListReprBuilder
|
2016-02-19 05:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *MapReprBuilder) WritePair(k, v string) {
|
2016-02-20 03:11:31 +08:00
|
|
|
b.WriteElem("&" + k + "=" + v)
|
2016-02-19 05:52:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *MapReprBuilder) String() string {
|
|
|
|
if b.buf.Len() == 0 {
|
|
|
|
return "[&]"
|
|
|
|
}
|
2016-02-20 03:11:31 +08:00
|
|
|
return b.ListReprBuilder.String()
|
2016-02-19 05:52:05 +08:00
|
|
|
}
|