use crate::frontend::Parser;
use crate::frontend::ParserDispatch;
use crate::frontend::TokenKind;
use crate::ir::Attribute;
use crate::ir::Block;
use crate::ir::BlockName;
use crate::ir::Op;
use crate::ir::OpOperand;
use crate::ir::OpOperands;
use crate::ir::Operation;
use crate::ir::Type;
use crate::ir::TypeConvert;
use crate::ir::Types;
use crate::ir::VariableRenamer;
use crate::shared::Shared;
use crate::shared::SharedExt;
use anyhow::Result;
use std::fmt::Display;
use std::sync::Arc;
pub enum BlockArgumentName {
Anonymous,
Name(String),
Unset,
}
pub struct BlockArgument {
pub name: BlockArgumentName,
typ: Shared<dyn Type>,
parent: Option<Shared<Block>>,
}
impl BlockArgument {
pub fn new(name: BlockArgumentName, typ: Shared<dyn Type>) -> Self {
BlockArgument {
name,
typ,
parent: None,
}
}
pub fn parent(&self) -> Option<Shared<Block>> {
self.parent.clone()
}
pub fn set_parent(&mut self, parent: Option<Shared<Block>>) {
self.parent = parent;
}
pub fn set_typ(&mut self, typ: Shared<dyn Type>) {
self.typ = typ;
}
pub fn typ(&self) -> Shared<dyn Type> {
self.typ.clone()
}
}
impl Display for BlockArgument {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let typ = self.typ.rd();
match &self.name {
BlockArgumentName::Anonymous => write!(f, "{typ}"),
BlockArgumentName::Name(name) => {
write!(f, "{name} : {typ}")
}
BlockArgumentName::Unset => {
write!(f, "<UNSET NAME> : {typ}")
}
}
}
}
pub struct BlockLabel {
name: String,
}
impl BlockLabel {
pub fn new(name: String) -> Self {
BlockLabel { name }
}
pub fn name(&self) -> String {
self.name.clone()
}
pub fn set_name(&mut self, name: String) {
self.name = name;
}
}
impl Display for BlockLabel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}
pub struct BlockPtr {
block: Shared<Block>,
}
impl BlockPtr {
pub fn new(block: Shared<Block>) -> Self {
BlockPtr { block }
}
pub fn block(&self) -> Shared<Block> {
self.block.clone()
}
}
impl Display for BlockPtr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "^{}", self.block.rd())
}
}
pub struct Constant {
value: Arc<dyn Attribute>,
}
impl Constant {
pub fn new(value: Arc<dyn Attribute>) -> Self {
Constant { value }
}
pub fn typ(&self) -> Shared<dyn Type> {
self.value.typ()
}
pub fn value(&self) -> Arc<dyn Attribute> {
self.value.clone()
}
}
impl Display for Constant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.value)
}
}
#[derive(Default)]
pub struct OpResult {
name: Option<String>,
typ: Option<Shared<dyn Type>>,
defining_op: Option<Shared<dyn Op>>,
}
impl OpResult {
pub fn new(
name: Option<String>,
typ: Option<Shared<dyn Type>>,
defining_op: Option<Shared<dyn Op>>,
) -> Self {
OpResult {
name,
typ,
defining_op,
}
}
pub fn name(&self) -> Option<String> {
self.name.clone()
}
pub fn typ(&self) -> Option<Shared<dyn Type>> {
self.typ.clone()
}
pub fn defining_op(&self) -> Option<Shared<dyn Op>> {
self.defining_op.clone()
}
pub fn set_name(&mut self, name: &str) {
self.name = Some(name.to_string());
}
pub fn set_typ(&mut self, typ: Shared<dyn Type>) {
self.typ = Some(typ);
}
pub fn set_defining_op(&mut self, op: Option<Shared<dyn Op>>) {
self.defining_op = op;
}
}
impl Display for OpResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name.clone().unwrap())
}
}
#[must_use = "the object should be further initialized, see the setter methods"]
pub struct UnsetOpResult {
result: Shared<Value>,
}
impl UnsetOpResult {
pub fn new(result: Shared<Value>) -> Self {
assert!(
matches!(&*result.rd(), Value::OpResult(_)),
"Expected OpResult"
);
UnsetOpResult { result }
}
pub fn set_defining_op(&self, op: Option<Shared<dyn Op>>) {
self.result.wr().set_defining_op(op);
}
pub fn set_typ(&self, typ: Shared<dyn Type>) {
self.result.wr().set_type(typ);
}
}
#[must_use = "the object should be further initialized, see the setter methods"]
pub struct UnsetOpResults {
results: Values,
}
impl UnsetOpResults {
pub fn new(results: Values) -> Self {
UnsetOpResults { results }
}
pub fn values(&self) -> Values {
self.results.clone()
}
pub fn set_defining_op(&self, op: Shared<dyn Op>) {
let values = self.values();
values.set_defining_op(op);
}
pub fn set_types(&self, types: Vec<Shared<dyn Type>>) {
let results = self.values().into_iter();
assert!(types.len() == results.len());
for (result, typ) in results.zip(types) {
result.wr().set_type(typ);
}
}
}
pub enum Users {
HasNoOpResults,
OpOperands(Vec<Shared<OpOperand>>),
}
impl Users {
pub fn len(&self) -> usize {
match self {
Users::HasNoOpResults => 0,
Users::OpOperands(users) => users.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub struct Variadic;
impl Display for Variadic {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "...")
}
}
pub enum Value {
BlockArgument(BlockArgument),
BlockLabel(BlockLabel),
BlockPtr(BlockPtr),
Constant(Constant),
FuncResult(Shared<dyn Type>),
OpResult(OpResult),
Variadic,
}
impl Value {
pub fn name(&self) -> Option<String> {
match self {
Value::BlockArgument(arg) => match &arg.name {
BlockArgumentName::Anonymous => None,
BlockArgumentName::Name(name) => Some(name.clone()),
BlockArgumentName::Unset => None,
},
Value::BlockLabel(label) => Some(label.name.clone()),
Value::BlockPtr(ptr) => match &ptr.block().rd().label {
BlockName::Name(name) => Some(name.clone()),
BlockName::Unnamed => None,
BlockName::Unset => None,
},
Value::Constant(_) => None,
Value::FuncResult(_) => None,
Value::OpResult(result) => result.name().clone(),
Value::Variadic => None,
}
}
pub fn typ(&self) -> Result<Shared<dyn Type>> {
match self {
Value::BlockArgument(arg) => Ok(arg.typ.clone()),
Value::BlockLabel(_) => panic!("BlockLabel has no type"),
Value::BlockPtr(_) => panic!("BlockPtr has no type"),
Value::Constant(constant) => Ok(constant.typ()),
Value::FuncResult(result) => Ok(result.clone()),
Value::OpResult(result) => match result.typ() {
Some(typ) => Ok(typ),
None => Err(anyhow::anyhow!("Type was not set for OpResult {}", self)),
},
Value::Variadic => panic!("Variadic has no type"),
}
}
pub fn set_type(&mut self, typ: Shared<dyn Type>) {
match self {
Value::BlockArgument(arg) => arg.set_typ(typ),
Value::BlockLabel(_) => todo!(),
Value::BlockPtr(_) => todo!(),
Value::Constant(_) => todo!(),
Value::FuncResult(result) => *result = typ,
Value::OpResult(result) => result.set_typ(typ),
Value::Variadic => todo!(),
}
}
pub fn set_defining_op(&mut self, op: Option<Shared<dyn Op>>) {
match self {
Value::BlockArgument(_) => panic!("Cannot set defining op for BlockArgument"),
Value::BlockLabel(_) => todo!("Cannot set defining op for BlockLabel"),
Value::BlockPtr(_) => todo!("Cannot set defining op for BlockPtr"),
Value::Constant(_) => panic!("Cannot set defining op for Constant"),
Value::FuncResult(_) => panic!("It is not necessary to set this defining op"),
Value::OpResult(op_res) => op_res.set_defining_op(op),
Value::Variadic => panic!("Cannot set defining op for Variadic"),
}
}
pub fn set_parent(&mut self, parent: Option<Shared<Block>>) {
match self {
Value::BlockArgument(arg) => arg.set_parent(parent),
Value::BlockLabel(_) => todo!(),
Value::BlockPtr(_) => todo!(),
Value::Constant(_) => todo!(),
Value::FuncResult(_) => todo!(),
Value::OpResult(_) => todo!(),
Value::Variadic => todo!(),
}
}
pub fn set_name(&mut self, name: &str) {
match self {
Value::BlockArgument(arg) => {
arg.name = BlockArgumentName::Name(name.to_string());
}
Value::BlockLabel(label) => label.set_name(name.to_string()),
Value::BlockPtr(_) => todo!(),
Value::Constant(_) => panic!("Cannot set name for Constant"),
Value::FuncResult(_) => panic!("It is not necessary to set this name"),
Value::OpResult(result) => result.set_name(name),
Value::Variadic => panic!("Cannot set name for Variadic"),
}
}
pub fn from_block(block: Shared<Block>) -> Self {
let ptr = BlockPtr::new(block);
Value::BlockPtr(ptr)
}
fn find_users(&self, ops: &[Shared<dyn Op>]) -> Vec<Shared<OpOperand>> {
let mut out = Vec::new();
for op in ops.iter() {
for operand in op.rd().operation().rd().operands().into_iter() {
let value = operand.rd().value();
if std::ptr::eq(&*value.rd() as *const Value, self as *const Value) {
out.push(operand.clone());
}
}
}
out
}
fn block_arg_users(&self, arg: &BlockArgument) -> Vec<Shared<OpOperand>> {
let parent = arg.parent();
let parent = if let Some(parent) = parent {
parent
} else {
panic!("BlockArgument {arg} has no parent operation");
};
let mut ops = parent.rd().ops.clone();
for successor in parent.rd().successors().unwrap().iter() {
ops.extend(successor.rd().ops.clone());
}
self.find_users(&ops)
}
fn op_result_users(&self, op_res: &OpResult) -> Vec<Shared<OpOperand>> {
let op = op_res.defining_op();
let op = if op_res.defining_op().is_some() {
op.unwrap()
} else {
panic!("Defining op not set for OpResult {op_res}");
};
let ops = op.rd().operation().rd().successors();
self.find_users(&ops)
}
pub fn users(&self) -> Users {
match self {
Value::BlockArgument(arg) => Users::OpOperands(self.block_arg_users(arg)),
Value::BlockLabel(_) => todo!(),
Value::BlockPtr(_) => todo!(),
Value::Constant(_) => todo!("so this is empty? not sure yet"),
Value::FuncResult(_) => todo!(),
Value::OpResult(op_res) => Users::OpOperands(self.op_result_users(op_res)),
Value::Variadic => Users::HasNoOpResults,
}
}
}
impl Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::BlockArgument(arg) => write!(f, "{arg}"),
Value::BlockLabel(label) => write!(f, "{label}"),
Value::BlockPtr(ptr) => write!(f, "{ptr}"),
Value::Constant(constant) => write!(f, "{constant}"),
Value::FuncResult(result) => write!(f, "{}", result.rd()),
Value::OpResult(result) => write!(f, "{result}"),
Value::Variadic => write!(f, "..."),
}
}
}
#[derive(Clone)]
pub struct Values {
values: Shared<Vec<Shared<Value>>>,
}
impl IntoIterator for Values {
type Item = Shared<Value>;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.values.rd().clone().into_iter()
}
}
impl Values {
pub fn from_vec(values: Vec<Shared<Value>>) -> Self {
Values {
values: Shared::new(values.into()),
}
}
pub fn vec(&self) -> Shared<Vec<Shared<Value>>> {
self.values.clone()
}
pub fn names(&self) -> Vec<String> {
self.values
.try_read()
.unwrap()
.iter()
.map(|value| value.rd().name().unwrap())
.collect()
}
pub fn len(&self) -> usize {
self.values.rd().len()
}
pub fn rename_variables(&self, renamer: &dyn VariableRenamer) -> Result<()> {
let values = self.values.rd();
for value in values.iter() {
let name = value.rd().name().unwrap();
value.wr().set_name(&renamer.rename(&name));
}
Ok(())
}
pub fn as_operands(&self) -> OpOperands {
let values = self.values.rd().clone().into_iter();
let values = values
.map(|value| {
if let Value::OpResult(_res) = &*value.rd() {
let operand = OpOperand::new(value.clone());
Shared::new(operand.into())
} else {
panic!("Expected `Value::OpResult`");
}
})
.collect::<Vec<_>>();
OpOperands::from_vec(values)
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn types(&self) -> Types {
let types = self
.values
.rd()
.iter()
.map(|value| value.rd().typ().unwrap())
.collect::<Vec<Shared<dyn Type>>>();
Types::from_vec(types)
}
pub fn update_types(&mut self, types: Vec<Shared<dyn Type>>) -> Result<()> {
let values = self.values.rd().clone().into_iter();
if values.len() != types.len() {
return Err(anyhow::anyhow!(
"Expected {} types, but got {}",
values.len(),
types.len()
));
}
for (i, value) in values.enumerate() {
value.wr().set_type(types[i].clone());
}
Ok(())
}
pub fn set_defining_op(&self, op: Shared<dyn Op>) {
for result in self.values.rd().iter() {
match &mut *result.wr() {
Value::BlockArgument(_) => {
panic!("Trying to set defining op for block argument")
}
Value::BlockLabel(_) => {
panic!("Trying to set defining op for block label")
}
Value::BlockPtr(_) => panic!("Trying to set defining op for block ptr"),
Value::Constant(_) => {
panic!("Trying to set defining op for constant")
}
Value::FuncResult(_) => {
panic!("Trying to set defining op for func result")
}
Value::OpResult(res) => res.set_defining_op(Some(op.clone())),
Value::Variadic => panic!("Trying to set defining op for variadic"),
}
}
}
pub fn convert_types<T: TypeConvert>(&self) -> Result<()> {
for value in self.values.rd().iter() {
let typ = value.rd().typ().unwrap();
value.wr().set_type(T::convert_type(&typ)?);
}
Ok(())
}
}
impl Default for Values {
fn default() -> Self {
Values {
values: Shared::new(vec![].into()),
}
}
}
impl Display for Values {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let joined = self
.values
.try_read()
.unwrap()
.iter()
.map(|o| o.rd().to_string())
.collect::<Vec<String>>()
.join(", ");
write!(f, "{joined}")
}
}
impl<T: ParserDispatch> Parser<T> {
pub fn parse_function_argument(&mut self) -> Result<Shared<Value>> {
if self.check(TokenKind::PercentIdentifier) {
let identifier = self.expect(TokenKind::PercentIdentifier)?;
let name = identifier.lexeme.clone();
let _colon = self.expect(TokenKind::Colon)?;
let typ = T::parse_type(self)?;
let name = BlockArgumentName::Name(name);
let arg = Value::BlockArgument(BlockArgument::new(name, typ));
let operand = Shared::new(arg.into());
if self.check(TokenKind::Comma) {
self.advance();
}
return Ok(operand);
}
if self.check(TokenKind::IntType) || self.check(TokenKind::Exclamation) {
let typ = T::parse_type(self)?;
let name = BlockArgumentName::Anonymous;
let arg = Value::BlockArgument(BlockArgument::new(name, typ));
let operand = Shared::new(arg.into());
if self.check(TokenKind::Comma) {
self.advance();
}
return Ok(operand);
}
if self.check(TokenKind::Dot) {
self.expect(TokenKind::Dot)?;
self.expect(TokenKind::Dot)?;
self.expect(TokenKind::Dot)?;
let variadic = Value::Variadic;
return Ok(Shared::new(variadic.into()));
}
Err(anyhow::anyhow!("Expected function argument"))
}
pub fn is_function_argument(&mut self) -> bool {
let perc = self.check(TokenKind::PercentIdentifier);
let int = self.check(TokenKind::IntType);
let excl = self.check(TokenKind::Exclamation);
let dot = self.check(TokenKind::Dot);
perc || int || excl || dot
}
pub fn parse_op_result(&mut self, token_kind: TokenKind) -> Result<UnsetOpResult> {
let identifier = self.expect(token_kind)?;
let name = identifier.lexeme.clone();
let mut op_result = OpResult::default();
op_result.set_name(&name);
let result = Value::OpResult(op_result);
Ok(UnsetOpResult::new(Shared::new(result.into())))
}
pub fn parse_op_result_into(
&mut self,
token_kind: TokenKind,
operation: &mut Operation,
) -> Result<UnsetOpResult> {
let result = self.parse_op_result(token_kind)?.result;
let results = Values::from_vec(vec![result.clone()]);
operation.set_results(results.clone());
Ok(UnsetOpResult::new(result))
}
pub fn parse_op_results(&mut self, token_kind: TokenKind) -> Result<UnsetOpResults> {
let mut results = vec![];
while self.check(token_kind) {
let result = self.parse_op_result(token_kind)?.result;
results.push(result);
if self.check(TokenKind::Comma) {
let _comma = self.advance();
}
}
let results = Shared::new(results.into());
let values = Values { values: results };
Ok(UnsetOpResults::new(values))
}
pub fn parse_op_results_into(
&mut self,
token_kind: TokenKind,
operation: &mut Operation,
) -> Result<UnsetOpResults> {
let results = self.parse_op_results(token_kind)?;
operation.set_results(results.values().clone());
Ok(results)
}
pub fn parse_function_arguments(&mut self) -> Result<Values> {
let _lparen = self.expect(TokenKind::LParen)?;
let mut operands = vec![];
while self.is_function_argument() {
operands.push(self.parse_function_argument()?);
}
let _rparen = self.expect(TokenKind::RParen);
let values = Values::from_vec(operands);
Ok(values)
}
pub fn parse_block_dest(&mut self) -> Result<OpOperand> {
let name = self.expect(TokenKind::CaretIdentifier)?;
let name = name.lexeme.clone();
let value = Value::BlockLabel(BlockLabel::new(name));
let value = Shared::new(value.into());
Ok(OpOperand::new(value))
}
}