Skip to content

Commit

Permalink
Distinguish assign and insert functions
Browse files Browse the repository at this point in the history
  • Loading branch information
raviqqe committed Jun 30, 2018
1 parent de6df66 commit 28ce7dc
Show file tree
Hide file tree
Showing 13 changed files with 275 additions and 89 deletions.
22 changes: 22 additions & 0 deletions examples/collections.feature
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,28 @@ Feature: Collections
When I successfully run `cloe main.cloe`
Then the stdout should contain exactly "42"

Scenario: Assign values to collections
Given a file named "main.cloe" with:
"""
(seq! ..(map print [
(assign {} "foo" 123)
(assign {"bar" 123} "bar" 456)
(assign [123] 1 456)
(assign [123 456 789] 2 42)
(assign "Hallo, world!" 2 "e")
(assign "right" 1 "l")]))
"""
When I successfully run `cloe main.cloe`
Then the stdout should contain exactly:
"""
{"foo" 123}
{"bar" 456}
[456]
[123 42 789]
Hello, world!
light
"""

Scenario: Convert a dictionary to a list
Given a file named "main.cloe" with:
"""
Expand Down
3 changes: 2 additions & 1 deletion src/lib/compile/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ var goBuiltins = func() environment {
"@": core.Index,
"delete": core.Delete,
"include": core.Include,
"assign": core.Assign,
"insert": core.Insert,
"merge": core.Merge,
"size": core.Size,
Expand Down Expand Up @@ -87,7 +88,7 @@ func builtinsEnvironment() environment {
(def (dictionary ..args)
(if (= args [])
{}
(insert
(assign
(dictionary ..(rest (rest args)))
(first args)
(first (rest args)))))
Expand Down
81 changes: 38 additions & 43 deletions src/lib/core/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,52 @@ package core
type collection interface {
Value

assign(Value, Value) Value
include(Value) Value
index(Value) Value
insert(Value, Value) Value
merge(...Value) Value
delete(Value) Value
toList() Value
size() Value
}

// Assign inserts an element into a sequence.
var Assign = NewLazyFunction(
NewSignature([]string{"collection"}, "keyValuePairs", nil, ""),
func(vs ...Value) (result Value) {
c, err := evalCollection(vs[0])

if err != nil {
return err
}

l, err := EvalList(vs[1])

if err != nil {
return err
}

for !l.Empty() {
k := l.First()

if l, err = EvalList(l.Rest()); err != nil {
return err
}

c, err = evalCollection(c.assign(EvalPure(k), l.First()))

if err != nil {
return err
}

if l, err = EvalList(l.Rest()); err != nil {
return err
}
}

return c
})

// Include returns true if a collection includes an element, or false otherwise.
var Include = NewStrictFunction(
NewSignature([]string{"collection", "elem"}, "", nil, ""),
Expand Down Expand Up @@ -49,48 +86,6 @@ var Index = NewStrictFunction(
return v
})

// Insert inserts an element into a collection.
var Insert FunctionType

func initInsert() FunctionType {
return NewLazyFunction(
NewSignature([]string{"collection"}, "keyValuePairs", nil, ""),
func(vs ...Value) (result Value) {
c, err := evalCollection(vs[0])

if err != nil {
return err
}

l, err := EvalList(vs[1])

if err != nil {
return err
}

for !l.Empty() {
k := l.First()
l, err = EvalList(l.Rest())

if err != nil {
return err
}

c, err = evalCollection(c.insert(EvalPure(k), l.First()))

if err != nil {
return err
}

if l, err = EvalList(l.Rest()); err != nil {
return err
}
}

return c
})
}

// Merge merges more than 2 collections.
var Merge FunctionType

Expand Down
30 changes: 15 additions & 15 deletions src/lib/core/dictionary.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,44 +34,44 @@ func NewDictionary(kvs []KeyValue) Value {
d := Value(EmptyDictionary)

for _, kv := range kvs {
d = PApp(Insert, d, kv.Key, kv.Value)
d = PApp(Assign, d, kv.Key, kv.Value)
}

return d
}

func (d *DictionaryType) index(v Value) (result Value) {
func (d *DictionaryType) assign(k Value, v Value) (result Value) {
defer func() {
if r := recover(); r != nil {
result = r.(Value)
}
}()

k, ok := v.(comparable)

if !ok {
return notComparableError(v)
}

if v, ok := d.Search(k); ok {
return v
if _, ok := k.(comparable); !ok {
return notComparableError(k)
}

return keyNotFoundError(k)
return d.Insert(k, v)
}

func (d *DictionaryType) insert(k Value, v Value) (result Value) {
func (d *DictionaryType) index(v Value) (result Value) {
defer func() {
if r := recover(); r != nil {
result = r.(Value)
}
}()

if _, ok := k.(comparable); !ok {
return notComparableError(k)
k, ok := v.(comparable)

if !ok {
return notComparableError(v)
}

return d.Insert(k, v)
if v, ok := d.Search(k); ok {
return v
}

return keyNotFoundError(k)
}

func (d *DictionaryType) toList() (result Value) {
Expand Down

0 comments on commit 28ce7dc

Please sign in to comment.