plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
f7bd316
— pyrossh
2024-03-01T12:19:38+05:30
add docs
Generated files not shown: website/package-lock.json
- .gitignore +1 -2
- readme.md +1 -651
- std/float.mi +0 -0
- std/int.mi +0 -0
- std/str.mi +3 -3
- website/.gitignore +21 -0
- website/.vscode/extensions.json +4 -0
- website/.vscode/launch.json +11 -0
- website/astro.config.mjs +53 -0
- website/package.json +17 -0
- website/public/favicon.svg +1 -0
- website/src/assets/houston.webp +0 -0
- website/src/content/config.ts +6 -0
- website/src/content/docs/declarations/aliases.md +11 -0
- website/src/content/docs/declarations/enum.md +29 -0
- website/src/content/docs/declarations/functions.md +28 -0
- website/src/content/docs/declarations/records.md +24 -0
- website/src/content/docs/declarations/traits.md +22 -0
- website/src/content/docs/index.mdx +162 -0
- website/src/content/docs/operators/logical.md +91 -0
- website/src/content/docs/primitive-types.md +55 -0
- website/src/content/docs/reference-types.md +150 -0
- website/src/content/docs/statements/constants.md +25 -0
- website/src/content/docs/statements/for.md +19 -0
- website/src/content/docs/statements/if.md +15 -0
- website/src/content/docs/statements/match.md +28 -0
- website/src/content/docs/statements/variables.md +18 -0
- website/src/content/docs/statements/while.md +20 -0
- website/src/env.d.ts +2 -0
- website/tsconfig.json +3 -0
.gitignore
CHANGED
|
@@ -8,5 +8,4 @@ src/language/generated/
|
|
|
8
8
|
static/bundle/
|
|
9
9
|
static/monaco-editor-workers/
|
|
10
10
|
static/worker/
|
|
11
|
-
syntaxes/
|
|
11
|
+
syntaxes/
|
|
12
|
-
website
|
readme.md
CHANGED
|
@@ -4,657 +4,7 @@
|
|
|
4
4
|
- The compiler users the tree-sitter parser so has out of the box syntax highlighting support for helix and zed editor
|
|
5
5
|
- Plans to be compiled to WASM
|
|
6
6
|
|
|
7
|
-
Here is some sample code, please enjoy
|
|
8
|
-
|
|
9
|
-
```rs
|
|
10
|
-
module lambda
|
|
11
|
-
|
|
12
|
-
import std/list
|
|
13
|
-
import std/math
|
|
14
|
-
import std/http
|
|
15
|
-
|
|
16
|
-
const DELTA = 11
|
|
17
|
-
|
|
18
|
-
fn sum(a: int, b: int): int = a + b + DELTA
|
|
19
|
-
|
|
20
|
-
fn sumAll(series: list[int]): int =
|
|
21
|
-
series.reduce(0, |v| v + 1)
|
|
22
|
-
|
|
23
|
-
fn fib(n: int): int =
|
|
24
|
-
match n
|
|
25
|
-
0 | 1 -> n
|
|
26
|
-
_ -> fib(n - 1) + fib(n - 2)
|
|
27
|
-
|
|
28
|
-
fn fib(n: int): int =
|
|
29
|
-
if n == 0 || n == 1
|
|
30
|
-
n
|
|
31
|
-
else
|
|
32
|
-
fib(n - 1) + fib(n - 2)
|
|
33
|
-
|
|
34
|
-
fn factorial(n: int): int =
|
|
35
|
-
match n
|
|
36
|
-
a -> 1
|
|
37
|
-
_ -> n * factorial(n - 1)
|
|
38
|
-
|
|
39
|
-
fn firstItem(items: list[int]): option[int] =
|
|
40
|
-
items.get(0)
|
|
41
|
-
|
|
42
|
-
fn toCelsius(f: float): float =
|
|
43
|
-
(f - 32) * (5 / 9)
|
|
44
|
-
|
|
45
|
-
// Variadic function
|
|
46
|
-
fn addItems(items ...str) =
|
|
47
|
-
list.add(items)
|
|
48
|
-
|
|
49
|
-
record Cat(
|
|
50
|
-
name: str
|
|
51
|
-
age: int
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
// Additional Cat Contructor which is just a static function on type Cat
|
|
55
|
-
fn Cat.withName(name: str): Cat =
|
|
56
|
-
Cat(name: name, age: 0)
|
|
57
|
-
|
|
58
|
-
// A simple method
|
|
59
|
-
fn fullname(c: Cat): str =
|
|
60
|
-
c.name + c.age.toStr()
|
|
61
|
-
|
|
62
|
-
fn talk(c: Cat) =
|
|
63
|
-
printLn("cat ${c.name} says meow")
|
|
64
|
-
|
|
65
|
-
fn toStr(c: Cat): str =
|
|
66
|
-
"Cat<{c.fullname()}, ${c.age}>"
|
|
67
|
-
|
|
68
|
-
trait Stringable where
|
|
69
|
-
fn toStr(): str
|
|
70
|
-
|
|
71
|
-
// `Cat is a speciecs of felidae
|
|
72
|
-
struct Cat is Stringable, Equal, Comparable =
|
|
73
|
-
| name: str
|
|
74
|
-
| age: int
|
|
75
|
-
|
|
76
|
-
fn Cat(name: str, age: int) =
|
|
77
|
-
self.name = name
|
|
78
|
-
self.age = age
|
|
79
|
-
|
|
80
|
-
fn Cat.withName(name: str): Cat =
|
|
81
|
-
`Create a cat with only name
|
|
82
|
-
Cat(name: name, age: 0)
|
|
83
|
-
|
|
84
|
-
fn fullname(): str =
|
|
85
|
-
name + age.toStr()
|
|
86
|
-
|
|
87
|
-
fn talk() =
|
|
88
|
-
printLn("cat ${name} says meow")
|
|
89
|
-
|
|
90
|
-
fn toStr(): str =
|
|
91
|
-
"Cat<${fullname()}, ${age}>"
|
|
92
|
-
|
|
93
|
-
enum Temperature where
|
|
94
|
-
| celsius(float)
|
|
95
|
-
| fahrenheit(float)
|
|
96
|
-
|
|
97
|
-
fn toStr(): str =
|
|
98
|
-
match self
|
|
99
|
-
celsius(t) && t > 30 -> "${t}C is above 30 celsius"
|
|
100
|
-
celsius(t) -> "${t}C is below 30 celsius"
|
|
101
|
-
fahrenheit(t) && t > 86 -> "${t}F is above 86 fahrenheit"
|
|
102
|
-
fahrenheit(t) -> "${t}F is below 86 fahrenheit"
|
|
103
|
-
|
|
104
|
-
type MapCallback = fn(v: a): v
|
|
105
|
-
|
|
106
|
-
struct DB(conn_url: str) where
|
|
107
|
-
|
|
108
|
-
fn connect(): Result[unit, DatabaseError] =
|
|
109
|
-
`connect to the database
|
|
110
|
-
online := status()
|
|
111
|
-
if !online
|
|
112
|
-
Err(NotOnline(conn_url))
|
|
113
|
-
else
|
|
114
|
-
Ok(unit)
|
|
115
|
-
|
|
116
|
-
fn status(): bool =
|
|
117
|
-
`check if the database is running
|
|
118
|
-
res := exec("select 1")
|
|
119
|
-
if res == None
|
|
120
|
-
false
|
|
121
|
-
else
|
|
122
|
-
true
|
|
123
|
-
|
|
124
|
-
fn exec(q: str): Result[unit] =
|
|
125
|
-
`exec some stuff
|
|
126
|
-
printLn("Going to exec q")
|
|
127
|
-
|
|
128
|
-
#[error]
|
|
129
|
-
enum DatabaseError =
|
|
130
|
-
NotOnline(conn_url: str)
|
|
131
|
-
RowReadFailure(query: str)
|
|
132
|
-
|
|
133
|
-
fn newDB(conn_url: str) result[DB, DatabaseError] =
|
|
134
|
-
db := DB(conn_url: str)
|
|
135
|
-
online := db.status()
|
|
136
|
-
if !online
|
|
137
|
-
err(NotOnline(conn_url))
|
|
138
|
-
else
|
|
139
|
-
db
|
|
140
|
-
|
|
141
|
-
fn (d: DB) status(): bool =
|
|
142
|
-
res := d.exec("select 1")
|
|
143
|
-
if res == None
|
|
144
|
-
false
|
|
145
|
-
else
|
|
146
|
-
true
|
|
147
|
-
|
|
148
|
-
suite "Cat" do
|
|
149
|
-
test "talks" do
|
|
150
|
-
c := Cat(name: "123", age: 1)
|
|
151
|
-
c2 := Cat(...c, age: c.age + 1)
|
|
152
|
-
c.talk()
|
|
153
|
-
|
|
154
|
-
test "fullname" do
|
|
155
|
-
Assert.equal(Cat("rabby", 21).fullname(), "rabby21")
|
|
156
|
-
|
|
157
|
-
test "ToStr" do
|
|
158
|
-
items := [Cat("Molly", 9), Cat("Fenton", 6)]
|
|
159
|
-
.retain(|p| p.name.size > 5)
|
|
160
|
-
.map(|p| describe(p))
|
|
161
|
-
.each(|d| printLn(d))
|
|
162
|
-
Assert.equal(items[0].toStr(), "Cat<Fenton, 6>")
|
|
163
|
-
|
|
164
|
-
suite "diagonal" do
|
|
165
|
-
test "3 4 5" do
|
|
166
|
-
Assert.equal 5.0 (diagonal 3.0 4.0)
|
|
167
|
-
test "5 12 13" do
|
|
168
|
-
Assert.equal 5.0 (diagonal 3.0 4.0)
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
# Types
|
|
172
|
-
|
|
173
|
-
### any
|
|
174
|
-
|
|
175
|
-
The any type is an empty trait and is used to represent all types
|
|
176
|
-
|
|
177
|
-
### error
|
|
178
|
-
|
|
179
|
-
The error type is a trait that represents all Error types
|
|
180
|
-
|
|
181
|
-
## bool
|
|
182
|
-
|
|
183
|
-
A bool can be either `true` or `false`. It is used in logical operations and conditional statements.
|
|
184
|
-
|
|
185
|
-
```rb
|
|
186
|
-
assert true != false
|
|
187
|
-
|
|
188
|
-
if true || false
|
|
189
|
-
print("works")
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
## byte
|
|
193
|
-
|
|
194
|
-
A byte represents an unsigned 8-bit number. It is mainly used to represent strings and binary data.
|
|
195
|
-
|
|
196
|
-
```go
|
|
197
|
-
up_event := 'a'
|
|
198
|
-
key_code := 102
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## int
|
|
202
|
-
|
|
203
|
-
An int is a signed 64-bit number. It can be represented in various ways,
|
|
204
|
-
|
|
205
|
-
| Notation | Type | Base | Example |
|
|
206
|
-
| -------- | ----------- | ------- | ------------------------- |
|
|
207
|
-
| 0b | Binary | Base 2 | `0b00101010`, `0b1_1111` |
|
|
208
|
-
| 0x | Hexadecimal | Base 16 | `0xff00ff`, `0xFF80_0000` |
|
|
209
|
-
| number | Standard | Base 10 | `98762`, `98_762` |
|
|
210
|
-
|
|
211
|
-
## float
|
|
212
|
-
|
|
213
|
-
A float represents a 64-bit floating point [IEEE-754-2008](https://en.wikipedia.org/wiki/Double-precision_floating-point_format).
|
|
214
|
-
|
|
215
|
-
| Type | Example |
|
|
216
|
-
| ----------- | ----------------- |
|
|
217
|
-
| Normal | `1.2`, `-0.4` |
|
|
218
|
-
| With suffix | `15.03f`, `12.0f` |
|
|
219
|
-
| E notation | `2.7e-12`, `1e10` |
|
|
220
|
-
|
|
221
|
-
## dec
|
|
222
|
-
|
|
223
|
-
A dec is a decimal floating-point numbering format which is 64-bit data type.
|
|
224
|
-
It is intended for applications where it is necessary to emulate decimal rounding exactly, such as financial and tax computations.
|
|
225
|
-
It supports 16 decimal digits of significand and an exponent range of −383 to +384.
|
|
226
|
-
|
|
227
|
-
| Type | Example |
|
|
228
|
-
| ---------- | ----------------- |
|
|
229
|
-
| Normal | `2.4d`, `-13.3d` |
|
|
230
|
-
| E notation | `2.7e-12`, `1e10` |
|
|
231
|
-
|
|
232
|
-
## str
|
|
233
|
-
|
|
234
|
-
A str represents an array of runes or unicode code points. It is encoded to UTF-8 by default.
|
|
235
|
-
It supports interpolation of variables/values that implement the ToStr interface.
|
|
236
|
-
|
|
237
|
-
```go
|
|
238
|
-
import std/os.{printLn}
|
|
239
|
-
|
|
240
|
-
sed := "Hello World"
|
|
241
|
-
name := "Pacos"
|
|
242
|
-
age := 1
|
|
243
|
-
printLn("Name ${name} age ${age}")
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
## list
|
|
247
|
-
|
|
248
|
-
```py
|
|
249
|
-
import std/list
|
|
250
|
-
|
|
251
|
-
a := List.of(1, 2, 3) # List[int]
|
|
252
|
-
b := List.of( # List[List[int]]
|
|
253
|
-
List.of(1),
|
|
254
|
-
List.of(2),
|
|
255
|
-
List.of(3),
|
|
256
|
-
)
|
|
257
|
-
c := List.of(1, 2, 3 * 4, 8, n)
|
|
258
|
-
|
|
259
|
-
actors := List.of("Krabs", "Squidward")
|
|
260
|
-
actors.add("Spongebob")
|
|
261
|
-
actors.length() // ==> 3
|
|
262
|
-
|
|
7
|
+
View the docs here [pacos.sh](https://pacos.sh)
|
|
263
|
-
actors.get(0) // => "Krabs"
|
|
264
|
-
actors.get(5) // => nil
|
|
265
|
-
|
|
266
|
-
items
|
|
267
|
-
.map(|v| v + 1)
|
|
268
|
-
.each(|v| printLn("v", v))
|
|
269
|
-
.reduce(0, |v| v + 1)
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## map
|
|
273
|
-
|
|
274
|
-
```rs
|
|
275
|
-
import std/map
|
|
276
|
-
|
|
277
|
-
nums := Map.of("one" => 1, "two" => 2)
|
|
278
|
-
map.get("one") // => some(1)
|
|
279
|
-
map.get("unknown") // => none
|
|
280
|
-
friends_tree := Map.of(
|
|
281
|
-
"value" => "Fred",
|
|
282
|
-
"left" => Map.of(
|
|
283
|
-
"value" => "Jim",
|
|
284
|
-
),
|
|
285
|
-
"right" => Map.of(
|
|
286
|
-
"value" => "Shiela",
|
|
287
|
-
"left" => Map.of(
|
|
288
|
-
"value" => "Alice",
|
|
289
|
-
),
|
|
290
|
-
"right" => Map.of(
|
|
291
|
-
"value" => "Bob"
|
|
292
|
-
),
|
|
293
|
-
),
|
|
294
|
-
)
|
|
295
|
-
|
|
296
|
-
friends_tree
|
|
297
|
-
.map(|k, v| v)
|
|
298
|
-
.each(|k, v| printLn("v", v))
|
|
299
|
-
.reduce(0, |k, v| v + 1)
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
## option
|
|
303
|
-
|
|
304
|
-
An option is a type that represents either value present `some` or nothing present `none`
|
|
305
|
-
|
|
306
|
-
```go
|
|
307
|
-
import std/option
|
|
308
|
-
|
|
309
|
-
c := some(2)
|
|
310
|
-
|
|
311
|
-
match c
|
|
312
|
-
none -> print("no car")
|
|
313
|
-
some(c) -> print("${c}")
|
|
314
|
-
|
|
315
|
-
if some(count) = c
|
|
316
|
-
printLn("Hello ${count}")
|
|
317
|
-
else
|
|
318
|
-
printLn("nothing")
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
## result
|
|
322
|
-
|
|
323
|
-
A result is a type that represents either success `ok` or failure `err`
|
|
324
|
-
|
|
325
|
-
```rs
|
|
326
|
-
import std/str
|
|
327
|
-
import std/result
|
|
328
|
-
|
|
329
|
-
#[error]
|
|
330
|
-
record FetchError()
|
|
331
|
-
|
|
332
|
-
#[error]
|
|
333
|
-
record IOError()
|
|
334
|
-
|
|
335
|
-
#[error]
|
|
336
|
-
record JsonParseError()
|
|
337
|
-
|
|
338
|
-
#[error("Version is nil")]
|
|
339
|
-
record ParseVersionError()
|
|
340
|
-
|
|
341
|
-
#[json]
|
|
342
|
-
record UserData(
|
|
343
|
-
id: int,
|
|
344
|
-
name: str,
|
|
345
|
-
roles: List[str]
|
|
346
|
-
)
|
|
347
|
-
|
|
348
|
-
fn parseVersion(header: List[int]): result[int, ParseVersionError] =
|
|
349
|
-
header.get(0) ?: ParseError()
|
|
350
|
-
|
|
351
|
-
fn doubleNumber(s: str): result[int] =
|
|
352
|
-
number_str.parse_int().map(|n| 2 * n)
|
|
353
|
-
|
|
354
|
-
fn fetchData(route: str): result[UserData] =
|
|
355
|
-
response := fetch(route)?
|
|
356
|
-
data := response.body.readAll()?
|
|
357
|
-
parseJson(data)?
|
|
358
|
-
|
|
359
|
-
fn main(): result[int] =
|
|
360
|
-
n := doubleNumber("10")?
|
|
361
|
-
version := parseVersion(list.of(1, 2))?
|
|
362
|
-
res := fetchData()
|
|
363
|
-
match res
|
|
364
|
-
ok(u) -> return ok(u.id)
|
|
365
|
-
err(IOError(e)) -> printLn("IO failed")
|
|
366
|
-
err(e) -> printLn("generic error ${e.msg()}")
|
|
367
|
-
ok(0)
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
# Declarations
|
|
371
|
-
|
|
372
|
-
## constants
|
|
373
|
-
|
|
374
|
-
Constants can be declared at the top level of a program. They cannot be reassigned.
|
|
375
|
-
|
|
376
|
-
- Primitive values like`int, float, str` are directly replaced in code.
|
|
377
|
-
- Reference values like `list, map, records` are initialized at program start and passed by reference when used. Their data can be modified.
|
|
378
|
-
|
|
379
|
-
```rb
|
|
380
|
-
const START_YEAR = 2101
|
|
381
|
-
const PI = 3.14159
|
|
382
|
-
const NAME = "pacos"
|
|
383
|
-
const DEBUG_ENABLED = true
|
|
384
|
-
const COUNT = count(10)
|
|
385
|
-
const COUNTRIES_LIST = list.of("US", "INDIA", "CANADA")
|
|
386
|
-
const COUNTRY_CODES = map.of(
|
|
387
|
-
"in" => "INDIA",
|
|
388
|
-
"us" => "United States",
|
|
389
|
-
"ca" => "Canada"
|
|
390
|
-
)
|
|
391
|
-
|
|
392
|
-
fn count(n: int): int = n * 1
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
## variables
|
|
396
|
-
|
|
397
|
-
Variables can be declared only at the local scope of a function as they are mutable. They are references/pointers to data.
|
|
398
|
-
We use the Short Variable Declaration Operator `:=` to declare a variable
|
|
399
|
-
|
|
400
|
-
```go
|
|
401
|
-
fn calculate(n: int): int =
|
|
402
|
-
a := 1 + n
|
|
403
|
-
b := 1 * n
|
|
404
|
-
a * b
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
## Functions
|
|
408
|
-
|
|
409
|
-
```rs
|
|
410
|
-
fn fib(n: int): int =
|
|
411
|
-
match n
|
|
412
|
-
0 | 1 -> n
|
|
413
|
-
_ -> fib(n - 1) + fib(n - 2)
|
|
414
|
-
|
|
415
|
-
fn log(level: str, msg: str) =
|
|
416
|
-
printLn("${level}: ${msg}")
|
|
417
|
-
|
|
418
|
-
fn info(msg: str) =
|
|
419
|
-
printLn("INFO", msg)
|
|
420
|
-
|
|
421
|
-
fn warning(msg: str) =
|
|
422
|
-
printLn("WARN", msg)
|
|
423
|
-
|
|
424
|
-
fn addLists[T](a: List[T], b: List[T]): List[T] =
|
|
425
|
-
a.concat(b)
|
|
426
|
-
|
|
427
|
-
// Variadic function
|
|
428
|
-
fn addItems(items ...str) =
|
|
429
|
-
for i, v := range items
|
|
430
|
-
printLn("${i} ${v}")
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
## Records
|
|
434
|
-
|
|
435
|
-
A record is a collect of data indexed by fields. It is a reference type and reference counted.
|
|
436
|
-
|
|
437
|
-
```rs
|
|
438
|
-
struct Cat is Stringable =
|
|
439
|
-
| name: str
|
|
440
|
-
| age: int
|
|
441
|
-
|
|
442
|
-
fn Cat.withName(name: str): Cat =
|
|
443
|
-
Cat(name: name, age: 0)
|
|
444
|
-
|
|
445
|
-
fn fullname(): str =
|
|
446
|
-
name + age.toStr()
|
|
447
|
-
|
|
448
|
-
fn talk() =
|
|
449
|
-
printLn("cat ${name} says meow")
|
|
450
|
-
|
|
451
|
-
fn toStr(): str =
|
|
452
|
-
"Cat<${fullname()}, ${age}>"
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
## Traits
|
|
456
|
-
|
|
457
|
-
```rs
|
|
458
|
-
trait Equatable[A] where
|
|
459
|
-
fn eq(left: A, right: A): bool
|
|
460
|
-
fn neq(left: A, right: A): bool
|
|
461
|
-
|
|
462
|
-
trait Comparable[A: Ord] where
|
|
463
|
-
fn compare(left: A, right: A): Ordering
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
## Enums
|
|
467
|
-
|
|
468
|
-
An Algebraic Data Type
|
|
469
|
-
|
|
470
|
-
```rs
|
|
471
|
-
enum Ordering is Stringable =
|
|
472
|
-
| LT
|
|
473
|
-
| EQ
|
|
474
|
-
| GT
|
|
475
|
-
|
|
476
|
-
fn toStr(): str =
|
|
477
|
-
match self
|
|
478
|
-
LT -> "LT"
|
|
479
|
-
EQ -> "EQ"
|
|
480
|
-
GT -> "GT"
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
## Type
|
|
484
|
-
|
|
485
|
-
```rs
|
|
486
|
-
type Size = int
|
|
487
|
-
type Metre = float
|
|
488
|
-
type MapString[T] = Map[String, T]
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
# Statements
|
|
492
|
-
|
|
493
|
-
## Assignment statement
|
|
494
|
-
|
|
495
|
-
```rb
|
|
496
|
-
low, mid, high := 0, 0, n.numItems
|
|
497
|
-
x := 10
|
|
498
|
-
y := 20
|
|
499
|
-
xy_list := List.of(1, 2, 3)
|
|
500
|
-
xy_map := Map.of(1 => "one", 2 => "two")
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
## while statement
|
|
504
|
-
|
|
505
|
-
```rb
|
|
506
|
-
low, mid, high := 0, 0, n.size
|
|
507
|
-
while low < high
|
|
508
|
-
mid = (low + high) / 2
|
|
509
|
-
low = cmp > 0 ? mid + 1 : low
|
|
510
|
-
high = cmp < 0 ? mid : high
|
|
511
|
-
if cmp == 0
|
|
512
|
-
return mid, true
|
|
513
|
-
|
|
514
|
-
while a > b
|
|
515
|
-
a += 1
|
|
516
|
-
|
|
517
|
-
while Some(top) = stack.pop()
|
|
518
|
-
printLn(top)
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
## for statement
|
|
522
|
-
|
|
523
|
-
```rb
|
|
524
|
-
for i := range 10
|
|
525
|
-
sum += i
|
|
526
|
-
|
|
527
|
-
n := 5
|
|
528
|
-
for i := range n
|
|
529
|
-
sum += i + 5
|
|
530
|
-
|
|
531
|
-
for k, v := range json_map
|
|
532
|
-
sum += k + v
|
|
533
|
-
|
|
534
|
-
for v := range list
|
|
535
|
-
sum += k + v
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
## if expression/statement
|
|
539
|
-
|
|
540
|
-
```py
|
|
541
|
-
if name == "Andreas"
|
|
542
|
-
printLn("What a nice name!")
|
|
543
|
-
else if name == "Pacman"
|
|
544
|
-
printLn("Game from the 80s")
|
|
545
|
-
else if name == ""
|
|
546
|
-
printLn("Don't you have a name?")
|
|
547
|
-
else
|
|
548
|
-
printLn("Boring name...")
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
## Match expression/statement
|
|
552
|
-
|
|
553
|
-
```rs
|
|
554
|
-
fn getPerimeter(shape: Shape): Result[float] =
|
|
555
|
-
match shape
|
|
556
|
-
Rectangle(r) -> Ok(2 * r.length() + 2 * r.width())
|
|
557
|
-
Circle(c) -> Ok(2 * c.radius() * PI)
|
|
558
|
-
_ -> Err(RuntimeError("expected shape but found ${@TypeName(shape)}"))
|
|
559
|
-
|
|
560
|
-
match x, y
|
|
561
|
-
1, 1 -> "both are 1"
|
|
562
|
-
1, _ -> "x is 1"
|
|
563
|
-
_, 1 -> "y is 1"
|
|
564
|
-
_, _ -> "neither is 1"
|
|
565
|
-
|
|
566
|
-
match n
|
|
567
|
-
2 | 4 | 6 | 8 -> "This is an even number"
|
|
568
|
-
1 | 3 | 5 | 7 -> "This is an odd number"
|
|
569
|
-
_ -> "I'm not sure"
|
|
570
|
-
|
|
571
|
-
match
|
|
572
|
-
cmp > 0 -> low = mid + 1
|
|
573
|
-
cmp < 0 -> high = mid
|
|
574
|
-
cmp == 0 -> return mid, true
|
|
575
|
-
```
|
|
576
|
-
|
|
577
|
-
## Operators
|
|
578
|
-
|
|
579
|
-
**assignment operator**
|
|
580
|
-
|
|
581
|
-
```go
|
|
582
|
-
x := 5
|
|
583
|
-
y := 3
|
|
584
|
-
x += y // 8
|
|
585
|
-
x -= y // 5
|
|
586
|
-
x *= y // 15
|
|
587
|
-
x /= y // 5
|
|
588
|
-
x %= y // 2
|
|
589
|
-
x &= y // 2
|
|
590
|
-
x |= y // 3
|
|
591
|
-
x <<= y // 24
|
|
592
|
-
x >>= y // 3
|
|
593
|
-
a ?= 2 // elvis assignment operator
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
**not operator**
|
|
597
|
-
|
|
598
|
-
```rb
|
|
599
|
-
!a
|
|
600
|
-
!true
|
|
601
|
-
```
|
|
602
|
-
|
|
603
|
-
**ternary operator**
|
|
604
|
-
|
|
605
|
-
```rb
|
|
606
|
-
x ? a : b
|
|
607
|
-
```
|
|
608
|
-
|
|
609
|
-
**safe navigation operator**
|
|
610
|
-
|
|
611
|
-
```rb
|
|
612
|
-
a?.b?.c?.d
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
**elvis operator**
|
|
616
|
-
|
|
617
|
-
```rb
|
|
618
|
-
x ?: y
|
|
619
|
-
```
|
|
620
|
-
|
|
621
|
-
**cascade operator (remove??)**
|
|
622
|
-
|
|
623
|
-
```dart
|
|
624
|
-
paint := Paint()
|
|
625
|
-
..color = Colors.black
|
|
626
|
-
..strokeCap = StrokeCap.round
|
|
627
|
-
..strokeWidth = 5.0
|
|
628
|
-
|
|
629
|
-
v := list.of(1, 2, 3)
|
|
630
|
-
..add(4, 5)
|
|
631
|
-
..get(0)
|
|
632
|
-
```
|
|
633
|
-
|
|
634
|
-
**range operator**
|
|
635
|
-
|
|
636
|
-
```rs
|
|
637
|
-
type Seq0 = fn(yield: fn(): bool): bool
|
|
638
|
-
type Seq1[V] = fn(yield: fn(V): bool): bool
|
|
639
|
-
type Seq2[K, V] = fn(yield: fn(K, V): bool): bool
|
|
640
|
-
|
|
641
|
-
struct Tree[E] =
|
|
642
|
-
| value E
|
|
643
|
-
| left: Option[Tree]
|
|
644
|
-
| right: Option[Tree]
|
|
645
|
-
|
|
646
|
-
fn op_range(yld: fn(E): bool): bool =
|
|
647
|
-
t ? true : t.left?.in_order(yld) && yld(t.val) && t.right?.in_order(yld)
|
|
648
|
-
|
|
649
|
-
let tree = Tree(
|
|
650
|
-
value: 10,
|
|
651
|
-
left: Tree(20, Tree(30), Tree(39)),
|
|
652
|
-
right: Tree(40),
|
|
653
|
-
)
|
|
654
|
-
|
|
655
|
-
for t := range tree:
|
|
656
|
-
printLn(v)
|
|
657
|
-
```
|
|
658
8
|
|
|
659
9
|
## Rules
|
|
660
10
|
|
std/float.mi
DELETED
|
File without changes
|
std/int.mi
DELETED
|
File without changes
|
std/str.mi
CHANGED
|
@@ -135,13 +135,13 @@ fn reverse(): str
|
|
|
135
135
|
start = start + 1
|
|
136
136
|
result
|
|
137
137
|
|
|
138
|
-
fn
|
|
138
|
+
fn parseInt(): int! =
|
|
139
139
|
0
|
|
140
140
|
|
|
141
|
-
fn
|
|
141
|
+
fn parseFloat(): float! =
|
|
142
142
|
0.0
|
|
143
143
|
|
|
144
|
-
fn
|
|
144
|
+
fn parseBool(): bool! =
|
|
145
145
|
match to_lower()
|
|
146
146
|
"true" -> bool::true
|
|
147
147
|
"false" -> bool::false
|
website/.gitignore
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# build output
|
|
2
|
+
dist/
|
|
3
|
+
# generated types
|
|
4
|
+
.astro/
|
|
5
|
+
|
|
6
|
+
# dependencies
|
|
7
|
+
node_modules/
|
|
8
|
+
|
|
9
|
+
# logs
|
|
10
|
+
npm-debug.log*
|
|
11
|
+
yarn-debug.log*
|
|
12
|
+
yarn-error.log*
|
|
13
|
+
pnpm-debug.log*
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# environment variables
|
|
17
|
+
.env
|
|
18
|
+
.env.production
|
|
19
|
+
|
|
20
|
+
# macOS-specific files
|
|
21
|
+
.DS_Store
|
website/.vscode/extensions.json
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"recommendations": ["astro-build.astro-vscode"],
|
|
3
|
+
"unwantedRecommendations": []
|
|
4
|
+
}
|
website/.vscode/launch.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"command": "./node_modules/.bin/astro dev",
|
|
6
|
+
"name": "Development server",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"type": "node-terminal"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
website/astro.config.mjs
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { defineConfig } from "astro/config";
|
|
2
|
+
import starlight from "@astrojs/starlight";
|
|
3
|
+
|
|
4
|
+
// https://astro.build/config
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
integrations: [
|
|
7
|
+
starlight({
|
|
8
|
+
title: "👾 pacos.sh",
|
|
9
|
+
social: {
|
|
10
|
+
github: "https://github.com/pyrossh/pacos.sh",
|
|
11
|
+
},
|
|
12
|
+
sidebar: [
|
|
13
|
+
{
|
|
14
|
+
label: "Basic Types",
|
|
15
|
+
link: "/primitive-types",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
label: "Reference Types",
|
|
19
|
+
link: "/reference-types",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
label: "Declarations",
|
|
23
|
+
items: [
|
|
24
|
+
{ label: "Records", link: "/declarations/records" },
|
|
25
|
+
{ label: "Traits", link: "/declarations/traits" },
|
|
26
|
+
{ label: "Enum", link: "/declarations/enum" },
|
|
27
|
+
{ label: "Type Alias", link: "/declarations/aliases" },
|
|
28
|
+
{ label: "Functions", link: "/declarations/functions" },
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: "Statements",
|
|
33
|
+
items: [
|
|
34
|
+
{ label: "Constants", link: "/statements/constants" },
|
|
35
|
+
{ label: "Variables", link: "/statements/variables" },
|
|
36
|
+
{ label: "If", link: "/statements/if" },
|
|
37
|
+
{ label: "While", link: "/statements/while" },
|
|
38
|
+
{ label: "For", link: "/statements/for" },
|
|
39
|
+
{ label: "Match", link: "/statements/match" },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: "Operators",
|
|
44
|
+
link: "/operators/logical",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
label: "Comments/Documentation",
|
|
48
|
+
link: "/operators/logical",
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
}),
|
|
52
|
+
],
|
|
53
|
+
});
|
website/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "website",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "astro dev",
|
|
7
|
+
"start": "astro dev",
|
|
8
|
+
"build": "astro build",
|
|
9
|
+
"preview": "astro preview",
|
|
10
|
+
"astro": "astro"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@astrojs/starlight": "^0.20.1",
|
|
14
|
+
"astro": "^4.3.5",
|
|
15
|
+
"sharp": "^0.32.5"
|
|
16
|
+
}
|
|
17
|
+
}
|
website/public/favicon.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill-rule="evenodd" d="M81 36 64 0 47 36l-1 2-9-10a6 6 0 0 0-9 9l10 10h-2L0 64l36 17h2L28 91a6 6 0 1 0 9 9l9-10 1 2 17 36 17-36v-2l9 10a6 6 0 1 0 9-9l-9-9 2-1 36-17-36-17-2-1 9-9a6 6 0 1 0-9-9l-9 10v-2Zm-17 2-2 5c-4 8-11 15-19 19l-5 2 5 2c8 4 15 11 19 19l2 5 2-5c4-8 11-15 19-19l5-2-5-2c-8-4-15-11-19-19l-2-5Z" clip-rule="evenodd"/><path d="M118 19a6 6 0 0 0-9-9l-3 3a6 6 0 1 0 9 9l3-3Zm-96 4c-2 2-6 2-9 0l-3-3a6 6 0 1 1 9-9l3 3c3 2 3 6 0 9Zm0 82c-2-2-6-2-9 0l-3 3a6 6 0 1 0 9 9l3-3c3-2 3-6 0-9Zm96 4a6 6 0 0 1-9 9l-3-3a6 6 0 1 1 9-9l3 3Z"/><style>path{fill:#000}@media (prefers-color-scheme:dark){path{fill:#fff}}</style></svg>
|
website/src/assets/houston.webp
ADDED
|
Binary file
|
website/src/content/config.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { defineCollection } from 'astro:content';
|
|
2
|
+
import { docsSchema } from '@astrojs/starlight/schema';
|
|
3
|
+
|
|
4
|
+
export const collections = {
|
|
5
|
+
docs: defineCollection({ schema: docsSchema() }),
|
|
6
|
+
};
|
website/src/content/docs/declarations/aliases.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Type Alias
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
```rs
|
|
8
|
+
type Size = int
|
|
9
|
+
type Metre = float
|
|
10
|
+
type MapString[T] = Map[String, T]
|
|
11
|
+
```
|
website/src/content/docs/declarations/enum.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Enum
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
An Algebraic Data Type
|
|
7
|
+
|
|
8
|
+
```rs
|
|
9
|
+
enum Ordering is Stringable =
|
|
10
|
+
| LT
|
|
11
|
+
| EQ
|
|
12
|
+
| GT
|
|
13
|
+
|
|
14
|
+
fn toStr(): str =
|
|
15
|
+
match self
|
|
16
|
+
LT -> "LT"
|
|
17
|
+
EQ -> "EQ"
|
|
18
|
+
GT -> "GT"
|
|
19
|
+
|
|
20
|
+
enum Shape where
|
|
21
|
+
| Circle(int)
|
|
22
|
+
| Square(int)
|
|
23
|
+
| Rectangle(int, int)
|
|
24
|
+
|
|
25
|
+
enum Shape where
|
|
26
|
+
Circle(int)
|
|
27
|
+
Square(int)
|
|
28
|
+
Rectangle(int, int)
|
|
29
|
+
```
|
website/src/content/docs/declarations/functions.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Functions
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```rs
|
|
7
|
+
fn fib(n: int): int =
|
|
8
|
+
match n
|
|
9
|
+
0 | 1 -> n
|
|
10
|
+
_ -> fib(n - 1) + fib(n - 2)
|
|
11
|
+
|
|
12
|
+
fn log(level: str, msg: str) =
|
|
13
|
+
printLn("${level}: ${msg}")
|
|
14
|
+
|
|
15
|
+
fn info(msg: str) =
|
|
16
|
+
printLn("INFO", msg)
|
|
17
|
+
|
|
18
|
+
fn warning(msg: str) =
|
|
19
|
+
printLn("WARN", msg)
|
|
20
|
+
|
|
21
|
+
fn addLists[T](a: List[T], b: List[T]): List[T] =
|
|
22
|
+
a.concat(b)
|
|
23
|
+
|
|
24
|
+
// Variadic function
|
|
25
|
+
fn addItems(items ...str) =
|
|
26
|
+
for i, v := range items
|
|
27
|
+
printLn("${i} ${v}")
|
|
28
|
+
```
|
website/src/content/docs/declarations/records.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Records
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
A record is a collect of data indexed by fields. It is a reference type and reference counted.
|
|
7
|
+
|
|
8
|
+
```rs
|
|
9
|
+
struct Cat is Stringable where
|
|
10
|
+
| name: str
|
|
11
|
+
| age: int
|
|
12
|
+
|
|
13
|
+
fn Cat.withName(name: str): Cat =
|
|
14
|
+
Cat(name: name, age: 0)
|
|
15
|
+
|
|
16
|
+
fn fullname(): str =
|
|
17
|
+
name + age.toStr()
|
|
18
|
+
|
|
19
|
+
fn talk() =
|
|
20
|
+
printLn("cat ${name} says meow")
|
|
21
|
+
|
|
22
|
+
fn toStr(): str =
|
|
23
|
+
"Cat<${fullname()}, ${age}>"
|
|
24
|
+
```
|
website/src/content/docs/declarations/traits.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Traits
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Traits are used to implement static/dynamic dispatch
|
|
7
|
+
|
|
8
|
+
```rs
|
|
9
|
+
trait HasEq[A] where
|
|
10
|
+
fn eq(other: A): bool
|
|
11
|
+
|
|
12
|
+
trait Equatable[A] where
|
|
13
|
+
fn eq(other: A): bool
|
|
14
|
+
fn ne(other: A): bool
|
|
15
|
+
|
|
16
|
+
trait Comparable[A: Ord] is Equatable where
|
|
17
|
+
fn lt(other: A): bool
|
|
18
|
+
fn le(other: A): bool
|
|
19
|
+
fn ge(other: A): bool
|
|
20
|
+
fn gt(other: A): bool
|
|
21
|
+
fn compare(other: A): int
|
|
22
|
+
```
|
website/src/content/docs/index.mdx
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 👾 pacos-lang
|
|
3
|
+
description: A statically typed, imperative programming language inspired by rust, koka
|
|
4
|
+
template: splash
|
|
5
|
+
hero:
|
|
6
|
+
tagline: A statically typed, imperative programming language inspired by rust, koka. With plans to be compiled to WASM.
|
|
7
|
+
image:
|
|
8
|
+
file: ../../assets/houston.webp
|
|
9
|
+
actions:
|
|
10
|
+
- text: Checkout the Documentation
|
|
11
|
+
link: /primitive-types
|
|
12
|
+
icon: right-arrow
|
|
13
|
+
variant: secondary
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
### Here is some sample code, please enjoy,
|
|
17
|
+
|
|
18
|
+
```rs
|
|
19
|
+
module lambda
|
|
20
|
+
|
|
21
|
+
import std/list
|
|
22
|
+
import std/math
|
|
23
|
+
import std/http
|
|
24
|
+
|
|
25
|
+
const DELTA = 11
|
|
26
|
+
|
|
27
|
+
fn sum(a: int, b: int): int = a + b + DELTA
|
|
28
|
+
|
|
29
|
+
fn sumAll(series: list[int]): int =
|
|
30
|
+
series.reduce(0, |v| v + 1)
|
|
31
|
+
|
|
32
|
+
fn fib(n: int): int =
|
|
33
|
+
match n
|
|
34
|
+
0 | 1 -> n
|
|
35
|
+
_ -> fib(n - 1) + fib(n - 2)
|
|
36
|
+
|
|
37
|
+
fn fib(n: int): int =
|
|
38
|
+
if n == 0 || n == 1
|
|
39
|
+
n
|
|
40
|
+
else
|
|
41
|
+
fib(n - 1) + fib(n - 2)
|
|
42
|
+
|
|
43
|
+
fn factorial(n: int): int =
|
|
44
|
+
match n
|
|
45
|
+
a -> 1
|
|
46
|
+
_ -> n * factorial(n - 1)
|
|
47
|
+
|
|
48
|
+
fn firstItem(items: list[int]): option[int] =
|
|
49
|
+
items.get(0)
|
|
50
|
+
|
|
51
|
+
fn toCelsius(f: float): float =
|
|
52
|
+
(f - 32) * (5 / 9)
|
|
53
|
+
|
|
54
|
+
// Variadic function
|
|
55
|
+
fn addItems(items ...str) =
|
|
56
|
+
list.add(items)
|
|
57
|
+
|
|
58
|
+
trait Stringable where
|
|
59
|
+
fn toStr(): str
|
|
60
|
+
|
|
61
|
+
// `Cat is a speciecs of felidae
|
|
62
|
+
struct Cat is Stringable, Equal, Comparable =
|
|
63
|
+
| name: str
|
|
64
|
+
| age: int
|
|
65
|
+
|
|
66
|
+
fn Cat(name: str, age: int) =
|
|
67
|
+
self.name = name
|
|
68
|
+
self.age = age
|
|
69
|
+
|
|
70
|
+
fn Cat.withName(name: str): Cat =
|
|
71
|
+
`Create a cat with only name
|
|
72
|
+
Cat(name: name, age: 0)
|
|
73
|
+
|
|
74
|
+
fn fullname(): str =
|
|
75
|
+
name + age.toStr()
|
|
76
|
+
|
|
77
|
+
fn talk() =
|
|
78
|
+
printLn("cat ${name} says meow")
|
|
79
|
+
|
|
80
|
+
fn toStr(): str =
|
|
81
|
+
"Cat<${fullname()}, ${age}>"
|
|
82
|
+
|
|
83
|
+
enum Temperature where
|
|
84
|
+
| celsius(float)
|
|
85
|
+
| fahrenheit(float)
|
|
86
|
+
|
|
87
|
+
fn toStr(): str =
|
|
88
|
+
match self
|
|
89
|
+
celsius(t) && t > 30 -> "${t}C is above 30 celsius"
|
|
90
|
+
celsius(t) -> "${t}C is below 30 celsius"
|
|
91
|
+
fahrenheit(t) && t > 86 -> "${t}F is above 86 fahrenheit"
|
|
92
|
+
fahrenheit(t) -> "${t}F is below 86 fahrenheit"
|
|
93
|
+
|
|
94
|
+
alias MapCallback = fn(v: a): v
|
|
95
|
+
|
|
96
|
+
struct DB where
|
|
97
|
+
let conn_url: str
|
|
98
|
+
|
|
99
|
+
fn connect(): Result[unit, DatabaseError] =
|
|
100
|
+
`connect to the database
|
|
101
|
+
online := status()
|
|
102
|
+
if !online
|
|
103
|
+
Err(NotOnline(conn_url))
|
|
104
|
+
else
|
|
105
|
+
Ok(unit)
|
|
106
|
+
|
|
107
|
+
fn status(): bool =
|
|
108
|
+
`check if the database is running
|
|
109
|
+
res := exec("select 1")
|
|
110
|
+
if res == None
|
|
111
|
+
false
|
|
112
|
+
else
|
|
113
|
+
true
|
|
114
|
+
|
|
115
|
+
fn exec(q: str): Result[unit] =
|
|
116
|
+
`exec some stuff
|
|
117
|
+
printLn("Going to exec q")
|
|
118
|
+
|
|
119
|
+
#[error]
|
|
120
|
+
enum DatabaseError =
|
|
121
|
+
NotOnline(conn_url: str)
|
|
122
|
+
RowReadFailure(query: str)
|
|
123
|
+
|
|
124
|
+
fn newDB(conn_url: str) result[DB, DatabaseError] =
|
|
125
|
+
db := DB(conn_url: str)
|
|
126
|
+
online := db.status()
|
|
127
|
+
if !online
|
|
128
|
+
err(NotOnline(conn_url))
|
|
129
|
+
else
|
|
130
|
+
db
|
|
131
|
+
|
|
132
|
+
fn (d: DB) status(): bool =
|
|
133
|
+
res := d.exec("select 1")
|
|
134
|
+
if res == None
|
|
135
|
+
false
|
|
136
|
+
else
|
|
137
|
+
true
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
#[test]
|
|
141
|
+
primitive CatTest
|
|
142
|
+
fn talk(t: TestHelper) =
|
|
143
|
+
c := Cat(name: "123", age: 1)
|
|
144
|
+
c2 := Cat(...c, age: c.age + 1)
|
|
145
|
+
c.talk()
|
|
146
|
+
|
|
147
|
+
fn fullname(t: TestHelper) =
|
|
148
|
+
Assert.equal(Cat("rabby", 21).fullname(), "rabby21")
|
|
149
|
+
|
|
150
|
+
fn toStr() =
|
|
151
|
+
items := [Cat("Molly", 9), Cat("Fenton", 6)]
|
|
152
|
+
.retain(|p| p.name.size > 5)
|
|
153
|
+
.map(|p| describe(p))
|
|
154
|
+
.each(|d| printLn(d))
|
|
155
|
+
Assert.equal(items[0].toStr(), "Cat<Fenton, 6>")
|
|
156
|
+
|
|
157
|
+
suite "diagonal" do
|
|
158
|
+
test "3 4 5" do
|
|
159
|
+
Assert.equal 5.0 (diagonal 3.0 4.0)
|
|
160
|
+
test "5 12 13" do
|
|
161
|
+
Assert.equal 5.0 (diagonal 3.0 4.0)
|
|
162
|
+
```
|
website/src/content/docs/operators/logical.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Operators
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
### Arithmetic
|
|
7
|
+
### Relational
|
|
8
|
+
### Logical
|
|
9
|
+
### Bitwise
|
|
10
|
+
### Assignment
|
|
11
|
+
### Precedence
|
|
12
|
+
|
|
13
|
+
**assignment operator**
|
|
14
|
+
|
|
15
|
+
```go
|
|
16
|
+
x := 5
|
|
17
|
+
y := 3
|
|
18
|
+
x += y // 8
|
|
19
|
+
x -= y // 5
|
|
20
|
+
x *= y // 15
|
|
21
|
+
x /= y // 5
|
|
22
|
+
x %= y // 2
|
|
23
|
+
x &= y // 2
|
|
24
|
+
x |= y // 3
|
|
25
|
+
x <<= y // 24
|
|
26
|
+
x >>= y // 3
|
|
27
|
+
a ?= 2 // elvis assignment operator
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**not operator**
|
|
31
|
+
|
|
32
|
+
```rb
|
|
33
|
+
!a
|
|
34
|
+
!true
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**ternary operator**
|
|
38
|
+
|
|
39
|
+
```rb
|
|
40
|
+
x ? a : b
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**safe navigation operator**
|
|
44
|
+
|
|
45
|
+
```rb
|
|
46
|
+
a?.b?.c?.d
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**elvis operator**
|
|
50
|
+
|
|
51
|
+
```rb
|
|
52
|
+
x ?: y
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**cascade operator (remove??)**
|
|
56
|
+
|
|
57
|
+
```dart
|
|
58
|
+
paint := Paint()
|
|
59
|
+
..color = Colors.black
|
|
60
|
+
..strokeCap = StrokeCap.round
|
|
61
|
+
..strokeWidth = 5.0
|
|
62
|
+
|
|
63
|
+
v := list.of(1, 2, 3)
|
|
64
|
+
..add(4, 5)
|
|
65
|
+
..get(0)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**range operator**
|
|
69
|
+
|
|
70
|
+
```rs
|
|
71
|
+
type Seq0 = fn(yield: fn(): bool): bool
|
|
72
|
+
type Seq1[V] = fn(yield: fn(V): bool): bool
|
|
73
|
+
type Seq2[K, V] = fn(yield: fn(K, V): bool): bool
|
|
74
|
+
|
|
75
|
+
struct Tree[E] =
|
|
76
|
+
| value E
|
|
77
|
+
| left: Option[Tree]
|
|
78
|
+
| right: Option[Tree]
|
|
79
|
+
|
|
80
|
+
fn op_range(yld: fn(E): bool): bool =
|
|
81
|
+
t ? true : t.left?.in_order(yld) && yld(t.val) && t.right?.in_order(yld)
|
|
82
|
+
|
|
83
|
+
let tree = Tree(
|
|
84
|
+
value: 10,
|
|
85
|
+
left: Tree(20, Tree(30), Tree(39)),
|
|
86
|
+
right: Tree(40),
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
for t := range tree:
|
|
90
|
+
printLn(v)
|
|
91
|
+
```
|
website/src/content/docs/primitive-types.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Basic Types
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## bool
|
|
7
|
+
|
|
8
|
+
A bool can be either `true` or `false`. It is used in logical operations and conditional statements.
|
|
9
|
+
|
|
10
|
+
```rb
|
|
11
|
+
assert true != false
|
|
12
|
+
|
|
13
|
+
if true || false
|
|
14
|
+
print("works")
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## byte
|
|
18
|
+
|
|
19
|
+
A byte represents an unsigned 8-bit number. It is mainly used to represent strings and binary data.
|
|
20
|
+
|
|
21
|
+
```go
|
|
22
|
+
up_event := 'a'
|
|
23
|
+
key_code := 102
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## int
|
|
27
|
+
|
|
28
|
+
An int is a signed 64-bit number. It can be represented in various ways,
|
|
29
|
+
|
|
30
|
+
| Notation | Type | Base | Example |
|
|
31
|
+
| -------- | ----------- | ------- | ------------------------- |
|
|
32
|
+
| 0b | Binary | Base 2 | `0b00101010`, `0b1_1111` |
|
|
33
|
+
| 0x | Hexadecimal | Base 16 | `0xff00ff`, `0xFF80_0000` |
|
|
34
|
+
| number | Standard | Base 10 | `98762`, `98_762` |
|
|
35
|
+
|
|
36
|
+
## float
|
|
37
|
+
|
|
38
|
+
A float represents a 64-bit floating point [IEEE-754-2008](https://en.wikipedia.org/wiki/Double-precision_floating-point_format).
|
|
39
|
+
|
|
40
|
+
| Type | Example |
|
|
41
|
+
| ----------- | ----------------- |
|
|
42
|
+
| Normal | `1.2`, `-0.4` |
|
|
43
|
+
| With suffix | `15.03f`, `12.0f` |
|
|
44
|
+
| E notation | `2.7e-12`, `1e10` |
|
|
45
|
+
|
|
46
|
+
## dec
|
|
47
|
+
|
|
48
|
+
A dec is a decimal floating-point numbering format which is 64-bit data type.
|
|
49
|
+
It is intended for applications where it is necessary to emulate decimal rounding exactly, such as financial and tax computations.
|
|
50
|
+
It supports 16 decimal digits of significand and an exponent range of −383 to +384.
|
|
51
|
+
|
|
52
|
+
| Type | Example |
|
|
53
|
+
| ---------- | ----------------- |
|
|
54
|
+
| Normal | `2.4d`, `-13.3d` |
|
|
55
|
+
| E notation | `2.7e-12`, `1e10` |
|
website/src/content/docs/reference-types.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Reference Types
|
|
3
|
+
description: These are basic refernce types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## any
|
|
7
|
+
|
|
8
|
+
The any type is an empty trait and is used to represent all types
|
|
9
|
+
|
|
10
|
+
## error
|
|
11
|
+
|
|
12
|
+
The error type is a trait that represents all Error types
|
|
13
|
+
|
|
14
|
+
## str
|
|
15
|
+
|
|
16
|
+
A str represents an array of runes or unicode code points. It is encoded to UTF-8 by default.
|
|
17
|
+
It supports interpolation of variables/values that implement the ToStr interface.
|
|
18
|
+
|
|
19
|
+
```go
|
|
20
|
+
import std/os.{printLn}
|
|
21
|
+
|
|
22
|
+
sed := "Hello World"
|
|
23
|
+
name := "Pacos"
|
|
24
|
+
age := 1
|
|
25
|
+
printLn("Name ${name} age ${age}")
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## list
|
|
29
|
+
|
|
30
|
+
```py
|
|
31
|
+
import std/list
|
|
32
|
+
|
|
33
|
+
a := List.of(1, 2, 3) # List[int]
|
|
34
|
+
b := List.of( # List[List[int]]
|
|
35
|
+
List.of(1),
|
|
36
|
+
List.of(2),
|
|
37
|
+
List.of(3),
|
|
38
|
+
)
|
|
39
|
+
c := List.of(1, 2, 3 * 4, 8, n)
|
|
40
|
+
|
|
41
|
+
actors := List.of("Krabs", "Squidward")
|
|
42
|
+
actors.add("Spongebob")
|
|
43
|
+
actors.length() // ==> 3
|
|
44
|
+
actors.contains("Krabs") // ==> true
|
|
45
|
+
actors.get(0) // => "Krabs"
|
|
46
|
+
actors.get(5) // => nil
|
|
47
|
+
|
|
48
|
+
items
|
|
49
|
+
.map(|v| v + 1)
|
|
50
|
+
.each(|v| printLn("v", v))
|
|
51
|
+
.reduce(0, |v| v + 1)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## map
|
|
55
|
+
|
|
56
|
+
```rs
|
|
57
|
+
import std/map
|
|
58
|
+
|
|
59
|
+
nums := Map.of("one" => 1, "two" => 2)
|
|
60
|
+
map.get("one") // => some(1)
|
|
61
|
+
map.get("unknown") // => none
|
|
62
|
+
friends_tree := Map.of(
|
|
63
|
+
"value" => "Fred",
|
|
64
|
+
"left" => Map.of(
|
|
65
|
+
"value" => "Jim",
|
|
66
|
+
),
|
|
67
|
+
"right" => Map.of(
|
|
68
|
+
"value" => "Shiela",
|
|
69
|
+
"left" => Map.of(
|
|
70
|
+
"value" => "Alice",
|
|
71
|
+
),
|
|
72
|
+
"right" => Map.of(
|
|
73
|
+
"value" => "Bob"
|
|
74
|
+
),
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
friends_tree
|
|
79
|
+
.map(|k, v| v)
|
|
80
|
+
.each(|k, v| printLn("v", v))
|
|
81
|
+
.reduce(0, |k, v| v + 1)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## option
|
|
85
|
+
|
|
86
|
+
An option is a type that represents either value present `some` or nothing present `none`
|
|
87
|
+
|
|
88
|
+
```go
|
|
89
|
+
import std/option
|
|
90
|
+
|
|
91
|
+
c := some(2)
|
|
92
|
+
|
|
93
|
+
match c
|
|
94
|
+
none -> print("no car")
|
|
95
|
+
some(c) -> print("${c}")
|
|
96
|
+
|
|
97
|
+
if some(count) = c
|
|
98
|
+
printLn("Hello ${count}")
|
|
99
|
+
else
|
|
100
|
+
printLn("nothing")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## result
|
|
104
|
+
|
|
105
|
+
A result is a type that represents either success `ok` or failure `err`
|
|
106
|
+
|
|
107
|
+
```rs
|
|
108
|
+
import std/str
|
|
109
|
+
import std/result
|
|
110
|
+
|
|
111
|
+
#[error]
|
|
112
|
+
record FetchError()
|
|
113
|
+
|
|
114
|
+
#[error]
|
|
115
|
+
record IOError()
|
|
116
|
+
|
|
117
|
+
#[error]
|
|
118
|
+
record JsonParseError()
|
|
119
|
+
|
|
120
|
+
#[error("Version is nil")]
|
|
121
|
+
record ParseVersionError()
|
|
122
|
+
|
|
123
|
+
#[json]
|
|
124
|
+
record UserData(
|
|
125
|
+
id: int,
|
|
126
|
+
name: str,
|
|
127
|
+
roles: List[str]
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
fn parseVersion(header: List[int]): result[int, ParseVersionError] =
|
|
131
|
+
header.get(0) ?: ParseError()
|
|
132
|
+
|
|
133
|
+
fn doubleNumber(s: str): result[int] =
|
|
134
|
+
number_str.parse_int().map(|n| 2 * n)
|
|
135
|
+
|
|
136
|
+
fn fetchData(route: str): result[UserData] =
|
|
137
|
+
response := fetch(route)?
|
|
138
|
+
data := response.body.readAll()?
|
|
139
|
+
parseJson(data)?
|
|
140
|
+
|
|
141
|
+
fn main(): result[int] =
|
|
142
|
+
n := doubleNumber("10")?
|
|
143
|
+
version := parseVersion(list.of(1, 2))?
|
|
144
|
+
res := fetchData()
|
|
145
|
+
match res
|
|
146
|
+
Ok(u) -> return Ok(u.id)
|
|
147
|
+
Err(IOError(e)) -> printLn("IO failed")
|
|
148
|
+
Err(e) -> printLn("generic error ${e.msg()}")
|
|
149
|
+
Ok(0)
|
|
150
|
+
```
|
website/src/content/docs/statements/constants.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Constants
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Constants can be declared at the top level of a program. They cannot be reassigned.
|
|
7
|
+
|
|
8
|
+
- Primitive values like`int, float, str` are directly replaced in code.
|
|
9
|
+
- Reference values like `list, map, records` are initialized at program start and passed by reference when used. Their data can be modified.
|
|
10
|
+
|
|
11
|
+
```rb
|
|
12
|
+
const START_YEAR = 2101
|
|
13
|
+
const PI = 3.14159
|
|
14
|
+
const NAME = "pacos"
|
|
15
|
+
const DEBUG_ENABLED = true
|
|
16
|
+
const COUNT = count(10)
|
|
17
|
+
const COUNTRIES_LIST = List.of("US", "INDIA", "CANADA")
|
|
18
|
+
const COUNTRY_CODES = Map.of(
|
|
19
|
+
"in" => "INDIA",
|
|
20
|
+
"us" => "United States",
|
|
21
|
+
"ca" => "Canada"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
fn count(n: int): int = n * 1
|
|
25
|
+
```
|
website/src/content/docs/statements/for.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: For Statement
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```rb
|
|
7
|
+
for i := range 10
|
|
8
|
+
sum += i
|
|
9
|
+
|
|
10
|
+
n := 5
|
|
11
|
+
for i := range n
|
|
12
|
+
sum += i + 5
|
|
13
|
+
|
|
14
|
+
for k, v := range json_map
|
|
15
|
+
sum += k + v
|
|
16
|
+
|
|
17
|
+
for v := range list
|
|
18
|
+
sum += k + v
|
|
19
|
+
```
|
website/src/content/docs/statements/if.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: If Statement
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```py
|
|
7
|
+
if name == "Andreas"
|
|
8
|
+
printLn("What a nice name!")
|
|
9
|
+
else if name == "Pacman"
|
|
10
|
+
printLn("Game from the 80s")
|
|
11
|
+
else if name == ""
|
|
12
|
+
printLn("Don't you have a name?")
|
|
13
|
+
else
|
|
14
|
+
printLn("Boring name...")
|
|
15
|
+
```
|
website/src/content/docs/statements/match.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Match
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```rs
|
|
7
|
+
fn getPerimeter(shape: Shape): Result[float] =
|
|
8
|
+
match shape
|
|
9
|
+
Rectangle(r) -> Ok(2 * r.length() + 2 * r.width())
|
|
10
|
+
Circle(c) -> Ok(2 * c.radius() * PI)
|
|
11
|
+
_ -> Err(RuntimeError("expected shape but found ${@TypeName(shape)}"))
|
|
12
|
+
|
|
13
|
+
match x, y
|
|
14
|
+
1, 1 -> "both are 1"
|
|
15
|
+
1, _ -> "x is 1"
|
|
16
|
+
_, 1 -> "y is 1"
|
|
17
|
+
_, _ -> "neither is 1"
|
|
18
|
+
|
|
19
|
+
match n
|
|
20
|
+
2 | 4 | 6 | 8 -> "This is an even number"
|
|
21
|
+
1 | 3 | 5 | 7 -> "This is an odd number"
|
|
22
|
+
_ -> "I'm not sure"
|
|
23
|
+
|
|
24
|
+
match _
|
|
25
|
+
cmp > 0 -> low = mid + 1
|
|
26
|
+
cmp < 0 -> high = mid
|
|
27
|
+
cmp == 0 -> return mid, true
|
|
28
|
+
```
|
website/src/content/docs/statements/variables.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Variables
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Variables can be declared only at the local scope of a function as they are mutable. They are references/pointers to data.
|
|
7
|
+
We use the Short Variable Declaration Operator `:=` to declare a variable
|
|
8
|
+
|
|
9
|
+
```rb
|
|
10
|
+
low, mid, high := 0, 0, n.numItems
|
|
11
|
+
x := 10
|
|
12
|
+
y := 20
|
|
13
|
+
xy_list := List.of(1, 2, 3)
|
|
14
|
+
xy_map := Map.of(1 => "one", 2 => "two")
|
|
15
|
+
a := 1 + n
|
|
16
|
+
b := 1 * n
|
|
17
|
+
a * b
|
|
18
|
+
```
|
website/src/content/docs/statements/while.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: While Statement
|
|
3
|
+
description: These are basic types
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
```rb
|
|
7
|
+
low, mid, high := 0, 0, n.size
|
|
8
|
+
while low < high
|
|
9
|
+
mid = (low + high) / 2
|
|
10
|
+
low = cmp > 0 ? mid + 1 : low
|
|
11
|
+
high = cmp < 0 ? mid : high
|
|
12
|
+
if cmp == 0
|
|
13
|
+
return mid, true
|
|
14
|
+
|
|
15
|
+
while a > b
|
|
16
|
+
a += 1
|
|
17
|
+
|
|
18
|
+
while Some(top) = stack.pop()
|
|
19
|
+
printLn(top)
|
|
20
|
+
```
|
website/src/env.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/// <reference path="../.astro/types.d.ts" />
|
|
2
|
+
/// <reference types="astro/client" />
|
website/tsconfig.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "astro/tsconfigs/strict"
|
|
3
|
+
}
|