diff options
author | 2021-04-27 12:00:10 -0700 | |
---|---|---|
committer | 2021-04-27 12:00:10 -0700 | |
commit | 02fbb8e82a7f41c466b5156821c68af029ce4448 (patch) | |
tree | c3b07a06aff4fbe7e1c9db94194d3a3685b2f6ca /src | |
parent | 90a76bda39e16c9641579e88995139ec81aa75d0 (diff) | |
download | bun-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.zig | 5 | ||||
-rw-r--r-- | src/js_parser.zig | 4 | ||||
-rw-r--r-- | src/js_printer.zig | 307 | ||||
-rw-r--r-- | src/json_parser.zig | 15 | ||||
-rw-r--r-- | src/main.zig | 52 | ||||
-rw-r--r-- | src/main_wasm.zig | 1 | ||||
-rw-r--r-- | src/options.zig | 2 |
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 = ¤t.body.data; + }, + .s_for_in => |current| { + s = ¤t.body.data; + }, + .s_for_of => |current| { + s = ¤t.body.data; + }, + .s_while => |current| { + s = ¤t.body.data; + }, + .s_with => |current| { + s = ¤t.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 }, |