aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-04-27 12:00:10 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-04-27 12:00:10 -0700
commit02fbb8e82a7f41c466b5156821c68af029ce4448 (patch)
treec3b07a06aff4fbe7e1c9db94194d3a3685b2f6ca /src
parent90a76bda39e16c9641579e88995139ec81aa75d0 (diff)
downloadbun-02fbb8e82a7f41c466b5156821c68af029ce4448.tar.gz
bun-02fbb8e82a7f41c466b5156821c68af029ce4448.tar.zst
bun-02fbb8e82a7f41c466b5156821c68af029ce4448.zip
json works in CLI sort of
Diffstat (limited to 'src')
-rw-r--r--src/js_ast.zig5
-rw-r--r--src/js_parser.zig4
-rw-r--r--src/js_printer.zig307
-rw-r--r--src/json_parser.zig15
-rw-r--r--src/main.zig52
-rw-r--r--src/main_wasm.zig1
-rw-r--r--src/options.zig2
7 files changed, 346 insertions, 40 deletions
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 0cbdc0bda..9602f42ab 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -2779,6 +2779,11 @@ pub const Part = struct {
is_live: bool = false,
};
+pub const Result = struct {
+ ast: Ast,
+ ok: bool = false,
+};
+
pub const StmtOrExpr = union(enum) {
stmt: StmtNodeIndex,
expr: ExprNodeIndex,
diff --git a/src/js_parser.zig b/src/js_parser.zig
index 7fbb83065..c36915e05 100644
--- a/src/js_parser.zig
+++ b/src/js_parser.zig
@@ -197,6 +197,8 @@ const ScopeOrder = struct {
scope: *js_ast.Scope,
};
+pub const Result = js_ast.Result;
+
const ParenExprOpts = struct {
async_range: logger.Range = logger.Range.None,
is_async: bool = false,
@@ -348,8 +350,6 @@ pub const Parser = struct {
allocator: *std.mem.Allocator,
p: ?*P,
- pub const Result = struct { ast: js_ast.Ast, ok: bool = false };
-
pub const Options = struct {
jsx: options.JSX,
ts: bool = true,
diff --git a/src/js_printer.zig b/src/js_printer.zig
index 0598fb1dc..71ca10402 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -77,6 +77,10 @@ pub const Options = struct {
// If we're writing out a source map, this table of line start indices lets
// us do binary search on to figure out what line a given AST node came from
// line_offset_tables: []LineOffsetTable
+
+ pub fn unindent(self: *Options) void {
+ self.indent = if (self.indent > 0) self.indent - 1 else 0;
+ }
};
pub const PrintResult = struct { js: string, source_map: ?SourceMapChunk = null };
@@ -185,8 +189,8 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
// }
// }
- pub fn printFmt(p: *Printer, fmt: comptime string, args: anytype) void {
- std.fmt.bufPrint(p.writer, fmt, args);
+ pub fn printFmt(p: *Printer, comptime fmt: string, args: anytype) void {
+ std.fmt.format(p.writer, fmt, args) catch unreachable;
}
pub fn print(p: *Printer, str: anytype) void {
@@ -226,7 +230,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.js.growBy(p.options.indent * " ".len) catch unreachable;
while (p.options.indent > 0) {
p.unsafePrint(" ");
- p.options.indent -= 1;
+ p.options.unindent();
}
}
@@ -277,7 +281,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printNewline();
p.options.indent += 1;
p.printStmt(stmt) catch unreachable;
- p.options.indent -= 1;
+ p.options.unindent();
},
}
}
@@ -291,7 +295,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printSemicolonIfNeeded();
p.printStmt(stmt) catch unreachable;
}
- p.options.indent -= 1;
+ p.options.unindent();
p.needs_semicolon = false;
p.printIndent();
@@ -397,7 +401,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
p.needs_semicolon = false;
- p.options.indent -= 1;
+ p.options.unindent();
p.printIndent();
p.print("}");
}
@@ -683,7 +687,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printQuotedUTF8(record.path.text, true);
if (leading_interior_comments.len > 0) {
p.printNewline();
- p.options.indent -= 1;
+ p.options.unindent();
p.printIndent();
}
@@ -954,7 +958,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
if (e.leading_interior_comments.len > 0) {
p.printNewline();
- p.options.indent -= 1;
+ p.options.unindent();
p.printIndent();
}
p.print(")");
@@ -1174,7 +1178,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
if (!e.is_single_line) {
- p.options.indent -= 1;
+ p.options.unindent();
p.printNewline();
p.printIndent();
}
@@ -1212,7 +1216,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
if (!e.is_single_line) {
- p.options.indent -= 1;
+ p.options.unindent();
p.printNewline();
p.printIndent();
}
@@ -1744,8 +1748,160 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
pub fn printBinding(p: *Printer, binding: Binding) void {
- notimpl();
+ p.addSourceMapping(binding.loc);
+
+ switch (binding.data) {
+ .b_missing => {},
+ .b_identifier => |b| {
+ p.printSymbol(b.ref);
+ },
+ .b_array => |b| {
+ p.print("[");
+ if (b.items.len > 0) {
+ if (!b.is_single_line) {
+ p.options.indent += 1;
+ }
+
+ var i: usize = 0;
+ while (i < b.items.len) : (i += 1) {
+ if (i != 0) {
+ p.print(",");
+ if (b.is_single_line) {
+ p.printSpace();
+ }
+ }
+
+ if (!b.is_single_line) {
+ p.printNewline();
+ p.printIndent();
+ }
+
+ const is_last = i + 1 == b.items.len;
+ if (b.has_spread and is_last) {
+ p.print("...");
+ }
+
+ const item = b.items[i];
+ p.printBinding(item.binding);
+
+ p.maybePrintDefaultBindingValue(item);
+
+ // Make sure there's a comma after trailing missing items
+ if (is_last) {
+ switch (item.binding.data) {
+ .b_missing => |ok| {
+ p.print(",");
+ },
+ else => {},
+ }
+ }
+ }
+
+ if (!b.is_single_line) {
+ p.options.unindent();
+ p.printNewline();
+ p.printIndent();
+ }
+ }
+
+ p.print("]");
+ },
+ .b_object => |b| {
+ p.print("{");
+ if (b.properties.len > 0) {
+ if (!b.is_single_line) {
+ p.options.indent += 1;
+ }
+
+ var i: usize = 0;
+ while (i < b.properties.len) : (i += 1) {
+ if (i != 0) {
+ p.print(",");
+ if (b.is_single_line) {
+ p.printSpace();
+ }
+ }
+
+ if (!b.is_single_line) {
+ p.printNewline();
+ p.printIndent();
+ }
+
+ const property = b.properties[i];
+
+ if (property.flags.is_spread) {
+ p.print("...");
+ } else {
+ if (property.flags.is_computed) {
+ p.print("[");
+ p.printExpr(property.key, .comma, ExprFlag.None());
+ p.print("]:");
+ p.printSpace();
+
+ p.printBinding(property.value);
+ p.maybePrintDefaultBindingValue(property);
+ continue;
+ }
+
+ switch (property.key.data) {
+ .e_string => |str| {
+ if (p.canPrintIdentifierUTF16(str.value)) {
+ p.addSourceMapping(property.key.loc);
+ p.printSpaceBeforeIdentifier();
+ p.printIdentifierUTF16(str.value) catch unreachable;
+
+ // Use a shorthand property if the names are the same
+ switch (property.value.data) {
+ .b_identifier => |id| {
+ if (strings.utf16EqlString(str.value, p.renamer.nameForSymbol(id.ref))) {
+ p.maybePrintDefaultBindingValue(property);
+ continue;
+ }
+ },
+ else => {
+ p.printExpr(property.key, .lowest, ExprFlag.None());
+ },
+ }
+ } else {
+ p.printExpr(property.key, .lowest, ExprFlag.None());
+ }
+ },
+ else => {
+ p.printExpr(property.key, .lowest, ExprFlag.None());
+ },
+ }
+
+ p.print(":");
+ p.printSpace();
+ }
+
+ p.printBinding(property.value);
+ p.maybePrintDefaultBindingValue(property);
+ }
+
+ if (!b.is_single_line) {
+ p.options.unindent();
+ p.printNewline();
+ p.printIndent();
+ }
+ }
+ p.print("}");
+ },
+ else => {
+ std.debug.panic("Unexpected binding of type {s}", .{binding});
+ },
+ }
+ }
+
+ pub fn maybePrintDefaultBindingValue(p: *Printer, property: anytype) void {
+ if (property.default_value) |default| {
+ p.printSpace();
+ p.print("=");
+ p.printSpace();
+ p.printExpr(default, .comma, ExprFlag.None());
+ }
}
+
pub fn printStmt(p: *Printer, stmt: Stmt) !void {
p.comptime_flush();
@@ -1893,7 +2049,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
if (!s.is_single_line) {
- p.options.indent -= 1;
+ p.options.unindent();
p.printNewline();
p.printIndent();
}
@@ -1937,7 +2093,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
if (!s.is_single_line) {
- p.options.indent -= 1;
+ p.options.unindent();
p.printNewline();
p.printIndent();
}
@@ -1981,7 +2137,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.options.indent += 1;
p.printStmt(s.body) catch unreachable;
p.printSemicolonIfNeeded();
- p.options.indent -= 1;
+ p.options.unindent();
p.printIndent();
},
}
@@ -2150,10 +2306,10 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.printSemicolonIfNeeded();
p.printStmt(st) catch unreachable;
}
- p.options.indent -= 1;
+ p.options.unindent();
}
- p.options.indent -= 1;
+ p.options.unindent();
p.printIndent();
p.print("}");
p.printNewline();
@@ -2179,7 +2335,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
p.print("{");
if (!s.is_single_line) {
- p.options.indent -= 1;
+ p.options.unindent();
}
var i: usize = 0;
@@ -2208,7 +2364,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
if (!s.is_single_line) {
- p.options.indent -= 1;
+ p.options.unindent();
p.printNewline();
p.printIndent();
}
@@ -2340,11 +2496,122 @@ pub fn NewPrinter(comptime ascii_only: bool) type {
}
}
pub fn printIf(p: *Printer, s: *S.If) void {
- notimpl();
+ p.printSpaceBeforeIdentifier();
+ p.print("if");
+ p.printSpace();
+ p.print("(");
+ p.printExpr(s.test_, .lowest, ExprFlag.None());
+ p.print(")");
+
+ switch (s.yes.data) {
+ .s_block => |block| {
+ p.printSpace();
+ p.printBlock(s.yes.loc, block.stmts);
+
+ if (s.no != null) {
+ p.printSpace();
+ } else {
+ p.printNewline();
+ }
+ },
+ else => {
+ if (wrapToAvoidAmbiguousElse(&s.yes.data)) {
+ p.printSpace();
+ p.print("{");
+ p.printNewline();
+
+ p.options.indent += 1;
+ p.printStmt(s.yes) catch unreachable;
+ p.options.unindent();
+ p.needs_semicolon = false;
+
+ p.printIndent();
+ p.print("}");
+
+ if (s.no != null) {
+ p.printSpace();
+ } else {
+ p.printNewline();
+ }
+ } else {
+ p.printNewline();
+ p.options.indent += 1;
+ p.printStmt(s.yes) catch unreachable;
+ p.options.unindent();
+
+ if (s.no != null) {
+ p.printIndent();
+ }
+ }
+ },
+ }
+
+ if (s.no) |no_block| {
+ p.printSemicolonIfNeeded();
+ p.printSpaceBeforeIdentifier();
+ p.print("else");
+
+ switch (no_block.data) {
+ .s_block => |no| {
+ p.printSpace();
+ p.printBlock(no_block.loc, no.stmts);
+ p.printNewline();
+ },
+ .s_if => |no| {
+ p.printIf(no);
+ },
+ else => {
+ p.printNewline();
+ p.options.indent += 1;
+ p.printStmt(no_block) catch unreachable;
+ p.options.unindent();
+ },
+ }
+ }
+ }
+
+ pub fn wrapToAvoidAmbiguousElse(_s: *Stmt.Data) bool {
+ var s = _s;
+
+ while (true) {
+ switch (s.*) {
+ .s_if => |*current| {
+ if (current.*.no) |*no| {
+ s = &no.data;
+ } else {
+ return true;
+ }
+ },
+ .s_for => |current| {
+ s = &current.body.data;
+ },
+ .s_for_in => |current| {
+ s = &current.body.data;
+ },
+ .s_for_of => |current| {
+ s = &current.body.data;
+ },
+ .s_while => |current| {
+ s = &current.body.data;
+ },
+ .s_with => |current| {
+ s = &current.body.data;
+ },
+ else => {
+ return false;
+ },
+ }
+ }
}
pub fn printDeclStmt(p: *Printer, is_export: bool, keyword: string, decls: []G.Decl) void {
- notimpl();
+ p.printIndent();
+ p.printSpaceBeforeIdentifier();
+ if (is_export) {
+ p.print("export ");
+ }
+ p.printDecls(keyword, decls, ExprFlag.None());
+ p.printSemicolonAfterStatement();
}
pub fn printIdentifier(p: *Printer, identifier: string) void {
diff --git a/src/json_parser.zig b/src/json_parser.zig
index a46375929..8b371d4e2 100644
--- a/src/json_parser.zig
+++ b/src/json_parser.zig
@@ -138,11 +138,15 @@ fn JSONLikeParser(opts: js_lexer.JSONOptions) type {
while (p.lexer.token != .t_close_brace) {
if (properties.items.len > 0) {
- is_single_line = if (p.lexer.has_newline_before) false else is_single_line;
+ if (p.lexer.has_newline_before) {
+ is_single_line = false;
+ }
if (!p.parseMaybeTrailingComma(.t_close_brace)) {
break;
}
- is_single_line = if (p.lexer.has_newline_before) false else is_single_line;
+ if (p.lexer.has_newline_before) {
+ is_single_line = false;
+ }
}
var key_string = p.lexer.string_literal;
@@ -162,7 +166,9 @@ fn JSONLikeParser(opts: js_lexer.JSONOptions) type {
properties.append(G.Property{ .key = key, .value = value }) catch unreachable;
}
- is_single_line = if (p.lexer.has_newline_before) false else is_single_line;
+ if (p.lexer.has_newline_before) {
+ is_single_line = false;
+ }
p.lexer.expect(.t_close_brace);
return p.e(E.Object{
.properties = properties.toOwnedSlice(),
@@ -269,6 +275,9 @@ test "ParseJSON" {
expectPrintedJSON("3.4159820837456", "3.4159820837456");
expectPrintedJSON("-10000.25", "-10000.25");
expectPrintedJSON("\"hi\"", "\"hi\"");
+ expectPrintedJSON("{\"hi\": 1, \"hey\": \"200\", \"boom\": {\"yo\": true}}", "({\"hi\": 1, \"hey\": \"200\", \"boom\": {\"yo\": true}})");
+ expectPrintedJSON("{\"hi\": \"hey\"}", "({hi: \"hey\"})");
+ expectPrintedJSON("{\"hi\": [\"hey\", \"yo\"]}", "({hi:[\"hey\",\"yo\"]})");
// TODO: emoji?
}
diff --git a/src/main.zig b/src/main.zig
index 6144fdf24..7c51411fb 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -4,40 +4,62 @@ const logger = @import("logger.zig");
const alloc = @import("alloc.zig");
const options = @import("options.zig");
const js_parser = @import("js_parser.zig");
+const json_parser = @import("json_parser.zig");
const js_printer = @import("js_printer.zig");
const js_ast = @import("js_ast.zig");
const linker = @import("linker.zig");
pub fn main() anyerror!void {
try alloc.setup(std.heap.page_allocator);
- // const args = try std.process.argsAlloc(alloc.dynamic);
- // // const stdout = std.io.getStdOut();
- // // const stderr = std.io.getStdErr();
+ const args = try std.process.argsAlloc(alloc.dynamic);
+ const stdout = std.io.getStdOut();
+ const stderr = std.io.getStdErr();
- // // if (args.len < 1) {
- // // const len = stderr.write("Pass a file");
- // // return;
- // // }
+ if (args.len < 1) {
+ const len = stderr.write("Pass a file");
+ return;
+ }
- // // alloc
-
- const entryPointName = "/var/foo/index.js";
- const code = "for (let i = 0; i < 100; i++) { console.log('hi') aposkdpoaskdpokasdpokasdpokasdpokasdpoaksdpoaksdpoaskdpoaksdpoaksdpoaskdpoaskdpoasdk; ";
+ const absolutePath = try std.fs.path.resolve(alloc.dynamic, args);
+ const entryPointName = std.fs.path.basename(absolutePath);
+ const file = try std.fs.openFileAbsolute(absolutePath, std.fs.File.OpenFlags{ .read = true });
+ const stat = try file.stat();
+ const code = try file.readToEndAlloc(alloc.dynamic, stat.size);
const opts = try options.TransformOptions.initUncached(alloc.dynamic, entryPointName, code);
var log = logger.Log.init(alloc.dynamic);
var source = logger.Source.initFile(opts.entry_point, alloc.dynamic);
- var parser = try js_parser.Parser.init(opts, &log, &source, alloc.dynamic);
- var res = try parser.parse();
+ var ast: js_ast.Ast = undefined;
+
+ switch (opts.loader) {
+ .json => {
+ var expr = try json_parser.ParseJSON(&source, &log, alloc.dynamic);
+ var stmt = js_ast.Stmt.alloc(alloc.dynamic, js_ast.S.SExpr{ .value = expr }, logger.Loc{ .start = 0 });
+ var part = js_ast.Part{
+ .stmts = &([_]js_ast.Stmt{stmt}),
+ };
+
+ ast = js_ast.Ast.initTest(&([_]js_ast.Part{part}));
+ },
+ .jsx, .tsx, .ts, .js => {
+ var parser = try js_parser.Parser.init(opts, &log, &source, alloc.dynamic);
+ var res = try parser.parse();
+ ast = res.ast;
+ },
+ else => {
+ std.debug.panic("Unsupported loader: {s}", .{opts.loader});
+ },
+ }
+
var _linker = linker.Linker{};
const printed = try js_printer.printAst(
alloc.dynamic,
- res.ast,
+ ast,
js_ast.Symbol.Map{},
false,
js_printer.Options{ .to_module_ref = js_ast.Ref{ .inner_index = 0 } },
&_linker,
);
- std.debug.print("{s}\n{s}", .{ res, printed });
+ _ = try stdout.write(printed.js);
}
diff --git a/src/main_wasm.zig b/src/main_wasm.zig
index 5410b0e2a..b954b3df8 100644
--- a/src/main_wasm.zig
+++ b/src/main_wasm.zig
@@ -26,6 +26,7 @@ pub fn main() anyerror!void {
const opts = try options.TransformOptions.initUncached(alloc.dynamic, entryPointName, code);
var log = logger.Log.init(alloc.dynamic);
var source = logger.Source.initFile(opts.entry_point, alloc.dynamic);
+
var parser = try js_parser.Parser.init(opts, &log, &source, alloc.dynamic);
var res = try parser.parse();
diff --git a/src/options.zig b/src/options.zig
index 35ea37e66..e7120ca07 100644
--- a/src/options.zig
+++ b/src/options.zig
@@ -14,10 +14,12 @@ pub const Loader = enum {
tsx,
css,
file,
+ json,
};
pub const defaultLoaders = std.ComptimeStringMap(Loader, .{
.{ ".jsx", Loader.jsx },
+ .{ ".json", Loader.json },
.{ ".js", Loader.js },
.{ ".mjs", Loader.js },
.{ ".css", Loader.css },