~repos /plum

#treesitter#compiler#wasm

git clone https://pyrossh.dev/repos/plum.git

A statically typed, imperative programming language inspired by rust, python


af78b68b pyrossh

1 year ago
update
Files changed (12) hide show
  1. readme.md +77 -4
  2. scratch.pc +3 -199
  3. std/bool.mi +4 -1
  4. std/float.mi +0 -0
  5. std/int.mi +0 -0
  6. std/list.mi +3 -3
  7. std/map.mi +8 -8
  8. std/math.mi +1 -0
  9. std/option.mi +15 -4
  10. std/os.mi +45 -2
  11. std/result.mi +16 -20
  12. std/str.mi +7 -5
readme.md CHANGED
@@ -162,9 +162,9 @@ The nil type is used to represent types that are nilable
162
162
 
163
163
  The any type is an empty trait and is used to represent all types
164
164
 
165
- **err**
165
+ **error**
166
166
 
167
- The err type is an enum of all errors
167
+ The error type is an trait that represents all Error types
168
168
 
169
169
  **bool**
170
170
 
@@ -234,7 +234,9 @@ A str represents an array of runes or unicode code points. It is encoded to UTF-
234
234
  It supports interpolation of variables/values that implement the ToStr interface.
235
235
 
236
236
  ```go
237
+ import std/os.{printLn}
238
+
237
- "Hello World"
239
+ sed := "Hello World"
238
240
  name := "Pacos"
239
241
  age := 1
240
242
  printLn("Name ${name} age ${age}")
@@ -296,6 +298,74 @@ friends_tree
296
298
  .reduce(0, |k, v| v + 1)
297
299
  ```
298
300
 
301
+ **option**
302
+
303
+ An option is a type that represents either value present Some or nothing present
304
+
305
+ ```go
306
+ import std/option
307
+
308
+ record Car(wheels: int)
309
+
310
+ c := some(Car(wheels: 2))
311
+
312
+ match c
313
+ none -> print("no car")
314
+ some(car) -> car.wheels
315
+ ```
316
+
317
+ **result**
318
+
319
+ A result is a type that represents either success ok or failure err.
320
+
321
+ ```rs
322
+ import std/str
323
+ import std/result
324
+
325
+ #[error]
326
+ record FetchError()
327
+
328
+ #[error]
329
+ record IOError()
330
+
331
+ #[error]
332
+ record JsonParseError()
333
+
334
+ #[json]
335
+ record UserData(
336
+ id: int,
337
+ name: str,
338
+ roles: List[str]
339
+ )
340
+
341
+ fn parse_version(header: List[int]): result[Version, error] =
342
+ header.get(0) != nil ? v : error.InvalidHeaderLength(header.get(0))
343
+
344
+ fn double_number(s: str): result[int] =
345
+ number_str.parse_int().map(|n| 2 * n)
346
+
347
+ fn fetch_data(route: str): result[UserData] =
348
+ response := fetch(route)?
349
+ data := response.body.readAll()?
350
+ parse_json(data)?
351
+
352
+ fn main(): result[int] =
353
+ double_number("10")?
354
+ version := parse_version(list.of(1, 2))
355
+ conn := pg.connect()?
356
+
357
+ match pg.connect()
358
+ ok(c) -> return 0
359
+ err(e) -> return e
360
+
361
+ res := fetch_data()
362
+ match res
363
+ ok(u) -> u.id
364
+ err(IOError(e)) -> printLn("IO failed")
365
+ err(e) -> printLn("generic error ${e.msg()}")
366
+ ok(0)
367
+ ```
368
+
299
369
  **constants**
300
370
 
301
371
  Constants can be declared at the top level of a program. They cannot be reassigned.
@@ -487,6 +557,10 @@ paint := Paint()
487
557
  ..color = Colors.black
488
558
  ..strokeCap = StrokeCap.round
489
559
  ..strokeWidth = 5.0
