~repos /plum

#treesitter#compiler#wasm

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

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


9dc4cfe9 pyrossh

2 years ago
update
Files changed (3) hide show
  1. readme.md +315 -0
  2. spec.gleam +10 -5
  3. test/corpus/types.txt +43 -1
readme.md ADDED
@@ -0,0 +1,315 @@
1
+ ![palm](https://user-images.githubusercontent.com/1687946/232222925-76a1d42d-fac9-4e6c-a24a-e622c4360871.svg)
2
+ JEYMESSOUSA
3
+
4
+ # Palm Programming Language
5
+
6
+ A programming language with a syntax mostly similar to [gleam](https://github.com/gleam-lang/gleam).
7
+ Aims to be compiled to AMD64 and ARM64 using [QBE](https://github.com/8l/qbe) a small and fast compiler backend and also support the C ABI.
8
+
9
+ ## Quick start
10
+
11
+ ```sh
12
+ palm new demo # Create a new project called demo
13
+ palm run # Run the project
14
+ palm test # Run the tests
15
+ ```
16
+
17
+ ## Syntax
18
+
19
+ ### 1. Imports
20
+
21
+ ```gleam
22
+ import nasa/rocket_ship
23
+ import animal/cat.{Cat, stroke}
24
+ import animal/cat as kitty
25
+ ```
26
+
27
+ #### 2. Constants
28
+
29
+ ```gleam
30
+ const start_year = 2101
31
+ const end_year = 2111
32
+ const name: String = "Gleam"
33
+ const size: Int = 100
34
+ ```
35
+
36
+ #### 3. Inbuilt Types
37
+
38
+ ```gleam
39
+ Byte
40
+ Bytes
41
+ Bool
42
+ Int
43
+ Float
44
+ List(element)
45
+ Nil
46
+ Result(value, error)
47
+ String
48
+ UtfCodepoint
49
+ Error
50
+ False
51
+ Nil
52
+ Ok
53
+ True
54
+ ```
55
+
56
+ #### 4. Expressions
57
+
58
+ ```gleam
59
+ import palm/string
60
+ import palm/bool
61
+
62
+ let value: Bool = {
63
+ "Hello"
64
+ 42 + 12
65
+ False
66
+ }
67
+ let celsius = { fahrenheit - 32 } * 5 / 9
68
+ let st = "Hello, {celsius}!"
69
+
70
+ case some_number {
71
+ 0 -> "Zero"
72
+ 1 -> "One"
73
+ 2 -> "Two"
74
+ n -> "Some other number" // This matches anything
75
+ }
76
+
77
+ let description =
78
+ case True {
79
+ True -> "It's true!"
80
+ False -> "It's not true."
81
+ }
82
+
83
+ case x, y {
84
+ 1, 1 -> "both are 1"
85
+ 1, _ -> "x is 1"
86
+ _, 1 -> "y is 1"
87
+ _, _ -> "neither is 1"
88
+ }
89
+
90
+ case number {
91
+ 2 | 4 | 6 | 8 -> "This is an even number"
92
+ 1 | 3 | 5 | 7 -> "This is an odd number"
93
+ _ -> "I'm not sure"
94
+ }
95
+
96
+ case xs {
97
+ [] -> "This list is empty"
98
+ [a] -> "This list has 1 element"
99
+ [a, b] -> "This list has 2 elements"
100
+ _other -> "This list has more than 2 elements"
101
+ }
102
+
103
+ // Pipe
104
+ "Hello"
105
+ |> string_builder.from_string
106
+ |> string_builder.reverse
107
+ |> string_builder.to_string // => "olleh"
108
+ ```
109
+
110
+ #### 5. Types
111
+
112
+ #### A. ADT (Algebraic Data Type)
113
+
114
+ ```gleam
115
+ type Bool = True | False
116
+
117
+ type MyDatabaseError =
118
+ | InvalidQuery
119
+ | NetworkTimeout
120
+
121
+ type User = LoggedIn(name: String) | Guest
122
+
123
+ fn get_name(user: User) {
124
+ case user {
125
+ LoggedIn(name) -> name
126
+ Guest -> "Guest user"
127
+ }
128
+ }
129
+
130
+ fn run() {
131
+ let sara = LoggedIn(name: "Sara")
132
+ let visitor = Guest
133
+ let name = sara
134
+ |> get_name() // => "Sara"
135
+ }
136
+
137
+ // Generics
138
+
139
+ type Result(value, reason) = Ok(value) | Error(reason)
140
+ ```
141
+
142
+ #### B. Record Type
143
+
144
+ ```gleam
145
+ import palm/option.{Option}
146
+
147
+ type Cat(name: String, cuteness: Int, age: Int)
148
+
149
+ type Person(
150
+ name: String,
151
+ gender: Option(String),
152
+ shoe_size: Int,
153
+ age: Int,
154
+ is_happy: Bool
155
+ )
156
+
157
+ fn have_birthday(person: Person) -> Person {
158
+ Person(..person, age: person.age + 1, is_happy: True)
159
+ }
160
+
161
+ fn run() {
162
+ let cat = Cat(name: "Felix", cuteness: 9001, age: 5)
163
+ }
164
+
165
+ // Generics
166
+ type Box(inner: inner_type)
167
+
168
+ let a = Box(123) // type is Box(Int)
169
+ let b = Box("G") // type is Box(String)
170
+
171
+ // Opaque types
172
+ // At times it may be useful to create a type and make the constructors and fields private so that
173
+ // users of this type can only use the type through publically exported functions.
174
+
175
+ type Counter(value: Int)
176
+
177
+ fn new() {
178
+ Counter(0)
179
+ }
180
+
181
+ fn increment(counter: Counter) {
182
+ Counter(counter.value + 1)
183
+ }
184
+
185
+ let c = Counter(0)
186
+ |> increment()
187
+ |> increment()
188
+
189
+ // Type aliases
190
+
191
+ type Headers = List(String, String)
192
+ ```
193
+
194
+ #### 6. Functions
195
+
196
+ ```gleam
197
+ fn add(x: Int, y: Int) -> Int:
198
+ x + y
199
+
200
+ fn multiply(x: Int, y: Int) -> Int {
201
+ x * y
202
+ }
203
+
204
+ /// HoF
205
+ fn twice(f: fn(t) -> t, x: t) -> t {
206
+ f(f(x))
207
+ }
208
+
209
+ fn add_one(x: Int) -> Int {
210
+ x + 1
211
+ }
212
+
213
+ fn add_two(x: Int) -> Int {
214
+ twice(add_one, x)
215
+ }
216
+
217
+ /// Type annotations
218
+
219
+ fn identity(x: some_type) -> some_type {
220
+ x
221
+ }
222
+
223
+ fn inferred_identity(x) {
224
+ x
225
+ }
226
+
227
+ /// Generic functions
228
+
229
+ fn list_of_two(my_value: a) -> List(a) {
230
+ [my_value, my_value]
231
+ }
232
+
233
+ fn multi_result(x: a, y: b, condition: Bool) -> Result(a, b):
234
+ case condition:
235
+ True -> Ok(x)
236
+ False -> Error(y)
237
+
238
+
239
+ /// Anonymous functions
240
+
241
+ fn run() {
242
+ let add = fn(x, y) { x + y }
243
+
244
+ add(1, 2)
245
+ }
246
+
247
+ /// Currying
248
+
249
+ fn add(x, y) {
250
+ x + y
251
+ }
252
+
253
+ fn run():
254
+ 1
255
+ |> add(3)
256
+ |> add(6)
257
+ |> add(9)
258
+
259
+ fn returns_nil(a) -> Nil {
260
+ Nil
261
+ }
262
+ ```
263
+
264
+ #### 7. Lists
265
+
266
+ ```gleam
267
+ import palm/list
268
+
269
+ list.new("Krabs")
270
+ |> list.add("Spongebob")
271
+ |> list.length() // ==> 3
272
+ |> list.contains("Krabs") // ==> true
273
+ |> list.get(0) // => Some("Krabs")
274
+ |> list.get(5) // => None
275
+
276
+ let x = list.new(2, 3)
277
+ let y = list.new(1, ..x)
278
+ ```
279
+
280
+ #### 8. Maps
281
+
282
+ ```gleam
283
+ import palm/map
284
+
285
+ let nums = map.new(:one => 1, :two => 2) // => Map(k, v)
286
+ nums |> map.get(:one) // => Some(1)
287
+ nums |> map.get(:unknown) // => None
288
+ ```
289
+
290
+ #### 9. Optional
291
+
292
+ ```gleam
293
+ import palm/option.{Some, None}
294
+
295
+ let number = Some(1)
296
+
297
+ case number {
298
+ Some(n) -> n
299
+ None -> 0
300
+ }
301
+ ```
302
+
303
+ #### 9. Result
304
+
305
+ ```gleam
306
+ import palm/io.{println}
307
+ import palm/result.{Ok, Error}
308
+
309
+ let connect_res = Error("Connection failed")
310
+
311
+ case connect_res {
312
+ Ok(a) -> println("Connection succeeded")
313
+ Err(a) -> println("Error occurred: {a}")
314
+ }
315
+ ```
spec.gleam CHANGED
@@ -93,13 +93,18 @@ pub fn is_during(year: Int) -> Bool {
93
93
  start_year <= year && year <= end_year
94
94
  }
95
95
 
96
+ struct Int:
97
+ fn is_before(year: Int) -> Bool:
98
+ year < start_year
99
+
100
+ fn is_during(year: Int) -> Bool:
101
+ start_year <= year && year <= end_year
102
+
96
- pub fn describe(year: Int) -> String {
103
+ fn describe(year: Int) -> String:
97
- case year {
104
+ case year:
98
105
  year if year < start_year -> "Before"
99
106
  year if year > end_year -> "After"
100
107
  _ -> "During"
101
- }
102
- }
103
108
 
104
109
  pub const name: String = "Gleam"
105
110
 
@@ -181,7 +186,7 @@ pub fn map(res: Response) -> Result(String, String) {
181
186
  | _ -> Ok("success")
182
187
  }
183
188
 
184
- pub fn getColorHex(c: String) -> Int {
189
+ pub fn get_hex(c: String) -> Int {
185
190
  when c {
186
191
  "red" -> 0xff0000
187
192
  "blue" -> 0xff0123
test/corpus/types.txt CHANGED
@@ -14,7 +14,7 @@ type Result(a, b) {
14
14
  Error(b)
15
15
  }
16
16
 
17
- type Cat(a)(
17
+ struct Cat[a](
18
18
  firstName: String
19
19
  middleName: String
20
20
  lastName: String
@@ -23,6 +23,48 @@ type Cat(a)(
23
23
  call: fn (String) -> String
24
24
  )
25
25
 
26
+ fn is_before(year: Int) -> Bool
27
+ year < start_year
28
+
29
+ fn is_during(year: Int) -> Bool:
30
+ start_year <= year && year <= end_year
31
+
32
+ var a = arr
33
+ .map { it * 2 }
34
+ .filter { it > 10 }
35
+ .reduce { acc, n -> acc + n}, 0
36
+
37
+ Row(
38
+ alignment: 1,
39
+ Container(
40
+ H1("123")
41
+ .color(Yellow)
42
+ )
43
+ )
44
+
45
+ <row align={1}>
46
+ <h1 color={Yellow}>
47
+ 123
48
+ </h1>
49
+ </row>
50
+
51
+ struct Cat[a] {
52
+ var firstName: str
53
+ var middleName: str
54
+ var lastName: str
55
+ var age: Int
56
+ var shape: a
57
+ var call: fn (String) -> String
58
+
59
+ fn talk() {
60
+ puts("meow")
61
+ }
62
+
63
+ fn walk() {
64
+ puts("walking")
65
+ }
66
+ }
67
+
26
68
  --------------------------------------------------------------------------------
27
69
 
28
70
  (source_file