~repos /plum

#treesitter#compiler#wasm

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

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


fd085d94 pyrossh

1 year ago
new rules
libs/std/bool.plum CHANGED
@@ -1,26 +1,66 @@
1
1
  module std
2
2
 
3
+ type Int =
4
+ add(b: Int) -> Int = this + b
5
+ sub(b: Int) -> Int = this - b
6
+
7
+
3
- Bool =
8
+ enum Bool =
4
9
  | True
5
10
  | False
6
11
 
12
+ and(other: Bool) -> Bool =
7
- # Might not be needed
13
+ match this, other
14
+ True, True => True
15
+ True, False => False
16
+ False, True => False
17
+ False, False => False
18
+
19
+ or(other: Bool) -> Bool =
20
+ match this, other
21
+ True, True => True
22
+ True, False => True
23
+ False, True => True
24
+ False, False => False
25
+
8
- Bool\toStr() -> Str =
26
+ toStr() -> Str =
27
+ match this
9
- if this == True
28
+ True => "True"
29
+ False => "False"
30
+
31
+ fromStr(s: Str) -> Result(Bool, Err) =
10
- "True"
32
+ if s == "true"
33
+ True
34
+ else if s == "false"
35
+ False
11
- else
36
+ else
37
+ Err("could not parse bool from '{s}'")
38
+
12
- "False"
39
+ type Result =
13
-
40
+ | Ok(a)
41
+ | Err(b)
42
+
43
+
44
+ type Option =
45
+ | Some(a)
46
+ | None
47
+
14
- Bool\and(other: Bool) -> Bool =
48
+ readFile() -> Result(String, Err) =
49
+ return Err
50
+
51
+ data = try readFile()
52
+
53
+ if Ok(d) = readFile()
54
+ println(d)
55
+
15
- match this, other is
56
+ match readFile()
57
+ Ok(d) =>
58
+ printLn(d)
16
- True, True => True
59
+ Err(e) =>
17
- True, False => False
60
+ printErr(e)
18
- False, True => False
61
+
19
- False, False => False
20
-
21
- Bool\or(other: Bool) -> Bool =
22
- match this, other is
62
+ type List =
63
+ | Empty
23
- True, True => True
64
+ | Node(a)
24
- True, False => True
65
+
25
- False, True => True
66
+ add() =
26
- False, False => False
libs/std/float.plum CHANGED
@@ -1,80 +1,52 @@
1
1
  module std/float
2
2
 
3
- # Euler's number, the base of natural logarithms, e, https://oeis.org/A001113
4
- E = 2.718f
5
-
6
- # The natural logarithm of 10, https://oeis.org/A002392
7
- LN10 = 2.302f
8
-
9
- # The natural logarithm of 2 https://oeis.org/A002162
10
- LN2 = 0.693f
11
-
12
- # The base 10 logarithm of e # formula: 1 / LN10
13
- LOG10E = 0.434f
14
-
15
- # The base 2 logarithm of e # formula: 1 / LN2
16
- LOG2E = 1.442f
17
-
18
- # The ratio of the circumference of a circle to its diameter https://oeis.org/A000796
19
- PI = 3.14159f
20
-
21
- # https://oeis.org/A001622
22
- PHI = 1.6180f
23
-
24
- # The square root of 1/2
25
- SQRT1_2 = 0.707f
26
-
27
- # The square root of 2 https://oeis.org/A002193
28
- SQRT2 = 1.414f
29
-
30
- # https://oeis.org/A019774
31
- SQRT_E = 1.64872f
32
-
33
- # https://oeis.org/A002161
34
- SQRT_PI = 1.77245f
35
-
36
- # https://oeis.org/A139339
37
- SQRT_PHI = 1.27201f
38
-
39
- # The difference between 1 and the smallest floating point number greater than 1 formula: 7/3 - 4/3 - 1
40
- EPSILON = 2.220446049250313e-16f
41
-
42
- # Lowest value of float
43
- MIN_FLOAT_VALUE = 4.9406564584124654417656879286822137236505980e-324
44
-
45
- # Highest value of float
46
- MAX_FLOAT_VALUE = 1.79769313486231570814527423731704356798070e+308
47
-
48
- Float::PI=3.14
49
-
50
- fn acosh(v: float): float =
51
- when
52
- x < 1 | IsNaN(x) -> // first case is special case
53
- NaN()
54
- x == 1 ->
55
- 0
56
- x >= Large ->
57
- Log(x) + Ln2 // x > 2**28
58
- x > 2 ->
59
- Log(2*x - 1/(x+Sqrt(x*x-1))) // 2**28 > x > 2
60
- _ ->
61
- t := x - 1
62
- // ((2*t+t*t).sqrt() + t).log1p()
63
- Log1p(t + Sqrt(2*t+t*t)) // 2 >= x > 1
64
-
65
- fn is_finite(): bool = true
66
- ` Check whether this number is finite, ie not +/-infinity and not NaN.
67
- ` True if exponent is not all 1s
68
- (bits() and 0x7FF0_0000_0000_0000) != 0x7FF0_0000_0000_0000
69
-
70
- # Check whether this number is +/-infinity
71
- is_infinite: Bool =>
3
+ type Float =
4
+ E = 2.718f # Euler's number, the base of natural logarithms, e, https://oeis.org/A001113
5
+ LN10 = 2.302f # The natural logarithm of 10, https://oeis.org/A002392
6
+ LN2 = 0.693f # The natural logarithm of 2 https://oeis.org/A002162
7
+ LOG10E = 0.434f # The base 10 logarithm of e # formula: 1 / LN10
8
+ LOG2E = 1.442f # The base 2 logarithm of e # formula: 1 / LN2
9
+ PI = 3.14159f # The ratio of the circumference of a circle to its diameter https://oeis.org/A000796
10
+ PHI = 1.6180f # https://oeis.org/A001622
11
+ SQRT1_2 = 0.707f # The square root of 1/2
12
+ SQRT2 = 1.414f # The square root of 2 https://oeis.org/A002193
13
+ SQRT_E = 1.64872f # https://oeis.org/A019774
14
+ SQRT_PI = 1.77245f # https://oeis.org/A002161
15
+ SQRT_PHI = 1.27201f # https://oeis.org/A139339
16
+ EPSILON = 2.220446049250313e-16f # The difference between 1 and the smallest floating point number greater than 1 formula: 7/3 - 4/3 - 1
17
+ MIN_FLOAT_VALUE = 4.9406564584124654417656879286822137236505980e-324 # Lowest value of float
18
+ MAX_FLOAT_VALUE = 1.79769313486231570814527423731704356798070e+308 # Highest value of float
19
+
20
+
21
+ ::fromStr(s: Str) -> Result(Float, Err) =
22
+ todo
23
+
24
+ acosh(v: Float) -> Float =
25
+ match
26
+ x < 1 | IsNaN(x) => NaN() # first case is special case
27
+ x == 1 => 0
28
+ x >= Large => x.log() + LN2 # x > 2**28
29
+ x > 2 => Log(2*x - 1/(x+Sqrt(x*x-1))) # 2**28 > x > 2
30
+ _ =>
31
+ t =
32
+ ((2*t+t*t).sqrt() + t).log1p() 2 >= x > 1
33
+
34
+ # Check whether this number is finite, ie not +/-infinity and not NaN.
35
+ # True if exponent is not all 1s
36
+ isFinite() -> Bool =
37
+ (bits() && 0x7FF0_0000_0000_0000) != 0x7FF0_0000_0000_0000
38
+
39
+ # Check whether this number is +/-infinity
72
40
  # True if exponent is all 1s and mantissa is 0
