2021-06-28 14:35:45 +00:00
|
|
|
use crate::*;
|
|
|
|
use crate::syntax::block::Emittable;
|
|
|
|
use crate::syntax::block::constructors::*;
|
2021-06-29 20:32:35 +00:00
|
|
|
use crate::gen::schema::*;
|
|
|
|
|
|
|
|
use super::context::ModuleContext;
|
2021-06-28 14:35:45 +00:00
|
|
|
use super::names;
|
|
|
|
|
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>),
|
2021-06-29 21:19:22 +00:00
|
|
|
Ref(Ref),
|
2021-06-28 14:35:45 +00:00
|
|
|
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)>);
|
|
|
|
|
2021-06-28 20:25:41 +00:00
|
|
|
pub fn definition_type(d: &Definition) -> TDefinition {
|
|
|
|
match d {
|
2021-06-29 14:54:29 +00:00
|
|
|
Definition::Or { pattern_0, pattern_1, pattern_n } =>
|
|
|
|
TDefinition::Union(or_definition_type(pattern_0, pattern_1, pattern_n)),
|
|
|
|
Definition::And { pattern_0, pattern_1, pattern_n } =>
|
|
|
|
TDefinition::Simple(and_definition_type(pattern_0, pattern_1, pattern_n)),
|
|
|
|
Definition::Pattern(p) =>
|
|
|
|
TDefinition::Simple(pattern_type(p)),
|
2021-06-28 14:35:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-29 14:54:29 +00:00
|
|
|
pub fn or_definition_type(
|
|
|
|
p0: &NamedAlternative,
|
|
|
|
p1: &NamedAlternative,
|
|
|
|
pn: &Vec<NamedAlternative>,
|
|
|
|
) -> Vec<(String, TSimple)> {
|
|
|
|
let mut entries = Vec::new();
|
|
|
|
entries.push((p0.variant_label.to_owned(), pattern_type(&p0.pattern)));
|
|
|
|
entries.push((p1.variant_label.to_owned(), pattern_type(&p1.pattern)));
|
|
|
|
for e in pn {
|
|
|
|
entries.push((e.variant_label.to_owned(), pattern_type(&e.pattern)));
|
|
|
|
}
|
|
|
|
entries
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn and_definition_type(
|
|
|
|
p0: &NamedPattern,
|
|
|
|
p1: &NamedPattern,
|
|
|
|
pn: &Vec<NamedPattern>,
|
|
|
|
) -> TSimple {
|
|
|
|
let mut arms = vec![p0, p1];
|
|
|
|
arms.extend(pn);
|
|
|
|
record_type(&arms)
|
|
|
|
}
|
|
|
|
|
2021-06-28 20:25:41 +00:00
|
|
|
pub fn pattern_type(p: &Pattern) -> TSimple {
|
|
|
|
match p {
|
|
|
|
Pattern::SimplePattern(p) =>
|
|
|
|
TSimple::Field(field_type(p)),
|
|
|
|
Pattern::CompoundPattern(_) =>
|
|
|
|
record_type(&vec![&NamedPattern::Anonymous(Box::new(p.clone()))]),
|
2021-06-28 14:35:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-28 20:25:41 +00:00
|
|
|
pub fn record_type(ps: &Vec<&NamedPattern>) -> TSimple {
|
|
|
|
let fs = gather_fields(ps, Vec::new());
|
2021-06-28 14:35:45 +00:00
|
|
|
if fs.is_empty() {
|
2021-06-28 20:25:41 +00:00
|
|
|
TSimple::Field(TField::Unit)
|
2021-06-28 14:35:45 +00:00
|
|
|
} else {
|
2021-06-28 20:25:41 +00:00
|
|
|
TSimple::Record(TRecord(fs))
|
2021-06-28 14:35:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-28 20:25:41 +00:00
|
|
|
pub fn gather_fields(ps: &Vec<&NamedPattern>, mut fs: Vec<(String, TField)>) -> Vec<(String, TField)>
|
2021-06-28 14:35:45 +00:00
|
|
|
{
|
|
|
|
for p in ps.iter() {
|
2021-06-28 20:25:41 +00:00
|
|
|
fs = gather_field(p, fs);
|
2021-06-28 14:35:45 +00:00
|
|
|
}
|
2021-06-28 20:25:41 +00:00
|
|
|
fs
|
2021-06-28 14:35:45 +00:00
|
|
|
}
|
|
|
|
|
2021-06-28 20:25:41 +00:00
|
|
|
pub fn gather_field(p: &NamedPattern, mut fs: Vec<(String, TField)>) -> Vec<(String, TField)> {
|
|
|
|
match p {
|
|
|
|
NamedPattern::Named(b) => {
|
|
|
|
let Binding { name, pattern } = &**b;
|
|
|
|
fs.push((name.to_owned(), field_type(pattern)));
|
|
|
|
fs
|
|
|
|
},
|
|
|
|
NamedPattern::Anonymous(p) => match &**p {
|
|
|
|
Pattern::SimplePattern(_) =>
|
|
|
|
fs,
|
|
|
|
Pattern::CompoundPattern(c) => match &**c {
|
|
|
|
CompoundPattern::Rec { label, fields } =>
|
|
|
|
gather_field(&*fields, gather_field(&*label, fs)),
|
|
|
|
CompoundPattern::Tuple { patterns } =>
|
|
|
|
gather_fields(&patterns.iter().collect(), fs),
|
|
|
|
CompoundPattern::TuplePrefix { fixed, variable } =>
|
|
|
|
gather_field(&promote(&**variable), gather_fields(&fixed.iter().collect(), fs)),
|
|
|
|
CompoundPattern::Dict { entries } => {
|
|
|
|
for (_k, p) in &entries.0 {
|
|
|
|
fs = gather_field(&promote(&p), fs);
|
|
|
|
}
|
|
|
|
fs
|
|
|
|
}
|
|
|
|
}
|
2021-06-28 14:35:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-28 20:25:41 +00:00
|
|
|
pub fn promote(p: &NamedSimplePattern) -> NamedPattern {
|
|
|
|
match p {
|
|
|
|
NamedSimplePattern::Anonymous(p) => NamedPattern::Anonymous(Box::new(Pattern::SimplePattern(p.clone()))),
|
|
|
|
NamedSimplePattern::Named(n) => NamedPattern::Named(n.clone()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn field_type(p: &SimplePattern) -> TField {
|
|
|
|
match p {
|
2021-06-30 07:53:32 +00:00
|
|
|
SimplePattern::Any => TField::Base("_Any".to_owned()),
|
2021-06-28 20:25:41 +00:00
|
|
|
SimplePattern::Atom { atom_kind: k } =>
|
|
|
|
match **k {
|
|
|
|
AtomKind::Boolean => TField::Base("bool".to_owned()),
|
2021-06-30 08:14:29 +00:00
|
|
|
AtomKind::Float => TField::Base("preserves::value::Float".to_owned()),
|
|
|
|
AtomKind::Double => TField::Base("preserves::value::Double".to_owned()),
|
2021-06-28 20:25:41 +00:00
|
|
|
AtomKind::SignedInteger => TField::Base("preserves::value::signed_integer::SignedInteger".to_owned()),
|
|
|
|
AtomKind::String => TField::Base("std::string::String".to_owned()),
|
|
|
|
AtomKind::ByteString => TField::Base("std::vec::Vec<u8>".to_owned()),
|
|
|
|
AtomKind::Symbol => TField::Base("std::string::String".to_owned()),
|
|
|
|
},
|
2021-06-29 21:19:22 +00:00
|
|
|
SimplePattern::Embedded { .. } => TField::Base("_Ptr".to_owned()),
|
2021-06-28 20:25:41 +00:00
|
|
|
SimplePattern::Lit { .. } => TField::Unit,
|
|
|
|
SimplePattern::Seqof { pattern: t } => TField::Array(Box::new(field_type(t))),
|
|
|
|
SimplePattern::Setof { pattern: t } => TField::Set(Box::new(field_type(t))),
|
|
|
|
SimplePattern::Dictof { key: k, value: v } =>
|
|
|
|
TField::Map(Box::new(field_type(k)), Box::new(field_type(v))),
|
2021-06-29 21:19:22 +00:00
|
|
|
SimplePattern::Ref(r) => TField::Ref((**r).clone()),
|
2021-06-28 14:35:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-29 20:32:35 +00:00
|
|
|
pub fn render_field_type(
|
|
|
|
ctxt: &ModuleContext,
|
|
|
|
box_needed: bool,
|
|
|
|
t: &TField,
|
|
|
|
) -> impl Emittable {
|
2021-06-28 14:35:45 +00:00
|
|
|
match t {
|
|
|
|
TField::Unit => seq!["()"],
|
2021-06-29 20:32:35 +00:00
|
|
|
TField::Array(t) => seq!["std::vec::Vec<", render_field_type(ctxt, false, t), ">"],
|
|
|
|
TField::Set(t) => seq!["preserves::value::Set<", render_field_type(ctxt, false, t), ">"],
|
2021-06-28 14:35:45 +00:00
|
|
|
TField::Map(k, v) => seq!["preserves::value::Map",
|
2021-06-29 20:32:35 +00:00
|
|
|
anglebrackets![render_field_type(ctxt, false, k),
|
|
|
|
render_field_type(ctxt, false, v)]],
|
2021-06-29 21:19:22 +00:00
|
|
|
TField::Ref(r) =>
|
2021-06-28 14:35:45 +00:00
|
|
|
if box_needed {
|
2021-06-29 21:19:22 +00:00
|
|
|
seq!["std::boxed::Box", anglebrackets![ctxt.render_ref(r)]]
|
2021-06-28 14:35:45 +00:00
|
|
|
} else {
|
2021-06-29 21:19:22 +00:00
|
|
|
seq![ctxt.render_ref(r)]
|
2021-06-28 14:35:45 +00:00
|
|
|
},
|
|
|
|
TField::Base(n) => seq![n.to_owned()],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-29 20:32:35 +00:00
|
|
|
pub fn render_recordlike_type(
|
|
|
|
ctxt: &ModuleContext,
|
|
|
|
is_struct: bool,
|
|
|
|
n: &str,
|
|
|
|
d: &TSimple,
|
|
|
|
) -> impl Emittable {
|
2021-06-28 14:35:45 +00:00
|
|
|
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-29 20:32:35 +00:00
|
|
|
seq![ppub, names::render_fieldname(n), ": ", render_field_type(ctxt, !is_struct, d)]
|
2021-06-28 14:35:45 +00:00
|
|
|
)).collect())],
|
|
|
|
TSimple::Field(TField::Unit) => semi,
|
2021-06-29 20:32:35 +00:00
|
|
|
TSimple::Field(t) => seq![parens![seq![ppub, render_field_type(ctxt, !is_struct, t)]], semi],
|
2021-06-28 14:35:45 +00:00
|
|
|
}]
|
|
|
|
}
|
|
|
|
|
2021-06-29 20:32:35 +00:00
|
|
|
pub fn render_definition_type(
|
|
|
|
ctxt: &ModuleContext,
|
|
|
|
n: &str,
|
|
|
|
t: &TDefinition,
|
|
|
|
) -> impl Emittable {
|
2021-06-30 07:53:32 +00:00
|
|
|
seq!["#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)]\n",
|
2021-06-28 14:35:45 +00:00
|
|
|
match t {
|
|
|
|
TDefinition::Union(items) =>
|
|
|
|
seq!["pub enum ", names::render_constructor(n), " ", braces(
|
2021-06-29 20:32:35 +00:00
|
|
|
items.iter().map(|(n, d)| item(render_recordlike_type(ctxt, false, n, d))).collect())],
|
2021-06-28 14:35:45 +00:00
|
|
|
TDefinition::Simple(s) =>
|
2021-06-29 20:32:35 +00:00
|
|
|
seq!["pub struct ", render_recordlike_type(ctxt, true, n, s)],
|
2021-06-28 14:35:45 +00:00
|
|
|
}]
|
|
|
|
}
|