use num_bigint::BigInt;
use crate::ids::{
ConcreteLibfuncId, ConcreteTypeId, FunctionId, GenericLibfuncId, GenericTypeId, UserTypeId,
VarId,
};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Program {
pub type_declarations: Vec<TypeDeclaration>,
pub libfunc_declarations: Vec<LibfuncDeclaration>,
pub statements: Vec<Statement>,
pub funcs: Vec<Function>,
}
impl Program {
pub fn get_statement(&self, id: &StatementIdx) -> Option<&Statement> {
self.statements.get(id.0)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TypeDeclaration {
pub id: ConcreteTypeId,
pub long_id: ConcreteTypeLongId,
pub declared_type_info: Option<DeclaredTypeInfo>,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct DeclaredTypeInfo {
pub storable: bool,
pub droppable: bool,
pub duplicatable: bool,
pub zero_sized: bool,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ConcreteTypeLongId {
pub generic_id: GenericTypeId,
pub generic_args: Vec<GenericArg>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LibfuncDeclaration {
pub id: ConcreteLibfuncId,
pub long_id: ConcreteLibfuncLongId,
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ConcreteLibfuncLongId {
pub generic_id: GenericLibfuncId,
pub generic_args: Vec<GenericArg>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FunctionSignature {
pub param_types: Vec<ConcreteTypeId>,
pub ret_types: Vec<ConcreteTypeId>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct GenFunction<StatementId> {
pub id: FunctionId,
pub signature: FunctionSignature,
pub params: Vec<Param>,
pub entry_point: StatementId,
}
impl<StatementId> GenFunction<StatementId> {
pub fn new(
id: FunctionId,
params: Vec<Param>,
ret_types: Vec<ConcreteTypeId>,
entry_point: StatementId,
) -> Self {
let param_types: Vec<_> = params.iter().map(|Param { id: _, ty }| ty.clone()).collect();
GenFunction {
id,
signature: FunctionSignature { param_types, ret_types },
params,
entry_point,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Param {
pub id: VarId,
pub ty: ConcreteTypeId,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct StatementIdx(pub usize);
impl StatementIdx {
pub fn next(&self, target: &BranchTarget) -> StatementIdx {
match target {
BranchTarget::Fallthrough => StatementIdx(self.0 + 1),
BranchTarget::Statement(id) => *id,
}
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum GenericArg {
UserType(UserTypeId),
Type(ConcreteTypeId),
Value(BigInt),
UserFunc(FunctionId),
Libfunc(ConcreteLibfuncId),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum GenStatement<StatementId> {
Invocation(GenInvocation<StatementId>),
Return(Vec<VarId>),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct GenInvocation<StatementId> {
pub libfunc_id: ConcreteLibfuncId,
pub args: Vec<VarId>,
pub branches: Vec<GenBranchInfo<StatementId>>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct GenBranchInfo<StatementId> {
pub target: GenBranchTarget<StatementId>,
pub results: Vec<VarId>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum GenBranchTarget<StatementId> {
Fallthrough,
Statement(StatementId),
}
pub type Function = GenFunction<StatementIdx>;
pub type Statement = GenStatement<StatementIdx>;
pub type Invocation = GenInvocation<StatementIdx>;
pub type BranchInfo = GenBranchInfo<StatementIdx>;
pub type BranchTarget = GenBranchTarget<StatementIdx>;