authorgravatar for me@paperdave.netdave caruso <me@paperdave.net> 2024-06-01 05:49:57-07:00
committergravatar for me@paperdave.netdave caruso <me@paperdave.net> 2024-06-01 05:49:57-07:00
loge8c6282cade26a0a2bd2b8a1d8bf20ec5d95908a
tree577ca5e14e64c229bd2162ba15919b9ed4dee23c
parent1822706c309b53326056cd1030df93696fe321c8
signature Commit is signed but in an unrecognized format.

some stuff


10 files changed, 254 insertions(+), 220 deletions(-)

CHANGELOG.md+1
......@@ -7,6 +7,7 @@
77- feat(transform): parse string escapes properly
88- feat(link): print string escapes properly
99- feat: implement the `comptime` keyword (many comptime ops are not implemented)
10- feat: add `@jsNew` to create JavaScript `new` expressions
1011- fix(sema): properly coerce assignments
1112- fix(transform): empty block generated in top level code tripped sema assertion
1213- fix(link): emit parenthesis to preserve operator precedence
build.zig+4-4
......@@ -58,7 +58,7 @@ pub fn build(b: *std.Build) void {
5858 test_all.dependOn(run_step);
5959 }
6060
61 // Language Server
61 // Language Reference Generator
6262 const langref_generator = b.addExecutable(.{
6363 .name = "generate-langref",
6464 .root_source_file = b.path("src/langref/generate-langref.zig"),
......@@ -70,10 +70,10 @@ pub fn build(b: *std.Build) void {
7070 langref_generator.root_module.addImport("core", native_debug.core);
7171 const langref_run = b.addRunArtifact(langref_generator);
7272 langref_run.addFileArg(native_debug.compiler.getEmittedBin());
73 langref_run.addFileArg(b.path("doc/langref.md"));
74 langref_run.addFileArg(b.path("src/langref/langref.template.html"));
73 langref_run.addFileArg(b.path("doc/language-reference.md"));
74 langref_run.addFileArg(b.path("src/langref/template.html"));
7575 const langref_out = langref_run.addOutputFileArg("language-reference.html");
76 const install_langref = b.addInstallFile(langref_out, "doc/langref.html");
76 const install_langref = b.addInstallFile(langref_out, "doc/README.html");
7777 b.step("langref", "build language reference").dependOn(&install_langref.step);
7878
7979 // const wasm_api = b.addExecutable(.{
doc/architecture.md created+7
......@@ -0,0 +1,7 @@
1# compiler architecture
2
3This document will outline the code structure of the language's SDK as well as the compilation pipeline architecture. The major components of the language are:
4
5- [**Core**][core]
6- [**Standard Library**][std]
7- [**Language Server**][lsp]
doc/langref.md deleted-137
......@@ -1,137 +0,0 @@
1# New Language Project
2
3This is a high-level, general purpose programming language. It is a mix of Rust, Zig, and JavaScript's great points.
4
5- **Rust** - Expressive control flow that is easy to write.
6- **Zig** - Execute any code at compile time, everything is an expression.
7- **JavaScript** - Garbage collected values with a versitile type system.
8
9Key goals of this project are:
10
11- **Ease of Use**: Use of type inference keeps code concise and easy to read and write.
12- **Fast Iteration**: The compiler is designed for quick incremental compilation and hot module reloading.
13- TODO: some more
14
15## Standard Library
16
17Currently, there is no standard library. One will be introduced later.
18
19## Hello World
20
21```lang:run
22let print = @js("console").log;
23print("Hello, world!");
24```
25
26The `print` function is implemented by getting an external reference to the `console` JavaScript global, and then retriving the `log` property from it.
27
28## Primative Data Types
29
30| name | ts equivilent | description |
31| ---------- | --------------------- | ---------------------------------------------- |
32| `int` | `number` | a number in signed 32-bit range |
33| `float` | `number` | a 64-bit floating point number |
34| `bool` | `boolean` | either `true` or `false` |
35| `string` | `string` | a sequence of text characters |
36| `void` | `undefined` or `null` | detectable lack of a value |
37| `noreturn` | `never` | control flow prevents this value from existing |
38
39> **note**: `bigint` is planned but not added
40
41## Built-in Constants
42
43In addition to the above types being built-in constants, the following are available.
44
45| name | description |
46| ------- | ------------------------------------- |
47| `true` | boolean true (result of `1 == 1`) |
48| `false` | boolean false (result of `1 == 2`) |
49| `std` | handle to the standard library module |
50
51These constants are reserved names, and it is an error to re-declare them.
52
53```lang:build
54let true = 1 == 0;
55```
56
57## Variables
58
59There are two types of variables, `let` and `var`.
60
61`let` bindings cannot be overridden, and should be thought of as aliases of the expression within. Referring to these identifiers is equivilent to inlining it's where it was used, aside from side effect duplication.
62
63```lang:run
64let hello: int = 1;
65let world = hello + 2;
66let hello = hello * world;
67
68@js("console").log(hello);
69```
70
71`var` bindings create mutable memory locations at runtime. This means they can be re-assigned to:
72
73```lang:run
74var message = "first message";
75
76if @js("Math").random() > 0.5 {
77 message = "second message"
78}
79
80@js("console").log(message);
81```
82
83Using `let` is preferred whenever possible, as it will lead to more readable code, and the compiler is able to optimize it better. The above can be rewritten as:
84
85```lang:run
86let message = if @js("Math").random() > 0.5 {
87 "second message"
88} else {
89 "first message"
90};
91
92@js("console").log(message);
93```
94
95It should be noted that numeric literals are a comptime-only data type, meaning it cannot be assigned to a `var` without an explicit type annotation. Since `int` is a strict subset of valid `float`s, the coersion will implicitly be a float, but a compiler warning will be emitted.
96
97```lang
98var number = 0; // `number` is a `float`, but not explicit
99var number: int = 0; // `number` is `int`
100var number: float = 0; // `number` is `float`
101```
102
103## Functions
104
105Functions are declared with the `fn` keyword. Parameter types must be annotated. The function body is a block, which may use implicit return to return.
106
107```lang:run
108fn add(a: int, b: int) -> int {
109 a + b
110}
111
112let print = @js("console").log;
113//print("Sum of 2 and 7" + add(2, 7));
114print(add(2, 7));
115```
116
117> **Bug**: Return types are currently required. Omitting the `-> type` syntax currently makes the return type `void`, but this will be changed in the future to be an inferred return type.
118
119The `return` expression can be used within functions to return early.
120
121```lang
122fn something(a: int) -> bool {
123 if a == 0 {
124 return false;
125 }
126
127 a > 100
128}
129```
130
131## Number Literals
132
133TODO
134
135## String Literals
136
137TODO
doc/language-reference.md created+154
......@@ -0,0 +1,154 @@
1# New Language Project
2
3This is a high-level, general purpose programming language. It is a mix of Rust, Zig, and JavaScript's great points.
4
5- **Rust** - Expressive control flow that is easy to write.
6- **Zig** - Execute any code at compile time, everything is an expression.
7- **JavaScript** - Garbage collected values with a versitile type system.
8
9Key goals of this project are:
10
11- **Ease of Use**: Use of type inference keeps code concise and easy to read and write.
12- **Fast Iteration**: The compiler is designed for quick incremental compilation and hot module reloading.
13- TODO: some more
14
15## Standard Library
16
17Currently, there is no standard library. One will be introduced later.
18
19## Hello World
20
21```lang:run
22let print = @js("console").log;
23print("Hello, world!");
24```
25
26The `print` function is implemented by getting an external reference to the `console` JavaScript global, and then retriving the `log` property from it.
27
28## Primative Data Types
29
30| name | ts equivilent | description |
31| ---------- | --------------------- | ---------------------------------------------- |
32| `int` | `number` | a number in signed 32-bit range |
33| `float` | `number` | a 64-bit floating point number |
34| `bool` | `boolean` | either `true` or `false` |
35| `string` | `string` | a sequence of text characters |
36| `void` | `undefined` or `null` | detectable lack of a value |
37| `noreturn` | `never` | control flow prevents this value from existing |
38
39> **note**: `bigint` is planned but not added
40
41## Built-in Constants
42
43In addition to the above types being built-in constants, the following are available.
44
45| name | description |
46| ------- | ------------------------------------- |
47| `true` | boolean true (result of `1 == 1`) |
48| `false` | boolean false (result of `1 == 2`) |
49| `std` | handle to the standard library module |
50
51These constants are reserved names, and it is an error to re-declare them.
52
53```lang:build
54let true = 1 == 0;
55```
56
57## Variables
58
59There are two types of variables, `let` and `var`.
60
61`let` bindings cannot be overridden, and should be thought of as aliases of the expression within. Referring to these identifiers is equivilent to inlining it's where it was used, aside from side effect duplication.
62
63```lang:run
64let hello: int = 1;
65let world = hello + 2;
66let hello = hello * world;
67
68@js("console").log(hello);
69```
70
71`var` bindings create mutable memory locations at runtime. This means they can be re-assigned to:
72
73```lang:run
74var message = "first message";
75
76if @js("Math").random() > 0.5 {
77 message = "second message"
78}
79
80@js("console").log(message);
81```
82
83Using `let` is preferred whenever possible, as it will lead to more readable code, and the compiler is able to optimize it better. The above can be rewritten as:
84
85```lang:run
86let message = if @js("Math").random() > 0.5 {
87 "second message"
88} else {
89 "first message"
90};
91
92@js("console").log(message);
93```
94
95It should be noted that numeric literals are a comptime-only data type, meaning it cannot be assigned to a `var` without an explicit type annotation. Since `int` is a strict subset of valid `float`s, the coersion will implicitly be a float, but a compiler warning will be emitted.
96
97```lang
98var number = 0; // `number` is a `float`, but not explicit
99var number: int = 0; // `number` is `int`
100var number: float = 0; // `number` is `float`
101```
102
103## Functions
104
105Functions are declared with the `fn` keyword. Parameter types must be annotated. The function body is a block, which may use implicit return to return.
106
107```lang:run
108fn add(a: int, b: int) -> int {
109 a + b
110}
111
112let print = @js("console").log;
113//print("Sum of 2 and 7" + add(2, 7));
114print(add(2, 7));
115```
116
117> **Bug**: Return types are currently required. Omitting the `-> type` syntax currently makes the return type `void`, but this will be changed in the future to be an inferred return type.
118
119The `return` expression can be used within functions to return early.
120
121```lang
122fn something(a: int) -> bool {
123 if a == 0 {
124 return false;
125 }
126
127 a > 100
128}
129```
130
131## Number Literals
132
133TODO
134
135## String Literals
136
137TODO
138
139## JavaScript Interop
140
141A global variable handle can be retrived with `@js`. We've seen this in the hello world. The plan is to eventually replace this construct with something else, but implementing a function like this is extremely trivial for the compiler.
142
143Many JS-exclusive actions are exposed via built-in functions, such as using `@jsNew` for calling constructors.
144
145```lang:run
146let date_constructor = @js("Date");
147let print = @js("console").log;
148
149fn currentYear() -> int {
150 @jsNew(date_constructor).getFullYear()
151}
152
153print(currentYear());
154```
src/cli.zig created+6
......@@ -0,0 +1,6 @@
1//! This is the `lang` command line interface. It combines all components
2//! of the software development kit into one. For development, it may
3//! be more reasonable to hack on individual components, which each
4//! expose their own CLIs
5
6pub fn main() !void {}
src/core/Transform.zig+2
......@@ -565,6 +565,7 @@ fn transformParamDecl(t: *Transform, decl: BlockContext, param: NodeIndex) Alloc
565565
566566pub const Builtin = enum {
567567 js,
568 js_new,
568569 import,
569570 fetch,
570571 compile_error,
......@@ -576,6 +577,7 @@ pub const Builtin = enum {
576577 .{ "fetch", .fetch },
577578 .{ "import", .import },
578579 .{ "js", .js },
580 .{ "jsNew", .js_new },
579581 .{ "typeOf", .type_of },
580582 // sort-lines: end
581583 });
src/langref/generate-langref.zig+2-1
......@@ -9,7 +9,8 @@ const ArrayList = std.ArrayList;
99
1010pub fn main() !void {
1111 comptime std.debug.assert(@import("builtin").mode == .Debug);
12 const gpa = std.heap.c_allocator;
12 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
13 const gpa = arena.allocator();
1314
1415 var args = try std.process.argsWithAllocator(gpa);
1516 _ = args.next().?;
src/langref/langref.template.html deleted-78
......@@ -1,78 +0,0 @@
1<!doctype html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Language Reference</title>
7 <style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9 body {
10 background-color: #fefefe;
11 font-family: sans-serif;
12 max-width: 45rem;
13 padding: 1rem;
14 margin: auto;
15 }
16 h1,h2,h3,h4,h5,h6,p,ul,pre,blockquote {
17 margin-bottom: 1rem;
18 }
19 ul {
20 padding-left: 2rem;
21 }
22 li {
23 margin-bottom: 0.25rem;
24 }
25 blockquote {
26 background-color: #ddd;
27 border-left: 4px solid black;
28 padding-left: 16px;
29 padding-top: 8px;
30 padding-bottom: 8px;
31 }
32 pre {
33 padding: 0.5rem;
34 }
35 pre > code {
36 border: none;
37 padding: 0;
38 background-color: transparent;
39 }
40 code, pre {
41 border: 1px solid #999;
42 background-color: #eeeeee;
43 border-radius: 4px;
44 padding: 2px 4px;
45 }
46 .term {
47 border: 1px solid #333;
48 background-color: #222;
49 color:white;
50 }
51 .ansi-1 {
52 font-weight: bold;
53 }
54 .ansi-31 {
55 color:rgb(255, 68, 68);
56 }
57 .ansi-2 {
58 color:#aaa;
59 }
60
61 .kw {
62 color: mediumpurple;
63 font-weight: bold;
64 }
65 .tok-string {
66 color: green;
67 }
68 .tok-number_int, .tok-number_float {
69 color: orangered;
70 }
71 </style>
72</head>
73<body>
74 <main>
75 {contents}
76 </main>
77</body>
78</html>
src/langref/template.html created+78
......@@ -0,0 +1,78 @@
1<!doctype html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Language Reference</title>
7 <style>
8 * { margin: 0; padding: 0; box-sizing: border-box; }
9 body {
10 background-color: #fefefe;
11 font-family: sans-serif;
12 max-width: 45rem;
13 padding: 1rem;
14 margin: auto;
15 }
16 h1,h2,h3,h4,h5,h6,p,ul,pre,blockquote {
17 margin-bottom: 1rem;
18 }
19 ul {
20 padding-left: 2rem;
21 }
22 li {
23 margin-bottom: 0.25rem;
24 }
25 blockquote {
26 background-color: #ddd;
27 border-left: 4px solid black;
28 padding-left: 16px;
29 padding-top: 8px;
30 padding-bottom: 8px;
31 }
32 pre {
33 padding: 0.5rem;
34 }
35 pre > code {
36 border: none;
37 padding: 0;
38 background-color: transparent;
39 }
40 code, pre {
41 border: 1px solid #999;
42 background-color: #eeeeee;
43 border-radius: 4px;
44 padding: 2px 4px;
45 }
46 .term {
47 border: 1px solid #333;
48 background-color: #222;
49 color:white;
50 }
51 .ansi-1 {
52 font-weight: bold;
53 }
54 .ansi-31 {
55 color:rgb(255, 68, 68);
56 }
57 .ansi-2 {
58 color:#aaa;
59 }
60
61 .kw {
62 color: mediumpurple;
63 font-weight: bold;
64 }
65 .tok-string {
66 color: green;
67 }
68 .tok-number_int, .tok-number_float {
69 color: orangered;
70 }
71 </style>
72</head>
73<body>
74 <main>
75 {contents}
76 </main>
77</body>
78</html>