Skip to content

Conversation

@daurnimator
Copy link
Contributor

Recreating #3155 (github doesn't seem to allow reopening PRs)

  • dump json of arbitrary types
  • load json of arbitrary types

@daurnimator daurnimator added the standard library This issue involves writing Zig code for the standard library. label Jan 28, 2020
@data-man
Copy link
Contributor

Vectors?

@daurnimator
Copy link
Contributor Author

daurnimator commented Jan 29, 2020

I don't understand the CI failure

204/1301 json.test "std-aarch64-linux-none-Debug-bare-multi parseFree descends into tagged union"...access of inactive union field
/home/vsts/work/1/s/lib/std/json.zig:1672:53: 0x37d473 in json.test "std-aarch64-linux-none-Debug-bare-multi parseFree descends into tagged union" (test)
    testing.expectEqualSlices(u8, "withąunicode", r.string);
                                                    ^

This line is directly following a check of the tag type:

    testing.expectEqual(@TagType(T).string, @as(@TagType(T), r));
    testing.expectEqualSlices(u8, "withąunicode", r.string);

@Vexu
Copy link
Member

Vexu commented Jan 29, 2020

Might be #4295? No idea why the previous line works.

@daurnimator
Copy link
Contributor Author

Bah; rebased on master and CI is still failing on that one line of code.

The failure seems to only happen on aarch64.

@LemonBoy
Copy link
Contributor

Bad news: you're hitting a LLVM bug!

Consider this small piece of LLVM IR:

; ModuleID = 'foo'
source_filename = "foo"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64v8.1a-unknown-linux-musl"

define internal fastcc void @foobar(i2*) unnamed_addr {
Entry:
  store i2 -2, i2* %0
  ret void
}

LLVM 9 assembles it as:

	mov	w8, #254
	strb	w8, [x0]
	ret

Notice the wrong integer literal 😱 every other backend gets it right so nobody hit this bug before:

	movb	$2, (%rdi)
	retq

The good news is that LLVM 10 already fixed this problem and produces the following asm:

	mov	w8, #2
	strb	w8, [x0]
	ret

@daurnimator
Copy link
Contributor Author

daurnimator commented Feb 17, 2020

@LemonBoy seems like you were looking into this at same time as me; Perhaps move your comment to #4492?

Is there a simple workaround to the LLVM bug so we can merge this PR?

@LemonBoy
Copy link
Contributor

Is there a simple workaround so the LLVM bug so we can merge this PR?

Not really, we'd have to widen the enum base type to a minumum of 8 bits... but that'd wreak havoc on pretty much every other piece of code :\

Copy link
Member

@andrewrk andrewrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is some really nice work, and a useful abstraction as well.

This is very close to merge-ready. I'm here to help get it landed; reach out if you have any questions or want to hand it off.

}

pub const JsonDumpOptions = struct {
// TODO: indentation options?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could take inspiration from

/// The string used for indenting.
one_indent: []const u8 = " ",
/// The string used as a newline character.
newline: []const u8 = "\n",
/// The string used as spacing.
space: []const u8 = " ",

pub const JsonDumpOptions = struct {
// TODO: indentation options?
// TODO: make escaping '/' in strings optional?
// TODO: allow picking if []u8 is string or array?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it should be somehow configurable on a per-field basis. Not necessary to solve this problem for this PR though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into adding support for overriding on a per-type basis:

    pub const Override = struct {
        comptime T: type,
        comptime jsonStringify: fn (
            value: T,
            options: StringifyOptions,
            context: var,
            comptime Errors: type,
            comptime output: fn (@TypeOf(context), []const u8) Errors!void,
        ) Errors!void,
    };
    comptime overrides: []Override = &[_]Override,

However this hit a few issues:

  • The "comptime struct field missing initialization value" error codepath doesn't seem to consider default values
  • I am unable to refer to the T field from the function type declaration: "error: use of undeclared identifier 'T'"
  • I get error: use of undeclared identifier 'context' for that function type declaration

Comment on lines 1382 to 1390
// TODO: using switches here segfault the compiler (#2727?)
if ((stringToken.escapes == .None and mem.eql(u8, field.name, key_source_slice)) or (stringToken.escapes == .Some and (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)))) {
// if (switch (stringToken.escapes) {
// .None => mem.eql(u8, field.name, key_source_slice),
// .Some => (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)),
// }) {
if (fields_seen[i]) {
// switch (options.onDuplicateField) {
// .UseFirst => {},
// .Error => {},
// .UseLast => {},
// }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is so ugly, that I'm motivated to try to solve #2727

(not a merge blocker though)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

standard library This issue involves writing Zig code for the standard library.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants