use std::ops::Index;
use serde::{Deserialize, Serialize};
#[repr(u8)]
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Type {
Integer,
Float,
UnsignedInteger,
Boolean,
String,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Instruction<'run> {
PushInt(i64),
PushFloat(f64),
PushUnsignedInt(u64),
PushBool(bool),
PushStr(usize),
PushList(usize),
PushUnit,
Get(usize),
Pop,
Swap,
Dup,
Store {
var_name: &'run str,
},
Load {
var_name: &'run str,
},
ListLoad,
ListStore,
NewList,
ListIndex(usize),
CastTo(Type),
IAdd,
FAdd,
UIAdd,
ISub,
FSub,
UISub,
IMul,
FMul,
UIMul,
IDiv,
FDiv,
UIDiv,
IMod,
FMod,
UIMod,
Eq,
Neq,
Gt,
Gte,
Lt,
Lte,
Jmp {
pos: isize,
},
JmpZ {
pos: isize,
},
DirectCall {
pos: usize,
args: u8,
},
Call {
args: u8,
},
CallFunction {
name: &'run str,
args: u8,
},
ExternCall {
name: &'run str,
args: u8,
},
Return,
Halt,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct ImportedLibrary {
pub name: String,
pub is_std: bool,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct Program<'run> {
pub labels: Vec<Label<'run>>,
pub entry_point: String,
pub libraries: Vec<ImportedLibrary>,
pub global: ConstantPool,
}
impl<'run> Index<usize> for Program<'run> {
type Output = Instruction<'run>;
fn index(&self, index: usize) -> &Self::Output {
let mut current_index = 0;
for label in &self.labels {
if current_index + label.body.len() > index {
return &label.body[index - current_index];
}
current_index += label.body.len();
}
panic!("Index out of bounds");
}
}
impl Default for Program<'_> {
fn default() -> Self {
Self::new()
}
}
impl Program<'_> {
pub fn len(&self) -> usize {
self.labels.iter().map(|label| label.body.len()).sum()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn new() -> Self {
Self {
labels: vec![],
entry_point: String::new(),
global: ConstantPool {
string_pool: vec![],
list_pool: vec![],
function_pool: vec![],
},
libraries: vec![],
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct ConstantPool {
pub string_pool: Vec<String>,
pub list_pool: Vec<Constant>,
pub function_pool: Vec<usize>,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub enum Constant {
String(String),
List(Vec<Constant>),
Integer(i64),
Float(f64),
UnsignedInteger(u64),
Bool(bool),
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize)]
pub struct Label<'run> {
pub name: String,
pub position: usize,
pub body: Vec<Instruction<'run>>,
}