Apply workaround for Zig struct re-assign miscompilation
This commit is contained in:
parent
3173dd52fe
commit
9435348877
|
@ -270,63 +270,168 @@ pub fn parse_expression(self: *Self) ParseError!Expression {
|
||||||
fn parse_factor(self: *Self) ParseError!Expression {
|
fn parse_factor(self: *Self) ParseError!Expression {
|
||||||
const allocator = self.arena.as_allocator();
|
const allocator = self.arena.as_allocator();
|
||||||
|
|
||||||
switch (self.tokenizer.token) {
|
var expression = @as(Expression, parse: {
|
||||||
.symbol_paren_left => {
|
switch (self.tokenizer.token) {
|
||||||
self.tokenizer.skip_newlines();
|
.symbol_paren_left => {
|
||||||
|
|
||||||
if (self.tokenizer.token == .end) {
|
|
||||||
return self.report("expected an expression after `(`");
|
|
||||||
}
|
|
||||||
|
|
||||||
const expression = try self.parse_expression();
|
|
||||||
|
|
||||||
if (self.tokenizer.token != .symbol_paren_right) {
|
|
||||||
return self.report("expected a closing `)` after expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
return Expression{.grouped_expression = try coral.io.allocate_one(allocator, expression)};
|
|
||||||
},
|
|
||||||
|
|
||||||
.keyword_nil => {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
return .nil_literal;
|
|
||||||
},
|
|
||||||
|
|
||||||
.keyword_true => {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
return .true_literal;
|
|
||||||
},
|
|
||||||
|
|
||||||
.keyword_false => {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
return .false_literal;
|
|
||||||
},
|
|
||||||
|
|
||||||
.number => |value| {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
return .{.number_literal = value};
|
|
||||||
},
|
|
||||||
|
|
||||||
.string => |value| {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
return .{.string_literal = value};
|
|
||||||
},
|
|
||||||
|
|
||||||
.identifier => |local_identifier| {
|
|
||||||
var expression = Expression{.get_local = local_identifier};
|
|
||||||
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
while (self.tokenizer.token == .symbol_period) {
|
|
||||||
self.tokenizer.skip_newlines();
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
if (self.tokenizer.token == .end) {
|
||||||
|
return self.report("expected an expression after `(`");
|
||||||
|
}
|
||||||
|
|
||||||
|
const expression = try self.parse_expression();
|
||||||
|
|
||||||
|
if (self.tokenizer.token != .symbol_paren_right) {
|
||||||
|
return self.report("expected a closing `)` after expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .{.grouped_expression = try coral.io.allocate_one(allocator, expression)};
|
||||||
|
},
|
||||||
|
|
||||||
|
.keyword_nil => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .nil_literal;
|
||||||
|
},
|
||||||
|
|
||||||
|
.keyword_true => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .true_literal;
|
||||||
|
},
|
||||||
|
|
||||||
|
.keyword_false => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .false_literal;
|
||||||
|
},
|
||||||
|
|
||||||
|
.number => |value| {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .{.number_literal = value};
|
||||||
|
},
|
||||||
|
|
||||||
|
.string => |value| {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .{.string_literal = value};
|
||||||
|
},
|
||||||
|
|
||||||
|
.identifier => |local_identifier| {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .{.get_local = local_identifier};
|
||||||
|
},
|
||||||
|
|
||||||
|
.symbol_brace_left => {
|
||||||
|
var table_literal = Expression.TableLiteral.make(allocator);
|
||||||
|
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
switch (self.tokenizer.token) {
|
||||||
|
.symbol_brace_right => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .{.table_literal = table_literal};
|
||||||
|
},
|
||||||
|
|
||||||
|
.symbol_bracket_left => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
if (self.tokenizer.token != .symbol_equals) {
|
||||||
|
return self.report("expected expression after identifier");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.symbol_period => {
|
||||||
|
self.tokenizer.step();
|
||||||
|
|
||||||
|
const identifier = switch (self.tokenizer.token) {
|
||||||
|
.identifier => |identifier| identifier,
|
||||||
|
else => return self.report("expected identifier after `.`"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
if (self.tokenizer.token != .symbol_equals) {
|
||||||
|
return self.report("expected `=` after key");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
if (self.tokenizer.token == .end) {
|
||||||
|
return self.report("unexpected end after `=`");
|
||||||
|
}
|
||||||
|
|
||||||
|
try table_literal.push_one(.{
|
||||||
|
.value_expression = try self.parse_expression(),
|
||||||
|
.key_expression = .{.symbol_literal = identifier},
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (self.tokenizer.token) {
|
||||||
|
.symbol_comma => self.tokenizer.skip_newlines(),
|
||||||
|
|
||||||
|
.symbol_brace_right => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break: parse .{.table_literal = table_literal};
|
||||||
|
},
|
||||||
|
|
||||||
|
else => return self.report("expected `,` or `}` after expression"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
else => return self.report("expected `}` or fields in table literal"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
.symbol_minus => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
if (self.tokenizer.token == .end) {
|
||||||
|
return self.report("expected expression after numeric negation (`-`)");
|
||||||
|
}
|
||||||
|
|
||||||
|
break: parse .{
|
||||||
|
.unary_operation = .{
|
||||||
|
.expression = try coral.io.allocate_one(allocator, try self.parse_factor()),
|
||||||
|
.operator = .numeric_negation,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
.symbol_bang => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
if (self.tokenizer.token == .end) {
|
||||||
|
return self.report("expected expression after boolean negation (`!`)");
|
||||||
|
}
|
||||||
|
|
||||||
|
break: parse .{
|
||||||
|
.unary_operation = .{
|
||||||
|
.expression = try coral.io.allocate_one(allocator, try self.parse_factor()),
|
||||||
|
.operator = .boolean_negation,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
else => return self.report("unexpected token in expression"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
switch (self.tokenizer.token) {
|
||||||
|
.symbol_period => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
// TODO: Remove when Zig fixes miscompilation with in-place struct re-assignment.
|
||||||
|
const unnecessary_temp = try coral.io.allocate_one(allocator, expression);
|
||||||
|
|
||||||
expression = .{
|
expression = .{
|
||||||
.get_field = .{
|
.get_field = .{
|
||||||
.identifier = switch (self.tokenizer.token) {
|
.identifier = switch (self.tokenizer.token) {
|
||||||
|
@ -334,112 +439,18 @@ fn parse_factor(self: *Self) ParseError!Expression {
|
||||||
else => return self.report("expected identifier after `.`"),
|
else => return self.report("expected identifier after `.`"),
|
||||||
},
|
},
|
||||||
|
|
||||||
.object_expression = try coral.io.allocate_one(allocator, expression),
|
.object_expression = unnecessary_temp,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
self.tokenizer.skip_newlines();
|
self.tokenizer.skip_newlines();
|
||||||
}
|
},
|
||||||
|
|
||||||
return expression;
|
else => break,
|
||||||
},
|
}
|
||||||
|
|
||||||
.symbol_brace_left => {
|
|
||||||
var table_literal = Expression.TableLiteral.make(allocator);
|
|
||||||
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
switch (self.tokenizer.token) {
|
|
||||||
.symbol_brace_right => {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
return .{.table_literal = table_literal};
|
|
||||||
},
|
|
||||||
|
|
||||||
.symbol_bracket_left => {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
if (self.tokenizer.token != .symbol_equals) {
|
|
||||||
return self.report("expected expression after identifier");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
.symbol_period => {
|
|
||||||
self.tokenizer.step();
|
|
||||||
|
|
||||||
const identifier = switch (self.tokenizer.token) {
|
|
||||||
.identifier => |identifier| identifier,
|
|
||||||
else => return self.report("expected identifier after `.`"),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
if (self.tokenizer.token != .symbol_equals) {
|
|
||||||
return self.report("expected `=` after key");
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
if (self.tokenizer.token == .end) {
|
|
||||||
return self.report("unexpected end after `=`");
|
|
||||||
}
|
|
||||||
|
|
||||||
try table_literal.push_one(.{
|
|
||||||
.value_expression = try self.parse_expression(),
|
|
||||||
.key_expression = .{.symbol_literal = identifier},
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (self.tokenizer.token) {
|
|
||||||
.symbol_comma => self.tokenizer.skip_newlines(),
|
|
||||||
|
|
||||||
.symbol_brace_right => {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
return .{.table_literal = table_literal};
|
|
||||||
},
|
|
||||||
|
|
||||||
else => return self.report("expected `,` or `}` after expression"),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
else => return self.report("expected `}` or fields in table literal"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
.symbol_minus => {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
if (self.tokenizer.token == .end) {
|
|
||||||
return self.report("expected expression after numeric negation (`-`)");
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.unary_operation = .{
|
|
||||||
.expression = try coral.io.allocate_one(allocator, try self.parse_factor()),
|
|
||||||
.operator = .numeric_negation,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
.symbol_bang => {
|
|
||||||
self.tokenizer.skip_newlines();
|
|
||||||
|
|
||||||
if (self.tokenizer.token == .end) {
|
|
||||||
return self.report("expected expression after boolean negation (`!`)");
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.unary_operation = .{
|
|
||||||
.expression = try coral.io.allocate_one(allocator, try self.parse_factor()),
|
|
||||||
.operator = .boolean_negation,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
else => return self.report("unexpected token in expression"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parse_term = binary_operation_parser(parse_factor, &.{
|
const parse_term = binary_operation_parser(parse_factor, &.{
|
||||||
|
|
Loading…
Reference in New Issue