authorgravatar for me@paperdave.netdave caruso <me@paperdave.net> 2024-07-27 23:32:02-07:00
committergravatar for me@paperdave.netdave caruso <me@paperdave.net> 2024-07-27 23:32:02-07:00
logc7cb405f654a9aae882cc17746d73301b896f87b
tree3a15f57d55e437f2b908dd75d9dfc031560097a5
parent84d69ae4e43f53b2b0b243cff4f1f67303825b4b
signature Commit is signed but in an unrecognized format.

feat: add --run flag


5 files changed, 207 insertions(+), 33 deletions(-)

CHANGELOG.md+1
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1## 0.1.61## 0.1.6
22
3- feat: add `--run` to execute the file in QuickJS instead of outputting source
3- fix: crash when printing unused struct declaration error4- fix: crash when printing unused struct declaration error
4- fix: provide array result type to sema5- fix: provide array result type to sema
5- fix: crash when analyzing an empty array without a result type6- fix: crash when analyzing an empty array without a result type
build.zig+24-24
...@@ -66,7 +66,7 @@ pub fn build(b: *Build) !void {...@@ -66,7 +66,7 @@ pub fn build(b: *Build) !void {
66 const native_debug = buildWithTarget(b, b.graph.host, .Debug, .none, version, no_llvm);66 const native_debug = buildWithTarget(b, b.graph.host, .Debug, .none, version, no_llvm);
67 const main = buildWithTarget(b, target, optimize, tracing, version, no_llvm);67 const main = buildWithTarget(b, target, optimize, tracing, version, no_llvm);
6868
69 b.installArtifact(main.cli(b, .{}));69 b.installArtifact(main.cli(b, BuildConfig.all));
7070
71 inline for (.{71 inline for (.{
72 .{ main.cli(b, BuildConfig.minimal), "compiler" },72 .{ main.cli(b, BuildConfig.minimal), "compiler" },
...@@ -159,28 +159,25 @@ pub fn build(b: *Build) !void {...@@ -159,28 +159,25 @@ pub fn build(b: *Build) !void {
159 @tagName(cross_target.result.os.tag),159 @tagName(cross_target.result.os.tag),
160 },160 },
161 ) catch @panic("OOM");161 ) catch @panic("OOM");
162 _ = name; // autofix
163162
164 const artifacts = buildWithTarget(b, cross_target, .ReleaseSafe, .none, version, no_llvm);163 const artifacts = buildWithTarget(b, cross_target, .ReleaseSafe, .none, version, no_llvm);
165 _ = artifacts; // autofix164
166165 inline for (.{
167 // inline for (.{166 .{ artifacts.cli(b, BuildConfig.all), "compiler" },
168 // .{ artifacts.compiler, "compiler" },167 }) |entry| {
169 // // .{ artifacts.lsp, "lsp" },168 const artifact, const bin_name = entry;
170 // }) |entry| {169 package.dependOn(&b.addInstallFile(
171 // const artifact, const bin_name = entry;170 artifact.getEmittedBin(),
172 // package.dependOn(&b.addInstallFile(171 b.pathJoin(&.{
173 // artifact.getEmittedBin(),172 "package",
174 // b.pathJoin(&.{173 name,
175 // "package",174 std.mem.concat(b.graph.arena, u8, &.{
176 // name,175 bin_name,
177 // std.mem.concat(b.graph.arena, u8, &.{176 cross_target.result.exeFileExt(),
178 // bin_name,177 }) catch @panic("OOM"),
179 // cross_target.result.exeFileExt(),178 }),
180 // }) catch @panic("OOM"),179 ).step);
181 // }),180 }
182 // ).step);
183 // }
184181
185 package.dependOn(&b.addInstallFile(b.path("CHANGELOG.md"), "package/CHANGELOG.md").step);182 package.dependOn(&b.addInstallFile(b.path("CHANGELOG.md"), "package/CHANGELOG.md").step);
186 package.dependOn(&b.addInstallFile(manual_out, "package/README.html").step);183 package.dependOn(&b.addInstallFile(manual_out, "package/README.html").step);
...@@ -208,8 +205,6 @@ const Artifacts = struct {...@@ -208,8 +205,6 @@ const Artifacts = struct {
208 const use_llvm = if (a.no_llvm) false else null;205 const use_llvm = if (a.no_llvm) false else null;
209 const use_lld = if (a.no_llvm) false else null;206 const use_lld = if (a.no_llvm) false else null;
210207
211 const tracer = b.dependency("tracer", dep_opts);
212
213 // Options208 // Options
214 const build_config = b.addOptions();209 const build_config = b.addOptions();
215 build_config.addOption(BuildConfig, "config", config);210 build_config.addOption(BuildConfig, "config", config);
...@@ -229,7 +224,12 @@ const Artifacts = struct {...@@ -229,7 +224,12 @@ const Artifacts = struct {
229 exe.root_module.addImport("build_options", a.opts_mod);224 exe.root_module.addImport("build_options", a.opts_mod);
230 exe.root_module.addImport("build_config", build_config_mod);225 exe.root_module.addImport("build_config", build_config_mod);
231 exe.root_module.addImport("core", a.core);226 exe.root_module.addImport("core", a.core);
232 exe.root_module.addImport("tracer", tracer.module("tracer"));227 exe.root_module.addImport("tracer", b.dependency("tracer", dep_opts).module("tracer"));
228
229 if (config.have_embedded_quickjs) {
230 exe.root_module.addImport("quickjs", b.dependency("quickjs", dep_opts).module("quickjs_libc"));
231 }
232
233 return exe;233 return exe;
234 }234 }
235};235};
src/cli.zig+71-6
...@@ -5,6 +5,7 @@...@@ -5,6 +5,7 @@
5//! needing to compile the formatter.5//! needing to compile the formatter.
66
7const have_debug_features = builtin.mode == .Debug;7const have_debug_features = builtin.mode == .Debug;
8const config = @import("build_config").config;
89
9pub fn main() !u8 {10pub fn main() !u8 {
10 try tracer.init();11 try tracer.init();
...@@ -37,6 +38,7 @@ pub fn main() !u8 {...@@ -37,6 +38,7 @@ pub fn main() !u8 {
37 defer if (exe_name) |path| alloc.free(path);38 defer if (exe_name) |path| alloc.free(path);
38 var dump_ir = false;39 var dump_ir = false;
39 var dump_state: ?[]const u8 = null;40 var dump_state: ?[]const u8 = null;
41 var run = false;
40 var has_errors = false;42 var has_errors = false;
41 {43 {
42 var args = try std.process.argsWithAllocator(alloc);44 var args = try std.process.argsWithAllocator(alloc);
...@@ -61,6 +63,11 @@ pub fn main() !u8 {...@@ -61,6 +63,11 @@ pub fn main() !u8 {
61 continue;63 continue;
62 }64 }
6365
66 if (config.have_embedded_quickjs and std.mem.eql(u8, arg, "--run")) {
67 run = true;
68 continue;
69 }
70
64 std.debug.print("error: unknown flag '{s}'\n", .{arg});71 std.debug.print("error: unknown flag '{s}'\n", .{arg});
65 has_errors = true;72 has_errors = true;
66 break;73 break;
...@@ -89,7 +96,13 @@ pub fn main() !u8 {...@@ -89,7 +96,13 @@ pub fn main() !u8 {
89 \\96 \\
90 , .{});97 , .{});
91 }98 }
92 if (builtin.mode == .Debug) {99 if (config.have_embedded_quickjs) {
100 std.debug.print(
101 \\ --run Run program using QuickJS
102 \\
103 , .{});
104 }
105 if (have_debug_features) {
93 std.debug.print(106 std.debug.print(
94 \\107 \\
95 \\Debug Mode Flags:108 \\Debug Mode Flags:
...@@ -129,6 +142,7 @@ pub fn main() !u8 {...@@ -129,6 +142,7 @@ pub fn main() !u8 {
129 error.TransformFail => {142 error.TransformFail => {
130 std.debug.print("Transform failed:\n", .{});143 std.debug.print("Transform failed:\n", .{});
131 try fail_report.dumpToStdErr(&comp);144 try fail_report.dumpToStdErr(&comp);
145 fail_report.deinit(comp.gpa);
132 return 1;146 return 1;
133 },147 },
134 error.ParseFail => {148 error.ParseFail => {
...@@ -148,17 +162,68 @@ pub fn main() !u8 {...@@ -148,17 +162,68 @@ pub fn main() !u8 {
148 else => return err,162 else => return err,
149 };163 };
150164
151 const output = std.io.getStdOut().writer();165 if (config.have_embedded_quickjs and run) {
152 var bufw = std.io.bufferedWriter(output);166 // Execute with QuickJS
153 const writer = bufw.writer();167 var out: std.ArrayListUnmanaged(u8) = .{};
154 try js_backend.link(&comp, entry_point, writer.any());168 defer out.deinit(alloc);
155 try bufw.flush();169 try js_backend.link(&comp, entry_point, out.writer(alloc).any());
170 try out.append(alloc, 0);
171 try runWithQuickJs(out.items[0 .. out.items.len - 1 :0]);
172 } else {
173 // Output to standard out
174 const output = std.io.getStdOut().writer();
175 var bufw = std.io.bufferedWriter(output);
176 const writer = bufw.writer();
177 try js_backend.link(&comp, entry_point, writer.any());
178 try bufw.flush();
179 }
156 }180 }
157181
158 std.process.cleanExit();182 std.process.cleanExit();
159 return 0;183 return 0;
160}184}
161185
186fn runWithQuickJs(js: [:0]const u8) !void {
187 const qjs = @import("quickjs");
188
189 const runtime = qjs.JS_NewRuntime() orelse
190 return error.UnexpectedError;
191 defer qjs.JS_FreeRuntime(runtime);
192 const js_ctx = qjs.JS_NewContext(runtime) orelse
193 return error.UnexpectedError;
194 defer qjs.JS_FreeContext(js_ctx);
195
196 // QuickJS provides a completely blank global context. It is a non-goal to
197 // be a full runtime, but adding simple globals to align with expectations
198 // is OK.
199
200 // 0 and null is zero process args
201 qjs.js_std_add_helpers(js_ctx, 0, null);
202
203 const result = qjs.JS_Eval(
204 js_ctx,
205 js.ptr,
206 js.len,
207 "test.js",
208 qjs.JS_EVAL_TYPE_GLOBAL,
209 );
210 defer qjs.JS_FreeValue(js_ctx, result);
211
212 if (qjs.JS_IsException(result) != 0) {
213 const exception = qjs.JS_GetException(js_ctx);
214 defer qjs.JS_FreeValue(js_ctx, exception);
215
216 const exception_str = qjs.JS_ToCString(js_ctx, exception);
217 defer qjs.JS_FreeCString(js_ctx, exception_str);
218
219 const slice = std.mem.span(exception_str);
220
221 std.debug.print("Exception: {s}\n", .{slice});
222
223 std.process.exit(1);
224 }
225}
226
162const core = @import("core");227const core = @import("core");
163const Comp = core.Comp;228const Comp = core.Comp;
164const Report = core.Report;229const Report = core.Report;
src/deps/quickjs/build.zig+103-3
...@@ -2,6 +2,9 @@ pub fn build(b: *Build) !void {...@@ -2,6 +2,9 @@ pub fn build(b: *Build) !void {
2 const target = b.standardTargetOptions(.{});2 const target = b.standardTargetOptions(.{});
3 const optimize = b.standardOptimizeOption(.{});3 const optimize = b.standardOptimizeOption(.{});
44
5 const pthread = WinPthreads.get(b, target, optimize);
6 const pthread_native = WinPthreads.get(b, b.graph.host, .Debug);
7
5 const src = b.dependency("quickjs", .{});8 const src = b.dependency("quickjs", .{});
69
7 const version = std.mem.trim(10 const version = std.mem.trim(
...@@ -35,8 +38,9 @@ pub fn build(b: *Build) !void {...@@ -35,8 +38,9 @@ pub fn build(b: *Build) !void {
35 .name = "quickjs",38 .name = "quickjs",
36 .target = target,39 .target = target,
37 .optimize = optimize,40 .optimize = optimize,
41 .link_libc = true,
38 });42 });
3943 pthread.configure(libquickjs);
40 libquickjs.addCSourceFiles(.{44 libquickjs.addCSourceFiles(.{
41 .root = src.path(""),45 .root = src.path(""),
42 .files = &.{46 .files = &.{
...@@ -52,11 +56,31 @@ pub fn build(b: *Build) !void {...@@ -52,11 +56,31 @@ pub fn build(b: *Build) !void {
52 libquickjs.root_module.addCMacro(def.name, def.value);56 libquickjs.root_module.addCMacro(def.name, def.value);
53 }57 }
5458
59 const libquickjs_libc = b.addStaticLibrary(.{
60 .name = "quickjs_libc",
61 .target = target,
62 .optimize = optimize,
63 .link_libc = true,
64 });
65 pthread.configure(libquickjs_libc);
66 libquickjs_libc.addCSourceFiles(.{
67 .root = src.path(""),
68 .files = &.{
69 "quickjs-libc.c",
70 },
71 .flags = c_flags,
72 });
73 for (defines) |def| {
74 libquickjs_libc.root_module.addCMacro(def.name, def.value);
75 }
76
55 const qjsc = b.addExecutable(.{77 const qjsc = b.addExecutable(.{
56 .name = "qjsc",78 .name = "qjsc",
57 .target = b.graph.host,79 .target = b.graph.host,
58 .optimize = .Debug,80 .optimize = .Debug,
81 .link_libc = true,
59 });82 });
83 pthread_native.configure(qjsc);
60 qjsc.addCSourceFiles(.{84 qjsc.addCSourceFiles(.{
61 .root = src.path(""),85 .root = src.path(""),
62 .files = &.{86 .files = &.{
...@@ -78,12 +102,13 @@ pub fn build(b: *Build) !void {...@@ -78,12 +102,13 @@ pub fn build(b: *Build) !void {
78 .name = "qjs",102 .name = "qjs",
79 .target = target,103 .target = target,
80 .optimize = optimize,104 .optimize = optimize,
105 .link_libc = true,
81 });106 });
107 pthread.configure(qjs);
82 qjs.addCSourceFiles(.{108 qjs.addCSourceFiles(.{
83 .root = src.path(""),109 .root = src.path(""),
84 .files = &.{110 .files = &.{
85 "qjs.c",111 "qjs.c",
86 "quickjs-libc.c",
87 },112 },
88 .flags = c_flags,113 .flags = c_flags,
89 });114 });
...@@ -99,18 +124,32 @@ pub fn build(b: *Build) !void {...@@ -99,18 +124,32 @@ pub fn build(b: *Build) !void {
99 qjs.root_module.addCMacro(def.name, def.value);124 qjs.root_module.addCMacro(def.name, def.value);
100 }125 }
101 qjs.linkLibrary(libquickjs);126 qjs.linkLibrary(libquickjs);
127 qjs.linkLibrary(libquickjs_libc);
102128
103 b.installArtifact(qjs);129 b.installArtifact(qjs);
104 b.installArtifact(libquickjs);130 b.installArtifact(libquickjs);
131 b.installArtifact(libquickjs_libc);
105132
106 const translate = b.addTranslateC(.{133 const translate = b.addTranslateC(.{
107 .root_source_file = src.path("quickjs.h"),134 .root_source_file = src.path("quickjs.h"),
108 .target = target,135 .target = target,
109 .optimize = optimize,136 .optimize = optimize,
110 .link_libc = false,137 .link_libc = true,
111 });138 });
139 if (pthread.pthreads) |pt| translate.addIncludeDir(pt.include.getPath(b));
112 const module = translate.addModule("quickjs");140 const module = translate.addModule("quickjs");
113 module.linkLibrary(libquickjs);141 module.linkLibrary(libquickjs);
142
143 const translate_libc = b.addTranslateC(.{
144 .root_source_file = src.path("quickjs-libc.h"),
145 .target = target,
146 .optimize = optimize,
147 .link_libc = true,
148 });
149 const module2 = translate_libc.addModule("quickjs_libc");
150 if (pthread.pthreads) |pt| translate_libc.addIncludeDir(pt.include.getPath(b));
151 module2.linkLibrary(libquickjs);
152 module2.linkLibrary(libquickjs_libc);
114}153}
115154
116fn runQjsc(b: *Build, qjsc: *Build.Step.Compile, in: Build.LazyPath) Build.LazyPath {155fn runQjsc(b: *Build, qjsc: *Build.Step.Compile, in: Build.LazyPath) Build.LazyPath {
...@@ -124,5 +163,66 @@ fn runQjsc(b: *Build, qjsc: *Build.Step.Compile, in: Build.LazyPath) Build.LazyP...@@ -124,5 +163,66 @@ fn runQjsc(b: *Build, qjsc: *Build.Step.Compile, in: Build.LazyPath) Build.LazyP
124 return out;163 return out;
125}164}
126165
166/// Zig doesnt include winpthreads, so we build it from source. This helper
167/// decides if it is needed, and provides a no-op `configure` function if it is
168/// not actually needed. Call .configure on any object files you need.
169const WinPthreads = struct {
170 pthreads: ?struct {
171 library: *Build.Step.Compile,
172 include: Build.LazyPath,
173 } = null,
174
175 pub fn get(
176 b: *Build,
177 target: Build.ResolvedTarget,
178 optimize: std.builtin.OptimizeMode,
179 ) WinPthreads {
180 if (target.result.os.tag == .windows) {
181 const dep = b.lazyDependency("mingw-w64", .{}) orelse
182 return .{};
183
184 const libpthread = b.addStaticLibrary(.{
185 .name = "winpthreads",
186 .target = target,
187 .optimize = optimize,
188 .link_libc = true,
189 });
190
191 libpthread.addCSourceFiles(.{
192 .root = dep.path("mingw-w64-libraries/winpthreads/src"),
193 .files = &.{
194 "barrier.c",
195 "clock.c",
196 "cond.c",
197 "misc.c",
198 "mutex.c",
199 "nanosleep.c",
200 "ref.c",
201 "rwlock.c",
202 "sched.c",
203 "sem.c",
204 "spinlock.c",
205 "thread.c",
206 },
207 });
208
209 libpthread.addIncludePath(dep.path("mingw-w64-libraries/winpthreads/include"));
210
211 return .{ .pthreads = .{
212 .library = libpthread,
213 .include = dep.path("mingw-w64-libraries/winpthreads/include"),
214 } };
215 }
216 return .{};
217 }
218
219 pub fn configure(this: WinPthreads, compile: *Build.Step.Compile) void {
220 if (this.pthreads) |pthreads| {
221 compile.linkLibrary(pthreads.library);
222 compile.addIncludePath(pthreads.include);
223 }
224 }
225};
226
127const std = @import("std");227const std = @import("std");
128const Build = std.Build;228const Build = std.Build;
src/deps/quickjs/build.zig.zon+8
...@@ -7,6 +7,14 @@...@@ -7,6 +7,14 @@
7 .url = "https://github.com/bellard/quickjs/archive/6e2e68fd0896957f92eb6c242a2e048c1ef3cae0.tar.gz",7 .url = "https://github.com/bellard/quickjs/archive/6e2e68fd0896957f92eb6c242a2e048c1ef3cae0.tar.gz",
8 .hash = "1220d49e57fc131eebbf4b09fb100f5d802b909d2f36e15d2d849a72f354cd24489d",8 .hash = "1220d49e57fc131eebbf4b09fb100f5d802b909d2f36e15d2d849a72f354cd24489d",
9 },9 },
10
11 // Required for building "pthread.h" on Windows
12 // https://github.com/ziglang/zig/issues/10989
13 .@"mingw-w64" = .{
14 .url = "https://github.com/mirror/mingw-w64/archive/eff726c461e09f35eeaed125a3570fa5f807f02b.tar.gz",
15 .hash = "1220cb412e58a63679fd29943e90331c4cc4d301382d792b1fba570eabfb0b032c81",
16 .lazy = true,
17 },
10 },18 },
1119
12 .paths = .{20 .paths = .{