Strength compile-time guarantees of AST operators
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
kayomn 2023-06-03 14:16:02 +00:00
parent 071d890391
commit bff3db0720
2 changed files with 56 additions and 30 deletions

View File

@ -9,6 +9,32 @@ arena: coral.arena.Stacking,
statements: StatementList,
error_message: []const u8,
pub const BinaryOperator = enum {
addition,
subtraction,
multiplication,
divsion,
equals_comparison,
greater_than_comparison,
greater_equals_comparison,
less_than_comparison,
less_equals_comparison,
fn token(self: BinaryOperator) tokens.Token {
return switch (self) {
.addition => .symbol_plus,
.subtraction => .symbol_minus,
.multiplication => .symbol_asterisk,
.divsion => .symbol_forward_slash,
.equals_comparison => .symbol_double_equals,
.greater_than_comparison => .symbol_greater_than,
.greater_equals_comparison => .symbol_greater_equals,
.less_than_comparison => .symbol_less_than,
.less_equals_comparison => .symbol_less_equals,
};
}
};
pub const Expression = union (enum) {
nil_literal,
true_literal,
@ -26,13 +52,13 @@ pub const Expression = union (enum) {
grouped_expression: *Expression,
binary_operation: struct {
operator: tokens.Token,
operator: BinaryOperator,
lhs_expression: *Expression,
rhs_expression: *Expression,
},
unary_operation: struct {
operator: tokens.Token,
operator: UnaryOperator,
expression: *Expression,
},
};
@ -48,12 +74,12 @@ pub const Statement = union (enum) {
const StatementList = coral.list.Stack(Statement);
const UnaryOperation = enum {
const UnaryOperator = enum {
boolean_negation,
numeric_negation,
};
fn binary_operation_parser(comptime parse_next: ExpressionParser, comptime operators: []const tokens.Token) ExpressionParser {
fn binary_operation_parser(comptime parse_next: ExpressionParser, comptime operators: []const BinaryOperator) ExpressionParser {
return struct {
fn parse(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!Expression {
var expression = try parse_next(self, tokenizer);
@ -62,10 +88,12 @@ fn binary_operation_parser(comptime parse_next: ExpressionParser, comptime opera
const allocator = self.arena.as_allocator();
inline for (operators) |operator| {
if (tokenizer.current_token == coral.io.tag_of(operator)) {
const token = comptime operator.token();
if (tokenizer.current_token == coral.io.tag_of(token)) {
try self.check_syntax(
tokenizer.step(.{.include_newlines = true}),
"expected right-hand side of expression after `" ++ comptime operator.text() ++ "`");
"expected right-hand side of expression after `" ++ comptime token.text() ++ "`");
expression = .{
.binary_operation = .{
@ -156,19 +184,19 @@ pub fn parse(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!void {
}
const parse_comparison = binary_operation_parser(parse_term, &.{
.symbol_greater_than,
.symbol_greater_equals,
.symbol_less_than,
.symbol_less_equals
.greater_than_comparison,
.greater_equals_comparison,
.less_than_comparison,
.less_equals_comparison
});
const parse_equality = binary_operation_parser(parse_comparison, &.{
.symbol_double_equals,
.equals_comparison,
});
const parse_expression = binary_operation_parser(parse_equality, &.{
.symbol_plus,
.symbol_minus,
.addition,
.subtraction,
});
fn parse_factor(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!Expression {
@ -305,7 +333,7 @@ fn parse_factor(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!Expr
self.arena.as_allocator(),
try self.parse_factor(tokenizer)),
.operator = .symbol_minus,
.operator = .numeric_negation,
},
};
},
@ -321,7 +349,7 @@ fn parse_factor(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!Expr
self.arena.as_allocator(),
try self.parse_factor(tokenizer)),
.operator = .symbol_bang,
.operator = .boolean_negation,
},
};
},
@ -331,8 +359,8 @@ fn parse_factor(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!Expr
}
const parse_term = binary_operation_parser(parse_factor, &.{
.symbol_asterisk,
.symbol_forward_slash,
.multiplication,
.divsion,
});
pub fn reset(self: *Self) void {

View File

@ -151,16 +151,15 @@ pub fn compile_expression(self: *Self, expression: Ast.Expression) types.Runtime
try self.compile_expression(operation.rhs_expression.*);
try self.emit_opcode(switch (operation.operator) {
.symbol_plus => .add,
.symbol_minus => .sub,
.symbol_asterisk => .mul,
.symbol_forward_slash => .div,
.symbol_double_equals => .compare_eq,
.symbol_greater_than => .compare_gt,
.symbol_greater_equals => .compare_ge,
.symbol_less_than => .compare_lt,
.symbol_less_equals => .compare_le,
else => unreachable,
.addition => .add,
.subtraction => .sub,
.multiplication => .mul,
.divsion => .div,
.greater_equals_comparison => .compare_eq,
.greater_than_comparison => .compare_gt,
.equals_comparison => .compare_ge,
.less_than_comparison => .compare_lt,
.less_equals_comparison => .compare_le,
});
},
@ -168,9 +167,8 @@ pub fn compile_expression(self: *Self, expression: Ast.Expression) types.Runtime
try self.compile_expression(operation.expression.*);
try self.emit_opcode(switch (operation.operator) {
.symbol_bang => .not,
.symbol_minus => .neg,
else => unreachable,
.boolean_negation => .not,
.numeric_negation => .neg,
});
},