use crate::argument::*;
use crate::block::*;
use crate::inst::*;
use crate::module::ModuleContext;
use crate::seq_body::*;
use crate::ty::*;
use crate::unit::*;
use crate::value::*;
pub struct Function {
id: FunctionRef,
global: bool,
name: String,
ty: Type,
args: Vec<Argument>,
body: SeqBody,
}
impl Function {
pub fn new(name: impl Into<String>, ty: Type) -> Function {
let args = {
let (arg_tys, _) = ty.as_func();
arg_tys.iter().map(|t| Argument::new(t.clone())).collect()
};
Function {
id: FunctionRef::new(ValueId::alloc()),
global: true,
name: name.into(),
ty: ty,
args: args,
body: SeqBody::new(),
}
}
pub fn as_ref(&self) -> FunctionRef {
self.id
}
pub fn name(&self) -> &str {
&self.name
}
pub fn return_ty(&self) -> &Type {
self.ty.as_func().1
}
pub fn arg(&self, idx: usize) -> ArgumentRef {
self.args[idx].as_ref()
}
pub fn args(&self) -> &[Argument] {
&self.args
}
pub fn args_mut(&mut self) -> &mut [Argument] {
&mut self.args
}
pub fn body(&self) -> &SeqBody {
&self.body
}
pub fn body_mut(&mut self) -> &mut SeqBody {
&mut self.body
}
}
impl Value for Function {
fn id(&self) -> ValueId {
self.id.into()
}
fn ty(&self) -> Type {
self.ty.clone()
}
fn name(&self) -> Option<&str> {
Some(&self.name)
}
fn is_global(&self) -> bool {
self.global
}
}
pub struct FunctionContext<'tctx> {
module: &'tctx ModuleContext<'tctx>,
function: &'tctx Function,
}
impl<'tctx> FunctionContext<'tctx> {
pub fn new(module: &'tctx ModuleContext, function: &'tctx Function) -> FunctionContext<'tctx> {
FunctionContext {
module: module,
function: function,
}
}
}
impl<'tctx> Context for FunctionContext<'tctx> {
fn parent(&self) -> Option<&Context> {
Some(self.module.as_context())
}
fn try_value(&self, value: &ValueRef) -> Option<&Value> {
match *value {
ValueRef::Inst(id) => Some(self.inst(id)),
ValueRef::Block(id) => Some(self.block(id)),
ValueRef::Argument(id) => Some(self.argument(id)),
_ => None,
}
}
}
impl<'tctx> UnitContext for FunctionContext<'tctx> {
fn inst(&self, inst: InstRef) -> &Inst {
self.function.body.inst(inst)
}
fn argument(&self, argument: ArgumentRef) -> &Argument {
self.function
.args
.iter()
.find(|x| argument == x.as_ref())
.unwrap()
}
}
impl<'tctx> SequentialContext for FunctionContext<'tctx> {
fn block(&self, block: BlockRef) -> &Block {
self.function.body.block(block)
}
}