41
+ isInfinite() -> Bool =
73
- ((bits() and 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) and # exp
42
+ ((bits() && 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) && # exp
74
- ((bits() and 0x000F_FFFF_FFFF_FFFF) == 0) // mantissa
43
+ ((bits() && 0x000F_FFFF_FFFF_FFFF) == 0) # mantissa
75
-
44
+
76
- // Check whether this number is NaN.
45
+ # Check whether this number is NaN.
77
- fn is_nan(): Bool =>
78
- // True if exponent is all 1s and mantissa is non-0
46
+ # True if exponent is all 1s and mantissa is non-0
47
+ isNaN() -> Bool =
79
- ((bits() and 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) and // exp
48
+ ((bits() && 0x7FF0_0000_0000_0000) == 0x7FF0_0000_0000_0000) && # exp
80
- ((bits() and 0x000F_FFFF_FFFF_FFFF) != 0) // mantissa
49
+ ((bits() && 0x000F_FFFF_FFFF_FFFF) != 0) # mantissa
50
+
51
+ toStr() -> Str =
52
+ todo
libs/std/int.plum CHANGED
@@ -1,95 +1,91 @@
1
1
  module std/int
2
2
 
3
- Int: Comparable, ToStr = ByteArray
3
+ type Int : Comparable, ToStr =
4
+ MIN_VALUE = -0x8000_0000_0000_0000 # Lowest value of Int
5
+ MAX_VALUE = 0x7FFF_FFFF_FFFF_FFFF # Highest value of Int
6
+ LARGE = 1 << 28 # 2**28
4
7
 
5
- # Lowest value of Int
6
- Int::MIN_VALUE = -0x8000_0000_0000_0000
8
+ ::random() -> Float = # Return random number
9
+ todo
7
10
 
8
- # Highest value of Int
9
- Int::MAX_VALUE = 0x7FFF_FFFF_FFFF_FFFF
11
+ ::parseInt() -> Result(Int, Err) =
12
+ 0
10
13
 
14
+ # returns the absolute value of the Int
11
- # 2**28
15
+ abs() -> Int =
12
- Int::LARGE = 1 << 28
16
+ this < 0 ? -this : this
13
17
 
14
- Int::random(): Float =
18
+ ceil() -> Float =
15
- todo
19
+ todo
16
20
 
17
- # returns the absolute value of the Int
18
- Int\abs() -> Int =
21
+ floor() -> Float =
19
- this < 0 ? -this : this
22
+ todo
20
23
 
21
- Int\ceil() -> Float =
24
+ round() -> Float =
22
- todo
25
+ todo
23
26
 
24
- Int\floor() -> Float =
27
+ trunc() -> Float =
25
- todo
28
+ todo
26
29
 
27
- Int\round() -> Float =
30
+ log() -> Float =
28
- todo
31
+ todo
29
32
 
30
- Int\trunc() -> Float =
33
+ log2() -> Float =
31
- todo
34
+ todo
32
35
 
33
- Int\log() -> Float =
36
+ log10() -> Float =
34
- todo
37
+ todo
35
38
 
36
- Int\log2() -> Float =
39
+ logb() -> Float =
37
- todo
40
+ todo
38
41
 
39
- Int\log10() -> Float =
42
+ pow(y: Float) -> Float =
40
- todo
43
+ LibM.pow(this, y)
41
44
 
42
- Int\logb() -> Float =
45
+ pow(y: Int) -> Float =
43
- todo
46
+ pow(y.toFloat())
44
47
 
45
- Int\pow(y: Float) -> Float =
46
- LibM.pow(this, y)
47
-
48
- Int\pow(y: Int) -> Float =
49
- pow(y.toFloat())
50
-
51
- Int\sqrt() -> Float =
48
+ sqrt() -> Float =
52
- if this < 0.0 then
49
+ if this < 0.0 then
53
- _nan()
50
+ _nan()
54
- else
51
+ else
55
- LibM.sqrt(this)
52
+ LibM.sqrt(this)
56
- end
57
53
 
58
- Int\asin(v: Float) =
54
+ asin(v: Float) =
59
- todo
55
+ todo
60
56
 
61
- Int\acos(v: Float) =
57
+ acos(v: Float) =
62
- if v < 0.1
58
+ if v < 0.1
63
- asin(v)
59
+ asin(v)
64
- else
60
+ else
65
- asin(-v)
61
+ asin(-v)
66
62
 
67
- Int\asinh(v: Float) =
63
+ asinh(v: Float) =
68
- todo
64
+ todo
69
65
 
70
- Int\atan(v: Float) =
66
+ atan(v: Float) =
71
- todo
67
+ todo
72
68
 
73
- Int\atan2(v: Float) =
69
+ atan2(v: Float) =
74
- todo
70
+ todo
75
71
 
76
- Int\atanh(v: Float) =
72
+ atanh(v: Float) =
77
- todo
73
+ todo
78
74
 
79
- Int\cbrt(v: Float) =
75
+ cbrt(v: Float) =
80
- todo
76
+ todo
81
77
 
82
- Int\ceil(v: Float) =
78
+ ceil(v: Float) =
83
- todo
79
+ todo
84
80
 
85
- Int\clz32(v: Float) =
81
+ clz32(v: Float) =
86
- todo
82
+ todo
87
83
 
88
- Int\cos(v: Float) =
84
+ cos(v: Float) =
89
- todo
85
+ todo
90
86
 
91
- Int\cosh(v: Float) =
87
+ cosh(v: Float) =
92
- todo
88
+ todo
93
89
 
94
- Int\exp(v: Float) =
90
+ exp(v: Float) =
95
- todo
91
+ todo
libs/std/json.plum CHANGED
@@ -15,7 +15,7 @@ JsonParseError = {
15
15
  token: Char
16
16
  }
17
17
 
18
- Json\\parse(src: Str | Buffer | IO) -> Json | JsonParseError =
18
+ Json::parse(src: Str | Buffer | IO) -> Json | JsonParseError =
19
19
  JsonParser.withSrc(src).parse()
20
20
 
21
21
  Json\parseNone() -> None | JsonParseError =
@@ -50,7 +50,7 @@ JsonParser::withSrc(src: Str | Buffer | IO) -> JsonParser =
50
50
  fn isSpace(c: U32): Bool => (c == ' ') or ((c >= '\t') and (c <= '\r'))
51
51
 
52
52
  fn isDelim(c: U32): Bool =>
53
- (c == ',') or (c == '}') or (c == ':') or (c == ']') or (_is_space(c)) or (c == 0)
53
+ (c == ',') || (c == '}') || (c == ':') || (c == ']') || (_is_space(c)) || (c == 0)
54
54
 
55
55
  fn isDigit(c: U32) -> Bool {
56
56
  return (c >= '0') && (c <= '9')
libs/std/list.plum CHANGED
@@ -1,176 +1,174 @@
1
1
  module std
2
2
 
3
- # A node stores the data in a list and contains pointers to the previous and next sibling nodes
3
+ `A node stores the data in a list and contains pointers to the previous and next sibling nodes
4
- Node = {
4
+ type Node =
5
- value: V
5
+ value: a
6
- prev: Node(a) | Nil
6
+ prev: Option[Node]
7
- next: Node(a) | Nil
7
+ next: Option[Node]
8
- }
8
+
9
-
10
- # A list is a data structure describing a contiguous section of an array stored separately from the slice variable itself.
9
+ `A list is a data structure describing a contiguous section of an array stored separately from the slice variable itself.
11
- # It contains the pointers to the start and end nodes (head, tail) and maintains the size as well
10
+ `It contains the pointers to the start and end nodes (head, tail) and maintains the size as well
12
- List = {
11
+ class List
13
- head: Node(a) | Nil
12
+ head: Option[Node]
14
- tail: Node(a) | Nil
13
+ tail: Option[Node]
15
14
  size: Int
16
- }
15
+
17
-
18
- List\init(values: ...a) -> List(a) =
16
+ init(values: ...a) -> List =
19
- List().add(values...)
17
+ List().add(values...)
20
-
18
+
21
- # gets the element at i'th index of the list
19
+ `gets the element at i'th index of the list
22
- List\get(i: Int) -> a =
20
+ get(i: Int) -> a =
23
- current = l.head
21
+ current = this.head
24
- index = 0
22
+ index = 0
25
- while current != Nil
23
+ while current != Nil
26
- if index == i
24
+ if index == i
27
- current.value
25
+ current.value
28
- else
26
+ else
27
+ current = current.next
28
+ index += 1
29
+
30
+ `sets the element at i'th index of the list
31
+ set(i: Int, v: a) -> a =
32
+ todo
33
+
34
+ `returns the no of elements in the list
35
+ length() -> Int =
36
+ this.size
37
+
38
+ add(values: ...a) =
39
+ `adds the specified elements to the start of the list
40
+ for v in values
41
+ this.head = Node(value: v, prev: Nil, next: this.head)
42
+ this.head.next.prev = this.head
43
+ this.size += 1
44
+
45
+ `removes the element at i'th index of the list
46
+ removeAt(i: Int) =
47
+ this.tail?.prev?.next = Nil
48
+ `old tail node gets deallocated due to zero reference count
49
+ this.tail = list.tail?.prev
50
+ this.size -= 1
51
+
52
+ `removes the element v from list
53
+ remove(v: a) =
54
+ this.tail?.prev?.next = Nil
55
+ `old tail node gets deallocated due to zero reference count
56
+ this.tail = list.tail?.prev
57
+ this.size -= 1
58
+
59
+ `removes all objects from this list
60
+ clear() =
61
+ this.tail?.prev?.next = Nil
62
+ `old tail node gets deallocated due to zero reference count
63
+ this.tail = list.tail?.prev
64
+ this.size -= 1
65
+
66
+
67
+ `returns a new list with the elements in reverse order.
68
+ reverse(v: fn(v: a) -> Bool) -> List =
69
+ todo
70
+
71
+ `returns a new list with the elements sorted by sorter
72
+ sort(sorter: fn(v: a) -> Bool) -> List =
73
+ todo
74
+
75
+ `returns an item and index in the list if the item is is equal to search item
76
+ find(search: a): Option[a] =
77
+ todo
78
+
79
+ `returns the index of an item in the list if present and comparable otherwise Nil
80
+ contains(v: a) -> Bool =
81
+ todo
82
+
83
+ `calls f for each elem in the list
84
+ each(cb: fn(v: a)) -> Unit =
85
+ current := this.head
86
+ while current != Nil
87
+ cb(current.value)
29
88
  current = current.next
30
- index += 1
31
-
32
- # sets the element at i'th index of the list
33
- List\set(i: Int, v: a) -> a =
34
- todo
35
-
36
- # returns the no of elements in the list
37
- List\length() -> a =
38
- self.size
39
-
40
- # adds the specified elements to the start of the list
41
- List\add(values: ...V) =
42
- for v in values
43
- l.head = Node(value: v, prev: Nil, next: l.head)
44
- l.head.next.prev = l.head
45
- l.size += 1
46
-
47
- # removes the element at i'th index of the list
48
- List\removeAt(i: Int) =
49
- l.tail?.prev?.next = Nil
50
- # old tail node gets deallocated due to zero reference count
51
- l.tail = list.tail?.prev
52
- l.size -= 1
53
-
54
- # removes the element v from list
55
- List\remove(v: a) =
56
- l.tail?.prev?.next = Nil
57
- # old tail node gets deallocated due to zero reference count
58
- l.tail = list.tail?.prev
59
- l.size -= 1
60
-
61
- # removes all objects from this list
62
- List\clear() =
63
- l.tail?.prev?.next = Nil
64
- # old tail node gets deallocated due to zero reference count
65
- l.tail = list.tail?.prev
66
- l.size -= 1
67
-
68
-
69
- # returns a new list with the elements in reverse order.
70
- List\reverse(v: fn(v: a) -> Bool) -> List[A] =
71
- todo
72
-
73
- # returns a new list with the elements sorted by sorter
74
- List\sort(sorter: fn(v: a) -> Bool) -> List(A) =
75
- todo
76
-
77
- # returns an item and index in the list if the item is is equal to search item
78
- List\find(search: V): V | Nil =
79
- todo
80
-
81
- # returns the index of an item in the list if present and comparable otherwise Nil
82
- List\contains(v: a) -> Bool =
83
- todo
84
-
85
- # calls f for each elem in the list
86
- List\each(cb: fn(v: a)) -> Unit =
87
- current := l.head
88
- while current != Nil
89
- cb(current.value)
90
- current = current.next
91
-
92
- # returns a list made up of B elements for each elem in the list
93
- List\map(cb: fn(v: a) -> b) -> List(b) =
94
- nl := []
95
- current := l.head
96
- while current != Nil
97
- item := cb(current.value)
98
- nl.push(item)
99
- nl
100
-
101
- # returns a new list with all elements shuffled`
102
- List\flatMap() =
103
- todo
104
-
105
- # returns a new list with the elements that matched the predicate
106
- List\retain(predicate: fn(v: a) -> A) -> List(A) =
107
- todo
108
-
109
- # returns a new list with the elements that matched the predicate removed
110
- List\reject(predicate: fn(v: a) -> A) -> List(A) =
111
- todo
112
-
113
- # returns true if any element in the list satisfies the predicate
114
- List\any(predicate: fn(v: a) -> Bool) -> Bool =
115
- todo
116
-
117
- # returns true if all of the elements in the list satisfies the predicate
118
- List\every(predicate: fn(v: a) -> Bool) -> Bool =
119
- todo
120
-
121
- # returns the accumulated value of all the elements in the list
122
- List\reduce[B](acc: B, cb: fn(v: a) -> A): B =
123
- todo
124
-
125
- # returns the first element in the list
126
- List\first() -> a | Nil =
127
- l.head?.value
128
-
129
- # returns the last element in the list
130
- List\last() -> a | Nil =
131
- l.tail?.value
132
-
133
- # returns a list containing the first n elements of the given list
134
- List\sublist(start: int, end: int) -> List(A) =
135
- todo
136
-
137
- # returns a list containing the first n elements of the given list
138
- List\take(n: int) -> List(A) =
139
- todo
140
-
141
- # returns a list containing the first n elements of the given list
142
- List\skip(n: int) -> List(A) =
143
- todo
144
-
145
- `Returns a list containing the first n elements of the given list
146
- List\drop(n: int) -> List(A) =
147
- todo
148
-
149
- # returns a new list with some of the elements taken randomly`
150
- List\sample() =
151
- todo
152
-
153
- # returns a new list with all elements shuffled`
154
- List\shuffle() =
155
- todo
156
-
157
- # returns a new list with all elements shuffled`
158
- List\partition() =
159
- todo
160
-
161
- # returns a new list with all elements shuffled`
162
- List\chunk() =
163
- todo
164
-
165
- # returns a new list with all elements grouped`
166
- List\groupBy() =
167
- todo
168
-
169
- List\join(sep: Str = ",") -> Str =
170
- res := Buffer()
171
- l.each() |v|
172
- if @HasTrait(V, ToStr)
173
- res.write(v.to_str(), sep)
174
- else
175
- res.write(@TypeToString(v), sep)
176
- res.to_str()
89
+
90
+ `returns a list made up of B elements for each elem in the list
91
+ map(cb: fn(v: a) -> b) -> List(b) =
92
+ nl := []
93
+ current := this.head
94
+ while current != Nil
95
+ item := cb(current.value)
96
+ nl.push(item)
97
+ nl
98
+
99
+ `returns a new list with all elements shuffled`
100
+ flatMap() =
101
+ todo
102
+
103
+ `returns a new list with the elements that matched the predicate
104
+ retain(predicate: fn(v: a) -> a) -> List =
105
+ todo
106
+
107
+ `returns a new list with the elements that matched the predicate removed
108
+ reject(predicate: fn(v: a) -> a) -> List =
109
+ todo
110
+
111
+ `returns true if any element in the list satisfies the predicate
112
+ any(predicate: fn(v: a) -> Bool) -> Bool =
113
+ todo
114
+
115
+ `returns true if all of the elements in the list satisfies the predicate
116
+ every(predicate: fn(v: a) -> Bool) -> Bool =
117
+ todo
118
+
119
+ `returns the accumulated value of all the elements in the list
120
+ reduce[B](acc: B, cb: fn(v: a) -> a): B =
121
+ todo
122
+
123
+ `returns the first element in the list
124
+ first() -> Option[a] =
125
+ this.head?.value
126
+
127
+ `returns the last element in the list
128
+ last() -> Option[a] =
129
+ this.tail?.value
130
+
131
+ `returns a list containing the first n elements of the given list
132
+ sublist(start: int, end: int) -> List =
133
+ todo
134
+
135
+ `returns a list containing the first n elements of the given list
136
+ take(n: int) -> List =
137
+ todo
138
+
139
+ `returns a list containing the first n elements of the given list
140
+ skip(n: int) -> List =
141
+ todo
142
+
143
+ `returns a list containing the first n elements of the given list
144
+ drop(n: int) -> List =
145
+ todo
146
+
147
+ `returns a new list with some of the elements taken randomly`
148
+ sample() =
149
+ todo
150
+
151
+ `returns a new list with all elements shuffled`
152
+ shuffle() =
153
+ todo
154
+
155
+ `returns a new list with all elements shuffled`
156
+ partition() =
157
+ todo
158
+
159
+ `returns a new list with all elements shuffled`
160
+ chunk() =
161
+ todo
162
+
163
+ `returns a new list with all elements grouped`
164
+ groupBy() =
165
+ todo
166
+
167
+ join(sep: Str = ",") -> Str =
168
+ res := Buffer()
169
+ this.each() |v|
170
+ if @HasTrait(V, ToStr)
171
+ res.write(v.to_str(), sep)
172
+ else
173
+ res.write(@TypeToString(v), sep)
174
+ res.to_str()
libs/std/map.plum CHANGED
@@ -27,6 +27,15 @@ Map\get(k: a) -> b | Nil =
27
27
  return v
28
28
  Nil
29
29
 
30
+ # Get a value from the Map using key k
31
+ Map\get(k: a) -> b | Nil =
32
+ found : Option(b) = None
33
+ for k, v in items do
34
+ if k == k
35
+ found = v
36
+ break
37
+ found
38
+
30
39
  # Put a value into the Map
31
40
  Map\set(k: a, v: b) =
32
41
  items.add(pair(k, v))
libs/std/str.plum CHANGED
@@ -1,177 +1,154 @@
1
1
  module std/str
2
2
 
3
- # ToStr defines any data that can be converted to a str
3
+ `ToStr defines any data that can be converted to a str
4
- ToStr = (
4
+ trait Stringable =
5
5
  toStr() -> Str
6
- )
7
-
8
- ```
9
- A Str is an array of contiguous data stored in memory with a null termination using hex 0x00 or ASCII 0x00.
10
- It is immutable and cannot be modified. It is copied for any changes and saved to a new memory location.
11
- The previous str is freed if its reference count is 0 within the block.
12
- ```
13
- Str : Comparable + ToStr = {
14
- data: Buffer
15
- }
16
-
17
- Str\get(i: Int) -> Char =
18
- data.get(i)
19
-
20
- Str\contains(search: Str) -> Bool =
21
- todo
22
6
 
7
+ `A Str is an array of contiguous data stored in memory with a null termination using hex 0x00 or ASCII 0x00.
8
+ `It is immutable and cannot be modified. It is copied for any changes and saved to a new memory location.
23
- Str\indexOf(sub: Str) -> Int =
9
+ `The previous str is freed if its reference count is 0 within the block.
24
- todo
25
-
26
- Str\test(pattern: Regex) -> Bool =
10
+ type Str is Comparable, Stringable, Readable, Writable =
27
- todo
11
+ data: Buffer
28
12
 
29
- Str\search(key: Str) -> (Int, Bool) =
30
- low, mid, high = 0, 0, n.numItems
31
- while low < high
13
+ get(i: Int) -> Char =
32
- mid = (low + high) / 2
33
- cmp = key > n.items[mid].key
34
- low = cmp > 0 ? mid + 1 : low
35
- high = cmp < 0 ? mid : high
36
- if cmp == 0 then
37
- return (mid, True)
38
- (low, False)
14
+ data.get(i)
39
15
 
40
- Str\startsWith(search: str) -> Bool =
16
+ contains(self, search: Str) -> Bool =
41
- todo
17
+ todo
42
18
 
43
- Str\concat(other: Str) -> Str =
19
+ indexOf(self, sub: Str) -> Int =
44
- s + other
20
+ todo
45
21
 
46
- Str\toStr() -> Str =
22
+ test(self, pattern: Regex) -> Bool =
47
- self
23
+ todo
48
24
 
49
- Str\matchPattern(pattern: Regex) -> List<Str> =
25
+ search(key: Str) -> (Int, Bool) =
26
+ low, mid, high = 0, 0, n.numItems
27
+ while low < high
28
+ mid = (low + high) / 2
29
+ cmp = key > n.items[mid].key
30
+ low = cmp > 0 ? mid + 1 : low
31
+ high = cmp < 0 ? mid : high
32
+ if cmp == 0 then
33
+ return (mid, True)
50
- todo
34
+ (low, False)
51
35
 
52
- Str\matchAll(pattern: Regex) -> List<Str> =
36
+ startsWith(search: str) -> Bool =
53
- todo
37
+ todo
54
38
 
55
- Str\padStart(sub: Str, count: Int) -> Str =
39
+ concat(other: Str) -> Str =
56
- todo
40
+ s + other
57
41
 
58
- Str\padEnd(sub: Str, count: Int) -> Str =
42
+ toStr(self) -> Str =
59
- todo
43
+ self
60
44
 
61
- Str\repeat(count: Int) -> Str =
45
+ matchPattern(self, pattern: Regex) -> List<Str> =
62
- todo
46
+ todo
63
47
 
64
- Str\replace(pattern: Regex, sub: Str) -> Str =
48
+ matchAll(self, pattern: Regex) -> List<Str> =
65
- todo
49
+ todo
66
50
 
67
- Str\replaceAll(pattern: Regex, sub: Str) -> Str =
51
+ padStart(self, sub: Str, count: Int) -> Str =
68
- todo
52
+ todo
69
53
 
70
- Str\search(pattern: Regex) -> Str =
54
+ padEnd(self, sub: Str, count: Int) -> Str =
71
- todo
55
+ todo
72
56
 
73
- Str\slice(start: Int, e: Int) -> Str =
57
+ repeat(self, count: Int) -> Str =
74
- todo
58
+ todo
75
59
 
76
- Str\split(separator: Str, limit: Int) -> []Str =
60
+ replace(pattern: Regex, sub: Str) -> Str =
77
- todo
61
+ todo
78
62
 
79
- Str\sub(start: Int, e: Int) -> Str =
63
+ replaceAll(pattern: Regex, sub: Str) -> Str =
80
- todo
64
+ todo
81
65
 
82
- Str\toLower() -> Str =
66
+ search(pattern: Regex) -> Str =
83
- todo
67
+ todo
84
68
 
85
- `reverses a Str
86
- Str\reverse() -> Str =
69
+ slice(start: Int, e: Int) -> Str =
87
- start := 0
88
- end := length - 1
89
- result := []
90
- while start < end
91
- const temp = data[start]
92
- result[start] = data[end]
93
- result[end] = temp
94
- end = end - 1
95
- start = start + 1
96
- result
70
+ todo
97
71
 
98
- Str\parseInt() -> Int =
72
+ split(separator: Str, limit: Int) -> []Str =
99
- 0
73
+ todo
100
74
 
101
- Str\parseFloat() -> Float =
75
+ sub(start: Int, e: Int) -> Str =
102
- 0.0
76
+ todo
103
77
 
104
- Str\parseBool() -> Bool =
78
+ toLower() -> Str =
105
- match self.to_lower()
106
- "true" -> True
107
- "false" -> False
108
- _ -> error("could not parse bool '${this}'")
109
- if self.lower() == "true"
110
- True
79
+ todo
111
- else if self.lower() == "false"
112
- False
113
- else
114
- error("could not parse bool '${this}'")
115
80
 
81
+ # reverses a Str
82
+ reverse() -> Str =
83
+ start := 0
84
+ end := length - 1
85
+ result := []
86
+ while start < end
87
+ const temp = data[start]
88
+ result[start] = data[end]
89
+ result[end] = temp
90
+ end = end - 1
91
+ start = start + 1
92
+ result
116
93
 
117
- Str\camelCase() -> Str =
94
+ camelCase() -> Str =
118
- todo
95
+ todo
119
96
 
120
- Str\snakeCase() -> Str =
97
+ snakeCase() -> Str =
121
- todo
98
+ todo
122
99
 
123
- Str\capitalize() -> Str =
100
+ capitalize() -> Str =
124
- todo
101
+ todo
125
102
 
126
- Str\kebabCase() -> Str =
103
+ kebabCase() -> Str =
127
- todo
104
+ todo
128
105
 
129
- Str\lowerCase() -> Str =
106
+ lowerCase() -> Str =
130
- todo
107
+ todo
131
108
 
132
- Str\lowerFirst() -> Str =
109
+ lowerFirst() -> Str =
133
- todo
110
+ todo
134
111
 
135
- Str\upperCase() -> Str =
112
+ upperCase() -> Str =
136
- todo
113
+ todo
137
114
 
138
- Str\upperFirst() -> Str =
115
+ upperFirst() -> Str =
139
- todo
116
+ todo
140
117
 
141
118
 
142
- Str\startCase() -> Str =
119
+ startCase() -> Str =
143
- todo
120
+ todo
144
121
 
145
- Str\deburr() -> Str =
122
+ deburr() -> Str =
146
- todo
123
+ todo
147
124
 
148
- Str\escape() -> Str =
125
+ escape() -> Str =
149
- todo
126
+ todo
150
127
 
151
- Str\escapeRegExp() -> Str =
128
+ escapeRegExp() -> Str =
152
- todo
129
+ todo
153
130
 
154
- Str\pad() -> Str =
131
+ pad() -> Str =
155
- todo
132
+ todo
156
133
 
157
- Str\template() -> Str =
134
+ template() -> Str =
158
- todo
135
+ todo
159
136
 
160
- Str\trim() -> Str =
137
+ trim() -> Str =
161
- todo
138
+ todo
162
139
 
163
- Str\trimEnd() -> Str =
140
+ trimEnd() -> Str =
164
- todo
141
+ todo
165
142
 
166
- Str\trimStart() -> Str =
143
+ trimStart() -> Str =
167
- todo
144
+ todo
168
145
 
169
- Str\truncate() -> Str =
146
+ truncate() -> Str =
170
- todo
147
+ todo
171
148
 
172
- Str\unescape() -> Str =
149
+ unescape() -> Str =
173
- todo
150
+ todo
174
151
 
175
- Str\words() -> Str =
152
+ words() -> Str =
176
- todo
153
+ todo
177
154
 
tooling/tree-sitter-plum/grammar.js CHANGED
@@ -65,13 +65,13 @@ module.exports = grammar({
65
65
  seq(
66
66
  optional(seq("module", $.module)),
67
67
  repeat($.import),
68
- repeat(choice($.record, $.object, $.trait, $.enum, $.fn)),
68
+ repeat(choice($.record, $.trait, $.enum, $.fn)),
69
69
  ),
70
70
 
71
- module: ($) => $.identifier,
71
+ module: ($) => $.var_identier,
72
72
 
73
73
  import: ($) => seq("import", $.url),
74
- url: ($) => sep1(/[a-zA-Z_][a-zA-Z_0-9]*/, "/"),
74
+ url: () => sep1(/[a-zA-Z_][a-zA-Z_0-9]*/, "/"),
75
75
 
76
76
  generics: ($) => seq("(", commaSep1($.generic_type), ")"),
77
77
  generic_type: ($) =>
@@ -80,7 +80,7 @@ module.exports = grammar({
80
80
  choice(
81
81
  seq(
82
82
  $.type_identifier,
83
- field("generics", optional(seq("(", commaSep1($.type), ")"))),
83
+ field("generics", optional(seq("[", commaSep1($.type), "]"))),
84
84
  ),
85
85
  $.generic,
86
86
  ),
@@ -88,24 +88,19 @@ module.exports = grammar({
88
88
 
89
89
  record: ($) =>
90
90
  seq(
91
+ "type",
91
92
  field("name", $.type_identifier),
92
93
  field("implements", optional(seq(":", sep1($.type_identifier, "+")))),
93
94
  field("generics", optional($.generics)),
94
95
  "=",
95
- field("fields", seq("{", $._newline, sep1($.record_field, $._newline), $._newline, "}")),
96
- ),
97
-
98
- record_field: ($) =>
99
- seq(field("name", $.identifier), ":", field("type", $.type)),
100
-
101
- object: ($) =>
102
- seq(
103
- "object",
96
+ $._indent,
104
- field("name", $.type_identifier),
97
+ optional(repeat($.record_field)),
105
- field("implements", optional(seq(":", commaSep1($.type_identifier)))),
106
- field("body", optional(seq("{", repeat($.fn), "}"))),
98
+ optional(repeat($.method)),
99
+ $._dedent,
107
100
  ),
108
101
 
102
+ record_field: ($) => seq(field("name", $.identifier), ":", field("type", $.type)),
103
+ method: ($) => alias($.fn, "method"),
109
104
  trait: ($) =>
110
105
  seq(
111
106
  "trait",
@@ -125,7 +120,7 @@ module.exports = grammar({
125
120
 
126
121
  param: ($) =>
127
122
  seq(
128
- field("name", $.identifier),
123
+ field("name", $.var_identier),
129
124
  ":",
130
125
  field("type", choice($.type, $.variadic_type)),
131
126
  optional(seq("=", field("value", $.expression))),
@@ -136,10 +131,12 @@ module.exports = grammar({
136
131
 
137
132
  enum: ($) =>
138
133
  seq(
134
+ "enum",
139
135
  field("name", $.type_identifier),
140
136
  "=",
141
137
  $._indent,
142
- field("fields", sep1($.enum_field, $._newline)),
138
+ optional(repeat($.enum_field)),
139
+ optional(repeat($.method)),
143
140
  $._dedent,
144
141
  ),
145
142
 
@@ -152,10 +149,10 @@ module.exports = grammar({
152
149
 
153
150
  fn: ($) =>
154
151
  seq(
155
- field("name", choice($.fn_identifier, $.method_identifier, $.static_identifier)),
152
+ field("name", choice($.identifier, $.static_identifier)),
156
153
  field("params", seq("(", optional(commaSep1($.param)), ")")),
157
154
  field("returns", optional(seq("->", $.return_type))),
158
- field("body", seq("=", $.body)),
155
+ field("body", seq("=", choice($.expression, $.body))),
159
156
  ),
160
157
 
161
158
  body: ($) => seq($._indent, repeat($._statement), $._dedent),
@@ -178,7 +175,7 @@ module.exports = grammar({
178
175
  assign: ($) =>
179
176
  prec.right(
180
177
  seq(
181
- field("left", commaSep1($.identifier)),
178
+ field("left", commaSep1($.var_identier)),
182
179
  "=",
183
180
  field("right", $.expression),
184
181
  ),
@@ -207,12 +204,9 @@ module.exports = grammar({
207
204
  reference: ($) =>
208
205
  prec(
209
206
  PREC.call,
210
- seq(choice($.identifier, $.type_identifier), optional(seq(".", $.identifier))),
207
+ seq(choice($.var_identier, $.type_identifier), optional(seq(".", $.identifier))),
211
208
  ),
212
209
 
213
- method_identifier: ($) =>
214
- seq($.type_identifier, "\\", $.fn_identifier),
215
-
216
210
  static_identifier: ($) =>
217
211
  seq($.type_identifier, "::", $.fn_identifier),
218
212
 
tooling/tree-sitter-plum/src/grammar.json CHANGED
Binary file
tooling/tree-sitter-plum/src/node-types.json CHANGED
Binary file
tooling/tree-sitter-plum/src/parser.c CHANGED
Binary file
tooling/tree-sitter-plum/test/corpus/assign.txt CHANGED
@@ -99,6 +99,8 @@ countriesList = listOf("US", "INDIA", "CANADA")
99
99
  a = list.of(1, 2, 3)
100
100
  b = list.of(list.of(1), list.of(2), list.of(3))
101
101
  c = list.of(1, 2, 3 * 4, 8, n)
102
+ d = "{name} {age}"
103
+ e = "Cat<{fullname()}, {age}>"
102
104
 
103
105
  --------------------------------------------------------------------------------
104
106
 
@@ -219,13 +221,13 @@ c = list.of(1, 2, 3 * 4, 8, n)
219
221
  assign - Call map
220
222
  ================================================================================
221
223
 
222
- countryCode = mapOf(
224
+ countryCode = Map(
223
225
  "in" => "INDIA",
224
226
  "us" => "United States",
225
227
  "ca" => "Canada"
226
228
  )
227
- a = mapOf("a" => 1, "b" => 2)
229
+ a = Map("a" => 1, "b" => 2)
228
- b = mapOf("a" => 1, "b" => map.of("c" => 3, "d" => 4))
230
+ b = Map("a" => 1, "b" => Map("c" => 3, "d" => 4))
229
231
 
230
232
  --------------------------------------------------------------------------------
231
233
 
tooling/tree-sitter-plum/test/corpus/enum.txt CHANGED
@@ -2,10 +2,13 @@
2
2
  enum
3
3
  ================================================================================
4
4
 
5
- Bool =
5
+ enum Bool
6
6
  | True
7
7
  | False
8
8
 
9
+ toStr() -> Str =
10
+ "Bool"
11
+
9
12
  --------------------------------------------------------------------------------
10
13
 
11
14
  (source
@@ -14,4 +17,14 @@ Bool =
14
17
  (enum_field
15
18
  (type_identifier))
16
19
  (enum_field
17
- (type_identifier))))
20
+ (type_identifier))
21
+ (method
22
+ (identifier)
23
+ (return_type
24
+ (type_identifier))
25
+ (body
26
+ (primary_expression
27
+ (string
28
+ (string_start)
29
+ (string_content)
30
+ (string_end)))))))
tooling/tree-sitter-plum/test/corpus/type.txt CHANGED
@@ -2,20 +2,35 @@
2
2
  type - definition
3
3
  ================================================================================
4
4
 
5
- Cat : ToStr = {
5
+ type Cat is Stringable =
6
6
  name: Str
7
7
  age: Int
8
- }
9
8
 
10
- Dog = {
9
+ type Dog =
11
10
  name: a
12
11
  age: b
13
- }
14
12
 
15
- Dog(a: Compare + String, b) = {
13
+ type Dog(a: Compare + Stringable, b) is Stringable =
16
14
  name: a
17
15
  age: b
16
+
17
+ type Int =
18
+ add(other: Int) -> Int = this + other
19
+ sub(other: Int) -> Int = this - other
20
+
21
+ type Cat is Stringable =
22
+ name: Str
18
- }
23
+ age: Int
24
+
25
+ withName(name: Str) -> Cat =
26
+ Cat(name = name, age = 0)
27
+
28
+ withAge(age: Int) -> Cat =
29
+ Cat(name = "", age = age)
30
+
31
+ Stringable() -> Str =
32
+ "Cat"
33
+
19
34
  --------------------------------------------------------------------------------
20
35
 
21
36
  (source
@@ -54,32 +69,39 @@ Dog(a: Compare + String, b) = {
54
69
  (record_field
55
70
  (identifier)
56
71
  (type
57
- (b)))))
72
+ (b))))
58
-
73
+ (record
59
- ================================================================================
74
+ (type_identifier)
60
- type - methods
75
+ (method
61
- ================================================================================
62
-
63
- Cat : ToStr = {
64
- name: Str
76
+ (identifier)
65
- age: Int
66
- }
67
-
68
- Cat\withName(name: Str) -> Cat =
69
- Cat(name = name, age = 0)
70
-
71
- Cat\withAge(age: Int) -> Cat =
72
- Cat(name = "", age = age)
73
-
74
- Cat\fullname() -> Str =
75
- "${name} ${age}"
76
-
77
- Cat\toStr() -> Str =
78
- "Cat<{fullname()}, {age}>"
79
-
80
- --------------------------------------------------------------------------------
81
-
82
- (source
77
+ (param
78
+ (var_identier)
79
+ (type
80
+ (type_identifier)))
81
+ (return_type
82
+ (type_identifier))
83
+ (expression
84
+ (primary_expression
85
+ (binary_operator
86
+ (primary_expression
87
+ (this))
88
+ (primary_expression
89
+ (identifier))))))
90
+ (method
91
+ (identifier)
92
+ (param
93
+ (var_identier)
94
+ (type
95
+ (type_identifier)))
96
+ (return_type
97
+ (type_identifier))
98
+ (expression
99
+ (primary_expression
100
+ (binary_operator
101
+ (primary_expression
102
+ (this))
103
+ (primary_expression
104
+ (identifier)))))))
83
105
  (record
84
106
  (type_identifier)
85
107
  (type_identifier)
@@ -88,82 +110,64 @@ Cat\toStr() -> Str =
88
110
  (type
89
111
  (type_identifier)))
90
112
  (record_field
91
- (identifier)
92
- (type
93
- (type_identifier))))
94
- (fn
95
- (method_identifier
96
- (type_identifier)
97
- (fn_identifier))
98
- (param
99
113
  (identifier)
100
114
  (type
101
115
  (type_identifier)))
102
- (return_type
103
- (type_identifier))
104
- (body
116
+ (method
105
- (primary_expression
106
- (type_call
107
- (type_identifier)
108
- (argument_list
109
- (keyword_argument
110
- (identifier)
111
- (expression
112
- (primary_expression
113
- (identifier))))
114
- (keyword_argument
115
- (identifier)
116
- (expression
117
- (primary_expression
118
- (integer)))))))))
119
- (fn
120
- (method_identifier
121
- (type_identifier)
122
- (fn_identifier))
123
- (param
124
117
  (identifier)
125
- (type
126
- (type_identifier)))
127
- (return_type
128
- (type_identifier))
129
- (body
130
- (primary_expression
131
- (type_call
132
- (type_identifier)
133
- (argument_list
134
- (keyword_argument
135
- (identifier)
136
- (expression
137
- (primary_expression
138
- (string
139
- (string_start)
140
- (string_end)))))
141
- (keyword_argument
142
- (identifier)
143
- (expression
144
- (primary_expression
145
- (identifier)))))))))
146
- (fn
147
- (method_identifier
148
- (type_identifier)
149
- (fn_identifier))
150
- (return_type
151
- (type_identifier))
152
- (body
153
- (primary_expression
154
- (string
155
- (string_start)
156
- (string_content)
157
- (string_end)))))
158
- (fn
159
- (method_identifier
160
- (type_identifier)
161
- (fn_identifier))
162
- (return_type
163
- (type_identifier))
164
- (body
165
- (primary_expression
166
- (string
167
- (string_start)
168
- (string_content)
169
- (string_end))))))
118
+ (param
119
+ (var_identier)
120
+ (type
121
+ (type_identifier)))
122
+ (return_type
123
+ (type_identifier))
124
+ (body
125
+ (primary_expression
126
+ (type_call
127
+ (type_identifier)
128
+ (argument_list
129
+ (keyword_argument
130
+ (identifier)
131
+ (expression
132
+ (primary_expression
133
+ (identifier))))
134
+ (keyword_argument
135
+ (identifier)
136
+ (expression
137
+ (primary_expression
138
+ (integer)))))))))
139
+ (method
140
+ (identifier)
141
+ (param
142
+ (var_identier)
143
+ (type
144
+ (type_identifier)))
145
+ (return_type
146
+ (type_identifier))
147
+ (body
148
+ (primary_expression
149
+ (type_call
150
+ (type_identifier)
151
+ (argument_list
152
+ (keyword_argument
153
+ (identifier)
154
+ (expression
155
+ (primary_expression
156
+ (string
157
+ (string_start)
158
+ (string_end)))))
159
+ (keyword_argument
160
+ (identifier)
161
+ (expression
162
+ (primary_expression
163
+ (identifier)))))))))
164
+ (method
165
+ (identifier)
166
+ (return_type
167
+ (type_identifier))
168
+ (body
169
+ (primary_expression
170
+ (string
171
+ (string_start)
172
+ (string_content)
173
+ (string_end)))))))
tooling/vscode-plum/syntaxes/plum.tmLanguage.json CHANGED
@@ -26,7 +26,7 @@
26
26
  "patterns": [
27
27
  {
28
28
  "name": "keyword.control.plum",
29
- "match": "\\b(do|in|this|return|continue|break|match|if|else|while|for|module|as|is|import|assert|todo|crash)\\b"
29
+ "match": "\\b(module|import|trait|type|enum|fn|in|this|return|continue|break|match|if|else|while|for|as|is|assert|crash|todo)\\b"
30
30
  },
31
31
  {
32
32
  "name": "keyword.operator.arrow.plum",
@@ -85,22 +85,7 @@
85
85
  "patterns": [
86
86
  {
87
87
  "name": "comment.line.plum",
88
- "match": "#.*"
88
+ "match": "`.*"
89
- },
90
- {
91
- "begin": "```",
92
- "beginCaptures": {
93
- "0": {
94
- "name": "punctuation.definition.comment.begin.plum"
95
- }
96
- },
97
- "end": "```",
98
- "endCaptures": {
99
- "0": {
100
- "name": "punctuation.definition.comment.end.plum"
101
- }
102
- },
103
- "name": "comment.block.plum"
104
89
  }
105
90
  ]
106
91
  },