use std::collections::HashMap;
use std::sync::Arc;
use crate::{Lt, Module, Variable};
pub fn list_functions(module: &Module) -> Vec<Variable> {
let mut functions = vec![];
let name: Arc<String> = Arc::new("name".into());
let arguments: Arc<String> = Arc::new("arguments".into());
let returns: Arc<String> = Arc::new("returns".into());
let takes: Arc<String> = Arc::new("takes".into());
let lifetime: Arc<String> = Arc::new("lifetime".into());
let ret_lifetime: Arc<String> = Arc::new("return".into());
let ty: Arc<String> = Arc::new("type".into());
let external: Arc<String> = Arc::new("external".into());
let loaded: Arc<String> = Arc::new("loaded".into());
for f in &*module.ext_prelude {
let mut obj = HashMap::new();
obj.insert(name.clone(), Variable::Str(f.name.clone()));
obj.insert(
returns.clone(),
Variable::Str(Arc::new(f.p.ret.description())),
);
obj.insert(ty.clone(), Variable::Str(external.clone()));
let mut args = vec![];
for (i, lt) in f.p.lts.iter().enumerate() {
let mut obj_arg = HashMap::new();
obj_arg.insert(name.clone(), Variable::Str(Arc::new(format!("arg{}", i))));
obj_arg.insert(
lifetime.clone(),
match *lt {
Lt::Default => Variable::Option(None),
Lt::Arg(ind) => Variable::Option(Some(Box::new(Variable::Str(Arc::new(
format!("arg{}", ind),
))))),
Lt::Return => {
Variable::Option(Some(Box::new(Variable::Str(ret_lifetime.clone()))))
}
},
);
obj_arg.insert(
takes.clone(),
Variable::Str(Arc::new(f.p.tys[i].description())),
);
args.push(Variable::Object(Arc::new(obj_arg)));
}
obj.insert(arguments.clone(), Variable::Array(Arc::new(args)));
functions.push(Variable::Object(Arc::new(obj)));
}
for f in &module.functions {
let mut obj = HashMap::new();
obj.insert(name.clone(), Variable::Str(f.name.clone()));
obj.insert(
returns.clone(),
Variable::Str(Arc::new(f.ret.description())),
);
obj.insert(ty.clone(), Variable::Str(loaded.clone()));
let mut args = vec![];
for arg in &f.args {
let mut obj_arg = HashMap::new();
obj_arg.insert(name.clone(), Variable::Str(arg.name.clone()));
obj_arg.insert(
lifetime.clone(),
match arg.lifetime {
None => Variable::Option(None),
Some(ref lt) => Variable::Option(Some(Box::new(Variable::Str(lt.clone())))),
},
);
obj_arg.insert(takes.clone(), Variable::Str(Arc::new(arg.ty.description())));
args.push(Variable::Object(Arc::new(obj_arg)));
}
obj.insert(arguments.clone(), Variable::Array(Arc::new(args)));
functions.push(Variable::Object(Arc::new(obj)));
}
functions.sort_by(|a, b| match (a, b) {
(&Variable::Object(ref a), &Variable::Object(ref b)) => match (&a[&name], &b[&name]) {
(&Variable::Str(ref a), &Variable::Str(ref b)) => a.cmp(b),
_ => panic!("Expected two strings"),
},
_ => panic!("Expected two objects"),
});
functions
}