authorchloe caruso <git@paperclover.net> 2024-06-01 19:45:28-07:00
committerchloe caruso <git@paperclover.net> 2024-06-01 19:45:28-07:00
logc92fd86aaae8e8f251562fa54b8ec350542ac294
tree1628c6fc46186ce8eae47cb2f5a97784c1b0d8f0
parentdee1ba048e5633e4475ccf8ec954a787958da354

upgrade zig


18 files changed, 264 insertions(+), 87 deletions(-)

.gitignore+1-1
......@@ -6,5 +6,5 @@
66# excludesfile = ~/.gitignore
77#
88
9.zig-cache
910zig-out
10zig-cache
build.zig+1-1
......@@ -127,7 +127,7 @@ pub fn build(b: *std.Build) void {
127127 package.dependOn(&b.addInstallFile(
128128 artifact.getEmittedBin(),
129129 b.pathJoin(&.{
130 "release",
130 "package",
131131 name,
132132 std.mem.concat(b.allocator, u8, &.{
133133 bin_name,
build.zig.zon+3-3
......@@ -2,12 +2,12 @@
22 .name = "",
33 .version = "0.0.0",
44
5 .minimum_zig_version = "0.12.0",
5 .minimum_zig_version = "0.13.0-dev.348+c564a16a0",
66
77 .dependencies = .{
88 .zg = .{
9 .url = "https://codeberg.org/dude_the_builder/zg/archive/16735685fcc3410de361ba3411788ad1fb4fe188.tar.gz",
10 .hash = "1220fe9ac5cdb41833d327a78745614e67d472469f8666567bd8cf9f5847a52b1c51",
9 .url = "https://codeberg.org/dude_the_builder/zg/archive/c425c9c8511bf92e14b8b612d1d16e774b186f2e.tar.gz",
10 .hash = "1220c79009f1e443b015db4de6e5319432538ead2fea10d271f3f35d3ae83c996789",
1111 },
1212 .tracer = .{
1313 .url = "https://github.com/paperdave/zig-tracer/archive/d4c2eff040e9e69b9f08d2175b315f3055ad7ba3.tar.gz",
doc/language-reference.md+14-11
......@@ -1,10 +1,6 @@
11# New Language Project
22
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.
3This is a high-level, general purpose programming language.
84
95Key goals of this project are:
106
......@@ -12,6 +8,12 @@ Key goals of this project are:
128- **Fast Iteration**: The compiler is designed for quick incremental compilation and hot module reloading.
139- TODO: some more
1410
11It primarily focuses on merging some great points of Rust, Zig, and JavaScript's language designs:
12
13- **Rust** - Expressive control flow that is easy to write.
14- **Zig** - Execute any code at compile time, everything is an expression.
15- **JavaScript** - Garbage collected values with a versitile type system.
16
1517## Standard Library
1618
1719Currently, there is no standard library. One will be introduced later.
......@@ -74,7 +76,7 @@ let hello = hello * world;
7476var message = "first message";
7577
7678if @js("Math").random() > 0.5 {
77 message = "second message"
79 message = "second message";
7880}
7981
8082@js("console").log(message);
......@@ -110,15 +112,14 @@ fn add(a: int, b: int) -> int {
110112}
111113
112114let print = @js("console").log;
113//print("Sum of 2 and 7" + add(2, 7));
114print(add(2, 7));
115print("Sum of 2 and 7" + add(2, 7));
115116```
116117
117118> **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.
118119
119120The `return` expression can be used within functions to return early.
120121
121```lang
122```lang:run
122123fn something(a: int) -> bool {
123124 if a == 0 {
124125 return false;
......@@ -126,6 +127,9 @@ fn something(a: int) -> bool {
126127
127128 a > 100
128129}
130
131let print = @js("console").log;
132print(something(0xFF), something(0));
129133```
130134
131135## Number Literals
......@@ -143,11 +147,10 @@ A global variable handle can be retrived with `@js`. We've seen this in the hell
143147Many JS-exclusive actions are exposed via built-in functions, such as using `@jsNew` for calling constructors.
144148
145149```lang:run
146let date_constructor = @js("Date");
147150let print = @js("console").log;
148151
149152fn currentYear() -> int {
150 @jsNew(date_constructor).getFullYear()
153 @jsNew(@js("Date")).getFullYear()
151154}
152155
153156print(currentYear());
src/core/Air.Dump.zig+2-2
......@@ -126,8 +126,8 @@ pub const State = struct {
126126 try tty.setColor(w, .reset);
127127 try w.writeAll(")");
128128 },
129 .call => {
130 const call: Air.Call = air.instData(.call, inst);
129 inline .call, .new => |t| {
130 const call: Air.Call = air.instData(t, inst);
131131 const call_data = call.call_data.get(air);
132132 try w.writeAll("(");
133133 try s.dumpRef(w, call.base);
src/core/Air.zig+3-2
......@@ -16,6 +16,7 @@ pub const Inst = struct {
1616 block,
1717 js_global_ref,
1818 call,
19 new,
1920 @"break",
2021 @"if",
2122 arg,
......@@ -45,7 +46,7 @@ pub const Inst = struct {
4546 .js_global_ref => InternPool.String.WithLen,
4647 .@"break" => Break,
4748 .@"if" => If,
48 .call => Call,
49 .call, .new => Call,
4950 .arg => Arg,
5051 .field => Field,
5152 .memory => Memory,
......@@ -258,7 +259,7 @@ pub fn typeOf(air: *const Air, ref: Inst.Ref, ip: *InternPool) InternPool.Type {
258259
259260pub fn typeOfIndex(air: *const Air, index: Inst.Index, ip: *InternPool) InternPool.Type {
260261 return switch (air.instTag(index)) {
261 .js_global_ref => .@"opaque",
262 .js_global_ref, .new => .@"opaque",
262263
263264 .block => {
264265 const items = air.instData(.block, index).slice(air);
src/core/Ast.zig+1
......@@ -38,6 +38,7 @@ utf8_source: [:0]const u8,
3838
3939tokens: Token.List.Slice,
4040nodes: Node.List.Slice,
41/// TODO: Move this to using array.ExtraStore
4142extra: []const u32,
4243
4344pub const Node = struct {
src/core/JsLink.zig+44-4
......@@ -152,9 +152,22 @@ fn printDecl(link: *JsLink, decl_index: Decl.Index, writer: anytype) !void {
152152 try link.printLocal(@intCast(id), writer);
153153 if (id != tree.param_count - 1) try writer.writeAll(", ");
154154 }
155 try writer.writeAll(") => {\n");
156 try link.printDeclContents(tree, writer);
157 try writer.writeAll("};\n");
155 try writer.writeAll(") => ");
156
157 const stmts = tree.mainStatements();
158 if (stmts.len == 1 and tree.nodeTag(stmts[0]) == .stmt_return) {
159 if (tree.nodeData(.stmt_return, stmts[0]).operand.unwrap()) |operand| {
160 try link.printExpr(tree, operand, writer);
161 } else {
162 try writer.writeAll("{}");
163 }
164 } else {
165 try writer.writeAll("{\n");
166 try link.printDeclContents(tree, writer);
167 try writer.writeAll("}");
168 }
169
170 try writer.writeAll(";\n");
158171}
159172
160173fn printDeclContents(link: *JsLink, tree: *const JsTree, writer: anytype) !void {
......@@ -167,7 +180,12 @@ fn printDeclContents(link: *JsLink, tree: *const JsTree, writer: anytype) !void
167180 }
168181}
169182
170fn printBlockContents(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList, writer: anytype) !void {
183fn printBlockContents(
184 link: *JsLink,
185 tree: *const JsTree,
186 list: JsTree.IndexList,
187 writer: anytype,
188) !void {
171189 var t = tracer.trace(@src());
172190 defer t.end();
173191
......@@ -377,6 +395,28 @@ fn printExprLevel(
377395
378396 try writer.writeAll(")");
379397 },
398 .new => {
399 const call: JsTree.Call = tree.nodeData(.new, node);
400 const args = call.args.get(tree);
401
402 if (Level.new.needsParens(level))
403 try writer.writeAll("(");
404 try writer.writeAll("new ");
405 try link.printExpr(tree, call.base, writer);
406
407 if (args.len > 0) {
408 try writer.writeAll("(");
409
410 for (args.slice(tree), 0..) |arg, i| {
411 if (i != 0) try writer.writeAll(", ");
412 try link.printExpr(tree, arg, writer);
413 }
414
415 try writer.writeAll(")");
416 }
417 if (Level.new.needsParens(level))
418 try writer.writeAll(")");
419 },
380420
381421 .field => {
382422 const field: JsTree.Field = tree.nodeData(.field, node);
src/core/JsNodeGen.zig+4-3
......@@ -260,8 +260,8 @@ fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void {
260260 try c.markExpression(inst, node);
261261 },
262262
263 .call => {
264 const data: Air.Call = c.air.instData(.call, inst);
263 inline .call, .new => |tag| {
264 const data: Air.Call = c.air.instData(tag, inst);
265265 const call_data = data.call_data.get(c.air);
266266
267267 try c.extra.list.ensureUnusedCapacity(c.gpa, call_data.args.len);
......@@ -274,7 +274,7 @@ fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void {
274274 dest.* = @intFromEnum(try c.fetchExpression(arg));
275275 }
276276
277 const node = try c.add(.call, .{
277 const node = try c.add(@field(JsTree.Tag, @tagName(tag)), .{
278278 .base = try c.fetchExpression(data.base),
279279 .args = try c.extra.append(c.gpa, JsTree.IndexList, .{
280280 .start = @intCast(start),
......@@ -603,6 +603,7 @@ fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool {
603603 .index => |index| switch (c.air.instTag(index)) {
604604 .js_global_ref,
605605 .call,
606 .new,
606607 .arg,
607608 .field,
608609 .add,
src/core/JsTree.zig+2-1
......@@ -39,6 +39,7 @@ pub const Tag = enum {
3939 gt,
4040 // exprs
4141 call,
42 new,
4243 field,
4344 ternary,
4445 // prefix ops
......@@ -84,7 +85,7 @@ pub const Tag = enum {
8485 .pre_inc,
8586 .pre_dec,
8687 => Un,
87 .call => Call,
88 .call, .new => Call,
8889 .field => Field,
8990 .stmt_if => StmtIf,
9091 .stmt_break => StmtBreak,
src/core/Report.zig+7-5
......@@ -817,11 +817,10 @@ pub const LazyNode = struct {
817817
818818 switch (teg.instTag(lazy.inst)) {
819819 .as => switch (node_tag) {
820 .var_decl => {
821 switch (lazy.operand) {
822 .rhs => return data.var_decl.init,
823 else => {},
824 }
820 .var_decl => switch (lazy.operand) {
821 .lhs => return data.var_decl.type.unwrap().?,
822 .rhs => return data.var_decl.init,
823 else => {},
825824 },
826825 else => {},
827826 },
......@@ -865,6 +864,9 @@ pub const LazyNode = struct {
865864 else => fn_decl.params.slice(ctx.ast)[lazy.operand.getArgId()],
866865 };
867866 },
867 .js => {
868 return base_node;
869 },
868870 else => {},
869871 }
870872
src/core/Sema.zig+30-3
......@@ -425,6 +425,31 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) Error!Air.Inst.Ref {
425425 }),
426426 });
427427 },
428 .js_new => {
429 const call: Teg.Inst.JsNew = s.code.instPayload(.js_new, in);
430 const base = try s.resolveRefRuntime(call.base);
431
432 const scratch = try s.arena.alloc(Air.Inst.Ref, call.args.len);
433 defer s.arena.free(scratch);
434 for (call.args.slice(&s.code), 0..) |arg, i| {
435 const ref = try s.ensureValueRuntime(
436 in.op(Report.Operand.argument(@intCast(i))),
437 try s.resolveRefRuntime(arg),
438 );
439 scratch[i] = ref;
440 }
441
442 const start = s.air_extra.list.items.len;
443 try s.air_extra.list.appendSlice(s.gpa, @ptrCast(scratch));
444
445 return s.addInstRef(.new, .{
446 .base = base,
447 .call_data = try s.air_extra.append(s.gpa, Air.Call.Data, .{ .args = .{
448 .start = @intCast(start),
449 .len = @intCast(scratch.len),
450 } }),
451 });
452 },
428453 .ensure_void => {
429454 const operand = try s.resolveRefRuntimeExtra(s.code.instData(.ensure_void, in).operand, false);
430455 const t = s.typeOfRef(operand);
......@@ -447,9 +472,8 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) Error!Air.Inst.Ref {
447472 .@"if" => {
448473 const data: Teg.Inst.If = s.code.instData(.@"if", in).extra_index.get(&s.code);
449474
450 const cond = try s.resolveRefRuntime(data.cond);
451
452 // try s.validateType(s.typeOfRef(cond), .bool_type);
475 const cond_raw = try s.resolveRefRuntime(data.cond);
476 const cond = try s.coerceRef(in.op(.operand), cond_raw, .bool);
453477
454478 // If known at comptime, only analyze the taken path
455479 if (cond.kind == .value) {
......@@ -636,6 +660,9 @@ fn coerceRef(s: *Sema, src: InstOp, value: Air.Inst.Ref, to: Type) !Air.Inst.Ref
636660 if (from == to) {
637661 return value;
638662 }
663 if (from == .@"opaque") {
664 return value;
665 }
639666 const index = switch (value.decode()) {
640667 .value => |v| return (try s.coerceValue(src, v, to)).toAir(),
641668 .index => |index| index,
src/core/Teg.Dump.zig+8
......@@ -186,6 +186,14 @@ const State = struct {
186186 try s.dumpRefMarkerList(writer, call.args.slice(teg), '[', ']');
187187 try writer.writeAll(")");
188188 },
189 .js_new => {
190 const call: Teg.Inst.JsNew = teg.instData(.js_new, inst).extra_index.get(teg);
191 try writer.writeAll("(");
192 try s.dumpRefMarker(writer, call.base);
193 try writer.writeAll(",");
194 try s.dumpRefMarkerList(writer, call.args.slice(teg), '[', ']');
195 try writer.writeAll(")");
196 },
189197 .load_decl => {
190198 const call: Teg.Inst.StrNode = teg.instData(.load_decl, inst);
191199
src/core/Teg.zig+8
......@@ -72,6 +72,8 @@ pub const Inst = struct {
7272
7373 /// Implements the `@js` builtin
7474 js,
75 /// Implements the `@jsNew` builtin
76 js_new,
7577 /// Implements the `@import` builtin
7678 import,
7779 /// Implements the `@fetch` builtin
......@@ -95,6 +97,7 @@ pub const Inst = struct {
9597 .load_decl => StrNode,
9698 .param => DataNode,
9799 .store => PlNode(Store),
100 .js_new => PlNode(JsNew),
98101
99102 // Single instruction operand
100103 .memory,
......@@ -307,6 +310,11 @@ pub const Inst = struct {
307310 no: Inst.Ref,
308311 };
309312
313 pub const JsNew = struct {
314 base: Inst.Ref,
315 args: RefList,
316 };
317
310318 /// This will contain trailing data depending on the .kind
311319 pub const Decl = struct {
312320 name: NullTerminatedString,
src/core/Tokenizer.zig+42-10
......@@ -274,7 +274,7 @@ pub const Token = struct {
274274 utf8_source[token.offset..][0..token.len(utf8_source)];
275275 }
276276
277 const keywords = std.ComptimeStringMap(Tag, keywords: {
277 const keywords = std.StaticStringMap(Tag).initComptime(keywords: {
278278 const fields = std.enums.values(Tag);
279279 const KV = struct { []const u8, Tag };
280280 var kws: [fields.len]KV = undefined;
......@@ -355,18 +355,33 @@ pub fn next(t: *Tokenizer) !?Token {
355355 (t.byteAt(3) orelse 0 != '/'))
356356 {
357357 const start = t.pos;
358 t.pos = @intCast(mem.indexOfScalarPos(u8, t.code, t.pos + 3, '\n') orelse t.code.len);
358 t.pos = @intCast(mem.indexOfScalarPos(
359 u8,
360 t.code,
361 t.pos + 3,
362 '\n',
363 ) orelse t.code.len);
359364 return .{ .tag = .doc_comment, .offset = start };
360365 }
361366
362367 if (t.byteAt(2) orelse 0 == '!') {
363368 const start = t.pos;
364 t.pos = @intCast(mem.indexOfScalarPos(u8, t.code, t.pos + 2, '\n') orelse t.code.len);
369 t.pos = @intCast(mem.indexOfScalarPos(
370 u8,
371 t.code,
372 t.pos + 2,
373 '\n',
374 ) orelse t.code.len);
365375 return .{ .tag = .module_doc_comment, .offset = start };
366376 }
367377
368378 // skip the comment
369 t.pos = @intCast(mem.indexOfScalarPos(u8, t.code, t.pos + 2, '\n') orelse t.code.len);
379 t.pos = @intCast(mem.indexOfScalarPos(
380 u8,
381 t.code,
382 t.pos + 2,
383 '\n',
384 ) orelse t.code.len);
370385 t.skipWhitespace();
371386 continue;
372387 },
......@@ -376,7 +391,12 @@ pub fn next(t: *Tokenizer) !?Token {
376391 '\\' => switch (t.nextByte()) {
377392 '\\' => {
378393 const start = t.pos;
379 t.pos = @intCast(mem.indexOfScalarPos(u8, t.code, t.pos + 2, '\n') orelse t.code.len);
394 t.pos = @intCast(mem.indexOfScalarPos(
395 u8,
396 t.code,
397 t.pos + 2,
398 '\n',
399 ) orelse t.code.len);
380400 return .{ .tag = .multiline_string, .offset = start };
381401 },
382402 else => return t.maybeUTF8Error(error.InvalidSyntax),
......@@ -607,8 +627,11 @@ fn tokenizeNumber(t: *Tokenizer) !?Token {
607627 else => unreachable,
608628 }
609629
630 const start = t.pos;
631 var tag: Token.Tag = .number_int;
632
610633 // Parse Hex, Binary, Octal numbers
611 if (t.byte() == '0') {
634 if (t.byte() == '0') alt_base: {
612635 switch (t.nextByte()) {
613636 'x', 'X' => {
614637 t.pos += 2;
......@@ -622,12 +645,21 @@ fn tokenizeNumber(t: *Tokenizer) !?Token {
622645 t.pos += 2;
623646 try t.consumeIntegerRadix(.octal);
624647 },
625 else => {},
648 '0' => @panic("TODO: no double zero"),
649 else => break :alt_base,
626650 }
627 }
628651
629 const start = t.pos;
630 var tag: Token.Tag = .number_int;
652 // after numbers must be a valid word break the above returns are right
653 // before parsing `.` so those can be unchecked.
654 if (try t.isAtIdentifierStart()) {
655 return error.InvalidSyntax;
656 }
657
658 return .{
659 .tag = tag,
660 .offset = start,
661 };
662 }
631663
632664 if (t.byte() == '.') {
633665 t.pos += 1;
src/core/Transform.zig+52-26
......@@ -216,7 +216,7 @@ const BlockContext = struct {
216216
217217const Liveness = enum { alive, dead };
218218
219const BuiltInIds = std.ComptimeStringMap(Inst.Ref, .{
219const BuiltInIds = std.StaticStringMap(Inst.Ref).initComptime(.{
220220 .{ "void", .void },
221221 .{ "true", .bool_true },
222222 .{ "false", .bool_false },
......@@ -571,7 +571,7 @@ pub const Builtin = enum {
571571 compile_error,
572572 type_of,
573573
574 const map = std.ComptimeStringMap(Builtin, .{
574 const map = std.StaticStringMap(Builtin).initComptime(.{
575575 // sort-lines: start
576576 .{ "compileError", .compile_error },
577577 .{ "fetch", .fetch },
......@@ -602,6 +602,30 @@ pub const Builtin = enum {
602602 });
603603 }
604604
605 fn builtin_jsNew(t: *Transform, decl: BlockContext, node: NodeIndex, args: []const NodeIndex) !?Inst.Ref {
606 const trace = tracer.trace(@src());
607 defer trace.end();
608
609 if (args.len == 0) {
610 try t.report.err(.builtin_mismatch_args, .{ .node = node, .args = 1 });
611 return .void;
612 }
613
614 const base = try t.transformExpression(decl, args[0]) orelse return null;
615 const args_list = try t.transformCallArgs(decl, args[1..]) orelse return null;
616
617 return try t.addInstRef(.{
618 .tag = .js_new,
619 .data = EncodedData.encode(.js_new, .{
620 .src_node = decl.nodeOffset(args[0]),
621 .extra_index = try t.extra.append(t.gpa, Inst.JsNew, .{
622 .base = base,
623 .args = args_list,
624 }),
625 }),
626 });
627 }
628
605629 fn builtin_compileError(t: *Transform, decl: BlockContext, node: NodeIndex, args: []const NodeIndex) !?Inst.Ref {
606630 const trace = tracer.trace(@src());
607631 defer trace.end();
......@@ -616,7 +640,7 @@ pub const Builtin = enum {
616640
617641 return try t.addInstRef(.{
618642 .tag = .compile_error,
619 .data = EncodedData.encode(.js, .{
643 .data = EncodedData.encode(.compile_error, .{
620644 .src_node = decl.nodeOffset(node),
621645 .operand = source,
622646 }),
......@@ -637,7 +661,7 @@ pub const Builtin = enum {
637661
638662 return try t.addInstRef(.{
639663 .tag = .type_of,
640 .data = EncodedData.encode(.js, .{
664 .data = EncodedData.encode(.type_of, .{
641665 .src_node = decl.nodeOffset(node),
642666 .operand = source,
643667 }),
......@@ -932,6 +956,7 @@ fn transformExpression(t: *Transform, decl: BlockContext, node: NodeIndex) Alloc
932956
933957 return switch (builtin) {
934958 .js => Builtin.builtin_js(t, decl, node, args),
959 .js_new => Builtin.builtin_jsNew(t, decl, node, args),
935960 // .import => Builtin.import(t, decl, node, args),
936961 // .fetch => Builtin.fetch(t, decl, node, args),
937962 .compile_error => Builtin.builtin_compileError(t, decl, node, args),
......@@ -945,28 +970,7 @@ fn transformExpression(t: *Transform, decl: BlockContext, node: NodeIndex) Alloc
945970 const args = t.ast.extraData(call.extra, Ast.Call).args.slice(&t.ast);
946971
947972 const base = try t.transformExpression(decl, call.base) orelse return null;
948
949 const args_list: RefList = brk: {
950 const args_top = t.call_args.items.len;
951 defer t.call_args.shrinkRetainingCapacity(args_top);
952
953 for (args) |arg| {
954 try t.call_args.append(
955 t.gpa,
956 try t.transformExpression(decl, arg) orelse
957 return null,
958 );
959 }
960
961 const items = t.call_args.items[args_top..];
962 const extra_top = t.extra.list.items.len;
963 try t.extra.list.appendSlice(t.gpa, @ptrCast(items));
964
965 break :brk .{
966 .start = @intCast(extra_top),
967 .len = @intCast(items.len),
968 };
969 };
973 const args_list = try t.transformCallArgs(decl, args) orelse return null;
970974
971975 const call_inst = try t.addInstRef(.{
972976 .tag = .call,
......@@ -1138,6 +1142,28 @@ fn transformExpression(t: *Transform, decl: BlockContext, node: NodeIndex) Alloc
11381142 }
11391143}
11401144
1145fn transformCallArgs(t: *Transform, decl: BlockContext, args: []const NodeIndex) !?RefList {
1146 const args_top = t.call_args.items.len;
1147 defer t.call_args.shrinkRetainingCapacity(args_top);
1148
1149 for (args) |arg| {
1150 try t.call_args.append(
1151 t.gpa,
1152 try t.transformExpression(decl, arg) orelse
1153 return null,
1154 );
1155 }
1156
1157 const items = t.call_args.items[args_top..];
1158 const extra_top = t.extra.list.items.len;
1159 try t.extra.list.appendSlice(t.gpa, @ptrCast(items));
1160
1161 return .{
1162 .start = @intCast(extra_top),
1163 .len = @intCast(items.len),
1164 };
1165}
1166
11411167fn transformAssignmentTarget(t: *Transform, decl: BlockContext, node: NodeIndex) Allocator.Error!?Inst.Index {
11421168 const node_tag = t.ast.nodes.items(.tag)[node];
11431169
src/langref/generate-langref.zig+6-1
......@@ -182,6 +182,8 @@ fn processMarkdown(gpa: std.mem.Allocator, src: []const u8, compiler_path: []con
182182 try writeTokenizedCode(gpa, code.items, writer);
183183 try writer.writeAll("</code></pre>");
184184
185 try code.append('\n');
186
185187 switch (tag) {
186188 .code_run,
187189 .code_build,
......@@ -208,7 +210,8 @@ fn processMarkdown(gpa: std.mem.Allocator, src: []const u8, compiler_path: []con
208210 }
209211 if (std.mem.trim(u8, out.items, " \n\r").len > 0) {
210212 try writer.writeAll("<pre><code>");
211 try writer.writeAll(out.items);
213 try writer.writeAll("// Compiled JavaScript Code");
214 try writer.writeAll(out.items[std.mem.indexOfScalar(u8, out.items, '\n').?..]);
212215 try writer.writeAll("</code></pre>");
213216 }
214217 },
......@@ -302,6 +305,8 @@ fn processInlineMarkdown(gpa: std.mem.Allocator, src: []const u8, writer: anytyp
302305 }
303306}
304307
308// TODO: Change this to use Tree-sitter, which would also make it very simple
309// to highlight JavaScript code in addition to the language.
305310fn writeTokenizedCode(gpa: std.mem.Allocator, code: []const u8, writer: anytype) !void {
306311 const code_z = try gpa.dupeZ(u8, code);
307312 defer gpa.free(code_z);
src/langref/template.html+36-14
......@@ -8,7 +8,7 @@
88 * { margin: 0; padding: 0; box-sizing: border-box; }
99 body {
1010 background-color: #fefefe;
11 font-family: sans-serif;
11 font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
1212 max-width: 45rem;
1313 padding: 1rem;
1414 margin: auto;
......@@ -29,44 +29,66 @@
2929 padding-top: 8px;
3030 padding-bottom: 8px;
3131 }
32 pre {
33 padding: 0.5rem;
34 }
3532 pre > code {
3633 border: none;
3734 padding: 0;
3835 background-color: transparent;
3936 }
4037 code, pre {
41 border: 1px solid #999;
42 background-color: #eeeeee;
38 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
39 font-size: 0.9rem;
40 border: 1px solid #9ca0b0;
41 background-color: #eff1f5;
4342 border-radius: 4px;
4443 padding: 2px 4px;
4544 }
45 pre {
46 padding: 0.75rem 0.75rem;
47 }
4648 .term {
47 border: 1px solid #333;
48 background-color: #222;
49 color:white;
49 border: 1px solid #11111b;
50 background-color: #24273a;
51 color: #cdd6f4;
5052 }
53
5154 .ansi-1 {
5255 font-weight: bold;
5356 }
5457 .ansi-31 {
55 color:rgb(255, 68, 68);
58 color: #ed8796;
59 }
60 .ansi-32 {
61 color: #a6e3a1;
62 }
63 .ansi-33 {
64 color: #eed49f;
65 }
66 .ansi-34 {
67 color: #8aadf4;
68 }
69 .ansi-35 {
70 color: #f5c2e7;
71 }
72 .ansi-36 {
73 color: #94e2d5;
5674 }
5775 .ansi-2 {
58 color:#aaa;
76 color: #8087a2;
5977 }
6078
6179 .kw {
62 color: mediumpurple;
80 color: #8839ef;
6381 font-weight: bold;
6482 }
6583 .tok-string {
66 color: green;
84 color: #40a02b;
85 }
86 .tok-builtin_id {
87 color: #d20f39;
88 font-weight: bold;
6789 }
6890 .tok-number_int, .tok-number_float {
69 color: orangered;
91 color: #fe640b;
7092 }
7193 </style>
7294</head>