use std::sync::Arc;
use syn::Type;
use super::bytecode::{
CapSource, Chunk, Const, EnumVariant, FmtSpec, Member, MethodName, Op, PPat, PatInfo, StructLit,
};
use super::pvalue::PStructShape;
#[derive(Clone)]
pub enum PMember {
Named(Arc<str>),
Indexed(usize),
}
pub struct PStructLit {
pub shape: Arc<PStructShape>,
pub has_rest: bool,
}
pub struct PEnumVariant {
pub enum_name: Arc<str>,
pub variant: Arc<str>,
}
pub struct PPatInfo {
pub pat: PPat,
pub binds: Vec<(String, u16)>,
}
pub struct PChunk {
pub code: Vec<Op>,
pub lines: Vec<u32>,
pub file: Arc<str>,
pub num_regs: usize,
pub num_params: usize,
pub name: String,
pub consts: Vec<Const>,
pub members: Vec<PMember>,
pub pats: Vec<PPatInfo>,
pub fmts: Vec<FmtSpec>,
pub struct_lits: Vec<PStructLit>,
pub enum_variants: Vec<PEnumVariant>,
pub casts: Vec<String>,
pub paths: Vec<Vec<String>>,
pub names: Vec<MethodName>,
pub children: Vec<Arc<PChunk>>,
pub child_caps: Vec<Vec<CapSource>>,
}
pub fn convert(chunk: &Chunk) -> Arc<PChunk> {
Arc::new(PChunk {
code: chunk.code.clone(),
lines: chunk.lines.clone(),
file: chunk.file.clone(),
num_regs: chunk.num_regs,
num_params: chunk.num_params,
name: chunk.name.clone(),
consts: chunk.consts.clone(),
members: chunk.members.iter().map(convert_member).collect(),
pats: chunk.pats.iter().map(convert_pat_info).collect(),
fmts: chunk.fmts.clone(),
struct_lits: chunk.struct_lits.iter().map(convert_lit).collect(),
enum_variants: chunk
.enum_variants
.iter()
.map(convert_enum_variant)
.collect(),
casts: chunk.casts.iter().map(|t| cast_target(t)).collect(),
paths: chunk.paths.iter().map(|(segs, _)| segs.clone()).collect(),
names: chunk.names.clone(),
children: chunk.children.iter().map(|c| convert(c)).collect(),
child_caps: chunk.child_caps.clone(),
})
}
fn convert_enum_variant(variant: &EnumVariant) -> PEnumVariant {
PEnumVariant {
enum_name: Arc::from(&*variant.enum_name),
variant: Arc::from(&*variant.variant),
}
}
fn convert_member(m: &Member) -> PMember {
match m {
Member::Named(n) => PMember::Named(Arc::from(&**n)),
Member::Indexed(i) => PMember::Indexed(*i),
}
}
fn convert_lit(lit: &StructLit) -> PStructLit {
let shape = &lit.shape;
let fields: Vec<Arc<str>> = shape.fields.iter().map(|f| Arc::from(&**f)).collect();
let renames: Vec<Option<Arc<str>>> = shape
.renames
.iter()
.map(|r| r.as_ref().map(|s| Arc::from(&**s)))
.collect();
let pshape = Arc::new(PStructShape {
name: Arc::from(&*shape.name),
fields,
renames,
});
PStructLit {
shape: pshape,
has_rest: lit.has_rest,
}
}
fn convert_pat_info(info: &PatInfo) -> PPatInfo {
PPatInfo {
pat: info.pat.clone(),
binds: info.binds.clone(),
}
}
fn cast_target(ty: &Type) -> String {
match ty {
Type::Path(p) => p
.path
.segments
.last()
.map(|s| s.ident.to_string())
.unwrap_or_default(),
_ => String::new(),
}
}