Strength compile-time guarantees of AST operators
This commit is contained in:
parent
071d890391
commit
bff3db0720
|
@ -9,6 +9,32 @@ arena: coral.arena.Stacking,
|
||||||
statements: StatementList,
|
statements: StatementList,
|
||||||
error_message: []const u8,
|
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) {
|
pub const Expression = union (enum) {
|
||||||
nil_literal,
|
nil_literal,
|
||||||
true_literal,
|
true_literal,
|
||||||
|
@ -26,13 +52,13 @@ pub const Expression = union (enum) {
|
||||||
grouped_expression: *Expression,
|
grouped_expression: *Expression,
|
||||||
|
|
||||||
binary_operation: struct {
|
binary_operation: struct {
|
||||||
operator: tokens.Token,
|
operator: BinaryOperator,
|
||||||
lhs_expression: *Expression,
|
lhs_expression: *Expression,
|
||||||
rhs_expression: *Expression,
|
rhs_expression: *Expression,
|
||||||
},
|
},
|
||||||
|
|
||||||
unary_operation: struct {
|
unary_operation: struct {
|
||||||
operator: tokens.Token,
|
operator: UnaryOperator,
|
||||||
expression: *Expression,
|
expression: *Expression,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -48,12 +74,12 @@ pub const Statement = union (enum) {
|
||||||
|
|
||||||
const StatementList = coral.list.Stack(Statement);
|
const StatementList = coral.list.Stack(Statement);
|
||||||
|
|
||||||
const UnaryOperation = enum {
|
const UnaryOperator = enum {
|
||||||
boolean_negation,
|
boolean_negation,
|
||||||
numeric_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 {
|
return struct {
|
||||||
fn parse(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!Expression {
|
fn parse(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!Expression {
|
||||||
var expression = try parse_next(self, tokenizer);
|
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();
|
const allocator = self.arena.as_allocator();
|
||||||
|
|
||||||
inline for (operators) |operator| {
|
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(
|
try self.check_syntax(
|
||||||
tokenizer.step(.{.include_newlines = true}),
|
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 = .{
|
expression = .{
|
||||||
.binary_operation = .{
|
.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, &.{
|
const parse_comparison = binary_operation_parser(parse_term, &.{
|
||||||
.symbol_greater_than,
|
.greater_than_comparison,
|
||||||
.symbol_greater_equals,
|
.greater_equals_comparison,
|
||||||
.symbol_less_than,
|
.less_than_comparison,
|
||||||
.symbol_less_equals
|
.less_equals_comparison
|
||||||
});
|
});
|
||||||
|
|
||||||
const parse_equality = binary_operation_parser(parse_comparison, &.{
|
const parse_equality = binary_operation_parser(parse_comparison, &.{
|
||||||
.symbol_double_equals,
|
.equals_comparison,
|
||||||
});
|
});
|
||||||
|
|
||||||
const parse_expression = binary_operation_parser(parse_equality, &.{
|
const parse_expression = binary_operation_parser(parse_equality, &.{
|
||||||
.symbol_plus,
|
.addition,
|
||||||
.symbol_minus,
|
.subtraction,
|
||||||
});
|
});
|
||||||
|
|
||||||
fn parse_factor(self: *Self, tokenizer: *tokens.Tokenizer) types.ParseError!Expression {
|
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(),
|
self.arena.as_allocator(),
|
||||||
try self.parse_factor(tokenizer)),
|
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(),
|
self.arena.as_allocator(),
|
||||||
try self.parse_factor(tokenizer)),
|
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, &.{
|
const parse_term = binary_operation_parser(parse_factor, &.{
|
||||||
.symbol_asterisk,
|
.multiplication,
|
||||||
.symbol_forward_slash,
|
.divsion,
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn reset(self: *Self) void {
|
pub fn reset(self: *Self) void {
|
||||||
|
|
|
@ -151,16 +151,15 @@ pub fn compile_expression(self: *Self, expression: Ast.Expression) types.Runtime
|
||||||
try self.compile_expression(operation.rhs_expression.*);
|
try self.compile_expression(operation.rhs_expression.*);
|
||||||
|
|
||||||
try self.emit_opcode(switch (operation.operator) {
|
try self.emit_opcode(switch (operation.operator) {
|
||||||
.symbol_plus => .add,
|
.addition => .add,
|
||||||
.symbol_minus => .sub,
|
.subtraction => .sub,
|
||||||
.symbol_asterisk => .mul,
|
.multiplication => .mul,
|
||||||
.symbol_forward_slash => .div,
|
.divsion => .div,
|
||||||
.symbol_double_equals => .compare_eq,
|
.greater_equals_comparison => .compare_eq,
|
||||||
.symbol_greater_than => .compare_gt,
|
.greater_than_comparison => .compare_gt,
|
||||||
.symbol_greater_equals => .compare_ge,
|
.equals_comparison => .compare_ge,
|
||||||
.symbol_less_than => .compare_lt,
|
.less_than_comparison => .compare_lt,
|
||||||
.symbol_less_equals => .compare_le,
|
.less_equals_comparison => .compare_le,
|
||||||
else => unreachable,
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -168,9 +167,8 @@ pub fn compile_expression(self: *Self, expression: Ast.Expression) types.Runtime
|
||||||
try self.compile_expression(operation.expression.*);
|
try self.compile_expression(operation.expression.*);
|
||||||
|
|
||||||
try self.emit_opcode(switch (operation.operator) {
|
try self.emit_opcode(switch (operation.operator) {
|
||||||
.symbol_bang => .not,
|
.boolean_negation => .not,
|
||||||
.symbol_minus => .neg,
|
.numeric_negation => .neg,
|
||||||
else => unreachable,
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue