Skip to content

Commit

Permalink
Fixes documentation, makes tests return simpler values, deletes usele…
Browse files Browse the repository at this point in the history
…ss snapshot
  • Loading branch information
In-Veritas committed Dec 20, 2024
1 parent 8d9a7e0 commit 2903f35
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 74 deletions.
131 changes: 78 additions & 53 deletions docs/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,15 @@ def Maybe/unwrap(m: Maybe(T)) -> T:
## Map

```python
type Map:
Node { value ~left ~right }
Leaf
type Map(T):
Node { value: Maybe(T), ~left: Map(T), ~right: Map(T) }
Leaf
```

**`Map`** represents a tree with values stored in the branches.
It is meant to be used as an efficient map data structure with integer keys and O(log n) read and write operations.

- **Node { value ~left ~right }**: Represents a map node with a `Maybe` and `left` and `right` subtrees. Empty nodes have `Maybe/None` stored in the `value` field, whislt non-empty nodes have `Maybe/Some` stored in the `value` field.
- **Node { value: Maybe(T), ~left: Map(T), ~right: Map(T) }**: Represents a map node with a `Maybe` and `left` and `right` subtrees. Empty nodes have `Maybe/None` stored in the `value` field, whilst non-empty nodes have `Maybe/Some` stored in the `value` field.
- **Leaf**: Represents an unwritten, empty portion of the map.

#### Syntax
Expand Down Expand Up @@ -241,22 +241,19 @@ Retrieves a `value` from the `map` based on the `key`.
Returns a tuple with the value and the `map` unchanged.

```rust
Map/get map key =
match map {
Map/Leaf: (*, map)
Map/Node:
switch _ = (== 0 key) {
0: switch _ = (% key 2) {
0:
let (got, rest) = (Map/get map.left (/ key 2))
(got, (Map/Node map.value rest map.right))
_:
let (got, rest) = (Map/get map.right (/ key 2))
(got, (Map/Node map.value map.left rest))
}
_: (map.value, map)
}
}
def Map/get (map: Map(T), key: u24) -> (T, Map(T)):
match map:
case Map/Leaf:
return (unreachable(), map)
case Map/Node:
if (0 == key):
return (Maybe/unwrap(map.value), map)
elif (key % 2 == 0):
(got, rest) = Map/get(map.left, (key / 2))
return(got, Map/Node(map.value, rest, map.right))
else:
(got, rest) = Map/get(map.right, (key / 2))
return(got, Map/Node(map.value, map.left, rest))
```

#### Syntax
Expand All @@ -281,29 +278,23 @@ And the value resultant from the get function would be:

### Map/set

Sets a `value` in the `map` at the specified `key`.
Returns the map with the new value.

```rust
Map/set map key value =
match map {
Map/Node:
switch _ = (== 0 key) {
0: switch _ = (% key 2) {
0: (Map/Node map.value (Map/set map.left (/ key 2) value) map.right)
_: (Map/Node map.value map.left (Map/set map.right (/ key 2) value))
}
_: (Map/Node value map.left map.right)
}
Map/Leaf:
switch _ = (== 0 key) {
0: switch _ = (% key 2) {
0: (Map/Node * (Map/set Map/Leaf (/ key 2) value) Map/Leaf)
_: (Map/Node * Map/Leaf (Map/set Map/Leaf (/ key 2) value))
}
_: (Map/Node value Map/Leaf Map/Leaf)
}
}
def Map/set (map: Map(T), key: u24, value: T) -> Map(T):
match map:
case Map/Node:
if (0 == key):
return Map/Node(Maybe/Some(value), map.left, map.right)
elif ((key % 2) == 0):
return Map/Node(map.value, Map/set(map.left, (key / 2), value), map.right)
else:
return Map/Node(map.value, map.left, Map/set(map.right, (key / 2), value))
case Map/Leaf:
if (0 == key):
return Map/Node(Maybe/Some(value), Map/Leaf, Map/Leaf)
elif ((key % 2) == 0):
return Map/Node(Maybe/None, Map/set(Map/Leaf, (key / 2), value), Map/Leaf)
else:
return Map/Node(Maybe/None, Map/Leaf, Map/set(Map/Leaf, (key / 2),value))
```

