Add support for binary comparison to Kym
This commit is contained in:
parent
fe8e98e753
commit
49ace97ee3
|
@ -34,6 +34,12 @@ const Opcode = enum (u8) {
|
||||||
sub,
|
sub,
|
||||||
mul,
|
mul,
|
||||||
div,
|
div,
|
||||||
|
|
||||||
|
compare_eq,
|
||||||
|
compare_gt,
|
||||||
|
compare_lt,
|
||||||
|
compare_ge,
|
||||||
|
compare_le,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
@ -144,6 +150,11 @@ pub fn compile_expression(self: *Self, expression: ast.Expression) types.Runtime
|
||||||
.subtraction => .sub,
|
.subtraction => .sub,
|
||||||
.multiplication => .mul,
|
.multiplication => .mul,
|
||||||
.division => .div,
|
.division => .div,
|
||||||
|
.equality_comparison => .compare_eq,
|
||||||
|
.greater_than_comparison => .compare_gt,
|
||||||
|
.greater_equals_comparison => .compare_ge,
|
||||||
|
.less_than_comparison => .compare_lt,
|
||||||
|
.less_equals_comparison => .compare_le,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,12 @@ pub const BinaryOperation = enum {
|
||||||
addition,
|
addition,
|
||||||
subtraction,
|
subtraction,
|
||||||
multiplication,
|
multiplication,
|
||||||
division
|
division,
|
||||||
|
equality_comparison,
|
||||||
|
greater_than_comparison,
|
||||||
|
greater_equals_comparison,
|
||||||
|
less_than_comparison,
|
||||||
|
less_equals_comparison,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ParsedExpression = union (enum) {
|
pub const ParsedExpression = union (enum) {
|
||||||
|
@ -16,11 +21,11 @@ pub const ParsedExpression = union (enum) {
|
||||||
invalid: []const u8,
|
invalid: []const u8,
|
||||||
|
|
||||||
pub fn init(allocator: coral.io.Allocator, tokenizer: *tokens.Tokenizer) coral.io.AllocationError!ParsedExpression {
|
pub fn init(allocator: coral.io.Allocator, tokenizer: *tokens.Tokenizer) coral.io.AllocationError!ParsedExpression {
|
||||||
var parsed_term_expression = try init_term(allocator, tokenizer);
|
var parsed_lhs_expression = try init_equality(allocator, tokenizer);
|
||||||
|
|
||||||
switch (parsed_term_expression) {
|
switch (parsed_lhs_expression) {
|
||||||
.valid => |*term_expression| {
|
.valid => |*lhs_expression| {
|
||||||
var expression = term_expression.*;
|
var expression = lhs_expression.*;
|
||||||
var is_invalid = true;
|
var is_invalid = true;
|
||||||
|
|
||||||
defer if (is_invalid) {
|
defer if (is_invalid) {
|
||||||
|
@ -32,12 +37,21 @@ pub const ParsedExpression = union (enum) {
|
||||||
return ParsedExpression{.invalid = "expected right-hand side of expression after `+`"};
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `+`"};
|
||||||
}
|
}
|
||||||
|
|
||||||
var parsed_binary_expression = try init_binary(allocator, tokenizer, &expression, .addition);
|
var parsed_rhs_expression = try init_equality(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.addition,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
expression = switch (parsed_binary_expression) {
|
|
||||||
.valid => |binary_expression| binary_expression,
|
|
||||||
.invalid => |details| return ParsedExpression{.invalid = details},
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenizer.current_token == .symbol_minus) {
|
if (tokenizer.current_token == .symbol_minus) {
|
||||||
|
@ -45,12 +59,21 @@ pub const ParsedExpression = union (enum) {
|
||||||
return ParsedExpression{.invalid = "expected right-hand side of expression after `-`"};
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `-`"};
|
||||||
}
|
}
|
||||||
|
|
||||||
var parsed_binary_expression = try init_binary(allocator, tokenizer, &expression, .subtraction);
|
var parsed_rhs_expression = try init_equality(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.subtraction,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
expression = switch (parsed_binary_expression) {
|
|
||||||
.valid => |binary_expression| binary_expression,
|
|
||||||
.invalid => |details| return ParsedExpression{.invalid = details},
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is_invalid = false;
|
is_invalid = false;
|
||||||
|
@ -58,41 +81,172 @@ pub const ParsedExpression = union (enum) {
|
||||||
return ParsedExpression{.valid = expression};
|
return ParsedExpression{.valid = expression};
|
||||||
},
|
},
|
||||||
|
|
||||||
.invalid => |details| {
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
return ParsedExpression{.invalid = details};
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_binary(allocator: coral.io.Allocator, tokenizer: *tokens.Tokenizer, lhs_expression: *const Expression, operation: BinaryOperation) coral.io.AllocationError!ParsedExpression {
|
pub fn init_comparison(
|
||||||
var parsed_expression = try init_term(allocator, tokenizer);
|
allocator: coral.io.Allocator,
|
||||||
|
tokenizer: *tokens.Tokenizer) coral.io.AllocationError!ParsedExpression {
|
||||||
|
|
||||||
switch (parsed_expression) {
|
var parsed_lhs_expression = try init_term(allocator, tokenizer);
|
||||||
.valid => |*expression| {
|
|
||||||
errdefer expression.deinit(allocator);
|
|
||||||
|
|
||||||
const rhs_expression = try coral.io.allocate_one(allocator, expression.*);
|
switch (parsed_lhs_expression) {
|
||||||
|
.valid => |*lhs_expression| {
|
||||||
|
var expression = lhs_expression.*;
|
||||||
|
var is_invalid = true;
|
||||||
|
|
||||||
errdefer coral.io.deallocate(allocator, rhs_expression);
|
defer if (is_invalid) {
|
||||||
|
expression.deinit(allocator);
|
||||||
return ParsedExpression{
|
|
||||||
.valid = .{
|
|
||||||
.binary_operation = .{
|
|
||||||
.kind = operation,
|
|
||||||
.lhs_expression = try coral.io.allocate_one(allocator, lhs_expression.*),
|
|
||||||
.rhs_expression = rhs_expression,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (tokenizer.current_token == .symbol_greater_than) {
|
||||||
|
if (!tokenizer.step()) {
|
||||||
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `>`"};
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsed_rhs_expression = try init_term(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.greater_than_comparison,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenizer.current_token == .symbol_greater_equals) {
|
||||||
|
if (!tokenizer.step()) {
|
||||||
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `>=`"};
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsed_rhs_expression = try init_term(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.greater_equals_comparison,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenizer.current_token == .symbol_less_than) {
|
||||||
|
if (!tokenizer.step()) {
|
||||||
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `<`"};
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsed_rhs_expression = try init_term(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.less_than_comparison,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenizer.current_token == .symbol_less_equals) {
|
||||||
|
if (!tokenizer.step()) {
|
||||||
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `<=`"};
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsed_rhs_expression = try init_term(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.less_equals_comparison,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is_invalid = false;
|
||||||
|
|
||||||
|
return ParsedExpression{.valid = expression};
|
||||||
},
|
},
|
||||||
|
|
||||||
.invalid => |details| {
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
return ParsedExpression{.invalid = details};
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_factor(allocator: coral.io.Allocator, tokenizer: *tokens.Tokenizer) coral.io.AllocationError!ParsedExpression {
|
fn init_equality(
|
||||||
|
allocator: coral.io.Allocator,
|
||||||
|
tokenizer: *tokens.Tokenizer) coral.io.AllocationError!ParsedExpression {
|
||||||
|
|
||||||
|
var parsed_lhs_expression = try init_comparison(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_lhs_expression) {
|
||||||
|
.valid => |*lhs_expression| {
|
||||||
|
var expression = lhs_expression.*;
|
||||||
|
var is_invalid = true;
|
||||||
|
|
||||||
|
defer if (is_invalid) {
|
||||||
|
expression.deinit(allocator);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tokenizer.current_token == .symbol_double_equals) {
|
||||||
|
if (!tokenizer.step()) {
|
||||||
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `==`"};
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsed_rhs_expression = try init_comparison(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.equality_comparison,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is_invalid = false;
|
||||||
|
|
||||||
|
return ParsedExpression{.valid = expression};
|
||||||
|
},
|
||||||
|
|
||||||
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_factor(
|
||||||
|
allocator: coral.io.Allocator,
|
||||||
|
tokenizer: *tokens.Tokenizer) coral.io.AllocationError!ParsedExpression {
|
||||||
|
|
||||||
switch (tokenizer.current_token) {
|
switch (tokenizer.current_token) {
|
||||||
.symbol_paren_left => {
|
.symbol_paren_left => {
|
||||||
if (!tokenizer.step()) {
|
if (!tokenizer.step()) {
|
||||||
|
@ -120,9 +274,7 @@ pub const ParsedExpression = union (enum) {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
.invalid => |details| {
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
return ParsedExpression{.invalid = details};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -180,7 +332,22 @@ pub const ParsedExpression = union (enum) {
|
||||||
return ParsedExpression{.invalid = "expected expression after numeric negation (`-`)"};
|
return ParsedExpression{.invalid = "expected expression after numeric negation (`-`)"};
|
||||||
}
|
}
|
||||||
|
|
||||||
return try init_unary(allocator, tokenizer, .numeric_negation);
|
var parsed_factor_expression = try init_factor(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_factor_expression) {
|
||||||
|
.valid => |*factor_expression| {
|
||||||
|
errdefer factor_expression.deinit(allocator);
|
||||||
|
|
||||||
|
return ParsedExpression{
|
||||||
|
.valid = try Expression.init_unary_operation(
|
||||||
|
allocator,
|
||||||
|
.numeric_negation,
|
||||||
|
factor_expression),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.symbol_bang => {
|
.symbol_bang => {
|
||||||
|
@ -188,19 +355,34 @@ pub const ParsedExpression = union (enum) {
|
||||||
return ParsedExpression{.invalid = "expected expression after boolean negation (`!`)"};
|
return ParsedExpression{.invalid = "expected expression after boolean negation (`!`)"};
|
||||||
}
|
}
|
||||||
|
|
||||||
return try init_unary(allocator, tokenizer, .boolean_negation);
|
var parsed_factor_expression = try init_factor(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_factor_expression) {
|
||||||
|
.valid => |*factor_expression| {
|
||||||
|
errdefer factor_expression.deinit(allocator);
|
||||||
|
|
||||||
|
return ParsedExpression{
|
||||||
|
.valid = try Expression.init_unary_operation(
|
||||||
|
allocator,
|
||||||
|
.boolean_negation,
|
||||||
|
factor_expression),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
else => return ParsedExpression{.invalid = "unexpected token in expression"},
|
else => return ParsedExpression{.invalid = "unexpected token in expression"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_term(allocator: coral.io.Allocator, tokenizer: *tokens.Tokenizer) coral.io.AllocationError!ParsedExpression {
|
pub fn init_term(allocator: coral.io.Allocator, tokenizer: *tokens.Tokenizer) coral.io.AllocationError!ParsedExpression {
|
||||||
var parsed_factor_expression = try init_factor(allocator, tokenizer);
|
var parsed_lhs_expression = try init_factor(allocator, tokenizer);
|
||||||
|
|
||||||
switch (parsed_factor_expression) {
|
switch (parsed_lhs_expression) {
|
||||||
.valid => |*factor_expression| {
|
.valid => |*lhs_expression| {
|
||||||
var expression = factor_expression.*;
|
var expression = lhs_expression.*;
|
||||||
var is_invalid = true;
|
var is_invalid = true;
|
||||||
|
|
||||||
defer if (is_invalid) {
|
defer if (is_invalid) {
|
||||||
|
@ -212,12 +394,21 @@ pub const ParsedExpression = union (enum) {
|
||||||
return ParsedExpression{.invalid = "expected right-hand side of expression after `*`"};
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `*`"};
|
||||||
}
|
}
|
||||||
|
|
||||||
var parsed_binary_expression = try init_binary(allocator, tokenizer, &expression, .multiplication);
|
var parsed_rhs_expression = try init_factor(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.multiplication,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
expression = switch (parsed_binary_expression) {
|
|
||||||
.valid => |binary_expression| binary_expression,
|
|
||||||
.invalid => |details| return ParsedExpression{.invalid = details},
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenizer.current_token == .symbol_forward_slash) {
|
if (tokenizer.current_token == .symbol_forward_slash) {
|
||||||
|
@ -225,12 +416,21 @@ pub const ParsedExpression = union (enum) {
|
||||||
return ParsedExpression{.invalid = "expected right-hand side of expression after `/`"};
|
return ParsedExpression{.invalid = "expected right-hand side of expression after `/`"};
|
||||||
}
|
}
|
||||||
|
|
||||||
var parsed_binary_expression = try init_binary(allocator, tokenizer, &expression, .division);
|
var parsed_rhs_expression = try init_equality(allocator, tokenizer);
|
||||||
|
|
||||||
|
switch (parsed_rhs_expression) {
|
||||||
|
.valid => |*rhs_expression| {
|
||||||
|
errdefer rhs_expression.deinit(allocator);
|
||||||
|
|
||||||
|
expression = try Expression.init_binary_operation(
|
||||||
|
allocator,
|
||||||
|
.division,
|
||||||
|
lhs_expression,
|
||||||
|
rhs_expression);
|
||||||
|
},
|
||||||
|
|
||||||
expression = switch (parsed_binary_expression) {
|
|
||||||
.valid => |binary_expression| binary_expression,
|
|
||||||
.invalid => |details| return ParsedExpression{.invalid = details},
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is_invalid = false;
|
is_invalid = false;
|
||||||
|
@ -238,32 +438,7 @@ pub const ParsedExpression = union (enum) {
|
||||||
return ParsedExpression{.valid = expression};
|
return ParsedExpression{.valid = expression};
|
||||||
},
|
},
|
||||||
|
|
||||||
.invalid => |details| {
|
.invalid => |details| return ParsedExpression{.invalid = details},
|
||||||
return ParsedExpression{.invalid = details};
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init_unary(allocator: coral.io.Allocator, tokenizer: *tokens.Tokenizer, operation: UnaryOperation) coral.io.AllocationError!ParsedExpression {
|
|
||||||
var parsed_factor_expression = try init_factor(allocator, tokenizer);
|
|
||||||
|
|
||||||
switch (parsed_factor_expression) {
|
|
||||||
.valid => |*factor_expression| {
|
|
||||||
errdefer factor_expression.deinit(allocator);
|
|
||||||
|
|
||||||
return ParsedExpression{
|
|
||||||
.valid = .{
|
|
||||||
.unary_operation = .{
|
|
||||||
.kind = operation,
|
|
||||||
.expression = try coral.io.allocate_one(allocator, factor_expression.*),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
.invalid => |details| {
|
|
||||||
return ParsedExpression{.invalid = details};
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -393,6 +568,46 @@ pub const Expression = union (enum) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_binary_operation(
|
||||||
|
allocator: coral.io.Allocator,
|
||||||
|
kind: BinaryOperation,
|
||||||
|
lhs_expression: *const Expression,
|
||||||
|
rhs_operation: *const Expression) coral.io.AllocationError!Expression {
|
||||||
|
|
||||||
|
const allocated_lhs_expression = try coral.io.allocate_one(allocator, lhs_expression.*);
|
||||||
|
|
||||||
|
errdefer coral.io.deallocate(allocator, allocated_lhs_expression);
|
||||||
|
|
||||||
|
const allocated_rhs_expression = try coral.io.allocate_one(allocator, rhs_operation.*);
|
||||||
|
|
||||||
|
errdefer coral.io.deallocate(allocator, allocated_rhs_expression);
|
||||||
|
|
||||||
|
return Expression{
|
||||||
|
.binary_operation = .{
|
||||||
|
.kind = kind,
|
||||||
|
.lhs_expression = allocated_lhs_expression,
|
||||||
|
.rhs_expression = allocated_rhs_expression,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_unary_operation(
|
||||||
|
allocator: coral.io.Allocator,
|
||||||
|
kind: UnaryOperation,
|
||||||
|
expression: *const Expression) coral.io.AllocationError!Expression {
|
||||||
|
|
||||||
|
const allocated_expression = try coral.io.allocate_one(allocator, expression.*);
|
||||||
|
|
||||||
|
errdefer coral.io.deallocate(allocator, allocated_expression);
|
||||||
|
|
||||||
|
return Expression{
|
||||||
|
.unary_operation = .{
|
||||||
|
.kind = kind,
|
||||||
|
.expression = allocated_expression,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Statements = struct {
|
pub const Statements = struct {
|
||||||
|
|
|
@ -22,7 +22,13 @@ pub const Token = union(enum) {
|
||||||
symbol_bracket_left,
|
symbol_bracket_left,
|
||||||
symbol_bracket_right,
|
symbol_bracket_right,
|
||||||
symbol_period,
|
symbol_period,
|
||||||
symbol_arrow,
|
symbol_lambda,
|
||||||
|
symbol_less_than,
|
||||||
|
symbol_less_equals,
|
||||||
|
symbol_greater_than,
|
||||||
|
symbol_greater_equals,
|
||||||
|
symbol_equals,
|
||||||
|
symbol_double_equals,
|
||||||
|
|
||||||
integer: []const u8,
|
integer: []const u8,
|
||||||
real: []const u8,
|
real: []const u8,
|
||||||
|
@ -311,9 +317,60 @@ pub const Tokenizer = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
'=' => {
|
'=' => {
|
||||||
self.current_token = .symbol_assign;
|
|
||||||
cursor += 1;
|
cursor += 1;
|
||||||
|
|
||||||
|
if (self.has_next()) {
|
||||||
|
switch (self.source[cursor]) {
|
||||||
|
'=' => {
|
||||||
|
cursor += 1;
|
||||||
|
self.current_token = .symbol_double_equals;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
'>' => {
|
||||||
|
cursor += 1;
|
||||||
|
self.current_token = .symbol_lambda;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_token = .symbol_equals;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
'<' => {
|
||||||
|
cursor += 1;
|
||||||
|
|
||||||
|
if (self.has_next() and (self.source[cursor] == '=')) {
|
||||||
|
cursor += 1;
|
||||||
|
self.current_token = .symbol_less_equals;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_token = .symbol_less_than;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
'>' => {
|
||||||
|
cursor += 1;
|
||||||
|
|
||||||
|
if (self.has_next() and (self.source[cursor] == '=')) {
|
||||||
|
cursor += 1;
|
||||||
|
self.current_token = .symbol_greater_equals;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_token = .symbol_greater_than;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -38,38 +38,6 @@ pub const RuntimeError = coral.io.AllocationError || CheckError || error {
|
||||||
BadSyntax,
|
BadSyntax,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn SmallStack(comptime Element: type, comptime default: Element) type {
|
|
||||||
const maximum = 255;
|
|
||||||
|
|
||||||
return struct {
|
|
||||||
buffer: [maximum]Element = [_]Element{default} ** maximum,
|
|
||||||
count: u8 = 0,
|
|
||||||
|
|
||||||
const Self = @This();
|
|
||||||
|
|
||||||
fn peek(self: Self) ?Element {
|
|
||||||
if (self.count == 0) return null;
|
|
||||||
|
|
||||||
return self.buffer[self.count - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pop(self: *Self) ?Element {
|
|
||||||
if (self.count == 0) return null;
|
|
||||||
|
|
||||||
self.count -= 1;
|
|
||||||
|
|
||||||
return self.buffer[self.count];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push(self: *Self, element: Element) !void {
|
|
||||||
if (self.count == maximum) return error.OutOfMemory;
|
|
||||||
|
|
||||||
self.buffer[self.count] = element;
|
|
||||||
self.count += 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const Val = union (Primitive) {
|
pub const Val = union (Primitive) {
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
|
|
Loading…
Reference in New Issue