#[macro_export]
macro_rules! token {
($self:expr, $token:expr) => {
crate::lexer::Token {
token_type: $token,
start_column: $self.start,
end_column: $self.line_current,
line: $self.line,
}
};
}
#[macro_export]
macro_rules! token_display {
( $match_to:expr, $f:expr, $( $name:tt),*) => {
match $match_to {
$( $name => { $f.write_str(stringify!($name))?; } ),*
_ => ()
}
}
}
#[macro_export]
macro_rules! lit {
($type:ident, $data:expr, $token:expr) => {
$crate::parser::AST {
ast_type: $crate::parser::ASTType::Lit($crate::parser::Lit::$type($data)),
start_line: $token.line,
end_line: $token.line,
start_column: $token.start_column,
end_column: $token.end_column,
}
};
}
#[macro_export]
macro_rules! ast_from_token {
($ast_type:expr, $start:expr, $end:expr) => {
AST {
ast_type: $ast_type,
start_line: $start.line,
end_line: $end.line,
start_column: $start.start_column,
end_column: $end.end_column,
}
};
}
#[macro_export]
macro_rules! ast_from_token_ast {
($ast_type:expr, $start:expr, $end:expr) => {
AST {
ast_type: $ast_type,
start_line: $start.line,
end_line: $end.end_line,
start_column: $start.start_column,
end_column: $end.end_column,
}
};
}
#[macro_export]
macro_rules! ast_from_ast {
($ast_type:expr, $start:expr, $end:expr) => {
AST {
ast_type: $ast_type,
start_line: $start.start_line,
end_line: $end.end_line,
start_column: $start.start_column,
end_column: $end.end_column,
}
};
}
#[macro_export]
macro_rules! ast_from_ast_token {
($ast_type:expr, $start:expr, $end:expr) => {
AST {
ast_type: $ast_type,
start_line: $start.start_line,
end_line: $end.line,
start_column: $start.start_column,
end_column: $end.end_column,
}
};
}
#[macro_export]
macro_rules! name {
($name:expr, $token:expr) => {
Name {
name: $name,
start_column: $token.start_column,
end_column: $token.end_column,
line: $token.line,
}
};
}
#[macro_export]
macro_rules! push_output {
( $match_to:expr, $output:expr, $( $name:tt ),*) => {
match $match_to {
$( $name => { $output += stringify!($name); } ),*
}
}
}
#[macro_export]
macro_rules! unexpected_token {
($self:expr, $message:expr, $token:expr) => {
$crate::error::KabelError::new(
$crate::error::ErrorKind::UnexpectedToken,
format!($message, $self.text[$token.line][$token.start_column..$token.end_column].to_string()),
$token.line,
$token.start_column,
$self.text[$token.line].to_string(),
)
};
}
#[macro_export]
macro_rules! out_of_scope {
($self:expr, $message:expr, $name:expr, $expr:expr) => {
$crate::error::KabelError::new(
$crate::error::ErrorKind::OutOfScope,
format!($message, $name),
$expr.start_line,
$expr.start_column,
$crate::collect_lines!($self.text[$expr.start_line..$expr.end_line+1]),
)
};
}
#[macro_export]
macro_rules! out_of_scope_var {
($self:expr, $message:expr, $name:expr, $expr:expr) => {
$crate::error::KabelError::new(
$crate::error::ErrorKind::OutOfScope,
format!($message, $name.name),
$expr.start_line,
$name.start_column,
$crate::collect_lines!($self.text[$expr.start_line..$expr.end_line+1]),
)
};
}
#[macro_export]
macro_rules! mismatched_types {
($self:expr, $message:expr, $( $args:expr ),*) => {
{
let line = $self.find_line();
$crate::runtime_error::KabelRuntimeError::new(
$crate::runtime_error::RuntimeErrorKind::MismatchedTypes,
format!($message, $( $args ),*),
line,
$self.text[line].to_string(),
)
}
};
}
#[macro_export]
macro_rules! wrong_type {
($self:expr, $message:expr) => {
{
let line = $self.find_line();
$crate::runtime_error::KabelRuntimeError::new(
$crate::runtime_error::RuntimeErrorKind::WrongType,
$message.to_string(),
line,
$self.text[line].to_string(),
)
}
};
}
#[macro_export]
macro_rules! collect_lines {
($string:expr) => {
$string.iter().fold("".to_string(), |acc, string| acc + string + "\n").trim_end().to_string()
};
}
#[macro_export]
macro_rules! codegen_binary {
($self:expr, $left:expr, $right:expr, $match_to:expr, $( $oper:tt, $code:tt ),*) => {
match $match_to {
$( $oper => {
$self.visit($right);
$self.visit($left);
$self.vm.chunk.push(OpCode::$code.into());
$self.vm.lines.last_mut().unwrap().1 += 1;
} )*
_ => { panic!("not implemented") }
}
};
}
#[macro_export]
macro_rules! vm_boolean_binary {
($self:expr, $oper:tt) => {
match ($self.stack.pop().unwrap(), $self.stack.pop().unwrap()) {
(Num(v1), Num(v2)) => $self.stack.push(Bool(v1 $oper v2)),
(Str(v1), Str(v2)) => $self.stack.push(Bool(v1 $oper v2)),
(Bool(v1), Bool(v2)) => $self.stack.push(Bool(v1 $oper v2)),
(_v1, _v2) => $self.stack.push(Bool(false)),
}
};
}