diff options
| author | Joel Martin <github@martintribe.org> | 2014-10-09 19:14:43 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-10-09 19:14:43 -0500 |
| commit | f2c9811fd8cbb205fad68952ebc1ba5d310f148d (patch) | |
| tree | 0a1d80a4ccfb6378014098475c70a90093b7efa7 /go/src/core | |
| parent | ad7e866ea1d4d035d876e58bca681a72099449af (diff) | |
| download | mal-f2c9811fd8cbb205fad68952ebc1ba5d310f148d.tar.gz mal-f2c9811fd8cbb205fad68952ebc1ba5d310f148d.zip | |
go: add hash-map support.
Diffstat (limited to 'go/src/core')
| -rw-r--r-- | go/src/core/core.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/go/src/core/core.go b/go/src/core/core.go index cd63930..cdb7d8f 100644 --- a/go/src/core/core.go +++ b/go/src/core/core.go @@ -46,6 +46,72 @@ func slurp(a []MalType) (MalType, error) { } +// Hash Map functions +func assoc(a []MalType) (MalType, error) { + if len(a) <3 { return nil, errors.New("assoc requires at least 3 arguments") } + if (len(a) % 2 != 1) { return nil, errors.New("assoc requires odd number of arguments") } + if !HashMap_Q(a[0]) { return nil, errors.New("assoc called on non-hash map") } + old_hm := a[0].(map[string]MalType) + new_hm := map[string]MalType{} + // copy + for k, v := range old_hm { new_hm[k] = v } + for i := 1; i < len(a); i+=2 { + key := a[i] + if !String_Q(key) { return nil, errors.New("assoc called with non-string key") } + new_hm[key.(string)] = a[i+1] + } + return new_hm, nil +} + +func dissoc(a []MalType) (MalType, error) { + if len(a) <2 { return nil, errors.New("dissoc requires at least 3 arguments") } + if !HashMap_Q(a[0]) { return nil, errors.New("dissoc called on non-hash map") } + old_hm := a[0].(map[string]MalType) + new_hm := map[string]MalType{} + // copy + for k, v := range old_hm { new_hm[k] = v } + for i := 1; i < len(a); i+=1 { + key := a[i] + if !String_Q(key) { return nil, errors.New("dissoc called with non-string key") } + delete(new_hm,key.(string)) + } + return new_hm, nil +} + +func get(a []MalType) (MalType, error) { + if len(a) != 2 { return nil, errors.New("get requires 2 arguments") } + if Nil_Q(a[0]) { return nil, nil } + if !HashMap_Q(a[0]) { return nil, errors.New("get called on non-hash map") } + if !String_Q(a[1]) { return nil, errors.New("get called with non-string key") } + return a[0].(map[string]MalType)[a[1].(string)], nil +} + +func contains_Q(hm MalType, key MalType) (MalType, error) { + if Nil_Q(hm) { return nil, nil } + if !HashMap_Q(hm) { return nil, errors.New("get called on non-hash map") } + if !String_Q(key) { return nil, errors.New("get called with non-string key") } + _, ok := hm.(map[string]MalType)[key.(string)] + return ok, nil +} + +func keys(a []MalType) (MalType, error) { + if !HashMap_Q(a[0]) { return nil, errors.New("keys called on non-hash map") } + slc := []MalType{} + for k, _ := range a[0].(map[string]MalType) { + slc = append(slc, k) + } + return List{slc}, nil +} +func vals(a []MalType) (MalType, error) { + if !HashMap_Q(a[0]) { return nil, errors.New("keys called on non-hash map") } + slc := []MalType{} + for _, v := range a[0].(map[string]MalType) { + slc = append(slc, v) + } + return List{slc}, nil +} + + // Sequence functions func cons(a []MalType) (MalType, error) { @@ -98,6 +164,7 @@ func count(a []MalType) (MalType, error) { switch obj := a[0].(type) { case List: return len(obj.Val), nil case Vector: return len(obj.Val), nil + case map[string]MalType: return len(obj), nil case nil: return 0, nil default: return nil, errors.New("Count called on non-sequence") } @@ -175,6 +242,21 @@ var NS = map[string]MalType{ return List{a}, nil }, "list?": func(a []MalType) (MalType, error) { return List_Q(a[0]), nil }, + "vector": func(a []MalType) (MalType, error) { + return Vector{a}, nil }, + "vector?": func(a []MalType) (MalType, error) { + return Vector_Q(a[0]), nil }, + "hash-map": func(a []MalType) (MalType, error) { + return NewHashMap(List{a}) }, + "map?": func(a []MalType) (MalType, error) { + return HashMap_Q(a[0]), nil }, + "assoc": assoc, + "dissoc": dissoc, + "get": get, + "contains?": func(a []MalType) (MalType, error) { + return contains_Q(a[0], a[1]) }, + "keys": keys, + "vals": vals, "sequential?": func(a []MalType) (MalType, error) { return Sequential_Q(a[0]), nil }, |