560
+
561
+ v := list.of(1, 2, 3)
562
+ ..add(4, 5)
563
+ ..get(0)
490
564
  ```
491
565
 
492
566
  **variadic operator**
@@ -526,7 +600,6 @@ fn add[T: int | float](a: List[T], b: List[T]): List[T] =
526
600
  | Modules | snake_case |
527
601
  | Types/Traits/Enum | UpperCamelCase |
528
602
  | Fields/Functions/Methods | lowerCamelCase |
529
- | Conversion constructors | from_some_other_type |
530
603
  | Local variables | snake_case |
531
604
  | Constants | SCREAMING_SNAKE_CASE |
532
605
  | Generics | single uppercase letter |
scratch.pc CHANGED
@@ -1,8 +1,4 @@
1
1
  data.price?.take_if(|a| a != "")
2
- trait Iterator(
3
- fun has_next(): Bool
4
- fun next(): T?
5
- )
6
2
 
7
3
  trait HasEq[A](
8
4
  fn eq(that: a): bool
@@ -57,175 +53,11 @@ fn (l: list) prepend(v: V) =
57
53
  l.first() = link(v, l.first())
58
54
 
59
55
 
60
- fn range(start: int, e: int, cb: fn(int)) =
61
- match start < end ->
62
- cb(start)
63
- range(start + 1, end, cb)
64
-
65
- fn repeat(n: int, cb: fn(int): void) =
66
- match n != 0
67
- cb()
68
- repeat(n - 1, cb)
69
-
70
- fn repeat(cb: fn(int): void) =
71
- cb()
72
- repeat(cb)
73
-
74
- fn iterate[T](l: list[T], cb: fn(t: T)) =
75
- pass
76
-
77
- fn main() =
78
- repeat(10) |i|
79
- println(i)
80
- range(10, 20) |i|
81
- println(i)
82
-
83
- ```
84
- fn create_post_action(req: Request): Result[Response] =
85
- post := Post(title = req.params.title, body = req.params.body)
86
- if post.valid()
87
- RenderNewView()
88
- else
89
- post := createRecord(post)
90
- setSuccessMessage("Post created")
91
- redirectTo("/posts")
92
-
93
- fn divide(dividend: u32, divisor: u32) !u32 =
94
- if divisor == 0
95
- error.DivideByZero
96
- else
97
- dividend / divisor
98
-
99
- error FileOpenError
100
- | AccessDenied(str)
101
- | OutOfMemory(str)
102
- | FileNotFound(str)
103
-
104
- fn parse_version(header: List[int]): result[Version, error] =
105
- header.get(0) != nil ? v : error.InvalidHeaderLength(header.get(0))
106
-
107
- fn main(): result[unit, unit] =
108
- version := parse_version(list.of(1, 2))
109
- match pg.connect()
110
- ok(c) -> return 0
111
- err(e) -> return e
112
-
113
- greeting_file := file.open("hello.txt").unwrap_or_else() |error|
114
- match error
115
- ErrorKind::NotFound ->
116
- File::create("hello.txt").unwrap_or_else() |error|
117
- panic!("Problem creating the file: {:?}", error)
118
- _ ->
119
- panic!("Problem opening the file: {:?}", error)
120
-
121
- conn := match pg.connect()?
122
- create_post_action(req)
123
- .map(|v| 0)
124
- .map_err(|err| 1)
125
-
126
- create_post_action(req)?
127
- ok()
128
-
129
- greeting_file := file.open("hello.txt")?
130
- ok()
131
-
132
- import std/str
133
- import std/result
134
-
135
- fn double_number(s: str): result[i32, unit] =
136
- number_str.parse_int().map(|n| 2 * n)
137
-
138
- fn main(): result<i32, unit> =
139
- double_number("10")
140
-
141
-
142
- use std::num::ParseIntError;
143
-
144
- fn double_number(number_str: &str) -> Result<i32, ParseIntError> {
145
- number_str.parse::<i32>().map(|n| 2 * n)
146
- }
147
-
148
- fn main() {
149
- match double_number("10") {
150
- Ok(n) => assert_eq!(n, 20),
151
- Err(err) => printLn!("Error: {:?}", err),
152
- }
153
- }
154
-
155
- trait error: debug + display (
156
- fn description(): str
157
- fn cause(): option<error>
158
- )
159
-
160
- trait From<T>(
161
- fn from(v: T) -> Self;
162
- )
163
-
164
- trait Debug(
165
- fn fmt(f: Formateer): result[unit, unit]
166
- )
167
-
168
- trait Display(
169
- fn fmt(f: Formateer): result[unit, unit]
170
- )
171
-
172
- record Car(wheels: int)
173
-
174
- fn getWheels() =
175
- returns 4
176
-
177
- fn main() =
178
- let c1 = some(Car(wheels: 2))
179
- let c2: option<Car> = none
180
-
181
- let c1 = Some(Car(wheels: 2))
182
- let c2: Option<Car> = None
183
-
184
- match c
185
- none -> print("no car")
186
- some(car) -> car.getWheels()
187
-
188
- Car c2 = null
189
- c2.getWheels() // Null pointer
190
- ```
191
-
192
56
  (1 + 2).mod(3).pow(2).sqrt()
193
57
 
194
- math.sqrt(math.pow(math.mod(1 + 2, 3)))
58
+ math.sqrt(math.pow(math.mod(1 + 2, 3), 2))
195
-
196
- repeat(10) |i|
197
- pass
198
-
199
- repeat(n) |i|
200
- pass
201
-
202
- data.each() |k, v|
203
- pass
204
-
205
- list.of(1, 2, 3).each() |v, i|
206
- pass
207
-
208
- map.of("a" => 1, "b" => 2).each() |k, v|
209
- pass
210
59
 
211
- repeat() |_|
212
- pass
213
-
214
- repeat(|_| i < 9) |i|
215
- pass
216
-
217
- repeat(|_| a > b && c < d) |i|
218
- pass
219
-
220
- let v = list.of(1, 2, 3)
221
- |> list.add(1, 2)
222
- |> list.get(0)
223
-
224
- let v = list.of(1, 2, 3)
225
- ..add(1, 2)
226
- ..get(0)
227
-
228
- if v == nil
60
+ if v == none
229
61
  error.Error
230
62
  else
231
63
  c * 20
@@ -241,20 +73,6 @@ match v
241
73
  Some(c) ->
242
74
  return c * 20
243
75
 
244
-
245
- #[json]
246
- record UserData(
247
- id: int,
248
- name: str,
249
- roles: List[str]
250
- )
251
-
252
- `This is to follow the http standards
253
- trait Error(
254
- fn code(): int
255
- fn msg(): str
256
- )
257
-
258
76
  `derive implements this func
259
77
  `Derive is a compiler plugin/generator similar to dart
