diff options
-rw-r--r-- | src/js_lexer.zig | 6 | ||||
-rw-r--r-- | src/js_printer.zig | 236 | ||||
-rw-r--r-- | src/string_immutable.zig | 30 |
3 files changed, 258 insertions, 14 deletions
diff --git a/src/js_lexer.zig b/src/js_lexer.zig index 409b3a269..bd018a254 100644 --- a/src/js_lexer.zig +++ b/src/js_lexer.zig @@ -1530,9 +1530,9 @@ pub fn isIdentifierUTF16(text: JavascriptString) bool { var i: usize = 0; while (i < n) : (i += 1) { - var r1 = text[i]; + var r1 = @intCast(i32, text[i]); if (r1 >= 0xD800 and r1 <= 0xDBFF and i + 1 < n) { - const r2 = text[i + 1]; + const r2 = @intCast(i32, text[i + 1]); if (r2 >= 0xDC00 and r2 <= 0xDFFF) { r1 = (r1 << 10) + r2 + (0x10000 - (0xD800 << 10) - 0xDC00); i += 1; @@ -1543,7 +1543,7 @@ pub fn isIdentifierUTF16(text: JavascriptString) bool { return false; } } else { - if (!isIDentifierContinue(@intCast(u21, r1))) { + if (!isIdentifierContinue(@intCast(u21, r1))) { return false; } } diff --git a/src/js_printer.zig b/src/js_printer.zig index 096a141ca..62390f99a 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -240,7 +240,10 @@ pub fn NewPrinter(comptime ascii_only: bool) type { p.print(";\n"); } pub fn printSemicolonIfNeeded(p: *Printer) void { - notimpl(); + if (p.needs_semicolon) { + p.print(";"); + p.needs_semicolon = false; + } } pub fn printSpaceBeforeIdentifier( p: *Printer, @@ -264,29 +267,139 @@ pub fn NewPrinter(comptime ascii_only: bool) type { } pub fn printBody(p: *Printer, stmt: Stmt) void { - notimpl(); + switch (stmt.data) { + .s_block => |block| { + p.printSpace(); + p.printBlock(stmt.loc, block.stmts); + p.printNewline(); + }, + else => { + p.printNewline(); + p.options.indent += 1; + p.printStmt(stmt) catch unreachable; + p.options.indent -= 1; + }, + } } pub fn printBlock(p: *Printer, loc: logger.Loc, stmts: []Stmt) void { - notimpl(); + p.addSourceMapping(loc); + p.print("{"); + p.printNewline(); + + p.options.indent += 1; + for (stmts) |stmt| { + p.printSemicolonIfNeeded(); + p.printStmt(stmt) catch unreachable; + } + p.options.indent -= 1; + p.needs_semicolon = false; + + p.printIndent(); + p.print("}"); } pub fn printDecls(p: *Printer, keyword: string, decls: []G.Decl, flags: ExprFlag) void { - notimpl(); + p.print(keyword); + p.printSpace(); + + var i: usize = 0; + + while (i < decls.len) : (i += 1) { + if (i != 0) { + p.print(","); + p.printSpace(); + } + + const decl = decls[i]; + + p.printBinding(decl.binding); + + if (decl.value) |value| { + p.printSpace(); + p.print("="); + p.printSpace(); + p.printExpr(value, .comma, ExprFlag.None()); + } + } } // noop for now pub fn addSourceMapping(p: *Printer, loc: logger.Loc) void {} pub fn printSymbol(p: *Printer, ref: Ref) void { - notimpl(); + const name = p.renamer.nameForSymbol(ref); + + p.printIdentifier(name); } pub fn printClauseAlias(p: *Printer, alias: string) void { - notimpl(); + if (js_lexer.isIdentifier(alias)) { + p.printSpaceBeforeIdentifier(); + p.printIdentifier(alias); + } else { + p.printQuotedUTF8(alias, false); + } } + + pub fn printFnArgs(p: *Printer, args: []G.Arg, has_rest_arg: bool, is_arrow: bool) void { + const wrap = true; + + if (wrap) { + p.print("("); + } + + var i: usize = 0; + while (i < args.len) : (i += 1) { + if (i != 0) {} + + if (has_rest_arg and i + 1 == args.len) { + p.print("..."); + } + const arg = args[i]; + + p.printBinding(arg.binding); + if (arg.default) |default| { + p.printSpace(); + p.print("="); + p.printSpace(); + p.printExpr(default, .comma, ExprFlag.None()); + } + } + + if (wrap) { + p.print(")"); + } + } + pub fn printFunc(p: *Printer, func: G.Fn) void { - notimpl(); + p.printFnArgs(func.args, func.flags.has_rest_arg, false); + p.printSpace(); + p.printBlock(func.body.?.loc, func.body.?.stmts); } pub fn printClass(p: *Printer, class: G.Class) void { - notimpl(); + if (class.extends) |extends| {} + + p.printSpace(); + + p.addSourceMapping(class.body_loc); + p.print("{"); + p.printNewline(); + p.options.indent += 1; + + for (class.properties) |item| { + p.printSemicolonIfNeeded(); + p.printIndent(); + p.printProperty(item); + + if (item.value == null) { + p.printSemicolonAfterStatement(); + } else { + p.printNewline(); + } + } + + p.needs_semicolon = false; + p.options.indent -= 1; + p.printIndent(); + p.print("}"); } pub fn bestQuoteCharForString(p: *Printer, str: anytype, allow_backtick: bool) u8 { @@ -1474,8 +1587,109 @@ pub fn NewPrinter(comptime ascii_only: bool) type { p.print(")"); } - pub fn printProperty(p: *Printer, prop: G.Property) void { - notimpl(); + pub fn printProperty(p: *Printer, item: G.Property) void { + if (item.kind == .spread) { + p.print("..."); + p.printExpr(item.value.?, .comma, ExprFlag.None()); + } + + if (item.flags.is_static) { + p.print("static"); + p.printSpace(); + } + + switch (item.kind) { + .get => { + p.printSpaceBeforeIdentifier(); + p.print("get"); + p.printSpace(); + }, + .set => { + p.printSpaceBeforeIdentifier(); + p.print("set"); + p.printSpace(); + }, + else => {}, + } + + if (item.value) |val| { + switch (val.data) { + .e_function => |func| { + if (item.flags.is_method) { + p.printSpaceBeforeIdentifier(); + p.print("set"); + p.printSpace(); + } + + if (func.func.flags.is_generator) { + p.print("*"); + } + }, + else => {}, + } + } + + if (item.flags.is_computed) { + p.print("["); + p.printExpr(item.key.?, .comma, ExprFlag.None()); + p.print("]"); + + if (item.value) |val| { + switch (val.data) { + .e_function => |func| { + if (item.flags.is_method) { + p.printFunc(func.func); + return; + } + }, + else => {}, + } + + p.print(":"); + p.printSpace(); + p.printExpr(val, .comma, ExprFlag.None()); + } + + if (item.initializer) |initial| { + p.printSpace(); + p.print("="); + p.printSpace(); + p.printExpr(initial, .comma, ExprFlag.None()); + } + return; + } + + switch (item.key.?.data) { + .e_private_identifier => |key| { + p.printSymbol(key.ref); + }, + .e_string => |key| { + p.addSourceMapping(item.key.?.loc); + if (p.canPrintIdentifierUTF16(key.value)) { + p.printSpaceBeforeIdentifier(); + p.printIdentifierUTF16(key.value) catch unreachable; + + // Use a shorthand property if the names are the same + if (item.value) |val| { + switch (val.data) { + .e_identifier => |e| { + const name = p.renamer.nameForSymbol(e.ref); + // if (strings) {} + }, + .e_import_identifier => |e| {}, + else => {}, + } + } else {} + } + }, + else => {}, + } + + if (item.kind != .normal) {} + + if (item.value) |val| {} + + if (item.initializer) |initial| {} } pub fn printBinding(p: *Printer, binding: Binding) void { notimpl(); @@ -2114,7 +2328,7 @@ pub fn NewPrinter(comptime ascii_only: bool) type { continue; } - const width = std.unicode.utf8Encode(c, temp); + const width = try std.unicode.utf8Encode(c, &temp); p.print(temp[0..width]); } } diff --git a/src/string_immutable.zig b/src/string_immutable.zig index c1197e6ef..14569b5a9 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -89,6 +89,36 @@ pub fn eqlUtf16(comptime self: string, other: JavascriptString) bool { return std.mem.eql(u16, std.unicode.utf8ToUtf16LeStringLiteral(self), other); } +pub fn utf16EqlString(text: []u16, str: string) bool { + if (text.len > str.len) { + // Strings can't be equal if UTF-16 encoding is longer than UTF-8 encoding + return false; + } + + var temp = [4]byte{ 0, 0, 0, 0 }; + const n = text.len; +} + +pub fn encodeWTF8Rune(p: []byte, b: u8) u3 { + // Negative values are erroneous. Making it unsigned addresses the problem. + const i = @intCast(u32, b); + switch (i) { + 0...0x7F => { + p[0] = b; + return 1; + }, + (0x7FF + 1)...0xFFFF => { + std.debug.panic("emoji not implemented yet!", .{}); + }, + (0x7F + 1)...(0x7FF) => { + std.debug.panic("emoji not implemented yet!", .{}); + }, + else => { + std.debug.panic("emoji not implemented yet!", .{}); + }, + } +} + pub fn toUTF16Buf(in: string, out: []u16) usize { var utf8Iterator = std.unicode.Utf8Iterator{ .bytes = in, .i = 0 }; |