diff --git a/pit-core/src/info.rs b/pit-core/src/info.rs new file mode 100644 index 0000000..7fe57e5 --- /dev/null +++ b/pit-core/src/info.rs @@ -0,0 +1,116 @@ +use std::{collections::BTreeMap, fmt::Display}; + +use nom::{ + bytes::complete::{tag, take_while_m_n}, character::complete::{alphanumeric1, multispace0}, multi::many0, sequence::delimited, IResult +}; + +use crate::{merge, parse_attr, Attr}; +#[derive(Default,Clone)] +pub struct Info { + pub interfaces: BTreeMap<[u8; 32], InfoEntry>, +} +impl Info{ + pub fn merge(self, x: Info) -> Info{ + let mut m: BTreeMap<[u8;32],InfoEntry> = BTreeMap::new(); + for (a,b) in self.interfaces.into_iter().chain(x.interfaces.into_iter()){ + let c = m.remove(&a).unwrap_or_default().merge(b); + m.insert(a, c); + } + Info { interfaces: m } + } +} +#[derive(Default,Clone)] +pub struct InfoEntry { + pub attrs: Vec, + pub methods: BTreeMap +} +impl InfoEntry{ + pub fn merge(self, x: InfoEntry) -> InfoEntry{ + let mut m: BTreeMap = BTreeMap::new(); + for (a,b) in self.methods.into_iter().chain(x.methods.into_iter()){ + let c = m.remove(&a).unwrap_or_default().merge(b); + m.insert(a, c); + } + InfoEntry { attrs: merge(self.attrs, x.attrs), methods: m } + } +} +#[derive(Default,Clone)] +pub struct MethEntry{ + pub attrs: Vec +} +impl MethEntry{ + pub fn merge(self, x: MethEntry) -> MethEntry{ + MethEntry { attrs: merge(self.attrs, x.attrs) } + } +} +impl Display for InfoEntry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for a in self.attrs.iter(){ + write!(f,"root {a}")?; + } + for (k,m) in self.methods.iter(){ + for a in m.attrs.iter(){ + write!(f,"method {k} {a}")?; + } + } + Ok(()) + } +} +impl Display for Info { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for (i, j) in self.interfaces.iter() { + write!(f, "{}: [{j}]", hex::encode(i))?; + } + Ok(()) + } +} +pub fn parse_entry(a: &str) -> IResult<&str, InfoEntry> { + let (a,_) = multispace0(a)?; + pub fn go1(a: &str) -> IResult<&str,Attr>{ + let (a,_) = multispace0(a)?; + let (a,_) = tag("root")(a)?; + let (a,_) = multispace0(a)?; + return parse_attr(a); + } + pub fn go2(a: &str) -> IResult<&str,(&str,Attr)>{ + let (a,_) = multispace0(a)?; + let (a,_) = tag("method")(a)?; + let (a,_) = multispace0(a)?; + let (a,b) = alphanumeric1(a)?; + let (a,_) = multispace0(a)?; + let (a,c) = parse_attr(a)?; + Ok((a,(b,c))) + } + let (a,mut e) = many0(go1)(a)?; + e.sort_by_key(|k|k.name.clone()); + let mut n: BTreeMap = BTreeMap::new(); + let (a,l) = many0(go2)(a)?; + for (k,v) in l{ + n.entry(k.to_owned()).or_insert_with(Default::default).attrs.push(v); + } + for v in n.values_mut(){ + v.attrs.sort_by_key(|k|k.name.clone()); + } + let (a,_) = multispace0(a)?; + Ok((a, InfoEntry { attrs: e, methods: n })) +} +pub fn parse_info(a: &str) -> IResult<&str, Info> { + pub fn go(a: &str) -> IResult<&str, ([u8; 32], InfoEntry)> { + let (a,_) = multispace0(a)?; + let (a, d) = take_while_m_n(64, 64, |a: char| a.is_digit(16))(a)?; + let mut b = [0u8; 32]; + hex::decode_to_slice(d, &mut b).unwrap(); + let (a,_) = multispace0(a)?; + let (a,_) = tag(":")(a)?; + let (a,_) = multispace0(a)?; + let (a, c) = delimited(tag("["), parse_entry, tag("]"))(a)?; + return Ok((a, (b, c))); + } + let (a, all) = many0(go)(a)?; + Ok(( + a, + Info { + interfaces: all.into_iter().collect(), + }, + )) +} diff --git a/pit-core/src/lib.rs b/pit-core/src/lib.rs index c9ed10c..822ab17 100644 --- a/pit-core/src/lib.rs +++ b/pit-core/src/lib.rs @@ -16,6 +16,14 @@ pub struct Attr { pub value: String, } +pub fn merge(a: Vec, b: Vec) -> Vec{ + let mut m = BTreeMap::new(); + for x in a.into_iter().chain(b){ + m.insert(x.name, x.value); + } + return m.into_iter().map(|(a,b)|Attr{name: a,value: b}).collect(); +} + pub fn parse_balanced(mut a: &str) -> IResult<&str, String> { let mut v = vec![]; let mut i = 0; @@ -244,3 +252,4 @@ impl Interface { return hex::encode(self.rid()); } } +pub mod info; \ No newline at end of file diff --git a/pit-patch/src/util.rs b/pit-patch/src/util.rs index 21b6963..f5921f4 100644 --- a/pit-patch/src/util.rs +++ b/pit-patch/src/util.rs @@ -142,7 +142,7 @@ pub fn tfree(m: &mut Module, t: Table) -> anyhow::Result { // use waffle::{util::new_sig, Module}; -pub fn to_waffle_type(t: &pit_core::Arg) -> waffle::Type { +pub fn to_waffle_type(t: &pit_core::Arg, tpit: bool) -> waffle::Type { match t { pit_core::Arg::I32 => waffle::Type::I32, pit_core::Arg::I64 => waffle::Type::I64, @@ -153,24 +153,32 @@ pub fn to_waffle_type(t: &pit_core::Arg) -> waffle::Type { nullable, take, ann, - } => waffle::Type::ExternRef, + } => if tpit{ + waffle::Type::I32 + }else{ + waffle::Type::ExternRef + }, } } -pub fn to_waffle_sig(m: &mut Module, t: &pit_core::Sig) -> waffle::Signature { +pub fn to_waffle_sig(m: &mut Module, t: &pit_core::Sig, tpit: bool,) -> waffle::Signature { return new_sig( m, waffle::SignatureData { - params: t.params.iter().map(to_waffle_type).collect(), - returns: t.rets.iter().map(to_waffle_type).collect(), + params: t.params.iter().map(|a|to_waffle_type(a,tpit)).collect(), + returns: t.rets.iter().map(|a|to_waffle_type(a,tpit)).collect(), }, ); } -pub fn waffle_funcs(m: &mut Module, i: &pit_core::Interface) -> BTreeMap { +pub fn waffle_funcs(m: &mut Module, i: &pit_core::Interface, tpit: bool,) -> BTreeMap { return i .methods .iter() .map(|(a, b)| { - let module = format!("pit/{}", i.rid_str()); + let module = format!("{}pit/{}", i.rid_str(), if tpit{ + "t" + }else{ + "" + }); let name = a.clone(); if let Some(f) = m.imports.iter().find_map(|i| { if i.module == module && i.name == name { @@ -184,7 +192,7 @@ pub fn waffle_funcs(m: &mut Module, i: &pit_core::Interface) -> BTreeMap anyhow::Result<()> { m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b); } } + if let Some(a) = import.name.strip_suffix(".tpit-res").map(|a|a.to_owned()){ + import.name = a; + if let ImportKind::Func(f) = &mut import.kind { + let p = m.signatures[m.funcs[*f].sig()].params.clone(); + let p = new_sig( + m, + SignatureData { + params: p, + returns: vec![Type::I32], + }, + ); + let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit"))); + let s = m.funcs[*f].sig(); + let o = replace(f, p); + let mut b = FunctionBody::new(&m, s); + let e = b.entry; + let arg = b.blocks[b.entry].params.iter().map(|a|a.1).collect::>(); + let arg = add_op( + &mut b, + &arg, + &[Type::ExternRef], + Operator::Call { + function_index: p, + }, + ); + b.append_to_block(e, arg); + b.set_terminator( + e, + waffle::Terminator::ReturnCall { + func: talloc, + args: vec![arg], + }, + ); + m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b); + } + } m.imports.push(import); } for i in is { - let f = waffle_funcs(m, &i); + let f = waffle_funcs(m, &i,false); for mut import in take(&mut m.imports) { if import.module == format!("tpit/{}", i.rid_str()) { match import.name.strip_prefix("~") { @@ -476,7 +520,7 @@ pub fn wrap(m: &mut Module) -> anyhow::Result<()> { .methods .get(&import.name) .context("in getting the method")?; - let p = to_waffle_sig(m, x); + let p = to_waffle_sig(m, x,false); let p = m.signatures[p].clone(); let p = new_sig( m, @@ -558,7 +602,7 @@ pub fn wrap(m: &mut Module) -> anyhow::Result<()> { } Some((a, b)) => { let x = i.methods.get(b).context("in getting the method")?; - let p = to_waffle_sig(m, x); + let p = to_waffle_sig(m, x,false); let p = m.signatures[p].clone(); let p = new_sig( m,