260
78
  `which runs automatically. Its not a macro more like a decorator.
@@ -267,18 +85,4 @@ type FetchDataError = FetchError | IOError | JsonParseError
267
85
  fn fetch_data(route: str): map[str, any] | UserData | FetchError | IOError | JsonParseError =
268
86
  res := fetch(route)?
269
87
  data := res.body.read_all()?
270
- parse_json(data)?
88
+ parse_json(data)?
271
-
272
- fn main() =
273
- res := fetch_data()
274
- if res is UserData
275
- printLn("Success ${res.id}")
276
- else if res is IOError
277
- printLn("IO failed")
278
- else if res is Error
279
- printLn("generic error ${res.msg()}")
280
-
281
- when res
282
- UserData -> printLn("Success ${res.id}")
283
- IOError -> printLn("IO failed")
284
- _ -> printLn("generic error ${res.msg()}")
std/bool.mi CHANGED
@@ -1,6 +1,9 @@
1
1
  module std
2
2
 
3
+ #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
3
- type bool = true | false
4
+ enum bool =
5
+ | true
6
+ | false
4
7
 
5
8
  fn (x: bool) op_eq(y: bool) = x == y
6
9
  fn (x: bool) op_ne(y: bool) = x != y
std/float.mi ADDED
File without changes
std/int.mi ADDED
File without changes
std/list.mi CHANGED
@@ -1,15 +1,15 @@
1
1
  module std
2
2
 
3
- `A list is a data structure describing a contiguous section of an array stored separately from the slice variable itself.
4
- `It contains the pointers to the start and end nodes (head, tail) and maintains the size as well
5
3
  record list[V](
4
+ `A list is a data structure describing a contiguous section of an array stored separately from the slice variable itself.
5
+ `It contains the pointers to the start and end nodes (head, tail) and maintains the size as well
6
6
  head: node[V]?
7
7
  tail: node[V]?
8
8
  _size: int
9
9
  )
10
10
 
11
- `A node stores the data in a list and contains pointers to the previous and next sibling nodes
12
11
  record node[V](
12
+ `A node stores the data in a list and contains pointers to the previous and next sibling nodes
13
13
  value: V
14
14
  prev: node[V]?
15
15
  next: node[V]?
std/map.mi CHANGED
@@ -1,17 +1,17 @@
1
1
  module std
2
2
 
3
- record Pair[K: Comparable, V](k: K, v: V)
3
+ record pair[K: Comparable, V](k: K, v: V)
4
4
 
5
+ record map[K, V](
5
- `A slice is a data structure describing a contiguous section of an array stored separately from the slice variable itself.
6
+ `A slice is a data structure describing a contiguous section of an array stored separately from the slice variable itself.
6
- `A slice is not an array. A slice describes a piece of an array.
7
+ `A slice is not an array. A slice describes a piece of an array.
7
- record Map[K, V](
8
- items: list[Pair[K, V]]
8
+ items: list[pair[K, V]]
9
9
  )
10
10
 
11
- fn Map.of[K, V](kvs: ...Pair[K, V]): map[K, V] =
11
+ fn Map.of[K, V](kvs: ...pair[K, V]): map[K, V] =
12
12
  map[K, V]().add(kvs)
13
13
 
14
- fn (m: Map) add(kvs: ...Pair[K, V]) =
14
+ fn (m: Map) add(kvs: ...pair[K, V]) =
15
15
  `adds the specified elements to the start of the list
16
16
  items.add(kvs)
17
17
 
@@ -28,7 +28,7 @@ fn (m: Map[K, V]) get(k K): V? =
28
28
  nil
29
29
 
30
30
  fn (m: Map) put(k K, v V) =
31
- list.add(Pair(k, v))
31
+ list.add(pair(k, v))
32
32
 
33
33
  fn (m: Map) put_if(k K, v V) =
34
34
  if
std/math.mi CHANGED
@@ -72,6 +72,7 @@ fn acos(v: float) =
72
72
 
73
73
  `2**28
74
74
  const LARGE = 1 << 28
75
+
75
76
  fn acosh(v: float): float =
76
77
  when
77
78
  x < 1 | IsNaN(x) -> // first case is special case
std/option.mi CHANGED
@@ -1,19 +1,30 @@
1
1
  module std
2
2
 
3
3
  enum option[T] =
4
+ `option is a type that represents either value present Some or nothing present
4
5
  | none
5
6
  | some(T)
6
7
 
8
+ fn (o option[t]) isNone(): option[T] =
9
+ match o
10
+ none -> true
7
- enum Option<T> =
11
+ some(t) -> false
12
+
8
- | None
13
+ fn (o option[t]) isSome(): option[T] =
9
- | Some(T)
14
+ !o.isNone()
10
15
 
11
16
  fn (o option[T]) get(): T =
12
17
  match o
13
18
  some(val) -> val
14
19
  none -> fail("called 'option.get()' on a 'none' value")
15
20
 
21
+ fn (o option[T]) getOrElse(default: T): T =
22
+ `get if present otherwise return default value
23
+ match o
24
+ some(val) -> val
25
+ none -> d
26
+
16
- fn (o option[T: ToStr]) to_str(): str =
27
+ fn (o option[T: ToStr]) toStr(): str =
17
28
  match o
18
29
  some(v) -> v.to_str()
19
30
  none -> "none"
std/os.mi CHANGED
@@ -1,5 +1,48 @@
1
1
  module std
2
2
 
3
- fn printLn(): result[unit, unit] =
3
+ fn printLn(): IOError =
4
4
  `Writes the specified data, followed by the current line terminator, to the standard output stream.
5
- pass
5
+ pass
6
+
7
+ fn readFile(path: str): IO =
8
+ `Returns a stream to a file from the fs
9
+ pass
10
+
11
+ fn writeFile(path: str, data: IO)
12
+ pass
13
+
14
+
15
+ fn access(path[, mode])
16
+ fn appendFile(path, data[, options])
17
+ fn chmod(path, mode)
18
+ fn chown(path, uid, gid)
19
+ fn copyFile(src, dest[, mode])
20
+ fn cp(src, dest[, options])
21
+ fn lchmod(path, mode)
22
+ fn lchown(path, uid, gid)
23
+ fn lutimes(path, atime, mtime)
24
+ fn link(existingPath, newPath)
25
+ fn lstat(path[, options])
26
+ fn mkdir(path[, options])
27
+ fn mkdtemp(prefix[, options])
28
+ fn open(path, flags[, mode])
29
+ fn opendir(path[, options])
30
+ fn readdir(path[, options])
31
+ fn readFile(path[, options])
32
+ fn readlink(path[, options])
33
+ fn realpath(path[, options])
34
+ fn rename(oldPath, newPath)
35
+ fn rmdir(path[, options])
36
+ fn rm(path[, options])
37
+ fn stat(path[, options])
38
+ fn statfs(path[, options])
39
+ fn symlink(target, path[, type])
40
+ fn truncate(path[, len])
41
+ fn unlink(path)
42
+ fn utimes(path, atime, mtime)
43
+ fn watch(filename[, options])
44
+
45
+
46
+ O_RDWR,
47
+ O_CREAT,
48
+ O_EXCL,
std/result.mi CHANGED
@@ -1,35 +1,31 @@
1
1
  module std
2
2
 
3
+ trait Error(
3
- `result is a type that represents either success ok or failure err.
4
+ `This is used to represent an error value across the language
5
+ fn code(): int
6
+ fn msg(): str
4
- #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
7
+ fn cause(): option<Error>
8
+ )
9
+
5
10
  enum result[T]
11
+ `result is a type that represents either success ok or failure err.
6
12
  | ok(T)
7
- | err(error)
13
+ | err(Error)
8
14
 
9
- fn (r result) is_ok(): bool =
15
+ fn (r result) isOk(): bool =
10
16
  match o
11
17
  ok(v) -> return true
12
18
  err(e) -> return false
13
19
 
14
- fn (r result) is_err(): bool =
20
+ fn (r result) isErr(): bool =
15
21
  !o.is_ok()
16
22
 
17
- fn (r result[T, E]) ok(): option[T] =
18
- match o
19
- ok(v) -> some(v)
20
- err(e) -> none
21
-
22
- fn (r result[T, E]) err(): option[E] =
23
- match o
24
- ok(v) -> none
25
- err(e) -> some(v)
26
-
27
23
  fn (r result) get(): T =
28
24
  match o
29
25
  ok(v) -> v
30
26
  err(e) -> panic("called `result.get()` on a `none` value")
31
27
 
32
- fn (r result) default(d: T): T =
28
+ fn (r result) getOrElse(d: T): T =
33
29
  match o
34
30
  ok(v) -> v
35
31
  err(e) -> d
@@ -37,9 +33,9 @@ fn (r result) default(d: T): T =
37
33
  fn (r result) map(cb: fn(v: T)): result =
38
34
  match o
39
35
  ok(v) -> cb(v)
40
- err(e) -> unreachable
36
+ err(e) -> r
41
37
 
42
- fn (r result) map_err(cb: fn(e: E)): result =
38
+ fn (r result) mapErr(cb: fn(e: error)): result =
43
39
  match o
44
- ok(v) -> unreachable
40
+ ok(v) -> r
45
- err(e) -> cb(v)
41
+ err(e) -> cb(v)
std/str.mi CHANGED
@@ -1,14 +1,16 @@
1
1
  module std
2
2
 
3
- `ToStr defines any data that can be converted to a str
4
3
  trait ToStr(
4
+ `ToStr defines any data that can be converted to a str
5
5
  fn to_str(): str
6
6
  )
7
7
 
8
+ record str(
8
- `A str is an array of contiguous data stored in memory with a null termination using hex 0x00 or ASCII 0x00.
9
+ `A str is an array of contiguous data stored in memory with a null termination using hex 0x00 or ASCII 0x00.
9
- `It is immutable and cannot be modified. It is copied for any changes and saved to a new memory location.
10
+ `It is immutable and cannot be modified. It is copied for any changes and saved to a new memory location.
10
- `The previous str is freed if its reference count is 0 within the block.
11
+ `The previous str is freed if its reference count is 0 within the block.
12
+ data: list[byte]
11
- record str(data: list[byte]): Comparable, ToStr
13
+ ): Comparable, ToStr
12
14
 
13
15
  fn str.of(bs ...byte): str =
14
16
  data.add(bs)