Skip to content

Commit 80acc25

Browse files
committed
Fix Readme examples (#389)
* Add tests for files in README Test readme examples to make sure: - Language is at the point where we expect it to be. - And that the examples themselves are correct. This servers as a baseline for current hotfixes. We will also update the examples in the README accordingly so that it conforms the current grammar. * Rename factorial check file * Update some README examples * is a logic excepts class identifier * [ci skip] is a logic excepts class identifier Bunch of other small modifications uncovered while trying to fix the README examples. * Fix handle test * Update version numbers in README
1 parent cf05218 commit 80acc25

17 files changed

Lines changed: 336 additions & 25 deletions

README.md

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,10 @@
1616
<a href="https://github.com/JSAbrahams/mamba/blob/main/LICENSE">
1717
<img src="https://img.shields.io/github/license/JSAbrahams/mamba.svg?style=for-the-badge" alt="License"/>
1818
</a>
19-
<img src="https://img.shields.io/badge/Built%20with-%E2%99%A5-red.svg?style=for-the-badge" alt="Built with Love"/>
20-
<br/>
2119
<a href="https://github.com/JSAbrahams/mamba/milestones">
2220
<img src="https://img.shields.io/github/milestones/open/JSAbrahams/mamba?style=for-the-badge" alt="Active milestones"/>
2321
</a>
22+
<img src="https://img.shields.io/badge/Built%20with-%E2%99%A5-red.svg?style=for-the-badge" alt="Built with Love"/>
2423
</p>
2524

2625
<h1 align="center">Mamba</h1>
@@ -56,7 +55,7 @@ def factorial(x: Int) -> Int => match x
5655
5756
def num := input("Compute factorial: ")
5857
if num.is_digit() then
59-
def result := factorial(int(num))
58+
def result := factorial(Int(num))
6059
print("Factorial {num} is: {result}.")
6160
else
6261
print("Input was not an integer.")
@@ -93,17 +92,21 @@ class MyServer(def ip_address: IPv4Address)
9392
def is_connected: Bool := False
9493
def _last_message: String? := None
9594
96-
def last_sent(fin self) -> String raise ServerError => if self._last_message /= None
97-
then self._last_message
98-
else raise ServerError("No last message!")
95+
def last_sent(fin self) -> String raise [ServerError] =>
96+
if self._last_message != None then
97+
self._last_message
98+
else
99+
raise ServerError("No last message!")
99100
100101
def connect(self) =>
101102
self.is_connected := True
102103
print(always_the_same_message)
103104
104-
def send(self, message: String) raise ServerError => if self.is_connected
105-
then self._last_message := message
106-
else raise ServerError("Not connected!")
105+
def send(self, message: String) raise [ServerError] =>
106+
if self.is_connected then
107+
self._last_message := message
108+
else
109+
raise ServerError("Not connected!")
107110
108111
def disconnect(self) => self.is_connected := False
109112
```
@@ -127,7 +130,7 @@ print("last message sent before disconnect: \"{my_server.last_sent()}\".")
127130
my_server.disconnect()
128131
```
129132

130-
### 🗃 Type refinement (🇻 0.6+)
133+
### 🗃 Type refinement (🇻 0.4.1+)
131134

132135
As shown above Mamba has a type system.
133136
Mamba however also has type refinement features to assign additional properties to types.
@@ -152,9 +155,11 @@ class MyServer(self: DisConnMyServer, def ip_address: IPv4Address): Server
152155
def is_connected: Bool := False
153156
def _last_message: String? := None
154157
155-
def last_sent(self) -> String raise ServerErr => if self.last_message /= None
156-
then self._last_message
157-
else raise ServerError("No last message!")
158+
def last_sent(self) -> String raise ServerErr =>
159+
if self.last_message != None then
160+
self._last_message
161+
else
162+
raise ServerError("No last message!")
158163
159164
def connect(self: DisConnMyServer) => self.is_connected := True
160165
@@ -208,7 +213,7 @@ Type refinement allows us to do some additional things:
208213
that certain conditions hold. We can simply ask whether a given object is a certain state by checking whether it is a
209214
certain type.
210215

211-
### 🔒 Pure functions (🇻 0.4.1)
216+
### 🔒 Pure functions (🇻 0.4.1+)
212217

213218
Mamba has features to ensure that functions are pure, meaning that if `x = y`, for any `f`, `f(x) = f(y)`.
214219
(Except if the output of the function is say `None` or `NaN`.)
@@ -242,7 +247,7 @@ def pure sin(x: Int) =>
242247
ans
243248
```
244249

245-
### ⚠ Error handling (🇻 0.5+)
250+
### ⚠ Error handling
246251

247252
Unlike Python, Mamba does not have `try` `except` and `finally` (or `try` `catch` as it is sometimes known).
248253
Instead, we aim to directly handle errors on-site so the origin of errors is more tracable.
@@ -274,15 +279,16 @@ This also prevents us from wrapping large code blocks in a `try`, where it might
274279
This is shown below:
275280

276281
```mamba
277-
def a := function_may_throw_err() handle
278-
err: MyErr =>
279-
print("We have a problem: {err.message}.")
280-
return # we return, halting execution
281-
err: MyOtherErr =>
282-
print("We have another problem: {err.message}.")
283-
0 # ... or we assign default value 0 to a
284-
285-
print("a has value {a}.")
282+
def g() =>
283+
def a := function_may_throw_err() handle
284+
err: MyErr =>
285+
print("We have a problem: {err.message}.")
286+
return # we return, halting execution
287+
err: MyOtherErr =>
288+
print("We have another problem: {err.message}.")
289+
0 # ... or we assign default value 0 to a
290+
291+
print("a has value {a}.")
286292
```
287293

288294
If we don't want to use a `handle`, we can simply use `raise` after a statement or exception to show that its execution might result in an exception, but we don't want to handle that here.

src/check/resource/primitive/bool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class bool:
2-
def __init__(self, arg: bool) -> bool: pass
2+
def __init__(self, arg: Union[int, str, bool]) -> bool: pass
33

44
def __bool__(self) -> bool: pass
55
def __str__(self) -> str: pass
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from ipaddress import IPv4Address
2+
3+
class ServerErr: Exception
4+
class MyServer(def ip_address: IPv4Address):
5+
def send(self, message: String) =>
6+
pass
7+
def disconnect() => pass
8+
9+
class ConnectedMyServer: MyServer
10+
11+
def fin some_ip := ipaddress.ip_address("151.101.193.140")
12+
def my_server := MyServer(some_ip)
13+
14+
def message := "Hello World!"
15+
my_server.send(message) handle
16+
err: ServerErr => print("Error while sending message: \"{message}\": {err}")
17+
18+
if my_server isa ConnectedMyServer then my_server.disconnect()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from ipaddress import IPv4Address
2+
from server import MyServer
3+
4+
class MyServer:
5+
def __init__(self, ip_address: IPv4Address):
6+
self.ip_address = ip_address
7+
8+
fin some_ip = ipaddress.ip_address("151.101.193.140")
9+
my_server = MyServer(some_ip)
10+
11+
def message = "Hello World!"
12+
try:
13+
my_server.send(message)
14+
except ServerErr as err:
15+
print(f"Error while sending message: \"{message}\": {err}")
16+
17+
if isinstance(my_server, ConnectedMyServer):
18+
my_server.disconnect()
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def factorial(x: Int) -> Int => match x
2+
0 => 1
3+
n =>
4+
def ans := 1
5+
for i in 1 ..= n do ans := ans * i
6+
ans
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
def factorial(x: int) -> int:
2+
match x:
3+
case 0:
4+
return 1
5+
case n:
6+
ans = 1
7+
for i in range(1, n, 1):
8+
ans = ans * i
9+
return ans
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class MyErr(def message: String): Exception
2+
class MyOtherErr(def message: String): Exception
3+
4+
def function_may_throw_err() -> Int raise [MyErr] => 10
5+
6+
def g() =>
7+
def a := function_may_throw_err() handle
8+
err: MyErr =>
9+
print("We have a problem: {err.message}.")
10+
return # we return, halting execution
11+
err: MyOtherErr =>
12+
print("We have another problem: {err.message}.")
13+
0 # ... or we assign default value 0 to a
14+
15+
print("a has value {a}.")
16+
17+
g()
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class MyErr(Exception):
2+
def __init__(self, message: str):
3+
Exception.__init__(self)
4+
self.message = message
5+
6+
class MyOtherErr(Exception):
7+
def __init__(self, message: str):
8+
Exception.__init__(self)
9+
self.message = message
10+
11+
def function_may_throw_err() -> int:
12+
return 10
13+
14+
def g():
15+
a = None
16+
try:
17+
a: int = function_may_throw_err()
18+
except MyErr as err:
19+
print(f"We have a problem: {err.message}.")
20+
return None
21+
except MyOtherErr as err:
22+
print(f"We have another problem: {err.message}.")
23+
a = 0
24+
25+
print(f"a has value {a}.")
26+
27+
g()
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
type PosInt: Int when
2+
self >= 0 else "Must be greater than 0"
3+
4+
def factorial(x: PosInt) -> PosInt => match x
5+
0 => 1
6+
n => n * factorial(n - 1)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# taylor is immutable, its value does not change during execution
2+
def fin taylor := 7
3+
4+
# the sin function is pure, its output depends solely on the input
5+
def pure sin(x: Int) =>
6+
def ans := x
7+
for i in 1 ..= taylor .. 2 do
8+
ans := ans + (x ^ (i + 2)) / (factorial (i + 2))
9+
ans

0 commit comments

Comments
 (0)