#### Syntax
Expand Down Expand Up @@ -344,17 +335,17 @@ Applies a function to a value in the map.
Returns the map with the value mapped.

```rust
Map/map (Map/Leaf) key f = Map/Leaf
Map/map (Map/Node value left right) key f =
switch _ = (== 0 key) {
0: switch _ = (% key 2) {
0:
(Map/Node value (Map/map left (/ key 2) f) right)
_:
(Map/Node value left (Map/map right (/ key 2) f))
}
_: (Map/Node (f value) left right)
}
def Map/map (map: Map(T), key: u24, f: T -> T) -> Map(T):
match map:
case Map/Leaf:
return Map/Leaf
case Map/Node:
if (0 == key):
return Map/Node(Maybe/Some(f(Maybe/unwrap(map.value))), map.left, map.right)
elif ((key % 2) == 0):
return Map/Node(map.value, Map/map(map.left, (key / 2), f), map.right)
else:
return Map/Node(map.value, map.left, Map/map(map.right, (key / 2), f))
```

#### Syntax
Expand All @@ -366,6 +357,40 @@ x[0] @= lambda y: String/concat(y, " and mapped")
# x[0] now contains "swapped and mapped"
```


### Map/contains
Checks if a `map` contains a given `key` and returns 0 or 1 as a `u24` number and the `map` unchanged.
```python
def Map/contains (map: Map(T), key: u24) -> (u24, Map(T)):
match map:
case Map/Leaf:
return (0, map)
case Map/Node:
if (0 == key):
match map.value:
case Maybe/Some:
return (1, map)
case Maybe/None:
return (0, map)
elif ((key % 2) == 0):
(new_value, new_map) = Map/contains(map.left, (key / 2))
return (new_value, Map/Node(map.value, new_map, map.right))
else:
(new_value, new_map) = Map/contains(map.right, (key / 2))
return (new_value, Map/Node(map.value, map.left, new_map))
```

#### Syntax

With the same map that we `set` in the previous section, we can call the function `Map/contains` explicitly:

```python
(num, map) = Map/contains(m, key)
return num
```
Whilst the `num` variable will contain 0 or 1 depending on if the key is in the map or not.


## Nat

```python
Expand Down
1 change: 1 addition & 0 deletions examples/example_fun.bend
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ bad_nums : Any = (+ id 1)
# Write new data types like this
type Option = (Some val) | None
type Bool = True | False

# You can have pattern matching on definitions
# Use `*` to ignore a pattern
(Option.unwrap_or (Option/Some val) *) = val
Expand Down
2 changes: 1 addition & 1 deletion src/fun/builtins.bend
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def Maybe/unwrap(m: Maybe(T)) -> T:
# MAP Impl

type Map(T):
Node { value: Maybe(T), ~left: Map(T), ~right: Map(T)}
Node { value: Maybe(T), ~left: Map(T), ~right: Map(T) }
Leaf

# Creates an empty Map
Expand Down
9 changes: 5 additions & 4 deletions tests/golden_tests/prelude/applies_function_to_map.bend
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# Checks if a generic map contains a given key, and if it does, applies a function to the value, otherwise it returns the map
def test(m: Map(u24), key: u24) -> Map(u24):
def test(m: Map(u24), key: u24) -> u24:
def addtwo (x: u24) -> u24:
return (x + 2)
(num, map) = Map/contains(m, key)
if (num == 0):
return m
return unreachable()
else:
return Map/map(m, key, addtwo())

m = Map/map(m, key, addtwo())
(value, map) = Map/get(m, key)
return value
def main() -> _:
m = {3: 255}
return test(m, 3)
8 changes: 4 additions & 4 deletions tests/golden_tests/prelude/get_values_from_map.bend
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
def test1() -> (u24, Map(u24)):
def test1() -> (u24):
m = {}
m = Map/set(Map/set(Map/set(Map/empty, 3, 4), 2, 3), 1, 2)
(val, map) = Map/get(m, 1)
return Map/get(map, val)

