-
Notifications
You must be signed in to change notification settings - Fork 55
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
Parser: improve typeof support #27
Conversation
Curious what you think of this approach. My biggest concern is that the various There are a bunch of places in |
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.
Curious what you think of this approach.
My biggest concern is that the various
typeof_
types could be a bit of a footgun if they're not explicitly checked any time types are dealt with.There are a bunch of places in
Parser
where a type specifier is directly checked for equality; these would all need to be updated to use something likety.is(specifier)
in order to check inside the typeof types.
Those places would've needed to be updated sooner or later anyways for attributed types. That is unless we find some other, better way to represent them.
src/Parser.zig
Outdated
} | ||
const typeof_expr = try p.parseNoEval(expr); | ||
try typeof_expr.expect(p); | ||
try p.expectClosing(l_paren, .r_paren); | ||
return typeof_expr.ty; | ||
|
||
const inner = try p.arena.create(Type.VLA); |
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 would probably be appropriate to rename Type.VLA
to Type.Expr
or something.
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.
Renamed it to Type.Expr
and renamed the members to be (I think) more consistent. It's in its own commit so should be easy to revert or change if you don't like it.
try w.writeAll(")"); | ||
}, | ||
.typeof_expr, .decayed_typeof_expr => { | ||
try w.writeAll("typeof(<expr>: "); |
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.
Someday I'll go through the effort of adding a token
field to Node
and then this can be changed to pretty print the expression like clang.
91ce614
to
c375f36
Compare
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 propose adding a fn get(ty: *const Type, specifier: Specifier) ?*const Type
function to make correct usage easier.
src/Parser.zig
Outdated
@@ -1909,7 +1933,7 @@ fn initializerItem(p: *Parser, il: *InitList, init_ty: Type) Error!bool { | |||
} else @intCast(u64, val), | |||
.unavailable => unreachable, | |||
}; | |||
const max_len = if (cur_ty.specifier == .array) cur_ty.data.array.len else std.math.maxInt(usize); | |||
const max_len = if (cur_ty.is(.array)) cur_ty.data.array.len else std.math.maxInt(usize); |
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.
This will lead to invalid usage of cur_ty.data
, adding an arrayLen
would stop the repetition of this line.
src/Parser.zig
Outdated
@@ -2018,7 +2042,7 @@ fn findScalarInitializer(p: *Parser, il: **InitList, ty: *Type) Error!bool { | |||
if (try p.findScalarInitializer(il, ty)) return true; | |||
} | |||
return false; | |||
} else if (ty.specifier == .@"struct") { | |||
} else if (ty.is(.@"struct")) { |
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.
This is also invalid, the function uses the fields on ty
extensively so there should be an unwrap at the top.
src/Parser.zig
Outdated
@@ -959,7 +983,7 @@ fn initDeclarator(p: *Parser, decl_spec: *DeclSpec) Error!?InitDeclarator { | |||
|
|||
var init_list_expr = try p.initializer(init_d.d.ty); | |||
init_d.initializer = init_list_expr.node; | |||
if (init_d.d.ty.specifier == .incomplete_array) { | |||
if (init_d.d.ty.is(.incomplete_array)) { |
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.
This will lead to invalid usage of ty.data
.
src/Parser.zig
Outdated
@@ -2039,7 +2063,7 @@ fn findScalarInitializer(p: *Parser, il: **InitList, ty: *Type) Error!bool { | |||
if (try p.findScalarInitializer(il, ty)) return true; | |||
} | |||
return false; | |||
} else if (ty.specifier == .@"union") { | |||
} else if (ty.is(.@"union")) { |
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.
Also invalid.
src/Parser.zig
Outdated
@@ -2203,7 +2227,7 @@ fn convertInitList(p: *Parser, il: InitList, init_ty: Type) Error!NodeIndex { | |||
.data = .{ .bin = .{ .lhs = .none, .rhs = .none } }, | |||
}; | |||
|
|||
if (init_ty.specifier == .incomplete_array) { | |||
if (init_ty.is(.incomplete_array)) { |
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.
arr_init_node == init_ty
so the below assignments should happen on a duped type (at least if init_ty is not a meta type).
src/Parser.zig
Outdated
@@ -2226,7 +2250,7 @@ fn convertInitList(p: *Parser, il: InitList, init_ty: Type) Error!NodeIndex { | |||
}, | |||
} | |||
return try p.addNode(arr_init_node); | |||
} else if (init_ty.specifier == .@"struct") { | |||
} else if (init_ty.is(.@"struct")) { |
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.
Will also lead to invalid use.
src/Parser.zig
Outdated
@@ -2258,7 +2282,7 @@ fn convertInitList(p: *Parser, il: InitList, init_ty: Type) Error!NodeIndex { | |||
}, | |||
} | |||
return try p.addNode(struct_init_node); | |||
} else if (init_ty.specifier == .@"union") { | |||
} else if (init_ty.is(.@"union")) { |
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.
Same.
@@ -1788,7 +1812,7 @@ fn paramDecls(p: *Parser) Error!?[]Type.Func.Param { | |||
} else if (param_ty.isArray()) { | |||
// params declared as arrays are converted to pointers | |||
param_ty.decayArray(); | |||
} else if (param_ty.specifier == .void) { | |||
} else if (param_ty.is(.void)) { |
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 use of qual.any()
below is invalid.
src/Parser.zig
Outdated
if (target.is(.array)) { | ||
assert(item.ty.is(.array)); |
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 use of target.data.array.len
below should be replaced with arrayLen
and the assert should be left as is since item
is supposed to be a string literal.
Good catch, that was pretty careless on my part. I'll add the |
c375f36
to
cc18d57
Compare
Couple questions:
|
It doesn't matter for initializers as the
Not sure I understand, can you give examples? Also you seem to have accidentally commited a binary, could you rebase that away? |
cc18d57
to
7d7a8fe
Compare
Specifically thinking of line 2992 in |
Any idea why the double-free would only happen on windows? I can dig out a windows box for debugging but it would be nice if it happened on mac or linux too :) |
995 is definitely wrong, for example: void foo(void) {
const typeof(int[]) arr = {1, 2, 3};
// var: '[3]int' should be [3]const int
// name: arr
} I don't see anything wrong with 2992 though.
No idea, I wouldn't be surprised if it was a bug in Zig's std. |
I'll get my Windows machine up to date and see if I can at least bisect it to one of my commits. Will also double check the qualifiers. |
7d7a8fe
to
d2ad397
Compare
Add two new type specifiers: `typeof_type` and `typeof_expr`, which are the types returned by `typeof` (depending on whether it's called with a type or an expression) This allows us to track the underlying type or expression that was used.
Allows typeof() types to function correctly with the parser
d2ad397
to
39dfcca
Compare
39dfcca
to
8c746e5
Compare
Ok, I updated things to make the qualifiers work better now, although I'm not super happy with the I get the sense that there is something I'm missing that would simplify this; possibly in the data representation. |
Thanks! That seems like something that could be improved but it's probably not worth investigating before attributed types are implemented. |
Add two new type specifiers:
typeof_type
andtypeof_expr
, whichare the types returned by
typeof
(depending on whether it's calledwith a type or an expression)
This allows us to track the underlying type or expression that was
used.