use std::fmt::Debug;
use crate::context::Context;
use crate::error::{ErrKind, Error};
use crate::generics::GenericUser;
use crate::instance::ObjectInstance;
use crate::location::SpanTuple;
use crate::typechecker::TypeCheck;
use colored::Colorize;
use downcast_rs::{impl_downcast, Downcast};
mod binary_op;
mod block;
mod dec_arg;
mod field_access;
mod function_call;
mod function_declaration;
mod if_else;
mod incl;
mod jk_inst;
mod jk_return;
mod loop_block;
mod method_call;
mod operator;
mod rename;
mod type_declaration;
mod type_instantiation;
mod var;
mod var_assignment;
mod var_or_empty_type;
pub use binary_op::BinaryOp;
pub use block::Block;
pub use dec_arg::DecArg;
pub use field_access::FieldAccess;
pub use function_call::FunctionCall;
pub use function_declaration::{FunctionDec, FunctionKind};
pub use if_else::IfElse;
pub use incl::Incl;
pub use jk_inst::{JkInst, JkInstKind};
pub use jk_return::Return;
pub use loop_block::{Loop, LoopKind};
pub use method_call::MethodCall;
pub use operator::Operator;
pub use type_declaration::TypeDec;
pub use type_instantiation::TypeInstantiation;
pub use var::Var;
pub use var_assignment::VarAssign;
pub use var_or_empty_type::VarOrEmptyType;
#[derive(Debug, PartialEq, Clone)]
pub enum InstrKind {
Statement,
Expression(Option<ObjectInstance>),
}
pub trait Instruction: InstructionClone + Downcast + TypeCheck + GenericUser {
fn execute(&self, _ctx: &mut Context) -> Option<ObjectInstance> {
unreachable!(
"\n{}\n --> {}",
self.print(),
"The execution of this instruction is not implemented yet. This is a bug".red(),
)
}
fn execute_expression(&self, ctx: &mut Context) -> Option<ObjectInstance> {
let instance = self.execute(ctx);
match instance {
Some(obj) => Some(obj),
None => {
ctx.error(Error::new(ErrKind::Context).with_msg(format!(
"statement found when expression was expected: {}",
self.print()
)));
None
}
}
}
fn execute_statement(&self, ctx: &mut Context) -> Result<(), Error> {
let instance = self.execute(ctx);
match instance {
None => Ok(()),
Some(_) => {
let e = Error::new(ErrKind::Context).with_msg(format!(
"expression found when statement was expected: {}",
self.print()
));
ctx.error(e.clone());
Err(e)
}
}
}
fn kind(&self) -> InstrKind;
fn print(&self) -> String;
fn location(&self) -> Option<&SpanTuple> {
None
}
}
impl_downcast!(Instruction);
impl Debug for dyn Instruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.print())
}
}
pub trait InstructionClone {
fn box_clone(&self) -> Box<dyn Instruction>;
}
impl<T> InstructionClone for T
where
T: 'static + Instruction + Clone,
{
fn box_clone(&self) -> Box<dyn Instruction> {
Box::new(self.clone())
}
}
impl Clone for Box<dyn Instruction> {
fn clone(&self) -> Self {
self.box_clone()
}
}