#![allow(dead_code)]
use super::objects::{ObjKey, TCObjects, TypeKey};
use super::typ;
use std::fmt;
use std::fmt::Write;
#[derive(Clone, Debug)]
pub enum SelectionKind {
FieldVal, MethodVal, MethodExpr, }
#[derive(Clone, Debug)]
pub struct Selection {
kind: SelectionKind,
recv: Option<TypeKey>, obj: ObjKey, indices: Vec<usize>, indirect: bool, typ: Option<TypeKey>, id: String,
}
impl Selection {
pub fn new(
kind: SelectionKind,
recv: Option<TypeKey>,
obj: ObjKey,
indices: Vec<usize>,
indirect: bool,
objs: &TCObjects,
) -> Selection {
Selection {
kind: kind,
recv: recv,
obj: obj,
indices: indices,
indirect: indirect,
typ: None,
id: objs.lobjs[obj].id(objs).to_string(),
}
}
pub fn init_type(&mut self, objs: &mut TCObjects) {
self.typ = Some(self.eval_type(objs));
}
pub fn kind(&self) -> &SelectionKind {
&self.kind
}
pub fn recv(&self) -> Option<TypeKey> {
self.recv
}
pub fn obj(&self) -> ObjKey {
self.obj
}
pub fn typ(&self) -> TypeKey {
self.typ.unwrap()
}
pub fn id(&self) -> &String {
&self.id
}
pub fn indices(&self) -> &Vec<usize> {
&self.indices
}
pub fn indirect(&self) -> &bool {
&self.indirect
}
pub fn fmt(&self, f: &mut fmt::Formatter<'_>, objs: &TCObjects) -> fmt::Result {
f.write_str(match self.kind {
SelectionKind::FieldVal => "field (",
SelectionKind::MethodVal => "method (",
SelectionKind::MethodExpr => "method expr (",
})?;
typ::fmt_type(self.recv(), f, objs)?;
write!(f, ") {}", objs.lobjs[self.obj].name())?;
match self.kind {
SelectionKind::FieldVal => {
f.write_char(' ')?;
typ::fmt_type(Some(self.typ()), f, objs)?;
}
_ => typ::fmt_signature(self.typ(), f, objs)?,
}
Ok(())
}
fn eval_type(&self, objs: &mut TCObjects) -> TypeKey {
let obj = &objs.lobjs[self.obj];
match self.kind {
SelectionKind::FieldVal => obj.typ().unwrap(),
SelectionKind::MethodVal => {
let t = &objs.types[obj.typ().unwrap()];
let mut sig = *t.try_as_signature().unwrap();
let mut new_recv = objs.lobjs[sig.recv().unwrap()].clone();
new_recv.set_type(self.recv);
sig.set_recv(Some(objs.lobjs.insert(new_recv)));
objs.types.insert(typ::Type::Signature(sig))
}
SelectionKind::MethodExpr => {
let t = &objs.types[obj.typ().unwrap()];
let mut sig = *t.try_as_signature().unwrap();
let mut arg0 = objs.lobjs[sig.recv().unwrap()].clone();
arg0.set_type(self.recv);
let arg0key = objs.lobjs.insert(arg0);
sig.set_recv(None);
let mut params = vec![arg0key];
let tup = &mut objs.types[sig.params()].try_as_tuple_mut().unwrap();
params.append(&mut tup.vars().clone());
sig.set_params(objs.new_t_tuple(params));
objs.types.insert(typ::Type::Signature(sig))
}
}
}
}