-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Stage2: more optionals stuff #6060
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
andrewrk
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, this is substantial progress :)
src-self-hosted/astgen.zig
Outdated
|
|
||
| fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { | ||
| const tree = scope.tree(); | ||
| const src = tree.token_locs[node.op_token].start; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused tree and src
| node.ptr_info.sentinel == null; | ||
|
|
||
| if (simple) { | ||
| const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this line and 494 can be moved up to above this branch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was planning on putting 494 after all the other attributes so that they would get analyzed in the order that they appear in the source but I couldn't figure how to pass child_type to the sentinel cast result loc. If the order is not important then I'll just move it before the shortcut.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh that makes sense. Never mind my review comment then!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would still depend on being able to refer to the child type before the sentinel which doesn't seem possible but all the other attributes before the child type would still be an improvement.
| node.ptr_info.volatile_token == null and | ||
| node.ptr_info.sentinel == null; | ||
|
|
||
| if (simple) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like how you did this 👍
| return @fieldParentPtr(T, "base", self.ptr_otherwise); | ||
| } | ||
|
|
||
| pub fn castPointer(self: Type) ?*Payload.Pointer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like Type.zig and Value.zig might benefit from being reworked into following the pattern set by std.zig.ast, ZIR, and IR with the castTag function (and the preference to use that function rather than the one that accepts the type parameter). This pattern has been working nicely elsewhere to make multiple tags map to the same payload type.
src-self-hosted/zir_sema.zig
Outdated
| try mod.singleConstPtrType(scope, unwrap.base.src, child_type) | ||
| else | ||
| try mod.singleMutPtrType(scope, unwrap.base.src, child_type); | ||
| var buf: Type.Payload.Pointer = undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like a reference to buf is escaping this function.
I think this would be fixed simply by allocating buf with scope.arena(). Possibly as an optimization, Type.zig could have another function for accepting an allocator that would only allocate buf if it needed to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The resulting child type is immediately copied but an optionalChildAlloc would be more explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh! I see the copy. This actually is a really nice API. I like what you did here 👍
src-self-hosted/Module.zig
Outdated
| return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val }); | ||
| } | ||
|
|
||
| // TODO how do we get the result location |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you need a pointer to write through, you would emit an alloc instruction. However, for cases where it could be treated as a value (such as here) I think what you have here is better. Since the zig language does not guarantee a memory layout for optionals, that means codegen.zig is allowed to represent the optional value in any way it chooses to. For some combinations of architectures and payload types, this may mean that it uses a single register to represent both the optional bit and the payload. I think it makes sense to make Module.zig / zir_sema.zig not have to care about such details.
src-self-hosted/codegen.zig
Outdated
| } | ||
|
|
||
| fn genTypedValue(self: *Self, src: usize, typed_value: TypedValue) !MCValue { | ||
| fn genTypedValue(self: *Self, src: usize, typed_value: TypedValue) error{ CodegenFail, OutOfMemory }!MCValue { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| fn genTypedValue(self: *Self, src: usize, typed_value: TypedValue) error{ CodegenFail, OutOfMemory }!MCValue { | |
| fn genTypedValue(self: *Self, src: usize, typed_value: TypedValue) InnerError!MCValue { |
src-self-hosted/astgen.zig
Outdated
| if (cond_kind != .optional) { | ||
| return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{}); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The presence of a payload capture here would make this an error union if (same deal with while below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that documented anywhere? I think it might be better to require the explicit |_| since that already seems to be more common.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm maybe I'm misunderstanding what the code is doing here. I'm thinking about this:
https://ziglang.org/documentation/master/#while-with-Error-Unions
When the else |x| syntax is present on a while expression, the while condition must have an Error Union Type.
What would be example zig code that would trigger this "else payload invalid on bool conditions" compile error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (errUnion) {} else |err| {} // else payload invalid on bool conditions
if (errUnion) |_| {} else |err| {} // explicitly ignoring the payloadLooking at the stdlib and tests explicitly ignoring the payload seems more common but that might be just people (like me) not realizing that it isn't necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh now I see. Hmm. Here's my proposal:
if (errUnion) {} else |err| {} on E!T where T is void should be allowed, but if T is not void then it should be "error: expression value is ignored" same as if you called a non-void function and didn't capture or discard the return value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me!
src-self-hosted/astgen.zig
Outdated
| const payload = payload_node.?.castTag(.PointerPayload).?; | ||
| const is_ptr = payload.ptr_token != null; | ||
| const ident_node = payload.value_symbol.castTag(.Identifier).?; | ||
| const ident_name = try identifierTokenString(mod, &then_scope.base, ident_node.token); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elsewhere in stage2 we've treated _ as the "discard" identifier, but @"_" as a normal identifier. Personally I could be persuaded to do it either way, but it should probably be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realize this was a thing. Should we try to somehow also apply it to primitive types to fix #1802?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a neat idea! Let's do a separate proposal for that, but I think it might be a good solution to the "sometimes we want to use names that collide with primitive types" problem.
andrewrk
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is just pending tests passing now
No description provided.