(val1, map1) = Map/get(m, 1)
(val2, map2) = Map/get(map1, val1)
return val2

def main() -> _:
return test1()
3 changes: 2 additions & 1 deletion tests/golden_tests/prelude/map_checked_test.bend
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#Tests the get_check function
def main() -> _:
m1 = {0: 42, 1: 7, 2: 13, 3: 255, 4: 100}
m1 = {0: 1, 3: 2}
return Map/get_check(m1, 3)

2 changes: 1 addition & 1 deletion tests/golden_tests/prelude/map_contains_test.bend
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
def main() -> _:
m1 = {0: 42, 1: 7, 2: 13, 3: 255, 4: 100}
m1 = {0: 23}
return Map/contains(m1, 3)
2 changes: 1 addition & 1 deletion tests/snapshots/prelude__applies_function_to_map.bend.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/prelude/applies_function_to_map.bend
---
Strict mode:
λa (a Map/Node/tag Maybe/None Map/Leaf λb (b Map/Node/tag Maybe/None Map/Leaf λc (c Map/Node/tag λd (d Maybe/Some/tag 257) Map/Leaf Map/Leaf)))
257
6 changes: 0 additions & 6 deletions tests/snapshots/prelude__builtin_Map_tests.bend.snap

This file was deleted.

2 changes: 1 addition & 1 deletion tests/snapshots/prelude__get_values_from_map.bend.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/prelude/get_values_from_map.bend
---
Strict mode:
(3, λa (a Map/Node/tag Maybe/None λb (b Map/Node/tag Maybe/None Map/Leaf λc (c Map/Node/tag λd (d Maybe/Some/tag 3) Map/Leaf Map/Leaf)) λe (e Map/Node/tag λf (f Maybe/Some/tag 2) Map/Leaf λg (g Map/Node/tag λh (h Maybe/Some/tag 4) Map/Leaf Map/Leaf))))
3
2 changes: 1 addition & 1 deletion tests/snapshots/prelude__map_checked_test.bend.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/prelude/map_checked_test.bend
---
Strict mode:
a (a Maybe/Some/tag 255), λb (b Map/Node/tag λc (c Maybe/Some/tag 42) λd (d Map/Node/tag Maybe/None λe (e Map/Node/tag Maybe/None Map/Leaf λf (f Map/Node/tag λg (g Maybe/Some/tag 100) Map/Leaf Map/Leaf)) λh (h Map/Node/tag λi (i Maybe/Some/tag 13) Map/Leaf Map/Leaf)) λj (j Map/Node/tag λk (k Maybe/Some/tag 7) Map/Leaf λl (l Map/Node/tag λm (m Maybe/Some/tag 255) Map/Leaf Map/Leaf))))
a (a Maybe/Some/tag 2), λb (b Map/Node/tag λc (c Maybe/Some/tag 1) Map/Leaf λd (d Map/Node/tag Maybe/None Map/Leaf λe (e Map/Node/tag λf (f Maybe/Some/tag 2) Map/Leaf Map/Leaf))))
2 changes: 1 addition & 1 deletion tests/snapshots/prelude__map_contains_test.bend.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ source: tests/golden_tests.rs
input_file: tests/golden_tests/prelude/map_contains_test.bend
---
Strict mode:
(1, λa (a Map/Node/tag λb (b Maybe/Some/tag 42) λc (c Map/Node/tag Maybe/None λd (d Map/Node/tag Maybe/None Map/Leaf λe (e Map/Node/tag λf (f Maybe/Some/tag 100) Map/Leaf Map/Leaf)) λg (g Map/Node/tag λh (h Maybe/Some/tag 13) Map/Leaf Map/Leaf)) λi (i Map/Node/tag λj (j Maybe/Some/tag 7) Map/Leaf λk (k Map/Node/tag λl (l Maybe/Some/tag 255) Map/Leaf Map/Leaf))))
(0, λa (a Map/Node/tag λb (b Maybe/Some/tag 23) Map/Leaf Map/Leaf))

0 comments on commit 2903f35

Please sign in to comment.