use std::{convert::TryFrom, fmt, io};
mod data;
pub use data::{Ident, Path};
pub mod forest;
pub mod input;
pub mod syn;
pub use forest::{Forest, Record};
mod exec;
pub use exec::PreparedRoot;
#[derive(Debug, Clone)]
pub enum TypeExpr<I, A> {
U(A, A),
I(A, A),
ArrayN(A, Box<TypeExpr<I, A>>),
ArrayV(Box<TypeExpr<I, A>>),
App(NodeApp<I, A>),
}
impl<I, A> TypeExpr<I, A> {
pub fn ident(ident: I) -> Self {
TypeExpr::App(NodeApp {
id: ident,
args: Vec::new(),
})
}
pub fn app(ident: I, args: impl IntoIterator<Item = A>) -> Self {
TypeExpr::App(NodeApp {
id: ident,
args: args.into_iter().collect(),
})
}
}
#[derive(Debug, Clone)]
pub struct NodeApp<I, A> {
pub id: I,
pub args: Vec<A>,
}
impl<I, A> NodeApp<I, A> {
fn lift<I1, A1, LI, LA, C, Err>(
&self,
ctx: &mut C,
lift_ident: LI,
lift_expr: LA,
) -> Result<NodeApp<I1, A1>, Err>
where
LI: Fn(&I, &mut C) -> Result<I1, Err>,
LA: Fn(&A, &mut C) -> Result<A1, Err>,
I1: 'static,
A1: 'static,
Err: 'static,
{
Ok(NodeApp {
id: lift_ident(&self.id, ctx)?,
args: self
.args
.iter()
.map(|expr| lift_expr(expr, ctx))
.collect::<Result<_, _>>()?,
})
}
}
#[derive(Debug, Clone)]
pub enum Type<I> {
U(u8, Endianness),
I(u8, Endianness),
ArrayN(usize, Box<Type<I>>),
ArrayV(Box<Type<I>>),
Ident(I),
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Endianness {
Little,
Big,
Native,
}
#[derive(Debug, Clone)]
pub enum R<F> {
Field(F),
Param(usize),
}
#[derive(Debug, Clone)]
pub enum Expr<T> {
Not(Box<Expr<T>>),
And(Vec<Expr<T>>),
Or(Vec<Expr<T>>),
Eq(Box<[Expr<T>; 2]>),
Add(Box<[Expr<T>; 2]>),
Sub(Box<[Expr<T>; 2]>),
Mul(Box<[Expr<T>; 2]>),
BitNot(Box<Expr<T>>),
BitAnd(Box<[Expr<T>; 2]>),
BitOr(Box<[Expr<T>; 2]>),
BitShl(Box<[Expr<T>; 2]>),
BitShr(Box<[Expr<T>; 2]>),
TypeProperty(T, String),
Ref(T),
Const(lexpr::Value),
}
impl<T> Expr<T> {
pub fn constant(value: impl Into<lexpr::Value>) -> Self {
Expr::Const(value.into())
}
pub fn equal(e1: impl Into<Expr<T>>, e2: impl Into<Expr<T>>) -> Self {
Expr::Eq(Box::new([e1.into(), e2.into()]))
}
pub fn add(e1: impl Into<Expr<T>>, e2: impl Into<Expr<T>>) -> Self {
Expr::Add(Box::new([e1.into(), e2.into()]))
}
pub fn sub(e1: impl Into<Expr<T>>, e2: impl Into<Expr<T>>) -> Self {
Expr::Sub(Box::new([e1.into(), e2.into()]))
}
pub fn mul(e1: impl Into<Expr<T>>, e2: impl Into<Expr<T>>) -> Self {
Expr::Mul(Box::new([e1.into(), e2.into()]))
}
pub fn bitwise_not(e: impl Into<Expr<T>>) -> Self {
Expr::BitNot(Box::new(e.into()))
}
pub fn bitwise_and(e1: impl Into<Expr<T>>, e2: impl Into<Expr<T>>) -> Self {
Expr::BitAnd(Box::new([e1.into(), e2.into()]))
}
pub fn bitwise_or(e1: impl Into<Expr<T>>, e2: impl Into<Expr<T>>) -> Self {
Expr::BitOr(Box::new([e1.into(), e2.into()]))
}
pub fn bitwise_shift_left(e1: impl Into<Expr<T>>, e2: impl Into<Expr<T>>) -> Self {
Expr::BitShl(Box::new([e1.into(), e2.into()]))
}
pub fn bitwise_shift_right(e1: impl Into<Expr<T>>, e2: impl Into<Expr<T>>) -> Self {
Expr::BitShr(Box::new([e1.into(), e2.into()]))
}
pub fn simplified(self) -> Self {
use Expr::*;
match self {
And(mut conds) => match conds.len() {
1 => conds.pop().unwrap().simplified(),
_ => And(conds.into_iter().map(Expr::simplified).collect()),
},
Or(mut conds) => match conds.len() {
1 => conds.pop().unwrap(),
_ => Or(conds.into_iter().map(Expr::simplified).collect()),
},
_ => self,
}
}
}
impl<T> From<T> for Expr<T> {
fn from(r: T) -> Self {
Expr::Ref(r)
}
}
#[derive(Debug, Clone)]
pub struct Field<T> {
pub name: Ident,
pub ty: T,
pub constant: Option<lexpr::Datum>,
pub hidden: bool,
}
#[derive(Debug, Clone)]
pub enum Value {
Bool(bool),
U32(u32),
U64(u64),
I32(i32),
I64(i64),
Array(Vec<Value>),
Shaped(Shaped),
}
impl Value {
fn as_u64(&self) -> Option<u64> {
use Value::*;
match self {
U32(n) => Some((*n).into()),
U64(n) => Some(*n),
_ => None,
}
}
fn is_true(&self) -> bool {
match self {
Value::Bool(false) => false,
_ => true,
}
}
fn display<'a>(&'a self, forest: &'a Forest, tree: &'a exec::Tree) -> ValueDisplay<'_> {
ValueDisplay {
value: self,
forest,
tree,
}
}
fn to_sexp(&self) -> lexpr::Value {
use Value::*;
match self {
Bool(b) => (*b).into(),
U32(n) => (*n).into(),
U64(n) => (*n).into(),
I32(n) => (*n).into(),
I64(n) => (*n).into(),
Array(elts) => lexpr::Value::list(elts.iter().map(|elt| elt.to_sexp())),
Shaped(shaped) => lexpr::Value::Vector(
shaped
.decoded()
.iter()
.map(|item| item.value().to_sexp())
.collect(),
),
}
}
fn to_sexp_named(&self, forest: &Forest, tree: &exec::Tree) -> lexpr::Value {
use Value::*;
match self {
Bool(b) => (*b).into(),
U32(n) => (*n).into(),
U64(n) => (*n).into(),
I32(n) => (*n).into(),
I64(n) => (*n).into(),
Array(elts) => {
lexpr::Value::list(elts.iter().map(|elt| elt.to_sexp_named(forest, tree)))
}
Shaped(shaped) => Record::new(shaped, forest, tree).into(),
}
}
}
impl PartialEq for Value {
fn eq(&self, other: &Value) -> bool {
use Value::*;
match (self, other) {
(Bool(b1), Bool(b2)) => b1 == b2,
(U32(n1), U32(n2)) => n1 == n2,
(U64(n1), U64(n2)) => n1 == n2,
(I32(n1), I32(n2)) => n1 == n2,
(I64(n1), I64(n2)) => n1 == n2,
(Array(a1), Array(a2)) => {
if a1.len() == a2.len() {
for (v1, v2) in a1.iter().zip(a2) {
if v1 != v2 {
return false;
}
}
true
} else {
false
}
}
_ => unimplemented!("comparison between {:?} and {:?}", self, other),
}
}
}
impl PartialEq<lexpr::Value> for Value {
fn eq(&self, other: &lexpr::Value) -> bool {
use lexpr::Value::*;
match (self, other) {
(Value::Bool(b1), Bool(b2)) => b1 == b2,
(Value::U32(n1), Number(n2)) => Some(u64::from(*n1)) == n2.as_u64(),
(Value::U64(n1), Number(n2)) => Some(*n1) == n2.as_u64(),
(Value::I32(n1), Number(n2)) => Some(i64::from(*n1)) == n2.as_i64(),
(Value::I64(n1), Number(n2)) => Some(*n1) == n2.as_i64(),
(Value::Array(a1), Vector(a2)) => {
if a1.len() == a2.len() {
for (v1, v2) in a1.iter().zip(a2.as_ref()) {
if v1 != v2 {
return false;
}
}
true
} else {
false
}
}
_ => unimplemented!("comparison between {:?} and {:?}", self, other),
}
}
}
impl PartialEq<Value> for lexpr::Value {
fn eq(&self, other: &Value) -> bool {
other == self
}
}
impl From<i64> for Value {
fn from(n: i64) -> Self {
if let Ok(n) = i32::try_from(n) {
Value::I32(n)
} else {
Value::I64(n)
}
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Value::*;
match self {
Bool(true) => write!(f, "true"),
Bool(false) => write!(f, "false"),
U32(n) => write!(f, "{}", n),
U64(n) => write!(f, "{}", n),
I32(n) => write!(f, "{}", n),
I64(n) => write!(f, "{}", n),
Array(elts) => {
f.write_str("[")?;
for (i, value) in elts.iter().enumerate() {
if i == 0 {
write!(f, "{}", value)?;
} else {
write!(f, ", {}", value)?;
}
}
f.write_str("]")?;
Ok(())
}
Shaped(shaped) => {
f.write_str("(")?;
for (i, value) in shaped.values().enumerate() {
if i == 0 {
write!(f, "{}", value)?;
} else {
write!(f, ", {}", value)?;
}
}
f.write_str(")")?;
Ok(())
}
}
}
}
#[derive(Debug, Clone)]
pub struct Shaped {
trace: exec::Trace,
decoded: Vec<exec::DecodedItem>,
}
impl Shaped {
pub fn root_id(&self) -> exec::ExecNodeId {
self.trace.root_id
}
pub fn branch_ids(&self) -> &[usize] {
&self.trace.branch_ids
}
pub fn values(&self) -> impl Iterator<Item = &Value> {
self.decoded.iter().map(|item| item.value())
}
pub fn decoded(&self) -> &[exec::DecodedItem] {
&self.decoded
}
}
#[derive(Debug)]
pub struct ValueDisplay<'a> {
value: &'a Value,
tree: &'a crate::exec::Tree,
forest: &'a crate::Forest,
}
impl<'a> fmt::Display for ValueDisplay<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Value::*;
match self.value {
Bool(true) => write!(f, "true"),
Bool(false) => write!(f, "false"),
U32(n) => write!(f, "{}", n),
U64(n) => write!(f, "{}", n),
I32(n) => write!(f, "{}", n),
I64(n) => write!(f, "{}", n),
Array(elts) => {
f.write_str("[")?;
for (i, value) in elts.iter().enumerate() {
if i == 0 {
write!(f, "{}", value.display(self.forest, self.tree))?;
} else {
write!(f, ", {}", value.display(self.forest, self.tree))?;
}
}
f.write_str("]")?;
Ok(())
}
Shaped(shaped) => {
let record = Record::new(shaped, self.forest, self.tree);
write!(f, "{}", record)
}
}
}
}
impl<I, E> TypeExpr<I, E> {
fn lift<I1, E1, LI, LE, C, Err>(
&self,
ctx: &mut C,
lift_ident: LI,
lift_expr: LE,
) -> Result<TypeExpr<I1, E1>, Err>
where
LI: Fn(&I, &mut C) -> Result<I1, Err>,
LE: Fn(&E, &mut C) -> Result<E1, Err>,
I1: 'static,
E1: 'static,
Err: 'static,
{
use TypeExpr::*;
let lifted = match self {
U(width, endianness) => U(lift_expr(width, ctx)?, lift_expr(endianness, ctx)?),
I(width, endianness) => I(lift_expr(width, ctx)?, lift_expr(endianness, ctx)?),
ArrayN(expr, et) => {
let lifted_expr = lift_expr(expr, ctx)?;
let lifted_et = et.lift(ctx, lift_ident, lift_expr)?;
ArrayN(lifted_expr, Box::new(lifted_et))
}
ArrayV(et) => {
let lifted_et = et.lift(ctx, lift_ident, lift_expr)?;
ArrayV(Box::new(lifted_et))
}
App(app) => App(app.lift(ctx, lift_ident, lift_expr)?),
};
Ok(lifted)
}
}
impl<I, A> fmt::Display for TypeExpr<I, A>
where
I: fmt::Display,
A: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use TypeExpr::*;
match self {
U(n, e) => write!(f, "(i {} {})", n, e),
I(n, e) => write!(f, "(u {} {})", n, e),
ArrayN(n, et) => write!(f, "[{}; {}]", et, n),
ArrayV(et) => write!(f, "[{}]", et),
App(app) => {
write!(f, "#<Type {}", app.id)?;
for (i, arg) in app.args.iter().enumerate() {
if i + 1 < app.args.len() {
write!(f, "{} ", arg)?;
} else {
write!(f, "{}", arg)?;
}
}
f.write_str(">")?;
Ok(())
}
}
}
}
pub fn read_into_forest<R: io::Read>(forest: &mut Forest, reader: &mut R) -> Result<(), ReadError> {
use syn::Def;
let mut parser = syn::Parser::new(reader);
while let Some(def) = parser.parse_def()? {
match def {
Def::Root(root) => {
forest.add_root(root)?;
}
Def::Branch(branch) => forest.add_branch(branch)?,
Def::Enum(en) => {
forest.add_enum(en)?;
}
}
}
Ok(())
}
#[derive(Debug)]
pub enum ReadError {
Syntax(syn::Error),
Forest(forest::Error),
}
#[derive(Debug)]
pub struct DisplayReadError<'a> {
error: &'a ReadError,
forest: &'a Forest,
}
impl<'a> fmt::Display for DisplayReadError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.error {
ReadError::Syntax(_) => write!(f, "{}", self.error),
ReadError::Forest(e) => write!(f, "{}", e.display(self.forest)),
}
}
}
impl<'a> std::error::Error for DisplayReadError<'a> {}
impl ReadError {
pub fn display<'a>(&'a self, forest: &'a Forest) -> DisplayReadError<'a> {
DisplayReadError {
error: self,
forest,
}
}
}
impl From<syn::Error> for ReadError {
fn from(e: syn::Error) -> Self {
ReadError::Syntax(e)
}
}
impl From<forest::Error> for ReadError {
fn from(e: forest::Error) -> Self {
ReadError::Forest(e)
}
}
impl fmt::Display for ReadError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ReadError::Syntax(e) => write!(f, "syntax error: {}", e),
ReadError::Forest(e) => write!(f, "could not add definition: {}", e),
}
}
}
impl std::error::Error for ReadError {}