plum

#treesitter#compiler#wasm

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 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
- actors.contains("Krabs") // ==> true
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 parse_int(): int! =
138
+ fn parseInt(): int! =
139
139
  0
140
140
 
141
- fn parse_float(): float! =
141
+ fn parseFloat(): float! =
142
142
  0.0
143
143
 
144
- fn parse_bool(): bool! =
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
+ }