authorgravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-17 12:30:19-08:00
committergravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-17 12:30:19-08:00
log9153cb96ee98310426d7dab102d4564af52589bd
tree129a9dfd35962415998d30928c2b79c219d2d27a
parent30d91f57ad954a930871abb4d9bfe9028b66f0b9

chore: split everything into different crates


38 files changed, 1758 insertions(+), 2192 deletions(-)

Cargo.lock+43-10
......@@ -65,6 +65,16 @@ dependencies = [
6565 "windows-sys",
6666]
6767
68[[package]]
69name = "ast"
70version = "0.1.0"
71dependencies = [
72 "miette",
73 "thiserror",
74 "tokenizer",
75 "util",
76]
77
6878[[package]]
6979name = "backtrace"
7080version = "0.3.69"
......@@ -154,10 +164,12 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
154164name = "cli"
155165version = "0.1.0"
156166dependencies = [
167 "ast",
157168 "clap",
158 "compiler",
169 "js_printer",
159170 "miette",
160171 "thiserror",
172 "tokenizer",
161173]
162174
163175[[package]]
......@@ -166,15 +178,6 @@ version = "1.0.0"
166178source = "registry+https://github.com/rust-lang/crates.io-index"
167179checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
168180
169[[package]]
170name = "compiler"
171version = "0.1.0"
172dependencies = [
173 "clap",
174 "miette",
175 "thiserror",
176]
177
178181[[package]]
179182name = "errno"
180183version = "0.3.8"
......@@ -220,6 +223,23 @@ version = "1.1.1"
220223source = "registry+https://github.com/rust-lang/crates.io-index"
221224checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
222225
226[[package]]
227name = "js_ast"
228version = "0.1.0"
229dependencies = [
230 "miette",
231 "thiserror",
232]
233
234[[package]]
235name = "js_printer"
236version = "0.1.0"
237dependencies = [
238 "ast",
239 "miette",
240 "thiserror",
241]
242
223243[[package]]
224244name = "libc"
225245version = "0.2.152"
......@@ -429,6 +449,15 @@ dependencies = [
429449 "syn",
430450]
431451
452[[package]]
453name = "tokenizer"
454version = "0.1.0"
455dependencies = [
456 "miette",
457 "thiserror",
458 "util",
459]
460
432461[[package]]
433462name = "unicode-ident"
434463version = "1.0.12"
......@@ -453,6 +482,10 @@ version = "0.2.1"
453482source = "registry+https://github.com/rust-lang/crates.io-index"
454483checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
455484
485[[package]]
486name = "util"
487version = "0.1.0"
488
456489[[package]]
457490name = "winapi"
458491version = "0.3.9"
Cargo.toml+1-1
......@@ -8,7 +8,7 @@ repository = "https://github.com/lino-levan/blight"
88
99[workspace]
1010resolver = "2"
11members = ["cli", "compiler"]
11members = ["crates/cli", "crates/util", "crates/tokenizer", "crates/ast", "crates/js_ast", "crates/js_printer"]
1212
1313[workspace.dependencies]
1414clap = { version = "4.4.12", features = ["derive"] }
README.md+14
......@@ -1,3 +1,17 @@
11# Blight
22
33Blight sure is a programming language.
4
5## Developing
6
7Compiling a file:
8
9```bash
10cargo run compile --stdout ./examples/basics/fib.blight
11```
12
13Running the compiler on a file:
14
15```bash
16cargo run run ./examples/basics/fib.blight
17```
cli/Cargo.lock deleted-532
......@@ -1,532 +0,0 @@
1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing.
3version = 3
4
5[[package]]
6name = "addr2line"
7version = "0.21.0"
8source = "registry+https://github.com/rust-lang/crates.io-index"
9checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
10dependencies = [
11 "gimli",
12]
13
14[[package]]
15name = "adler"
16version = "1.0.2"
17source = "registry+https://github.com/rust-lang/crates.io-index"
18checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19
20[[package]]
21name = "anstream"
22version = "0.6.5"
23source = "registry+https://github.com/rust-lang/crates.io-index"
24checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
25dependencies = [
26 "anstyle",
27 "anstyle-parse",
28 "anstyle-query",
29 "anstyle-wincon",
30 "colorchoice",
31 "utf8parse",
32]
33
34[[package]]
35name = "anstyle"
36version = "1.0.4"
37source = "registry+https://github.com/rust-lang/crates.io-index"
38checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
39
40[[package]]
41name = "anstyle-parse"
42version = "0.2.3"
43source = "registry+https://github.com/rust-lang/crates.io-index"
44checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
45dependencies = [
46 "utf8parse",
47]
48
49[[package]]
50name = "anstyle-query"
51version = "1.0.2"
52source = "registry+https://github.com/rust-lang/crates.io-index"
53checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
54dependencies = [
55 "windows-sys",
56]
57
58[[package]]
59name = "anstyle-wincon"
60version = "3.0.2"
61source = "registry+https://github.com/rust-lang/crates.io-index"
62checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
63dependencies = [
64 "anstyle",
65 "windows-sys",
66]
67
68[[package]]
69name = "backtrace"
70version = "0.3.69"
71source = "registry+https://github.com/rust-lang/crates.io-index"
72checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
73dependencies = [
74 "addr2line",
75 "cc",
76 "cfg-if",
77 "libc",
78 "miniz_oxide",
79 "object",
80 "rustc-demangle",
81]
82
83[[package]]
84name = "backtrace-ext"
85version = "0.2.1"
86source = "registry+https://github.com/rust-lang/crates.io-index"
87checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
88dependencies = [
89 "backtrace",
90]
91
92[[package]]
93name = "bitflags"
94version = "2.4.1"
95source = "registry+https://github.com/rust-lang/crates.io-index"
96checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
97
98[[package]]
99name = "blight"
100version = "0.1.0"
101dependencies = [
102 "clap",
103 "miette",
104 "thiserror",
105]
106
107[[package]]
108name = "cc"
109version = "1.0.83"
110source = "registry+https://github.com/rust-lang/crates.io-index"
111checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
112dependencies = [
113 "libc",
114]
115
116[[package]]
117name = "cfg-if"
118version = "1.0.0"
119source = "registry+https://github.com/rust-lang/crates.io-index"
120checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
121
122[[package]]
123name = "clap"
124version = "4.4.12"
125source = "registry+https://github.com/rust-lang/crates.io-index"
126checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d"
127dependencies = [
128 "clap_builder",
129 "clap_derive",
130]
131
132[[package]]
133name = "clap_builder"
134version = "4.4.12"
135source = "registry+https://github.com/rust-lang/crates.io-index"
136checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
137dependencies = [
138 "anstream",
139 "anstyle",
140 "clap_lex",
141 "strsim",
142]
143
144[[package]]
145name = "clap_derive"
146version = "4.4.7"
147source = "registry+https://github.com/rust-lang/crates.io-index"
148checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
149dependencies = [
150 "heck",
151 "proc-macro2",
152 "quote",
153 "syn",
154]
155
156[[package]]
157name = "clap_lex"
158version = "0.6.0"
159source = "registry+https://github.com/rust-lang/crates.io-index"
160checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
161
162[[package]]
163name = "colorchoice"
164version = "1.0.0"
165source = "registry+https://github.com/rust-lang/crates.io-index"
166checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
167
168[[package]]
169name = "errno"
170version = "0.3.8"
171source = "registry+https://github.com/rust-lang/crates.io-index"
172checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
173dependencies = [
174 "libc",
175 "windows-sys",
176]
177
178[[package]]
179name = "gimli"
180version = "0.28.1"
181source = "registry+https://github.com/rust-lang/crates.io-index"
182checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
183
184[[package]]
185name = "heck"
186version = "0.4.1"
187source = "registry+https://github.com/rust-lang/crates.io-index"
188checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
189
190[[package]]
191name = "hermit-abi"
192version = "0.3.3"
193source = "registry+https://github.com/rust-lang/crates.io-index"
194checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
195
196[[package]]
197name = "is-terminal"
198version = "0.4.10"
199source = "registry+https://github.com/rust-lang/crates.io-index"
200checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
201dependencies = [
202 "hermit-abi",
203 "rustix",
204 "windows-sys",
205]
206
207[[package]]
208name = "is_ci"
209version = "1.1.1"
210source = "registry+https://github.com/rust-lang/crates.io-index"
211checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
212
213[[package]]
214name = "libc"
215version = "0.2.151"
216source = "registry+https://github.com/rust-lang/crates.io-index"
217checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
218
219[[package]]
220name = "linux-raw-sys"
221version = "0.4.12"
222source = "registry+https://github.com/rust-lang/crates.io-index"
223checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
224
225[[package]]
226name = "memchr"
227version = "2.7.1"
228source = "registry+https://github.com/rust-lang/crates.io-index"
229checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
230
231[[package]]
232name = "miette"
233version = "5.10.0"
234source = "registry+https://github.com/rust-lang/crates.io-index"
235checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e"
236dependencies = [
237 "backtrace",
238 "backtrace-ext",
239 "is-terminal",
240 "miette-derive",
241 "once_cell",
242 "owo-colors",
243 "supports-color",
244 "supports-hyperlinks",
245 "supports-unicode",
246 "terminal_size",
247 "textwrap",
248 "thiserror",
249 "unicode-width",
250]
251
252[[package]]
253name = "miette-derive"
254version = "5.10.0"
255source = "registry+https://github.com/rust-lang/crates.io-index"
256checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c"
257dependencies = [
258 "proc-macro2",
259 "quote",
260 "syn",
261]
262
263[[package]]
264name = "miniz_oxide"
265version = "0.7.1"
266source = "registry+https://github.com/rust-lang/crates.io-index"
267checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
268dependencies = [
269 "adler",
270]
271
272[[package]]
273name = "object"
274version = "0.32.2"
275source = "registry+https://github.com/rust-lang/crates.io-index"
276checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
277dependencies = [
278 "memchr",
279]
280
281[[package]]
282name = "once_cell"
283version = "1.19.0"
284source = "registry+https://github.com/rust-lang/crates.io-index"
285checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
286
287[[package]]
288name = "owo-colors"
289version = "3.5.0"
290source = "registry+https://github.com/rust-lang/crates.io-index"
291checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
292
293[[package]]
294name = "proc-macro2"
295version = "1.0.73"
296source = "registry+https://github.com/rust-lang/crates.io-index"
297checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1"
298dependencies = [
299 "unicode-ident",
300]
301
302[[package]]
303name = "quote"
304version = "1.0.34"
305source = "registry+https://github.com/rust-lang/crates.io-index"
306checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a"
307dependencies = [
308 "proc-macro2",
309]
310
311[[package]]
312name = "rustc-demangle"
313version = "0.1.23"
314source = "registry+https://github.com/rust-lang/crates.io-index"
315checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
316
317[[package]]
318name = "rustix"
319version = "0.38.28"
320source = "registry+https://github.com/rust-lang/crates.io-index"
321checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
322dependencies = [
323 "bitflags",
324 "errno",
325 "libc",
326 "linux-raw-sys",
327 "windows-sys",
328]
329
330[[package]]
331name = "smawk"
332version = "0.3.2"
333source = "registry+https://github.com/rust-lang/crates.io-index"
334checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
335
336[[package]]
337name = "strsim"
338version = "0.10.0"
339source = "registry+https://github.com/rust-lang/crates.io-index"
340checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
341
342[[package]]
343name = "supports-color"
344version = "2.1.0"
345source = "registry+https://github.com/rust-lang/crates.io-index"
346checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89"
347dependencies = [
348 "is-terminal",
349 "is_ci",
350]
351
352[[package]]
353name = "supports-hyperlinks"
354version = "2.1.0"
355source = "registry+https://github.com/rust-lang/crates.io-index"
356checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d"
357dependencies = [
358 "is-terminal",
359]
360
361[[package]]
362name = "supports-unicode"
363version = "2.0.0"
364source = "registry+https://github.com/rust-lang/crates.io-index"
365checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7"
366dependencies = [
367 "is-terminal",
368]
369
370[[package]]
371name = "syn"
372version = "2.0.44"
373source = "registry+https://github.com/rust-lang/crates.io-index"
374checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d"
375dependencies = [
376 "proc-macro2",
377 "quote",
378 "unicode-ident",
379]
380
381[[package]]
382name = "terminal_size"
383version = "0.1.17"
384source = "registry+https://github.com/rust-lang/crates.io-index"
385checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
386dependencies = [
387 "libc",
388 "winapi",
389]
390
391[[package]]
392name = "textwrap"
393version = "0.15.2"
394source = "registry+https://github.com/rust-lang/crates.io-index"
395checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
396dependencies = [
397 "smawk",
398 "unicode-linebreak",
399 "unicode-width",
400]
401
402[[package]]
403name = "thiserror"
404version = "1.0.53"
405source = "registry+https://github.com/rust-lang/crates.io-index"
406checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09"
407dependencies = [
408 "thiserror-impl",
409]
410
411[[package]]
412name = "thiserror-impl"
413version = "1.0.53"
414source = "registry+https://github.com/rust-lang/crates.io-index"
415checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19"
416dependencies = [
417 "proc-macro2",
418 "quote",
419 "syn",
420]
421
422[[package]]
423name = "unicode-ident"
424version = "1.0.12"
425source = "registry+https://github.com/rust-lang/crates.io-index"
426checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
427
428[[package]]
429name = "unicode-linebreak"
430version = "0.1.5"
431source = "registry+https://github.com/rust-lang/crates.io-index"
432checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
433
434[[package]]
435name = "unicode-width"
436version = "0.1.11"
437source = "registry+https://github.com/rust-lang/crates.io-index"
438checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
439
440[[package]]
441name = "utf8parse"
442version = "0.2.1"
443source = "registry+https://github.com/rust-lang/crates.io-index"
444checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
445
446[[package]]
447name = "winapi"
448version = "0.3.9"
449source = "registry+https://github.com/rust-lang/crates.io-index"
450checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
451dependencies = [
452 "winapi-i686-pc-windows-gnu",
453 "winapi-x86_64-pc-windows-gnu",
454]
455
456[[package]]
457name = "winapi-i686-pc-windows-gnu"
458version = "0.4.0"
459source = "registry+https://github.com/rust-lang/crates.io-index"
460checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
461
462[[package]]
463name = "winapi-x86_64-pc-windows-gnu"
464version = "0.4.0"
465source = "registry+https://github.com/rust-lang/crates.io-index"
466checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
467
468[[package]]
469name = "windows-sys"
470version = "0.52.0"
471source = "registry+https://github.com/rust-lang/crates.io-index"
472checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
473dependencies = [
474 "windows-targets",
475]
476
477[[package]]
478name = "windows-targets"
479version = "0.52.0"
480source = "registry+https://github.com/rust-lang/crates.io-index"
481checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
482dependencies = [
483 "windows_aarch64_gnullvm",
484 "windows_aarch64_msvc",
485 "windows_i686_gnu",
486 "windows_i686_msvc",
487 "windows_x86_64_gnu",
488 "windows_x86_64_gnullvm",
489 "windows_x86_64_msvc",
490]
491
492[[package]]
493name = "windows_aarch64_gnullvm"
494version = "0.52.0"
495source = "registry+https://github.com/rust-lang/crates.io-index"
496checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
497
498[[package]]
499name = "windows_aarch64_msvc"
500version = "0.52.0"
501source = "registry+https://github.com/rust-lang/crates.io-index"
502checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
503
504[[package]]
505name = "windows_i686_gnu"
506version = "0.52.0"
507source = "registry+https://github.com/rust-lang/crates.io-index"
508checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
509
510[[package]]
511name = "windows_i686_msvc"
512version = "0.52.0"
513source = "registry+https://github.com/rust-lang/crates.io-index"
514checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
515
516[[package]]
517name = "windows_x86_64_gnu"
518version = "0.52.0"
519source = "registry+https://github.com/rust-lang/crates.io-index"
520checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
521
522[[package]]
523name = "windows_x86_64_gnullvm"
524version = "0.52.0"
525source = "registry+https://github.com/rust-lang/crates.io-index"
526checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
527
528[[package]]
529name = "windows_x86_64_msvc"
530version = "0.52.0"
531source = "registry+https://github.com/rust-lang/crates.io-index"
532checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
cli/Cargo.toml deleted-15
......@@ -1,15 +0,0 @@
1[package]
2name = "cli"
3version = "0.1.0"
4edition = "2021"
5
6[[bin]]
7name = "blight"
8path = "./src/main.rs"
9
10[dependencies]
11clap.workspace = true
12miette.workspace = true
13thiserror.workspace = true
14
15compiler = { path = "../compiler" }
cli/src/main.rs deleted-99
......@@ -1,99 +0,0 @@
1use std::path::PathBuf;
2
3use clap::{Parser, Subcommand};
4use miette::Result;
5
6use compiler::transpile;
7
8#[derive(Parser)]
9#[command(author, version, about, long_about = None)]
10struct Cli {
11 /// Turn debugging information on
12 #[arg(short, long, action = clap::ArgAction::Count)]
13 debug: u8,
14
15 #[command(subcommand)]
16 command: Commands,
17}
18
19#[derive(Subcommand)]
20enum Commands {
21 /// Compiles a file into javascript
22 Compile {
23 file: PathBuf,
24 // Whether to output to stdout instead of a file
25 #[arg(long, default_value_t = false)]
26 stdout: bool,
27 },
28 Run {
29 file: PathBuf,
30 /// What javascript runtime to use
31 #[arg(short, long, default_value = "deno")]
32 runtime: String,
33 },
34}
35
36fn get_runtime(runtime: &String) -> String {
37 match std::env::var("USER") {
38 Ok(user) if user == "dave" => String::from("bun"),
39 _ => runtime.clone(),
40 }
41}
42
43fn main() -> Result<()> {
44 let cli = Cli::parse();
45
46 match cli.command {
47 Commands::Compile { file, stdout } => {
48 let contents = std::fs::read_to_string(file.clone()).unwrap();
49 let result = transpile(contents.clone())?;
50
51 if stdout {
52 println!("{}", result);
53 } else {
54 std::fs::write(file.with_extension("js"), result).unwrap();
55 }
56 }
57 Commands::Run { file, runtime } => {
58 let contents = std::fs::read_to_string(file.clone()).unwrap();
59 let result = transpile(contents.clone())?;
60 let mut temp_file = std::env::temp_dir();
61 temp_file.push("temp.js");
62 std::fs::write(temp_file.clone(), result).unwrap();
63
64 let rt = get_runtime(&runtime);
65
66 match rt.as_str() {
67 "deno" => {
68 let output = std::process::Command::new("deno")
69 .arg("run")
70 .arg("-A")
71 .arg(temp_file)
72 .output()
73 .expect("Failed to execute process");
74 println!("{}", String::from_utf8_lossy(&output.stdout));
75 }
76 "node" => {
77 let output = std::process::Command::new("node")
78 .arg(temp_file)
79 .output()
80 .expect("Failed to execute process");
81 println!("{}", String::from_utf8_lossy(&output.stdout));
82 }
83 "bun" => {
84 let output = std::process::Command::new("bun")
85 .arg("run")
86 .arg(temp_file)
87 .output()
88 .expect("Failed to execute process");
89 println!("{}", String::from_utf8_lossy(&output.stdout));
90 }
91 _ => {
92 println!("Unknown runtime: {}", runtime);
93 }
94 }
95 }
96 }
97
98 Ok(())
99}
compiler/Cargo.lock deleted-532
......@@ -1,532 +0,0 @@
1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing.
3version = 3
4
5[[package]]
6name = "addr2line"
7version = "0.21.0"
8source = "registry+https://github.com/rust-lang/crates.io-index"
9checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
10dependencies = [
11 "gimli",
12]
13
14[[package]]
15name = "adler"
16version = "1.0.2"
17source = "registry+https://github.com/rust-lang/crates.io-index"
18checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19
20[[package]]
21name = "anstream"
22version = "0.6.5"
23source = "registry+https://github.com/rust-lang/crates.io-index"
24checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
25dependencies = [
26 "anstyle",
27 "anstyle-parse",
28 "anstyle-query",
29 "anstyle-wincon",
30 "colorchoice",
31 "utf8parse",
32]
33
34[[package]]
35name = "anstyle"
36version = "1.0.4"
37source = "registry+https://github.com/rust-lang/crates.io-index"
38checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
39
40[[package]]
41name = "anstyle-parse"
42version = "0.2.3"
43source = "registry+https://github.com/rust-lang/crates.io-index"
44checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
45dependencies = [
46 "utf8parse",
47]
48
49[[package]]
50name = "anstyle-query"
51version = "1.0.2"
52source = "registry+https://github.com/rust-lang/crates.io-index"
53checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
54dependencies = [
55 "windows-sys",
56]
57
58[[package]]
59name = "anstyle-wincon"
60version = "3.0.2"
61source = "registry+https://github.com/rust-lang/crates.io-index"
62checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
63dependencies = [
64 "anstyle",
65 "windows-sys",
66]
67
68[[package]]
69name = "backtrace"
70version = "0.3.69"
71source = "registry+https://github.com/rust-lang/crates.io-index"
72checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
73dependencies = [
74 "addr2line",
75 "cc",
76 "cfg-if",
77 "libc",
78 "miniz_oxide",
79 "object",
80 "rustc-demangle",
81]
82
83[[package]]
84name = "backtrace-ext"
85version = "0.2.1"
86source = "registry+https://github.com/rust-lang/crates.io-index"
87checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
88dependencies = [
89 "backtrace",
90]
91
92[[package]]
93name = "bitflags"
94version = "2.4.1"
95source = "registry+https://github.com/rust-lang/crates.io-index"
96checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
97
98[[package]]
99name = "blight"
100version = "0.1.0"
101dependencies = [
102 "clap",
103 "miette",
104 "thiserror",
105]
106
107[[package]]
108name = "cc"
109version = "1.0.83"
110source = "registry+https://github.com/rust-lang/crates.io-index"
111checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
112dependencies = [
113 "libc",
114]
115
116[[package]]
117name = "cfg-if"
118version = "1.0.0"
119source = "registry+https://github.com/rust-lang/crates.io-index"
120checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
121
122[[package]]
123name = "clap"
124version = "4.4.12"
125source = "registry+https://github.com/rust-lang/crates.io-index"
126checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d"
127dependencies = [
128 "clap_builder",
129 "clap_derive",
130]
131
132[[package]]
133name = "clap_builder"
134version = "4.4.12"
135source = "registry+https://github.com/rust-lang/crates.io-index"
136checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
137dependencies = [
138 "anstream",
139 "anstyle",
140 "clap_lex",
141 "strsim",
142]
143
144[[package]]
145name = "clap_derive"
146version = "4.4.7"
147source = "registry+https://github.com/rust-lang/crates.io-index"
148checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
149dependencies = [
150 "heck",
151 "proc-macro2",
152 "quote",
153 "syn",
154]
155
156[[package]]
157name = "clap_lex"
158version = "0.6.0"
159source = "registry+https://github.com/rust-lang/crates.io-index"
160checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
161
162[[package]]
163name = "colorchoice"
164version = "1.0.0"
165source = "registry+https://github.com/rust-lang/crates.io-index"
166checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
167
168[[package]]
169name = "errno"
170version = "0.3.8"
171source = "registry+https://github.com/rust-lang/crates.io-index"
172checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
173dependencies = [
174 "libc",
175 "windows-sys",
176]
177
178[[package]]
179name = "gimli"
180version = "0.28.1"
181source = "registry+https://github.com/rust-lang/crates.io-index"
182checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
183
184[[package]]
185name = "heck"
186version = "0.4.1"
187source = "registry+https://github.com/rust-lang/crates.io-index"
188checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
189
190[[package]]
191name = "hermit-abi"
192version = "0.3.3"
193source = "registry+https://github.com/rust-lang/crates.io-index"
194checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
195
196[[package]]
197name = "is-terminal"
198version = "0.4.10"
199source = "registry+https://github.com/rust-lang/crates.io-index"
200checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
201dependencies = [
202 "hermit-abi",
203 "rustix",
204 "windows-sys",
205]
206
207[[package]]
208name = "is_ci"
209version = "1.1.1"
210source = "registry+https://github.com/rust-lang/crates.io-index"
211checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
212
213[[package]]
214name = "libc"
215version = "0.2.151"
216source = "registry+https://github.com/rust-lang/crates.io-index"
217checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
218
219[[package]]
220name = "linux-raw-sys"
221version = "0.4.12"
222source = "registry+https://github.com/rust-lang/crates.io-index"
223checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
224
225[[package]]
226name = "memchr"
227version = "2.7.1"
228source = "registry+https://github.com/rust-lang/crates.io-index"
229checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
230
231[[package]]
232name = "miette"
233version = "5.10.0"
234source = "registry+https://github.com/rust-lang/crates.io-index"
235checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e"
236dependencies = [
237 "backtrace",
238 "backtrace-ext",
239 "is-terminal",
240 "miette-derive",
241 "once_cell",
242 "owo-colors",
243 "supports-color",
244 "supports-hyperlinks",
245 "supports-unicode",
246 "terminal_size",
247 "textwrap",
248 "thiserror",
249 "unicode-width",
250]
251
252[[package]]
253name = "miette-derive"
254version = "5.10.0"
255source = "registry+https://github.com/rust-lang/crates.io-index"
256checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c"
257dependencies = [
258 "proc-macro2",
259 "quote",
260 "syn",
261]
262
263[[package]]
264name = "miniz_oxide"
265version = "0.7.1"
266source = "registry+https://github.com/rust-lang/crates.io-index"
267checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
268dependencies = [
269 "adler",
270]
271
272[[package]]
273name = "object"
274version = "0.32.2"
275source = "registry+https://github.com/rust-lang/crates.io-index"
276checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
277dependencies = [
278 "memchr",
279]
280
281[[package]]
282name = "once_cell"
283version = "1.19.0"
284source = "registry+https://github.com/rust-lang/crates.io-index"
285checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
286
287[[package]]
288name = "owo-colors"
289version = "3.5.0"
290source = "registry+https://github.com/rust-lang/crates.io-index"
291checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
292
293[[package]]
294name = "proc-macro2"
295version = "1.0.73"
296source = "registry+https://github.com/rust-lang/crates.io-index"
297checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1"
298dependencies = [
299 "unicode-ident",
300]
301
302[[package]]
303name = "quote"
304version = "1.0.34"
305source = "registry+https://github.com/rust-lang/crates.io-index"
306checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a"
307dependencies = [
308 "proc-macro2",
309]
310
311[[package]]
312name = "rustc-demangle"
313version = "0.1.23"
314source = "registry+https://github.com/rust-lang/crates.io-index"
315checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
316
317[[package]]
318name = "rustix"
319version = "0.38.28"
320source = "registry+https://github.com/rust-lang/crates.io-index"
321checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
322dependencies = [
323 "bitflags",
324 "errno",
325 "libc",
326 "linux-raw-sys",
327 "windows-sys",
328]
329
330[[package]]
331name = "smawk"
332version = "0.3.2"
333source = "registry+https://github.com/rust-lang/crates.io-index"
334checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
335
336[[package]]
337name = "strsim"
338version = "0.10.0"
339source = "registry+https://github.com/rust-lang/crates.io-index"
340checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
341
342[[package]]
343name = "supports-color"
344version = "2.1.0"
345source = "registry+https://github.com/rust-lang/crates.io-index"
346checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89"
347dependencies = [
348 "is-terminal",
349 "is_ci",
350]
351
352[[package]]
353name = "supports-hyperlinks"
354version = "2.1.0"
355source = "registry+https://github.com/rust-lang/crates.io-index"
356checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d"
357dependencies = [
358 "is-terminal",
359]
360
361[[package]]
362name = "supports-unicode"
363version = "2.0.0"
364source = "registry+https://github.com/rust-lang/crates.io-index"
365checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7"
366dependencies = [
367 "is-terminal",
368]
369
370[[package]]
371name = "syn"
372version = "2.0.44"
373source = "registry+https://github.com/rust-lang/crates.io-index"
374checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d"
375dependencies = [
376 "proc-macro2",
377 "quote",
378 "unicode-ident",
379]
380
381[[package]]
382name = "terminal_size"
383version = "0.1.17"
384source = "registry+https://github.com/rust-lang/crates.io-index"
385checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
386dependencies = [
387 "libc",
388 "winapi",
389]
390
391[[package]]
392name = "textwrap"
393version = "0.15.2"
394source = "registry+https://github.com/rust-lang/crates.io-index"
395checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
396dependencies = [
397 "smawk",
398 "unicode-linebreak",
399 "unicode-width",
400]
401
402[[package]]
403name = "thiserror"
404version = "1.0.53"
405source = "registry+https://github.com/rust-lang/crates.io-index"
406checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09"
407dependencies = [
408 "thiserror-impl",
409]
410
411[[package]]
412name = "thiserror-impl"
413version = "1.0.53"
414source = "registry+https://github.com/rust-lang/crates.io-index"
415checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19"
416dependencies = [
417 "proc-macro2",
418 "quote",
419 "syn",
420]
421
422[[package]]
423name = "unicode-ident"
424version = "1.0.12"
425source = "registry+https://github.com/rust-lang/crates.io-index"
426checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
427
428[[package]]
429name = "unicode-linebreak"
430version = "0.1.5"
431source = "registry+https://github.com/rust-lang/crates.io-index"
432checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
433
434[[package]]
435name = "unicode-width"
436version = "0.1.11"
437source = "registry+https://github.com/rust-lang/crates.io-index"
438checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
439
440[[package]]
441name = "utf8parse"
442version = "0.2.1"
443source = "registry+https://github.com/rust-lang/crates.io-index"
444checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
445
446[[package]]
447name = "winapi"
448version = "0.3.9"
449source = "registry+https://github.com/rust-lang/crates.io-index"
450checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
451dependencies = [
452 "winapi-i686-pc-windows-gnu",
453 "winapi-x86_64-pc-windows-gnu",
454]
455
456[[package]]
457name = "winapi-i686-pc-windows-gnu"
458version = "0.4.0"
459source = "registry+https://github.com/rust-lang/crates.io-index"
460checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
461
462[[package]]
463name = "winapi-x86_64-pc-windows-gnu"
464version = "0.4.0"
465source = "registry+https://github.com/rust-lang/crates.io-index"
466checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
467
468[[package]]
469name = "windows-sys"
470version = "0.52.0"
471source = "registry+https://github.com/rust-lang/crates.io-index"
472checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
473dependencies = [
474 "windows-targets",
475]
476
477[[package]]
478name = "windows-targets"
479version = "0.52.0"
480source = "registry+https://github.com/rust-lang/crates.io-index"
481checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
482dependencies = [
483 "windows_aarch64_gnullvm",
484 "windows_aarch64_msvc",
485 "windows_i686_gnu",
486 "windows_i686_msvc",
487 "windows_x86_64_gnu",
488 "windows_x86_64_gnullvm",
489 "windows_x86_64_msvc",
490]
491
492[[package]]
493name = "windows_aarch64_gnullvm"
494version = "0.52.0"
495source = "registry+https://github.com/rust-lang/crates.io-index"
496checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
497
498[[package]]
499name = "windows_aarch64_msvc"
500version = "0.52.0"
501source = "registry+https://github.com/rust-lang/crates.io-index"
502checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
503
504[[package]]
505name = "windows_i686_gnu"
506version = "0.52.0"
507source = "registry+https://github.com/rust-lang/crates.io-index"
508checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
509
510[[package]]
511name = "windows_i686_msvc"
512version = "0.52.0"
513source = "registry+https://github.com/rust-lang/crates.io-index"
514checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
515
516[[package]]
517name = "windows_x86_64_gnu"
518version = "0.52.0"
519source = "registry+https://github.com/rust-lang/crates.io-index"
520checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
521
522[[package]]
523name = "windows_x86_64_gnullvm"
524version = "0.52.0"
525source = "registry+https://github.com/rust-lang/crates.io-index"
526checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
527
528[[package]]
529name = "windows_x86_64_msvc"
530version = "0.52.0"
531source = "registry+https://github.com/rust-lang/crates.io-index"
532checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
compiler/Cargo.toml deleted-11
......@@ -1,11 +0,0 @@
1[package]
2name = "compiler"
3version = "0.1.0"
4edition = "2021"
5
6[lib]
7
8[dependencies]
9clap.workspace = true
10miette.workspace = true
11thiserror.workspace = true
compiler/src/ast/error.rs deleted-17
......@@ -1,17 +0,0 @@
1use miette::Diagnostic;
2use thiserror::Error;
3
4#[derive(Error, Diagnostic, Debug)]
5#[error("AstError")]
6pub struct AstError {
7 #[help]
8 error: String,
9}
10
11impl AstError {
12 pub fn new(error: &'static str) -> AstError {
13 AstError {
14 error: String::from(error),
15 }
16 }
17}
compiler/src/ast/mod.rs deleted-26
......@@ -1,26 +0,0 @@
1use miette::Result;
2
3mod error;
4mod parse_block;
5mod parse_expression;
6mod parse_statement;
7mod parse_type;
8mod types;
9
10pub use super::tokenizer::Token;
11
12use parse_statement::parse_statement;
13use types::ParserContext;
14
15pub use types::{Ast, Block, Type};
16
17pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>> {
18 let mut ctx = ParserContext::new(tokens);
19 let mut ast: Vec<Ast> = Vec::new();
20
21 while !ctx.empty() {
22 ast.push(parse_statement(&mut ctx)?);
23 }
24
25 Ok(ast)
26}
compiler/src/ast/parse_block.rs deleted-54
......@@ -1,54 +0,0 @@
1use miette::Result;
2
3use super::error::AstError;
4use super::parse_expression::parse_expression;
5use super::parse_statement::parse_statement;
6use super::types::Block;
7use super::types::ParserContext;
8use super::Token;
9
10pub fn parse_block(tokens: &mut ParserContext) -> Result<Block> {
11 match tokens.next() {
12 Some(Token::OpenBracket) => (),
13 _ => return Err(AstError::new("Expected { when parsing block").into()),
14 }
15
16 let mut value = Vec::new();
17 let mut implicit_return = false;
18
19 loop {
20 match tokens.peek() {
21 Some(Token::ClosedBracket) => {
22 tokens.next();
23 break;
24 }
25 _ => (),
26 }
27
28 let current_cursor = tokens.cursor;
29 let result = parse_statement(tokens);
30
31 match result {
32 Ok(ast) => value.push(ast),
33 Err(_) => {
34 tokens.cursor = current_cursor;
35 value.push(parse_expression(tokens)?);
36 implicit_return = true;
37 match tokens.peek() {
38 Some(Token::ClosedBracket) => (),
39 _ => {
40 return Err(AstError::new(
41 "Expected closed bracket after expression in function body",
42 )
43 .into());
44 }
45 }
46 }
47 }
48 }
49
50 Ok(Block {
51 value,
52 implicit_return,
53 })
54}
compiler/src/ast/parse_expression.rs deleted-116
......@@ -1,116 +0,0 @@
1use miette::Result;
2
3use super::error::AstError;
4use super::parse_block::parse_block;
5use super::types::{Ast, ParserContext};
6use super::Token;
7
8pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
9 let left = match tokens.next() {
10 Some(token) => match token {
11 Token::Number(number) => Ast::Number(number.clone()),
12 Token::String(string) => Ast::String(string.clone()),
13 Token::True => Ast::Bool(true),
14 Token::False => Ast::Bool(false),
15 Token::OpenBracket => {
16 // FRICK we consumed the open bracket
17 // we need to put the cursor back
18 tokens.back();
19 Ast::Block(parse_block(tokens)?)
20 }
21 Token::If => {
22 let condition = parse_expression(tokens)?;
23
24 let value = parse_block(tokens)?;
25
26 let mut else_value = None;
27
28 match tokens.peek() {
29 Some(Token::Else) => {
30 tokens.next();
31 match tokens.peek() {
32 Option::Some(Token::If) => {
33 else_value = Some(Box::new(parse_expression(tokens)?));
34 }
35 Option::Some(Token::OpenBracket) => {
36 else_value = Some(Box::new(Ast::Block(parse_block(tokens)?)));
37 }
38 _ => {
39 return Err(AstError::new(
40 "Expected if or open bracket after else in if statement",
41 )
42 .into())
43 }
44 }
45 }
46 _ => (),
47 }
48
49 return Ok(Ast::If {
50 condition: Box::new(condition),
51 value,
52 else_value,
53 });
54 }
55 Token::Identifier(name) => match tokens.peek() {
56 Some(Token::OpenParanthesis) => {
57 tokens.next();
58
59 let mut arguments = Vec::new();
60
61 loop {
62 match tokens.peek() {
63 Some(Token::ClosedParanthesis) => {
64 tokens.next();
65 break;
66 }
67 _ => (),
68 }
69 arguments.push(parse_expression(tokens)?);
70
71 match tokens.peek() {
72 Some(Token::Comma) => {
73 tokens.next();
74 }
75 Some(Token::ClosedParanthesis) => (),
76 _ => {
77 return Err(AstError::new(
78 "Expected ) or , but found something else instead.",
79 )
80 .into())
81 }
82 }
83 }
84
85 Ast::FunctionCall {
86 name: name.clone(),
87 arguments,
88 }
89 }
90 _ => Ast::Identifier(name.clone()),
91 },
92 _ => {
93 println!("token: {:?}", token);
94 return Err(AstError::new("Expected expression, but did not get it").into());
95 }
96 },
97 None => return Err(AstError::new("Expected expression, but got nothing instead").into()),
98 };
99
100 match tokens.peek() {
101 Some(token) => match token {
102 Token::Operator(operator) => {
103 tokens.next();
104 return Ok(Ast::Operation {
105 operator: operator.clone(),
106 left: Box::new(left),
107 right: Box::new(parse_expression(tokens)?),
108 });
109 }
110 _ => (),
111 },
112 _ => (),
113 }
114
115 Ok(left)
116}
compiler/src/ast/parse_statement.rs deleted-268
......@@ -1,268 +0,0 @@
1use miette::Result;
2
3use super::error::AstError;
4use super::parse_block::parse_block;
5use super::parse_expression::parse_expression;
6use super::parse_type::parse_type;
7use super::types::{Argument, Ast, ParserContext};
8use super::Token;
9
10/// Precondition: There is at least one token in the iterator
11pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
12 let token = tokens.next().unwrap();
13 match token {
14 Token::Pub => {
15 match tokens.peek() {
16 Some(Token::Let) | Some(Token::Var) | Some(Token::Function) => (),
17 _ => return Err(AstError::new("Expected let, var, or fn after pub").into()),
18 }
19
20 let inner = parse_statement(tokens)?;
21
22 return Ok(Ast::Public {
23 value: Box::new(inner),
24 });
25 }
26 Token::Let => {
27 let name = match tokens.next() {
28 Some(Token::Identifier(name)) => name,
29 _ => return Err(AstError::new("Expected identifier after var").into()),
30 };
31 let return_type = match tokens.next() {
32 Some(Token::Colon) => parse_type(tokens)?,
33 _ => return Err(AstError::new("Expected colon after identifier").into()),
34 };
35 let value = match tokens.next() {
36 Some(Token::Equals) => parse_expression(tokens)?,
37 _ => return Err(AstError::new("Expected equals after identifier").into()),
38 };
39 match tokens.next() {
40 Some(Token::Semicolon) => (),
41 _ => {
42 return Err(
43 AstError::new("Expected semicolon after variable declaration").into(),
44 )
45 }
46 };
47 Ok(Ast::ConstantDeclaration {
48 name: name.clone(),
49 return_type,
50 value: Box::new(value),
51 })
52 }
53 Token::Var => {
54 let name = match tokens.next() {
55 Some(Token::Identifier(name)) => name,
56 _ => return Err(AstError::new("Expected identifier after var").into()),
57 };
58 let return_type = match tokens.next() {
59 Some(Token::Colon) => parse_type(tokens)?,
60 _ => return Err(AstError::new("Expected colon after identifier").into()),
61 };
62 let value = match tokens.next() {
63 Some(Token::Equals) => parse_expression(tokens)?,
64 _ => return Err(AstError::new("Expected equals after identifier").into()),
65 };
66 match tokens.next() {
67 Some(Token::Semicolon) => (),
68 _ => {
69 return Err(
70 AstError::new("Expected semicolon after variable declaration").into(),
71 )
72 }
73 };
74 Ok(Ast::VariableDeclaration {
75 name: name.clone(),
76 return_type,
77 value: Box::new(value),
78 })
79 }
80 Token::Return => {
81 let expression = parse_expression(tokens)?;
82
83 match tokens.next() {
84 Some(Token::Semicolon) => (),
85 _ => return Err(AstError::new("Expected semicolon after return statement").into()),
86 };
87
88 Ok(Ast::Return {
89 return_value: Box::new(expression),
90 })
91 }
92 Token::Function => {
93 let name = match tokens.next() {
94 Some(Token::Identifier(name)) => name.clone(),
95 _ => return Err(AstError::new("Expected identifier after fn").into()),
96 };
97
98 match tokens.next() {
99 Some(Token::OpenParanthesis) => (),
100 _ => {
101 return Err(AstError::new(
102 "Expected open paranthesis after identifier in function",
103 )
104 .into())
105 }
106 };
107
108 let mut arguments = Vec::new();
109
110 loop {
111 match tokens.peek() {
112 Some(Token::ClosedParanthesis) => {
113 tokens.next();
114 break;
115 }
116 _ => (),
117 }
118
119 let argument_name = match tokens.next() {
120 Some(Token::Identifier(name)) => name,
121 _ => {
122 return Err(AstError::new(
123 "Expected identifier for argument name in function",
124 )
125 .into())
126 }
127 };
128
129 let return_type = match tokens.next() {
130 Some(Token::Colon) => parse_type(tokens)?,
131 _ => return Err(AstError::new("Expected colon after identifier").into()),
132 };
133
134 match tokens.peek() {
135 Some(Token::Comma) => {
136 tokens.next();
137 }
138 _ => (),
139 }
140
141 arguments.push(Argument {
142 name: argument_name.clone(),
143 return_type,
144 })
145 }
146
147 let return_type = match tokens.next() {
148 Some(Token::RightArrow) => parse_type(tokens)?,
149 _ => {
150 return Err(AstError::new(
151 "Expected right arrow after argument list in function",
152 )
153 .into())
154 }
155 };
156
157 match tokens.peek() {
158 Some(Token::OpenBracket) => (),
159 _ => {
160 return Err(AstError::new(
161 "Expected open bracket after type in function declaration",
162 )
163 .into())
164 }
165 };
166
167 let block = parse_block(tokens)?;
168
169 return Ok(Ast::Function {
170 name,
171 arguments,
172 return_type,
173 block,
174 });
175 }
176 Token::If => {
177 let condition = parse_expression(tokens)?;
178
179 let value = parse_block(tokens)?;
180
181 let mut else_value = None;
182
183 match tokens.peek() {
184 Some(Token::Else) => {
185 tokens.next();
186 match tokens.peek() {
187 Option::Some(Token::If) => {
188 else_value = Some(Box::new(parse_expression(tokens)?));
189 }
190 Option::Some(Token::OpenBracket) => {
191 else_value = Some(Box::new(Ast::Block(parse_block(tokens)?)));
192 }
193 _ => {
194 return Err(AstError::new(
195 "Expected if or open bracket after else in if statement",
196 )
197 .into())
198 }
199 }
200 }
201 _ => (),
202 }
203
204 return Ok(Ast::If {
205 condition: Box::new(condition),
206 value,
207 else_value,
208 });
209 }
210 Token::Identifier(name) => match tokens.peek() {
211 Some(Token::OpenParanthesis) => {
212 tokens.next();
213
214 let mut arguments = Vec::new();
215
216 loop {
217 match tokens.peek() {
218 Some(Token::ClosedParanthesis) => {
219 tokens.next();
220 break;
221 }
222 _ => (),
223 }
224 arguments.push(parse_expression(tokens)?);
225
226 match tokens.peek() {
227 Some(Token::Comma) => {
228 tokens.next();
229 }
230 Some(Token::ClosedParanthesis) => (),
231 _ => {
232 return Err(AstError::new(
233 "Expected ) or , but found something else instead.",
234 )
235 .into())
236 }
237 }
238 }
239
240 match tokens.next() {
241 Some(Token::Semicolon) => (),
242 _ => return Err(AstError::new("Expected semicolon after function call").into()),
243 };
244
245 Ok(Ast::FunctionCall {
246 name: name.clone(),
247 arguments,
248 })
249 }
250 _ => Err(AstError::new("Unexpected identifier").into()),
251 },
252 Token::Comment(comment) => Ok(Ast::Comment(comment.clone())),
253 Token::DocComment(comment) => {
254 let mut concatted_comments = comment.clone();
255 loop {
256 match tokens.peek() {
257 Some(Token::DocComment(comment)) => {
258 concatted_comments.push_str(format!("\n{}", comment).as_str());
259 tokens.next();
260 }
261 _ => break,
262 }
263 }
264 Ok(Ast::DocComment(concatted_comments))
265 }
266 _ => return Err(AstError::new("Unexpected token").into()),
267 }
268}
compiler/src/ast/parse_type.rs deleted-19
......@@ -1,19 +0,0 @@
1use miette::Result;
2
3use super::error::AstError;
4use super::types::{ParserContext, Type};
5use super::Token;
6
7pub fn parse_type(tokens: &mut ParserContext) -> Result<Type> {
8 match tokens.next() {
9 Some(Token::Identifier(typ)) => match typ.as_str() {
10 "int" => Ok(Type::Int),
11 "float" => Ok(Type::Float),
12 "bigint" => Ok(Type::Bigint),
13 "bool" => Ok(Type::Bool),
14 "string" => Ok(Type::String),
15 _ => return Err(AstError::new("Expected type").into()),
16 },
17 _ => return Err(AstError::new("Expected type").into()),
18 }
19}
compiler/src/ast/types.rs deleted-110
......@@ -1,110 +0,0 @@
1// TODO(lino-levan): Split up AST into expressions, statements, etc.
2
3use crate::tokenizer::Token;
4use crate::util::Operator;
5
6#[derive(Debug)]
7pub struct ParserContext {
8 pub tokens: Vec<Token>,
9 pub cursor: usize,
10}
11
12impl ParserContext {
13 pub fn new(tokens: Vec<Token>) -> ParserContext {
14 ParserContext { tokens, cursor: 0 }
15 }
16
17 pub fn empty(&self) -> bool {
18 self.cursor == self.tokens.len()
19 }
20
21 pub fn back(&mut self) {
22 self.cursor -= 1;
23 }
24
25 pub fn next(&mut self) -> Option<Token> {
26 if self.cursor == self.tokens.len() {
27 return None;
28 }
29
30 let token = self.tokens[self.cursor].clone();
31 self.cursor += 1;
32 Some(token)
33 }
34
35 pub fn peek(&self) -> Option<Token> {
36 if self.cursor == self.tokens.len() {
37 return None;
38 }
39
40 Some(self.tokens[self.cursor].clone())
41 }
42}
43
44#[derive(Debug)]
45pub enum Type {
46 Int,
47 Float,
48 Bigint,
49 Bool,
50 String,
51}
52
53#[derive(Debug)]
54pub struct Block {
55 pub value: Vec<Ast>,
56 pub implicit_return: bool,
57}
58
59#[derive(Debug)]
60pub struct Argument {
61 pub name: String,
62 pub return_type: Type,
63}
64
65#[derive(Debug)]
66pub enum Ast {
67 Public {
68 value: Box<Ast>,
69 },
70 ConstantDeclaration {
71 name: String,
72 return_type: Type,
73 value: Box<Ast>,
74 },
75 VariableDeclaration {
76 name: String,
77 return_type: Type,
78 value: Box<Ast>,
79 },
80 Operation {
81 operator: Operator,
82 left: Box<Ast>,
83 right: Box<Ast>,
84 },
85 Return {
86 return_value: Box<Ast>,
87 },
88 Function {
89 name: String,
90 arguments: Vec<Argument>,
91 return_type: Type,
92 block: Block,
93 },
94 FunctionCall {
95 name: String,
96 arguments: Vec<Ast>,
97 },
98 If {
99 condition: Box<Ast>,
100 value: Block,
101 else_value: Option<Box<Ast>>,
102 },
103 Block(Block),
104 Number(String),
105 Bool(bool),
106 String(String),
107 Identifier(String),
108 Comment(String),
109 DocComment(String),
110}
compiler/src/lib.rs deleted-20
......@@ -1,20 +0,0 @@
1use miette::Result;
2
3pub mod ast;
4pub mod tokenizer;
5pub mod printer;
6
7pub mod util;
8
9pub fn transpile(content: String) -> Result<String> {
10 // 1. Tokenize the input
11 let tokens = tokenizer::tokenize(content)?;
12 // 2. Parse the tokens into an AST
13 let tree = ast::parse(tokens)?;
14 // 3. Type check the AST
15 // type_check(tree.clone())?;
16 // 4. Transpile the AST into javascript
17 let result = printer::transpile(tree)?;
18 // 5. Return the javascript
19 return Ok(result);
20}
compiler/src/printer/mod.rs deleted-139
......@@ -1,139 +0,0 @@
1use miette::Result;
2
3use super::ast::{Ast, Type};
4
5fn transpile_helper(tree: &Ast) -> Result<String> {
6 Ok(match tree {
7 Ast::Number(number) => format!("{}", number),
8 Ast::Identifier(name) => format!("{}", name),
9 Ast::Bool(value) => format!("{}", value),
10 Ast::String(value) => format!("\"{}\"", value),
11 Ast::Comment(comment) => format!("// {}\n", comment),
12 Ast::DocComment(comment) => format!("/** {} */\n", comment),
13 Ast::Operation {
14 operator,
15 left,
16 right,
17 } => format!(
18 "{} {} {}",
19 transpile_helper(left)?,
20 operator.clone().to_string(),
21 transpile_helper(right)?
22 ),
23 Ast::Public { value } => format!("export {}", transpile_helper(value)?),
24 Ast::VariableDeclaration {
25 name,
26 return_type,
27 value,
28 } => match return_type {
29 Type::Bigint => format!("let {} = BigInt({});\n", name, transpile_helper(value)?),
30 _ => format!("let {} = {};\n", name, transpile_helper(value)?),
31 },
32 Ast::ConstantDeclaration {
33 name,
34 return_type,
35 value,
36 } => match return_type {
37 Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(value)?),
38 _ => format!("const {} = {};\n", name, transpile_helper(value)?),
39 },
40 Ast::Return { return_value } => format!("return {};\n", transpile_helper(return_value)?),
41 Ast::Function {
42 name,
43 arguments,
44 return_type: _,
45 block,
46 } => {
47 let mut result = format!("function {}(", name);
48
49 for (i, argument) in arguments.iter().enumerate() {
50 if i == 0 {
51 result += argument.name.as_str();
52 } else {
53 result += format!(", {}", argument.name).as_str();
54 }
55 }
56
57 result += ") {\n";
58
59 for (i, statement) in block.value.iter().enumerate() {
60 if block.implicit_return && i == block.value.len() - 1 {
61 result += format!("return {};\n", transpile_helper(statement)?).as_str();
62 break;
63 }
64 result += transpile_helper(statement)?.as_str();
65 }
66
67 result += "}\n";
68
69 result
70 }
71 Ast::If {
72 condition,
73 value,
74 else_value,
75 } => {
76 let mut result = format!("if ({}) {{\n", transpile_helper(condition)?,);
77
78 for (i, statement) in value.value.iter().enumerate() {
79 if value.implicit_return && i == value.value.len() - 1 {
80 result += format!("return {};\n", transpile_helper(statement)?).as_str();
81 break;
82 }
83 result += transpile_helper(statement)?.as_str();
84 }
85
86 result += "}";
87
88 if let Some(val) = else_value {
89 result += format!(" else {{\n{}}}", transpile_helper(val)?).as_str();
90 } else {
91 result += "\n";
92 }
93
94 result
95 }
96 Ast::FunctionCall { name, arguments } => {
97 let mut result = match name.as_str() {
98 "print" => String::from("console.log("),
99 _ => format!("{}(", name),
100 };
101
102 for (i, argument) in arguments.iter().enumerate() {
103 if i == 0 {
104 result += transpile_helper(argument)?.as_str();
105 } else {
106 result += format!(", {}", transpile_helper(argument)?).as_str();
107 }
108 }
109
110 result += ")";
111
112 result
113 }
114 Ast::Block(block) => {
115 let mut result = String::from("(()=>{\n");
116 for (i, statement) in block.value.iter().enumerate() {
117 if block.implicit_return && i == block.value.len() - 1 {
118 result += format!("return {};\n", transpile_helper(statement)?).as_str();
119 break;
120 }
121 result += transpile_helper(statement)?.as_str();
122 }
123
124 result += "})()\n";
125
126 result
127 }
128 })
129}
130
131pub fn transpile(forest: Vec<Ast>) -> Result<String> {
132 let mut result = String::new();
133
134 for tree in forest {
135 result.push_str(&transpile_helper(&tree)?);
136 }
137
138 Ok(result)
139}
compiler/src/tokenizer.rs deleted-199
......@@ -1,199 +0,0 @@
1use miette::{Diagnostic, Result};
2use thiserror::Error;
3
4use super::util::Operator;
5
6#[derive(Error, Diagnostic, Debug)]
7#[error("UnknownCharacter")]
8struct UnknownCharacter {
9 #[help]
10 error: String,
11}
12
13#[derive(Debug, Clone)]
14pub enum Token {
15 // Literals
16 Identifier(String),
17 Number(String),
18 String(String),
19 // Comments
20 Comment(String),
21 DocComment(String),
22 // Keywords
23 True,
24 False,
25 Let,
26 Var,
27 If,
28 Else,
29 Return,
30 Pub,
31 Function,
32 RightArrow,
33 Comma,
34 OpenParanthesis,
35 ClosedParanthesis,
36 OpenBracket,
37 ClosedBracket,
38 Colon,
39 Equals,
40 Semicolon,
41 // Operators
42 Operator(Operator),
43}
44
45pub fn tokenize(content: String) -> Result<Vec<Token>> {
46 let mut tokens: Vec<Token> = Vec::new();
47 let mut chars = content.chars().enumerate().peekable();
48
49 loop {
50 match chars.next() {
51 Some((_, c)) => match c {
52 'a'..='z' | 'A'..='Z' | '_' => {
53 let mut current_token = String::new();
54 current_token.push(c);
55 loop {
56 let c = chars.peek();
57 if c.is_none() {
58 break;
59 }
60 let (_, c) = c.unwrap();
61 match c {
62 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => {
63 current_token.push(*c);
64 chars.next();
65 }
66 _ => break,
67 }
68 }
69
70 match current_token.as_str() {
71 "var" => tokens.push(Token::Var),
72 "let" => tokens.push(Token::Let),
73 "if" => tokens.push(Token::If),
74 "else" => tokens.push(Token::Else),
75 "pub" => tokens.push(Token::Pub),
76 "fn" => tokens.push(Token::Function),
77 "return" => tokens.push(Token::Return),
78 "true" => tokens.push(Token::True),
79 "false" => tokens.push(Token::False),
80 _ => tokens.push(Token::Identifier(current_token)),
81 }
82 }
83 '"' => {
84 let mut current_token = String::new();
85 loop {
86 let c = chars.next();
87 if c.is_none() {
88 break;
89 }
90 let (_, c) = c.unwrap();
91 match c {
92 '"' => break,
93 _ => current_token.push(c),
94 }
95 }
96 tokens.push(Token::String(current_token));
97 }
98 '0'..='9' => {
99 let mut current_token = String::new();
100 current_token.push(c);
101 loop {
102 let c = chars.peek();
103 if c.is_none() {
104 break;
105 }
106 let (_, c) = c.unwrap();
107 match c {
108 '0'..='9' => {
109 current_token.push(*c);
110 chars.next();
111 }
112 _ => break,
113 }
114 }
115 tokens.push(Token::Number(current_token));
116 }
117 ':' => tokens.push(Token::Colon),
118 '=' => match chars.peek() {
119 Some((_, '=')) => {
120 chars.next();
121 tokens.push(Token::Operator(Operator::Equals));
122 }
123 _ => tokens.push(Token::Equals),
124 },
125 ';' => tokens.push(Token::Semicolon),
126 '>' => tokens.push(Token::Operator(Operator::GreaterThan)),
127 '+' => tokens.push(Token::Operator(Operator::Add)),
128 '-' => match chars.peek() {
129 Some((_, '>')) => {
130 chars.next();
131 tokens.push(Token::RightArrow);
132 }
133 _ => tokens.push(Token::Operator(Operator::Substract)),
134 },
135 '*' => match chars.peek() {
136 Some((_, '*')) => {
137 chars.next();
138 tokens.push(Token::Operator(Operator::Power));
139 }
140 _ => tokens.push(Token::Operator(Operator::Multiply)),
141 },
142 '/' => {
143 match chars.peek() {
144 Some((_, '/')) => {
145 chars.next(); // Consume the second slash
146
147 let is_doc_comment = match chars.peek() {
148 Some((_, '/')) => {
149 chars.next(); // Consume the third slash
150 true
151 }
152 _ => false,
153 };
154
155 let mut comment = String::new();
156 loop {
157 let c = chars.next();
158 if c.is_none() {
159 break;
160 }
161 let (_, c) = c.unwrap();
162 match c {
163 '\n' => break,
164 _ => {
165 comment.push(c.clone());
166 }
167 }
168 }
169
170 comment = comment.trim().to_string();
171
172 if is_doc_comment {
173 tokens.push(Token::DocComment(comment));
174 } else {
175 tokens.push(Token::Comment(comment));
176 }
177 }
178 _ => tokens.push(Token::Operator(Operator::Divide)),
179 }
180 }
181 ',' => tokens.push(Token::Comma),
182 '(' => tokens.push(Token::OpenParanthesis),
183 ')' => tokens.push(Token::ClosedParanthesis),
184 '{' => tokens.push(Token::OpenBracket),
185 '}' => tokens.push(Token::ClosedBracket),
186 s if s.is_whitespace() => (),
187 _ => {
188 return Err(UnknownCharacter {
189 error: format!("Unsupported character: {}", c),
190 }
191 .into())
192 }
193 },
194 None => break,
195 }
196 }
197
198 Ok(tokens)
199}
compiler/src/util.rs deleted-24
......@@ -1,24 +0,0 @@
1#[derive(Debug, Clone)]
2pub enum Operator {
3 Add,
4 Substract,
5 Multiply,
6 Divide,
7 Power,
8 Equals,
9 GreaterThan,
10}
11
12impl Operator {
13 pub fn to_string(self) -> String {
14 String::from(match self {
15 Self::Add => "+",
16 Self::Substract => "-",
17 Self::Divide => "/",
18 Self::Multiply => "*",
19 Self::Power => "**",
20 Self::Equals => "===",
21 Self::GreaterThan => ">",
22 })
23 }
24}
crates/ast/Cargo.toml created+13
......@@ -0,0 +1,13 @@
1[package]
2name = "ast"
3version = "0.1.0"
4edition = "2021"
5
6[lib]
7
8[dependencies]
9miette.workspace = true
10thiserror.workspace = true
11
12tokenizer = { path = "../tokenizer" }
13util = { path = "../util" }
crates/ast/src/error.rs created+17
......@@ -0,0 +1,17 @@
1use miette::Diagnostic;
2use thiserror::Error;
3
4#[derive(Error, Diagnostic, Debug)]
5#[error("AstError")]
6pub struct AstError {
7 #[help]
8 error: String,
9}
10
11impl AstError {
12 pub fn new(error: &'static str) -> AstError {
13 AstError {
14 error: String::from(error),
15 }
16 }
17}
crates/ast/src/lib.rs created+26
......@@ -0,0 +1,26 @@
1use miette::Result;
2
3mod error;
4mod parse_block;
5mod parse_expression;
6mod parse_statement;
7mod parse_type;
8mod types;
9
10use tokenizer::Token;
11
12use parse_statement::parse_statement;
13use types::ParserContext;
14
15pub use types::{Ast, Block, Type};
16
17pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>> {
18 let mut ctx = ParserContext::new(tokens);
19 let mut ast: Vec<Ast> = Vec::new();
20
21 while !ctx.empty() {
22 ast.push(parse_statement(&mut ctx)?);
23 }
24
25 Ok(ast)
26}
crates/ast/src/parse_block.rs created+55
......@@ -0,0 +1,55 @@
1use miette::Result;
2
3use tokenizer::Token;
4
5use super::error::AstError;
6use super::parse_expression::parse_expression;
7use super::parse_statement::parse_statement;
8use super::types::Block;
9use super::types::ParserContext;
10
11pub fn parse_block(tokens: &mut ParserContext) -> Result<Block> {
12 match tokens.next() {
13 Some(Token::OpenBracket) => (),
14 _ => return Err(AstError::new("Expected { when parsing block").into()),
15 }
16
17 let mut value = Vec::new();
18 let mut implicit_return = false;
19
20 loop {
21 match tokens.peek() {
22 Some(Token::ClosedBracket) => {
23 tokens.next();
24 break;
25 }
26 _ => (),
27 }
28
29 let current_cursor = tokens.cursor;
30 let result = parse_statement(tokens);
31
32 match result {
33 Ok(ast) => value.push(ast),
34 Err(_) => {
35 tokens.cursor = current_cursor;
36 value.push(parse_expression(tokens)?);
37 implicit_return = true;
38 match tokens.peek() {
39 Some(Token::ClosedBracket) => (),
40 _ => {
41 return Err(AstError::new(
42 "Expected closed bracket after expression in function body",
43 )
44 .into());
45 }
46 }
47 }
48 }
49 }
50
51 Ok(Block {
52 value,
53 implicit_return,
54 })
55}
crates/ast/src/parse_expression.rs created+117
......@@ -0,0 +1,117 @@
1use miette::Result;
2
3use tokenizer::Token;
4
5use super::error::AstError;
6use super::parse_block::parse_block;
7use super::types::{Ast, ParserContext};
8
9pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
10 let left = match tokens.next() {
11 Some(token) => match token {
12 Token::Number(number) => Ast::Number(number.clone()),
13 Token::String(string) => Ast::String(string.clone()),
14 Token::True => Ast::Bool(true),
15 Token::False => Ast::Bool(false),
16 Token::OpenBracket => {
17 // FRICK we consumed the open bracket
18 // we need to put the cursor back
19 tokens.back();
20 Ast::Block(parse_block(tokens)?)
21 }
22 Token::If => {
23 let condition = parse_expression(tokens)?;
24
25 let value = parse_block(tokens)?;
26
27 let mut else_value = None;
28
29 match tokens.peek() {
30 Some(Token::Else) => {
31 tokens.next();
32 match tokens.peek() {
33 Option::Some(Token::If) => {
34 else_value = Some(Box::new(parse_expression(tokens)?));
35 }
36 Option::Some(Token::OpenBracket) => {
37 else_value = Some(Box::new(Ast::Block(parse_block(tokens)?)));
38 }
39 _ => {
40 return Err(AstError::new(
41 "Expected if or open bracket after else in if statement",
42 )
43 .into())
44 }
45 }
46 }
47 _ => (),
48 }
49
50 return Ok(Ast::If {
51 condition: Box::new(condition),
52 value,
53 else_value,
54 });
55 }
56 Token::Identifier(name) => match tokens.peek() {
57 Some(Token::OpenParanthesis) => {
58 tokens.next();
59
60 let mut arguments = Vec::new();
61
62 loop {
63 match tokens.peek() {
64 Some(Token::ClosedParanthesis) => {
65 tokens.next();
66 break;
67 }
68 _ => (),
69 }
70 arguments.push(parse_expression(tokens)?);
71
72 match tokens.peek() {
73 Some(Token::Comma) => {
74 tokens.next();
75 }
76 Some(Token::ClosedParanthesis) => (),
77 _ => {
78 return Err(AstError::new(
79 "Expected ) or , but found something else instead.",
80 )
81 .into())
82 }
83 }
84 }
85
86 Ast::FunctionCall {
87 name: name.clone(),
88 arguments,
89 }
90 }
91 _ => Ast::Identifier(name.clone()),
92 },
93 _ => {
94 println!("token: {:?}", token);
95 return Err(AstError::new("Expected expression, but did not get it").into());
96 }
97 },
98 None => return Err(AstError::new("Expected expression, but got nothing instead").into()),
99 };
100
101 match tokens.peek() {
102 Some(token) => match token {
103 Token::Operator(operator) => {
104 tokens.next();
105 return Ok(Ast::Operation {
106 operator: operator.clone(),
107 left: Box::new(left),
108 right: Box::new(parse_expression(tokens)?),
109 });
110 }
111 _ => (),
112 },
113 _ => (),
114 }
115
116 Ok(left)
117}
crates/ast/src/parse_statement.rs created+269
......@@ -0,0 +1,269 @@
1use miette::Result;
2
3use tokenizer::Token;
4
5use super::error::AstError;
6use super::parse_block::parse_block;
7use super::parse_expression::parse_expression;
8use super::parse_type::parse_type;
9use super::types::{Argument, Ast, ParserContext};
10
11/// Precondition: There is at least one token in the iterator
12pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
13 let token = tokens.next().unwrap();
14 match token {
15 Token::Pub => {
16 match tokens.peek() {
17 Some(Token::Let) | Some(Token::Var) | Some(Token::Function) => (),
18 _ => return Err(AstError::new("Expected let, var, or fn after pub").into()),
19 }
20
21 let inner = parse_statement(tokens)?;
22
23 return Ok(Ast::Public {
24 value: Box::new(inner),
25 });
26 }
27 Token::Let => {
28 let name = match tokens.next() {
29 Some(Token::Identifier(name)) => name,
30 _ => return Err(AstError::new("Expected identifier after var").into()),
31 };
32 let return_type = match tokens.next() {
33 Some(Token::Colon) => parse_type(tokens)?,
34 _ => return Err(AstError::new("Expected colon after identifier").into()),
35 };
36 let value = match tokens.next() {
37 Some(Token::Equals) => parse_expression(tokens)?,
38 _ => return Err(AstError::new("Expected equals after identifier").into()),
39 };
40 match tokens.next() {
41 Some(Token::Semicolon) => (),
42 _ => {
43 return Err(
44 AstError::new("Expected semicolon after variable declaration").into(),
45 )
46 }
47 };
48 Ok(Ast::ConstantDeclaration {
49 name: name.clone(),
50 return_type,
51 value: Box::new(value),
52 })
53 }
54 Token::Var => {
55 let name = match tokens.next() {
56 Some(Token::Identifier(name)) => name,
57 _ => return Err(AstError::new("Expected identifier after var").into()),
58 };
59 let return_type = match tokens.next() {
60 Some(Token::Colon) => parse_type(tokens)?,
61 _ => return Err(AstError::new("Expected colon after identifier").into()),
62 };
63 let value = match tokens.next() {
64 Some(Token::Equals) => parse_expression(tokens)?,
65 _ => return Err(AstError::new("Expected equals after identifier").into()),
66 };
67 match tokens.next() {
68 Some(Token::Semicolon) => (),
69 _ => {
70 return Err(
71 AstError::new("Expected semicolon after variable declaration").into(),
72 )
73 }
74 };
75 Ok(Ast::VariableDeclaration {
76 name: name.clone(),
77 return_type,
78 value: Box::new(value),
79 })
80 }
81 Token::Return => {
82 let expression = parse_expression(tokens)?;
83
84 match tokens.next() {
85 Some(Token::Semicolon) => (),
86 _ => return Err(AstError::new("Expected semicolon after return statement").into()),
87 };
88
89 Ok(Ast::Return {
90 return_value: Box::new(expression),
91 })
92 }
93 Token::Function => {
94 let name = match tokens.next() {
95 Some(Token::Identifier(name)) => name.clone(),
96 _ => return Err(AstError::new("Expected identifier after fn").into()),
97 };
98
99 match tokens.next() {
100 Some(Token::OpenParanthesis) => (),
101 _ => {
102 return Err(AstError::new(
103 "Expected open paranthesis after identifier in function",
104 )
105 .into())
106 }
107 };
108
109 let mut arguments = Vec::new();
110
111 loop {
112 match tokens.peek() {
113 Some(Token::ClosedParanthesis) => {
114 tokens.next();
115 break;
116 }
117 _ => (),
118 }
119
120 let argument_name = match tokens.next() {
121 Some(Token::Identifier(name)) => name,
122 _ => {
123 return Err(AstError::new(
124 "Expected identifier for argument name in function",
125 )
126 .into())
127 }
128 };
129
130 let return_type = match tokens.next() {
131 Some(Token::Colon) => parse_type(tokens)?,
132 _ => return Err(AstError::new("Expected colon after identifier").into()),
133 };
134
135 match tokens.peek() {
136 Some(Token::Comma) => {
137 tokens.next();
138 }
139 _ => (),
140 }
141
142 arguments.push(Argument {
143 name: argument_name.clone(),
144 return_type,
145 })
146 }
147
148 let return_type = match tokens.next() {
149 Some(Token::RightArrow) => parse_type(tokens)?,
150 _ => {
151 return Err(AstError::new(
152 "Expected right arrow after argument list in function",
153 )
154 .into())
155 }
156 };
157
158 match tokens.peek() {
159 Some(Token::OpenBracket) => (),
160 _ => {
161 return Err(AstError::new(
162 "Expected open bracket after type in function declaration",
163 )
164 .into())
165 }
166 };
167
168 let block = parse_block(tokens)?;
169
170 return Ok(Ast::Function {
171 name,
172 arguments,
173 return_type,
174 block,
175 });
176 }
177 Token::If => {
178 let condition = parse_expression(tokens)?;
179
180 let value = parse_block(tokens)?;
181
182 let mut else_value = None;
183
184 match tokens.peek() {
185 Some(Token::Else) => {
186 tokens.next();
187 match tokens.peek() {
188 Option::Some(Token::If) => {
189 else_value = Some(Box::new(parse_expression(tokens)?));
190 }
191 Option::Some(Token::OpenBracket) => {
192 else_value = Some(Box::new(Ast::Block(parse_block(tokens)?)));
193 }
194 _ => {
195 return Err(AstError::new(
196 "Expected if or open bracket after else in if statement",
197 )
198 .into())
199 }
200 }
201 }
202 _ => (),
203 }
204
205 return Ok(Ast::If {
206 condition: Box::new(condition),
207 value,
208 else_value,
209 });
210 }
211 Token::Identifier(name) => match tokens.peek() {
212 Some(Token::OpenParanthesis) => {
213 tokens.next();
214
215 let mut arguments = Vec::new();
216
217 loop {
218 match tokens.peek() {
219 Some(Token::ClosedParanthesis) => {
220 tokens.next();
221 break;
222 }
223 _ => (),
224 }
225 arguments.push(parse_expression(tokens)?);
226
227 match tokens.peek() {
228 Some(Token::Comma) => {
229 tokens.next();
230 }
231 Some(Token::ClosedParanthesis) => (),
232 _ => {
233 return Err(AstError::new(
234 "Expected ) or , but found something else instead.",
235 )
236 .into())
237 }
238 }
239 }
240
241 match tokens.next() {
242 Some(Token::Semicolon) => (),
243 _ => return Err(AstError::new("Expected semicolon after function call").into()),
244 };
245
246 Ok(Ast::FunctionCall {
247 name: name.clone(),
248 arguments,
249 })
250 }
251 _ => Err(AstError::new("Unexpected identifier").into()),
252 },
253 Token::Comment(comment) => Ok(Ast::Comment(comment.clone())),
254 Token::DocComment(comment) => {
255 let mut concatted_comments = comment.clone();
256 loop {
257 match tokens.peek() {
258 Some(Token::DocComment(comment)) => {
259 concatted_comments.push_str(format!("\n{}", comment).as_str());
260 tokens.next();
261 }
262 _ => break,
263 }
264 }
265 Ok(Ast::DocComment(concatted_comments))
266 }
267 _ => return Err(AstError::new("Unexpected token").into()),
268 }
269}
crates/ast/src/parse_type.rs created+20
......@@ -0,0 +1,20 @@
1use miette::Result;
2
3use tokenizer::Token;
4
5use super::error::AstError;
6use super::types::{ParserContext, Type};
7
8pub fn parse_type(tokens: &mut ParserContext) -> Result<Type> {
9 match tokens.next() {
10 Some(Token::Identifier(typ)) => match typ.as_str() {
11 "int" => Ok(Type::Int),
12 "float" => Ok(Type::Float),
13 "bigint" => Ok(Type::Bigint),
14 "bool" => Ok(Type::Bool),
15 "string" => Ok(Type::String),
16 _ => return Err(AstError::new("Expected type").into()),
17 },
18 _ => return Err(AstError::new("Expected type").into()),
19 }
20}
crates/ast/src/types.rs created+110
......@@ -0,0 +1,110 @@
1// TODO(lino-levan): Split up AST into expressions, statements, etc.
2
3use tokenizer::Token;
4use util::Operator;
5
6#[derive(Debug)]
7pub struct ParserContext {
8 pub tokens: Vec<Token>,
9 pub cursor: usize,
10}
11
12impl ParserContext {
13 pub fn new(tokens: Vec<Token>) -> ParserContext {
14 ParserContext { tokens, cursor: 0 }
15 }
16
17 pub fn empty(&self) -> bool {
18 self.cursor == self.tokens.len()
19 }
20
21 pub fn back(&mut self) {
22 self.cursor -= 1;
23 }
24
25 pub fn next(&mut self) -> Option<Token> {
26 if self.cursor == self.tokens.len() {
27 return None;
28 }
29
30 let token = self.tokens[self.cursor].clone();
31 self.cursor += 1;
32 Some(token)
33 }
34
35 pub fn peek(&self) -> Option<Token> {
36 if self.cursor == self.tokens.len() {
37 return None;
38 }
39
40 Some(self.tokens[self.cursor].clone())
41 }
42}
43
44#[derive(Debug)]
45pub enum Type {
46 Int,
47 Float,
48 Bigint,
49 Bool,
50 String,
51}
52
53#[derive(Debug)]
54pub struct Block {
55 pub value: Vec<Ast>,
56 pub implicit_return: bool,
57}
58
59#[derive(Debug)]
60pub struct Argument {
61 pub name: String,
62 pub return_type: Type,
63}
64
65#[derive(Debug)]
66pub enum Ast {
67 Public {
68 value: Box<Ast>,
69 },
70 ConstantDeclaration {
71 name: String,
72 return_type: Type,
73 value: Box<Ast>,
74 },
75 VariableDeclaration {
76 name: String,
77 return_type: Type,
78 value: Box<Ast>,
79 },
80 Operation {
81 operator: Operator,
82 left: Box<Ast>,
83 right: Box<Ast>,
84 },
85 Return {
86 return_value: Box<Ast>,
87 },
88 Function {
89 name: String,
90 arguments: Vec<Argument>,
91 return_type: Type,
92 block: Block,
93 },
94 FunctionCall {
95 name: String,
96 arguments: Vec<Ast>,
97 },
98 If {
99 condition: Box<Ast>,
100 value: Block,
101 else_value: Option<Box<Ast>>,
102 },
103 Block(Block),
104 Number(String),
105 Bool(bool),
106 String(String),
107 Identifier(String),
108 Comment(String),
109 DocComment(String),
110}
crates/cli/Cargo.lock created+532
......@@ -0,0 +1,532 @@
1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing.
3version = 3
4
5[[package]]
6name = "addr2line"
7version = "0.21.0"
8source = "registry+https://github.com/rust-lang/crates.io-index"
9checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
10dependencies = [
11 "gimli",
12]
13
14[[package]]
15name = "adler"
16version = "1.0.2"
17source = "registry+https://github.com/rust-lang/crates.io-index"
18checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19
20[[package]]
21name = "anstream"
22version = "0.6.5"
23source = "registry+https://github.com/rust-lang/crates.io-index"
24checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
25dependencies = [
26 "anstyle",
27 "anstyle-parse",
28 "anstyle-query",
29 "anstyle-wincon",
30 "colorchoice",
31 "utf8parse",
32]
33
34[[package]]
35name = "anstyle"
36version = "1.0.4"
37source = "registry+https://github.com/rust-lang/crates.io-index"
38checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
39
40[[package]]
41name = "anstyle-parse"
42version = "0.2.3"
43source = "registry+https://github.com/rust-lang/crates.io-index"
44checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
45dependencies = [
46 "utf8parse",
47]
48
49[[package]]
50name = "anstyle-query"
51version = "1.0.2"
52source = "registry+https://github.com/rust-lang/crates.io-index"
53checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
54dependencies = [
55 "windows-sys",
56]
57
58[[package]]
59name = "anstyle-wincon"
60version = "3.0.2"
61source = "registry+https://github.com/rust-lang/crates.io-index"
62checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
63dependencies = [
64 "anstyle",
65 "windows-sys",
66]
67
68[[package]]
69name = "backtrace"
70version = "0.3.69"
71source = "registry+https://github.com/rust-lang/crates.io-index"
72checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
73dependencies = [
74 "addr2line",
75 "cc",
76 "cfg-if",
77 "libc",
78 "miniz_oxide",
79 "object",
80 "rustc-demangle",
81]
82
83[[package]]
84name = "backtrace-ext"
85version = "0.2.1"
86source = "registry+https://github.com/rust-lang/crates.io-index"
87checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
88dependencies = [
89 "backtrace",
90]
91
92[[package]]
93name = "bitflags"
94version = "2.4.1"
95source = "registry+https://github.com/rust-lang/crates.io-index"
96checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
97
98[[package]]
99name = "blight"
100version = "0.1.0"
101dependencies = [
102 "clap",
103 "miette",
104 "thiserror",
105]
106
107[[package]]
108name = "cc"
109version = "1.0.83"
110source = "registry+https://github.com/rust-lang/crates.io-index"
111checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
112dependencies = [
113 "libc",
114]
115
116[[package]]
117name = "cfg-if"
118version = "1.0.0"
119source = "registry+https://github.com/rust-lang/crates.io-index"
120checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
121
122[[package]]
123name = "clap"
124version = "4.4.12"
125source = "registry+https://github.com/rust-lang/crates.io-index"
126checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d"
127dependencies = [
128 "clap_builder",
129 "clap_derive",
130]
131
132[[package]]
133name = "clap_builder"
134version = "4.4.12"
135source = "registry+https://github.com/rust-lang/crates.io-index"
136checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
137dependencies = [
138 "anstream",
139 "anstyle",
140 "clap_lex",
141 "strsim",
142]
143
144[[package]]
145name = "clap_derive"
146version = "4.4.7"
147source = "registry+https://github.com/rust-lang/crates.io-index"
148checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
149dependencies = [
150 "heck",
151 "proc-macro2",
152 "quote",
153 "syn",
154]
155
156[[package]]
157name = "clap_lex"
158version = "0.6.0"
159source = "registry+https://github.com/rust-lang/crates.io-index"
160checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
161
162[[package]]
163name = "colorchoice"
164version = "1.0.0"
165source = "registry+https://github.com/rust-lang/crates.io-index"
166checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
167
168[[package]]
169name = "errno"
170version = "0.3.8"
171source = "registry+https://github.com/rust-lang/crates.io-index"
172checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
173dependencies = [
174 "libc",
175 "windows-sys",
176]
177
178[[package]]
179name = "gimli"
180version = "0.28.1"
181source = "registry+https://github.com/rust-lang/crates.io-index"
182checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
183
184[[package]]
185name = "heck"
186version = "0.4.1"
187source = "registry+https://github.com/rust-lang/crates.io-index"
188checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
189
190[[package]]
191name = "hermit-abi"
192version = "0.3.3"
193source = "registry+https://github.com/rust-lang/crates.io-index"
194checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
195
196[[package]]
197name = "is-terminal"
198version = "0.4.10"
199source = "registry+https://github.com/rust-lang/crates.io-index"
200checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
201dependencies = [
202 "hermit-abi",
203 "rustix",
204 "windows-sys",
205]
206
207[[package]]
208name = "is_ci"
209version = "1.1.1"
210source = "registry+https://github.com/rust-lang/crates.io-index"
211checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
212
213[[package]]
214name = "libc"
215version = "0.2.151"
216source = "registry+https://github.com/rust-lang/crates.io-index"
217checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
218
219[[package]]
220name = "linux-raw-sys"
221version = "0.4.12"
222source = "registry+https://github.com/rust-lang/crates.io-index"
223checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
224
225[[package]]
226name = "memchr"
227version = "2.7.1"
228source = "registry+https://github.com/rust-lang/crates.io-index"
229checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
230
231[[package]]
232name = "miette"
233version = "5.10.0"
234source = "registry+https://github.com/rust-lang/crates.io-index"
235checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e"
236dependencies = [
237 "backtrace",
238 "backtrace-ext",
239 "is-terminal",
240 "miette-derive",
241 "once_cell",
242 "owo-colors",
243 "supports-color",
244 "supports-hyperlinks",
245 "supports-unicode",
246 "terminal_size",
247 "textwrap",
248 "thiserror",
249 "unicode-width",
250]
251
252[[package]]
253name = "miette-derive"
254version = "5.10.0"
255source = "registry+https://github.com/rust-lang/crates.io-index"
256checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c"
257dependencies = [
258 "proc-macro2",
259 "quote",
260 "syn",
261]
262
263[[package]]
264name = "miniz_oxide"
265version = "0.7.1"
266source = "registry+https://github.com/rust-lang/crates.io-index"
267checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
268dependencies = [
269 "adler",
270]
271
272[[package]]
273name = "object"
274version = "0.32.2"
275source = "registry+https://github.com/rust-lang/crates.io-index"
276checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
277dependencies = [
278 "memchr",
279]
280
281[[package]]
282name = "once_cell"
283version = "1.19.0"
284source = "registry+https://github.com/rust-lang/crates.io-index"
285checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
286
287[[package]]
288name = "owo-colors"
289version = "3.5.0"
290source = "registry+https://github.com/rust-lang/crates.io-index"
291checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
292
293[[package]]
294name = "proc-macro2"
295version = "1.0.73"
296source = "registry+https://github.com/rust-lang/crates.io-index"
297checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1"
298dependencies = [
299 "unicode-ident",
300]
301
302[[package]]
303name = "quote"
304version = "1.0.34"
305source = "registry+https://github.com/rust-lang/crates.io-index"
306checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a"
307dependencies = [
308 "proc-macro2",
309]
310
311[[package]]
312name = "rustc-demangle"
313version = "0.1.23"
314source = "registry+https://github.com/rust-lang/crates.io-index"
315checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
316
317[[package]]
318name = "rustix"
319version = "0.38.28"
320source = "registry+https://github.com/rust-lang/crates.io-index"
321checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
322dependencies = [
323 "bitflags",
324 "errno",
325 "libc",
326 "linux-raw-sys",
327 "windows-sys",
328]
329
330[[package]]
331name = "smawk"
332version = "0.3.2"
333source = "registry+https://github.com/rust-lang/crates.io-index"
334checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
335
336[[package]]
337name = "strsim"
338version = "0.10.0"
339source = "registry+https://github.com/rust-lang/crates.io-index"
340checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
341
342[[package]]
343name = "supports-color"
344version = "2.1.0"
345source = "registry+https://github.com/rust-lang/crates.io-index"
346checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89"
347dependencies = [
348 "is-terminal",
349 "is_ci",
350]
351
352[[package]]
353name = "supports-hyperlinks"
354version = "2.1.0"
355source = "registry+https://github.com/rust-lang/crates.io-index"
356checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d"
357dependencies = [
358 "is-terminal",
359]
360
361[[package]]
362name = "supports-unicode"
363version = "2.0.0"
364source = "registry+https://github.com/rust-lang/crates.io-index"
365checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7"
366dependencies = [
367 "is-terminal",
368]
369
370[[package]]
371name = "syn"
372version = "2.0.44"
373source = "registry+https://github.com/rust-lang/crates.io-index"
374checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d"
375dependencies = [
376 "proc-macro2",
377 "quote",
378 "unicode-ident",
379]
380
381[[package]]
382name = "terminal_size"
383version = "0.1.17"
384source = "registry+https://github.com/rust-lang/crates.io-index"
385checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
386dependencies = [
387 "libc",
388 "winapi",
389]
390
391[[package]]
392name = "textwrap"
393version = "0.15.2"
394source = "registry+https://github.com/rust-lang/crates.io-index"
395checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
396dependencies = [
397 "smawk",
398 "unicode-linebreak",
399 "unicode-width",
400]
401
402[[package]]
403name = "thiserror"
404version = "1.0.53"
405source = "registry+https://github.com/rust-lang/crates.io-index"
406checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09"
407dependencies = [
408 "thiserror-impl",
409]
410
411[[package]]
412name = "thiserror-impl"
413version = "1.0.53"
414source = "registry+https://github.com/rust-lang/crates.io-index"
415checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19"
416dependencies = [
417 "proc-macro2",
418 "quote",
419 "syn",
420]
421
422[[package]]
423name = "unicode-ident"
424version = "1.0.12"
425source = "registry+https://github.com/rust-lang/crates.io-index"
426checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
427
428[[package]]
429name = "unicode-linebreak"
430version = "0.1.5"
431source = "registry+https://github.com/rust-lang/crates.io-index"
432checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
433
434[[package]]
435name = "unicode-width"
436version = "0.1.11"
437source = "registry+https://github.com/rust-lang/crates.io-index"
438checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
439
440[[package]]
441name = "utf8parse"
442version = "0.2.1"
443source = "registry+https://github.com/rust-lang/crates.io-index"
444checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
445
446[[package]]
447name = "winapi"
448version = "0.3.9"
449source = "registry+https://github.com/rust-lang/crates.io-index"
450checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
451dependencies = [
452 "winapi-i686-pc-windows-gnu",
453 "winapi-x86_64-pc-windows-gnu",
454]
455
456[[package]]
457name = "winapi-i686-pc-windows-gnu"
458version = "0.4.0"
459source = "registry+https://github.com/rust-lang/crates.io-index"
460checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
461
462[[package]]
463name = "winapi-x86_64-pc-windows-gnu"
464version = "0.4.0"
465source = "registry+https://github.com/rust-lang/crates.io-index"
466checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
467
468[[package]]
469name = "windows-sys"
470version = "0.52.0"
471source = "registry+https://github.com/rust-lang/crates.io-index"
472checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
473dependencies = [
474 "windows-targets",
475]
476
477[[package]]
478name = "windows-targets"
479version = "0.52.0"
480source = "registry+https://github.com/rust-lang/crates.io-index"
481checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
482dependencies = [
483 "windows_aarch64_gnullvm",
484 "windows_aarch64_msvc",
485 "windows_i686_gnu",
486 "windows_i686_msvc",
487 "windows_x86_64_gnu",
488 "windows_x86_64_gnullvm",
489 "windows_x86_64_msvc",
490]
491
492[[package]]
493name = "windows_aarch64_gnullvm"
494version = "0.52.0"
495source = "registry+https://github.com/rust-lang/crates.io-index"
496checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
497
498[[package]]
499name = "windows_aarch64_msvc"
500version = "0.52.0"
501source = "registry+https://github.com/rust-lang/crates.io-index"
502checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
503
504[[package]]
505name = "windows_i686_gnu"
506version = "0.52.0"
507source = "registry+https://github.com/rust-lang/crates.io-index"
508checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
509
510[[package]]
511name = "windows_i686_msvc"
512version = "0.52.0"
513source = "registry+https://github.com/rust-lang/crates.io-index"
514checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
515
516[[package]]
517name = "windows_x86_64_gnu"
518version = "0.52.0"
519source = "registry+https://github.com/rust-lang/crates.io-index"
520checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
521
522[[package]]
523name = "windows_x86_64_gnullvm"
524version = "0.52.0"
525source = "registry+https://github.com/rust-lang/crates.io-index"
526checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
527
528[[package]]
529name = "windows_x86_64_msvc"
530version = "0.52.0"
531source = "registry+https://github.com/rust-lang/crates.io-index"
532checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
crates/cli/Cargo.toml created+17
......@@ -0,0 +1,17 @@
1[package]
2name = "cli"
3version = "0.1.0"
4edition = "2021"
5
6[[bin]]
7name = "blight"
8path = "./src/main.rs"
9
10[dependencies]
11clap.workspace = true
12miette.workspace = true
13thiserror.workspace = true
14
15tokenizer = { path = "../tokenizer" }
16ast = { path = "../ast" }
17js_printer = { path = "../js_printer" }
crates/cli/src/main.rs created+120
......@@ -0,0 +1,120 @@
1use std::path::PathBuf;
2
3use clap::{Parser, Subcommand};
4use miette::Result;
5
6use tokenizer;
7use ast;
8use js_printer;
9
10#[derive(Parser)]
11#[command(author, version, about, long_about = None)]
12struct Cli {
13 /// Turn debugging information on
14 #[arg(short, long, action = clap::ArgAction::Count)]
15 debug: u8,
16
17 #[command(subcommand)]
18 command: Commands,
19}
20
21#[derive(Subcommand)]
22enum Commands {
23 /// Compiles a file into javascript
24 Compile {
25 file: PathBuf,
26 // Whether to output to stdout instead of a file
27 #[arg(long, default_value_t = false)]
28 stdout: bool,
29 },
30 Run {
31 file: PathBuf,
32 /// What javascript runtime to use
33 #[arg(short, long, default_value = "deno")]
34 runtime: String,
35 },
36}
37
38fn get_runtime(runtime: &String) -> String {
39 match std::env::var("USER") {
40 Ok(user) if user == "dave" => String::from("bun"),
41 _ => runtime.clone(),
42 }
43}
44
45
46pub fn transpile(content: String) -> Result<String> {
47 // 1. Tokenize the input
48 let tokens = tokenizer::tokenize(content)?;
49 // 2. Parse the tokens into an AST
50 let blight_ast = ast::parse(tokens)?;
51 // 3. Type check the AST
52 // type_check(tree.clone())?;
53 // 4. Optimize the AST
54 // optimize(tree.clone())?;
55 // 5. Translate the AST into javascript
56 // translate(tree.clone())?;
57 // 6. Print the JS AST
58 let javascript = js_printer::transpile(blight_ast)?;
59 // 7. Return the javascript
60 return Ok(javascript);
61}
62
63
64fn main() -> Result<()> {
65 let cli = Cli::parse();
66
67 match cli.command {
68 Commands::Compile { file, stdout } => {
69 let contents = std::fs::read_to_string(file.clone()).unwrap();
70 let result = transpile(contents.clone())?;
71
72 if stdout {
73 println!("{}", result);
74 } else {
75 std::fs::write(file.with_extension("js"), result).unwrap();
76 }
77 }
78 Commands::Run { file, runtime } => {
79 let contents = std::fs::read_to_string(file.clone()).unwrap();
80 let result = transpile(contents.clone())?;
81 let mut temp_file = std::env::temp_dir();
82 temp_file.push("temp.js");
83 std::fs::write(temp_file.clone(), result).unwrap();
84
85 let rt = get_runtime(&runtime);
86
87 match rt.as_str() {
88 "deno" => {
89 let output = std::process::Command::new("deno")
90 .arg("run")
91 .arg("-A")
92 .arg(temp_file)
93 .output()
94 .expect("Failed to execute process");
95 println!("{}", String::from_utf8_lossy(&output.stdout));
96 }
97 "node" => {
98 let output = std::process::Command::new("node")
99 .arg(temp_file)
100 .output()
101 .expect("Failed to execute process");
102 println!("{}", String::from_utf8_lossy(&output.stdout));
103 }
104 "bun" => {
105 let output = std::process::Command::new("bun")
106 .arg("run")
107 .arg(temp_file)
108 .output()
109 .expect("Failed to execute process");
110 println!("{}", String::from_utf8_lossy(&output.stdout));
111 }
112 _ => {
113 println!("Unknown runtime: {}", runtime);
114 }
115 }
116 }
117 }
118
119 Ok(())
120}
crates/js_ast/Cargo.toml created+10
......@@ -0,0 +1,10 @@
1[package]
2name = "js_ast"
3version = "0.1.0"
4edition = "2021"
5
6[lib]
7
8[dependencies]
9miette.workspace = true
10thiserror.workspace = true
crates/js_ast/src/lib.rs created
crates/js_printer/Cargo.toml created+12
......@@ -0,0 +1,12 @@
1[package]
2name = "js_printer"
3version = "0.1.0"
4edition = "2021"
5
6[lib]
7
8[dependencies]
9miette.workspace = true
10thiserror.workspace = true
11
12ast = { path = "../ast" }
crates/js_printer/src/lib.rs created+139
......@@ -0,0 +1,139 @@
1use miette::Result;
2
3use ast::{Ast, Type};
4
5fn transpile_helper(tree: &Ast) -> Result<String> {
6 Ok(match tree {
7 Ast::Number(number) => format!("{}", number),
8 Ast::Identifier(name) => format!("{}", name),
9 Ast::Bool(value) => format!("{}", value),
10 Ast::String(value) => format!("\"{}\"", value),
11 Ast::Comment(comment) => format!("// {}\n", comment),
12 Ast::DocComment(comment) => format!("/** {} */\n", comment),
13 Ast::Operation {
14 operator,
15 left,
16 right,
17 } => format!(
18 "{} {} {}",
19 transpile_helper(left)?,
20 operator.clone().to_string(),
21 transpile_helper(right)?
22 ),
23 Ast::Public { value } => format!("export {}", transpile_helper(value)?),
24 Ast::VariableDeclaration {
25 name,
26 return_type,
27 value,
28 } => match return_type {
29 Type::Bigint => format!("let {} = BigInt({});\n", name, transpile_helper(value)?),
30 _ => format!("let {} = {};\n", name, transpile_helper(value)?),
31 },
32 Ast::ConstantDeclaration {
33 name,
34 return_type,
35 value,
36 } => match return_type {
37 Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(value)?),
38 _ => format!("const {} = {};\n", name, transpile_helper(value)?),
39 },
40 Ast::Return { return_value } => format!("return {};\n", transpile_helper(return_value)?),
41 Ast::Function {
42 name,
43 arguments,
44 return_type: _,
45 block,
46 } => {
47 let mut result = format!("function {}(", name);
48
49 for (i, argument) in arguments.iter().enumerate() {
50 if i == 0 {
51 result += argument.name.as_str();
52 } else {
53 result += format!(", {}", argument.name).as_str();
54 }
55 }
56
57 result += ") {\n";
58
59 for (i, statement) in block.value.iter().enumerate() {
60 if block.implicit_return && i == block.value.len() - 1 {
61 result += format!("return {};\n", transpile_helper(statement)?).as_str();
62 break;
63 }
64 result += transpile_helper(statement)?.as_str();
65 }
66
67 result += "}\n";
68
69 result
70 }
71 Ast::If {
72 condition,
73 value,
74 else_value,
75 } => {
76 let mut result = format!("if ({}) {{\n", transpile_helper(condition)?,);
77
78 for (i, statement) in value.value.iter().enumerate() {
79 if value.implicit_return && i == value.value.len() - 1 {
80 result += format!("return {};\n", transpile_helper(statement)?).as_str();
81 break;
82 }
83 result += transpile_helper(statement)?.as_str();
84 }
85
86 result += "}";
87
88 if let Some(val) = else_value {
89 result += format!(" else {{\n{}}}", transpile_helper(val)?).as_str();
90 } else {
91 result += "\n";
92 }
93
94 result
95 }
96 Ast::FunctionCall { name, arguments } => {
97 let mut result = match name.as_str() {
98 "print" => String::from("console.log("),
99 _ => format!("{}(", name),
100 };
101
102 for (i, argument) in arguments.iter().enumerate() {
103 if i == 0 {
104 result += transpile_helper(argument)?.as_str();
105 } else {
106 result += format!(", {}", transpile_helper(argument)?).as_str();
107 }
108 }
109
110 result += ")";
111
112 result
113 }
114 Ast::Block(block) => {
115 let mut result = String::from("(()=>{\n");
116 for (i, statement) in block.value.iter().enumerate() {
117 if block.implicit_return && i == block.value.len() - 1 {
118 result += format!("return {};\n", transpile_helper(statement)?).as_str();
119 break;
120 }
121 result += transpile_helper(statement)?.as_str();
122 }
123
124 result += "})()\n";
125
126 result
127 }
128 })
129}
130
131pub fn transpile(forest: Vec<Ast>) -> Result<String> {
132 let mut result = String::new();
133
134 for tree in forest {
135 result.push_str(&transpile_helper(&tree)?);
136 }
137
138 Ok(result)
139}
crates/tokenizer/Cargo.toml created+12
......@@ -0,0 +1,12 @@
1[package]
2name = "tokenizer"
3version = "0.1.0"
4edition = "2021"
5
6[lib]
7
8[dependencies]
9miette.workspace = true
10thiserror.workspace = true
11
12util = { path = "../util" }
crates/tokenizer/src/lib.rs created+199
......@@ -0,0 +1,199 @@
1use miette::{Diagnostic, Result};
2use thiserror::Error;
3
4use util::Operator;
5
6#[derive(Error, Diagnostic, Debug)]
7#[error("UnknownCharacter")]
8struct UnknownCharacter {
9 #[help]
10 error: String,
11}
12
13#[derive(Debug, Clone)]
14pub enum Token {
15 // Literals
16 Identifier(String),
17 Number(String),
18 String(String),
19 // Comments
20 Comment(String),
21 DocComment(String),
22 // Keywords
23 True,
24 False,
25 Let,
26 Var,
27 If,
28 Else,
29 Return,
30 Pub,
31 Function,
32 RightArrow,
33 Comma,
34 OpenParanthesis,
35 ClosedParanthesis,
36 OpenBracket,
37 ClosedBracket,
38 Colon,
39 Equals,
40 Semicolon,
41 // Operators
42 Operator(Operator),
43}
44
45pub fn tokenize(content: String) -> Result<Vec<Token>> {
46 let mut tokens: Vec<Token> = Vec::new();
47 let mut chars = content.chars().enumerate().peekable();
48
49 loop {
50 match chars.next() {
51 Some((_, c)) => match c {
52 'a'..='z' | 'A'..='Z' | '_' => {
53 let mut current_token = String::new();
54 current_token.push(c);
55 loop {
56 let c = chars.peek();
57 if c.is_none() {
58 break;
59 }
60 let (_, c) = c.unwrap();
61 match c {
62 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => {
63 current_token.push(*c);
64 chars.next();
65 }
66 _ => break,
67 }
68 }
69
70 match current_token.as_str() {
71 "var" => tokens.push(Token::Var),
72 "let" => tokens.push(Token::Let),
73 "if" => tokens.push(Token::If),
74 "else" => tokens.push(Token::Else),
75 "pub" => tokens.push(Token::Pub),
76 "fn" => tokens.push(Token::Function),
77 "return" => tokens.push(Token::Return),
78 "true" => tokens.push(Token::True),
79 "false" => tokens.push(Token::False),
80 _ => tokens.push(Token::Identifier(current_token)),
81 }
82 }
83 '"' => {
84 let mut current_token = String::new();
85 loop {
86 let c = chars.next();
87 if c.is_none() {
88 break;
89 }
90 let (_, c) = c.unwrap();
91 match c {
92 '"' => break,
93 _ => current_token.push(c),
94 }
95 }
96 tokens.push(Token::String(current_token));
97 }
98 '0'..='9' => {
99 let mut current_token = String::new();
100 current_token.push(c);
101 loop {
102 let c = chars.peek();
103 if c.is_none() {
104 break;
105 }
106 let (_, c) = c.unwrap();
107 match c {
108 '0'..='9' => {
109 current_token.push(*c);
110 chars.next();
111 }
112 _ => break,
113 }
114 }
115 tokens.push(Token::Number(current_token));
116 }
117 ':' => tokens.push(Token::Colon),
118 '=' => match chars.peek() {
119 Some((_, '=')) => {
120 chars.next();
121 tokens.push(Token::Operator(Operator::Equals));
122 }
123 _ => tokens.push(Token::Equals),
124 },
125 ';' => tokens.push(Token::Semicolon),
126 '>' => tokens.push(Token::Operator(Operator::GreaterThan)),
127 '+' => tokens.push(Token::Operator(Operator::Add)),
128 '-' => match chars.peek() {
129 Some((_, '>')) => {
130 chars.next();
131 tokens.push(Token::RightArrow);
132 }
133 _ => tokens.push(Token::Operator(Operator::Substract)),
134 },
135 '*' => match chars.peek() {
136 Some((_, '*')) => {
137 chars.next();
138 tokens.push(Token::Operator(Operator::Power));
139 }
140 _ => tokens.push(Token::Operator(Operator::Multiply)),
141 },
142 '/' => {
143 match chars.peek() {
144 Some((_, '/')) => {
145 chars.next(); // Consume the second slash
146
147 let is_doc_comment = match chars.peek() {
148 Some((_, '/')) => {
149 chars.next(); // Consume the third slash
150 true
151 }
152 _ => false,
153 };
154
155 let mut comment = String::new();
156 loop {
157 let c = chars.next();
158 if c.is_none() {
159 break;
160 }
161 let (_, c) = c.unwrap();
162 match c {
163 '\n' => break,
164 _ => {
165 comment.push(c.clone());
166 }
167 }
168 }
169
170 comment = comment.trim().to_string();
171
172 if is_doc_comment {
173 tokens.push(Token::DocComment(comment));
174 } else {
175 tokens.push(Token::Comment(comment));
176 }
177 }
178 _ => tokens.push(Token::Operator(Operator::Divide)),
179 }
180 }
181 ',' => tokens.push(Token::Comma),
182 '(' => tokens.push(Token::OpenParanthesis),
183 ')' => tokens.push(Token::ClosedParanthesis),
184 '{' => tokens.push(Token::OpenBracket),
185 '}' => tokens.push(Token::ClosedBracket),
186 s if s.is_whitespace() => (),
187 _ => {
188 return Err(UnknownCharacter {
189 error: format!("Unsupported character: {}", c),
190 }
191 .into())
192 }
193 },
194 None => break,
195 }
196 }
197
198 Ok(tokens)
199}
crates/util/Cargo.toml created+8
......@@ -0,0 +1,8 @@
1[package]
2name = "util"
3version = "0.1.0"
4edition = "2021"
5
6[lib]
7
8[dependencies]
crates/util/src/lib.rs created+24
......@@ -0,0 +1,24 @@
1#[derive(Debug, Clone)]
2pub enum Operator {
3 Add,
4 Substract,
5 Multiply,
6 Divide,
7 Power,
8 Equals,
9 GreaterThan,
10}
11
12impl Operator {
13 pub fn to_string(self) -> String {
14 String::from(match self {
15 Self::Add => "+",
16 Self::Substract => "-",
17 Self::Divide => "/",
18 Self::Multiply => "*",
19 Self::Power => "**",
20 Self::Equals => "===",
21 Self::GreaterThan => ">",
22 })
23 }
24}