preserves/implementations/rust/preserves-schema/src/compiler/types.rs

176 lines
7.0 KiB
Rust
Raw Normal View History

2021-06-28 14:35:45 +00:00
use crate::*;
use crate::syntax::block::Emittable;
use crate::syntax::block::constructors::*;
use super::names;
use preserves::value::{IOValue, NestedValue};
use preserves::error::Error;
2021-06-28 15:26:41 +00:00
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
2021-06-28 14:35:45 +00:00
pub enum TDefinition {
Union(Vec<(String, TSimple)>),
Simple(TSimple),
}
2021-06-28 15:26:41 +00:00
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
2021-06-28 14:35:45 +00:00
pub enum TSimple {
Field(TField),
Record(TRecord),
}
2021-06-28 15:26:41 +00:00
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
2021-06-28 14:35:45 +00:00
pub enum TField {
Unit,
Array(Box<TField>),
Set(Box<TField>),
Map(Box<TField>, Box<TField>),
Ref(Vec<String>),
Base(String),
}
2021-06-28 15:26:41 +00:00
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
2021-06-28 14:35:45 +00:00
pub struct TRecord(pub Vec<(String, TField)>);
pub fn definition_type(d: &IOValue) -> Result<TDefinition, Error> {
if let Some(fs) = d.value().as_simple_record("or", Some(1)) {
let mut entries = Vec::new();
for e in fs[0].value().to_sequence()?.iter() {
let e = e.value().to_sequence()?;
entries.push((e[0].value().to_string()?.to_owned(), simple_type(&e[1])?));
}
Ok(TDefinition::Union(entries))
} else if let Some(fs) = d.value().as_simple_record("and", Some(1)) {
Ok(TDefinition::Simple(record_type(fs[0].value().to_sequence()?)?))
} else {
Ok(TDefinition::Simple(simple_type(d)?))
}
}
pub fn simple_type(p: &IOValue) -> Result<TSimple, Error> {
if let Some(t) = field_type(p)? {
Ok(TSimple::Field(t))
} else {
record_type(&vec![p.clone()])
}
}
pub fn record_type(ps: &Vec<IOValue>) -> Result<TSimple, Error> {
let fs = gather_fields(ps, Vec::new())?;
if fs.is_empty() {
Ok(TSimple::Field(TField::Unit))
} else {
Ok(TSimple::Record(TRecord(fs)))
}
}
pub fn gather_fields(ps: &Vec<IOValue>, mut fs: Vec<(String, TField)>) ->
Result<Vec<(String, TField)>, Error>
{
for p in ps.iter() {
fs = gather_field(p, fs)?;
}
Ok(fs)
}
pub fn gather_field(p: &IOValue, mut fs: Vec<(String, TField)>) ->
Result<Vec<(String, TField)>, Error>
{
if let Some(n) = p.value().as_simple_record("named", Some(2)) {
let name = n[0].value().to_symbol()?;
fs.push((name.to_owned(), field_type(&n[1])?.unwrap()));
Ok(fs)
} else if let Some(label_and_fields) = p.value().as_simple_record("rec", Some(2)) {
Ok(gather_field(&label_and_fields[1], gather_field(&label_and_fields[0], fs)?)?)
} else if let Some(tfs) = p.value().as_simple_record("tuple", Some(1)) {
Ok(gather_fields(tfs[0].value().to_sequence()?, fs)?)
} else if let Some(tfs) = p.value().as_simple_record("tuplePrefix", Some(2)) {
Ok(gather_field(&tfs[1], gather_fields(tfs[0].value().to_sequence()?, fs)?)?)
} else if let Some(dfs) = p.value().as_simple_record("dict", Some(1)) {
let es = dfs[0].value().to_dictionary()?;
for (_k, p) in es.iter() {
fs = gather_field(p, fs)?;
}
Ok(fs)
} else {
Ok(fs)
}
}
pub fn field_type(p: &IOValue) -> Result<Option<TField>, Error> {
if p.value().as_symbol() == Some(&"any".to_owned()) {
Ok(Some(TField::Base("preserves::value::IOValue".to_owned())))
} else if let Some(fs) = p.value().as_simple_record("atom", Some(1)) {
match fs[0].value().as_symbol().unwrap().as_str() {
"Boolean" => Ok(Some(TField::Base("bool".to_owned()))),
"Float" => Ok(Some(TField::Base("f32".to_owned()))),
"Double" => Ok(Some(TField::Base("f64".to_owned()))),
"SignedInteger" => Ok(Some(TField::Base("preserves::value::signed_integer::SignedInteger".to_owned()))),
"String" => Ok(Some(TField::Base("std::string::String".to_owned()))),
"ByteString" => Ok(Some(TField::Base("std::vec::Vec<u8>".to_owned()))),
"Symbol" => Ok(Some(TField::Base("std::string::String".to_owned()))),
_ => Err(Error::Message("Unexpected AtomKind".to_owned())),
}
} else if let Some(_) = p.value().as_simple_record("embedded", Some(1)) {
Ok(Some(TField::Base("_ptr".to_owned())))
} else if let Some(_) = p.value().as_simple_record("lit", Some(1)) {
Ok(Some(TField::Unit))
} else if let Some(fs) = p.value().as_simple_record("seqof", Some(1)) {
Ok(Some(TField::Array(Box::new(field_type(&fs[0])?.unwrap()))))
} else if let Some(fs) = p.value().as_simple_record("setof", Some(1)) {
Ok(Some(TField::Set(Box::new(field_type(&fs[0])?.unwrap()))))
} else if let Some(fs) = p.value().as_simple_record("dictof", Some(2)) {
Ok(Some(TField::Map(Box::new(field_type(&fs[0])?.unwrap()),
Box::new(field_type(&fs[1])?.unwrap()))))
} else if let Some(fs) = p.value().as_simple_record("ref", Some(2)) {
let mut pieces = fs[0].value().to_sequence()?.iter()
.map(|v| v.value().to_symbol().map(String::to_owned))
.collect::<Result<Vec<String>,_>>()?;
pieces.push(fs[1].value().to_symbol()?.to_owned());
Ok(Some(TField::Ref(pieces)))
} else {
Ok(None)
}
}
pub fn render_field_type(box_needed: bool, t: &TField) -> impl Emittable {
match t {
TField::Unit => seq!["()"],
TField::Array(t) => seq!["std::vec::Vec<", render_field_type(false, t), ">"],
TField::Set(t) => seq!["preserves::value::Set<", render_field_type(false, t), ">"],
TField::Map(k, v) => seq!["preserves::value::Map",
anglebrackets![render_field_type(false, k),
render_field_type(false, v)]],
TField::Ref(pieces) =>
if box_needed {
seq!["std::boxed::Box", anglebrackets![names::render_ref(pieces.clone())]]
} else {
seq![names::render_ref(pieces.clone())]
},
TField::Base(n) => seq![n.to_owned()],
}
}
pub fn render_recordlike_type(is_struct: bool, n: &str, d: &TSimple) -> impl Emittable {
let semi = if is_struct { seq![";"] } else { seq![] };
2021-06-28 15:08:44 +00:00
let ppub = if is_struct { "pub " } else { "" };
2021-06-28 14:35:45 +00:00
seq![names::render_constructor(n), match d {
TSimple::Record(TRecord(fs)) => seq![" ", braces(
fs.iter().map(|(n, d)| item(
2021-06-28 15:26:41 +00:00
seq![ppub, names::render_fieldname(n), ": ", render_field_type(!is_struct, d)]
2021-06-28 14:35:45 +00:00
)).collect())],
TSimple::Field(TField::Unit) => semi,
2021-06-28 15:26:41 +00:00
TSimple::Field(t) => seq![parens![seq![ppub, render_field_type(!is_struct, t)]], semi],
2021-06-28 14:35:45 +00:00
}]
}
pub fn render_definition_type(n: &str, t: &TDefinition) -> impl Emittable {
2021-06-28 15:26:41 +00:00
seq!["#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)]\n",
2021-06-28 14:35:45 +00:00
match t {
TDefinition::Union(items) =>
seq!["pub enum ", names::render_constructor(n), " ", braces(
items.iter().map(|(n, d)| item(render_recordlike_type(false, n, d))).collect())],
TDefinition::Simple(s) =>
seq!["pub struct ", render_recordlike_type(true, n, s)],
}]
}