Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 52 additions & 26 deletions rust/candid_parser/src/bindings/motoko.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This module implements the Candid to Motoko binding as specified in
// https://github.com/dfinity/motoko/blob/master/design/IDL-Motoko.md

use crate::syntax::{self, IDLActorType, IDLMergedProg, IDLType};
use crate::syntax::{self, IDLActorType, IDLMergedProg, IDLType, IDLTypeKind};
use candid::pretty::candid::is_valid_as_id;
use candid::pretty::utils::*;
use candid::types::{Field, FuncMode, Function, Label, SharedLabel, Type, TypeInner};
Expand Down Expand Up @@ -97,24 +97,44 @@ fn escape(id: &str, is_method: bool) -> RcDoc<'_> {
}

fn pp_ty_rich<'a>(ty: &'a Type, syntax: Option<&'a IDLType>) -> RcDoc<'a> {
match (ty.as_ref(), syntax) {
(TypeInner::Service(ref meths), Some(IDLType::ServT(methods))) => {
pp_service(meths, Some(methods))
match ty.as_ref() {
TypeInner::Service(ref meths) => {
if let Some(IDLTypeKind::ServT(methods)) = syntax {
return pp_service(meths, Some(methods));
}
pp_service(meths, None)
}
TypeInner::Class(ref args, t) => {
if let Some(IDLTypeKind::ClassT(_, syntax_t)) = syntax {
return pp_class((args, t), Some(syntax_t));
}
pp_class((args, t), None)
}
(TypeInner::Class(ref args, t), Some(IDLType::ClassT(_, syntax_t))) => {
pp_class((args, t), Some(syntax_t))
TypeInner::Record(ref fields) => {
if let Some(IDLTypeKind::RecordT(syntax_fields)) = syntax {
return pp_record(fields, Some(syntax_fields));
}
pp_record(fields, None)
}
(TypeInner::Record(ref fields), Some(IDLType::RecordT(syntax_fields))) => {
pp_record(fields, Some(syntax_fields))
TypeInner::Variant(ref fields) => {
if let Some(IDLTypeKind::VariantT(syntax_fields)) = syntax {
return pp_variant(fields, Some(syntax_fields));
}
pp_variant(fields, None)
}
(TypeInner::Variant(ref fields), Some(IDLType::VariantT(syntax_fields))) => {
pp_variant(fields, Some(syntax_fields))
TypeInner::Opt(ref inner) => {
if let Some(IDLTypeKind::OptT(syntax_inner)) = syntax {
return str("?").append(pp_ty_rich(inner, Some(syntax_inner)));
}
str("?").append(pp_ty(inner))
}
(TypeInner::Opt(ref inner), Some(IDLType::OptT(syntax))) => {
str("?").append(pp_ty_rich(inner, Some(syntax)))
TypeInner::Vec(ref inner) => {
if let Some(IDLTypeKind::VecT(syntax_inner)) = syntax {
return pp_vec(inner, Some(syntax_inner));
}
pp_vec(inner, None)
}
(TypeInner::Vec(ref inner), Some(IDLType::VecT(syntax))) => pp_vec(inner, Some(syntax)),
(_, _) => pp_ty(ty),
_ => pp_ty(ty),
}
}

Expand Down Expand Up @@ -310,27 +330,33 @@ fn pp_defs<'a>(env: &'a TypeEnv, prog: &'a IDLMergedProg) -> RcDoc<'a> {
fn pp_actor<'a>(ty: &'a Type, syntax: Option<&'a IDLActorType>) -> RcDoc<'a> {
let self_doc = kwd("public type Self =");
match ty.as_ref() {
TypeInner::Service(ref serv) => match syntax {
Some(IDLActorType {
typ: IDLType::ServT(ref fields),
TypeInner::Service(ref serv) => {
if let Some(IDLActorType {
typ: IDLTypeKind::ServT(fields),
docs,
}) => {
..
}) = syntax
{
let docs = pp_docs(docs);
docs.append(self_doc).append(pp_service(serv, Some(fields)))
} else {
pp_service(serv, None)
}
_ => pp_service(serv, None),
},
TypeInner::Class(ref args, ref t) => match syntax {
Some(IDLActorType {
typ: IDLType::ClassT(_, syntax_t),
}
TypeInner::Class(ref args, ref t) => {
if let Some(IDLActorType {
typ: IDLTypeKind::ClassT(_, syntax_t),
docs,
}) => {
..
}) = syntax
{
let docs = pp_docs(docs);
docs.append(self_doc)
.append(pp_class((args, t), Some(syntax_t)))
} else {
self_doc.append(pp_class((args, t), None))
}
_ => self_doc.append(pp_class((args, t), None)),
},
}
TypeInner::Var(_) => self_doc.append(pp_ty(ty)),
_ => unreachable!(),
}
Expand Down
60 changes: 26 additions & 34 deletions rust/candid_parser/src/bindings/rust.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::analysis::{chase_actor, infer_rec};
use crate::{
configs::{ConfigState, ConfigTree, Configs, Context, StateElem},
syntax::{self, IDLActorType, IDLMergedProg, IDLType},
syntax::{self, IDLActorType, IDLMergedProg, IDLType, IDLTypeKind},
Deserialize,
};
use candid::pretty::utils::*;
Expand Down Expand Up @@ -157,19 +157,17 @@ fn find_field<'a>(
}

fn record_syntax_fields(syntax: Option<&IDLType>) -> Option<&[syntax::TypeField]> {
if let Some(IDLType::RecordT(syntax_fields)) = syntax {
Some(syntax_fields.as_slice())
} else {
None
}
syntax.and_then(|ty| match ty {
IDLTypeKind::RecordT(fields) => Some(fields.as_slice()),
_ => None,
})
}

fn variant_syntax_fields(syntax: Option<&IDLType>) -> Option<&[syntax::TypeField]> {
if let Some(IDLType::VariantT(syntax_fields)) = syntax {
Some(syntax_fields.as_slice())
} else {
None
}
syntax.and_then(|ty| match ty {
IDLTypeKind::VariantT(fields) => Some(fields.as_slice()),
_ => None,
})
}

fn actor_methods(actor: Option<&IDLActorType>) -> &[syntax::Binding] {
Expand All @@ -179,14 +177,11 @@ fn actor_methods(actor: Option<&IDLActorType>) -> &[syntax::Binding] {
};

match typ {
IDLType::ServT(methods) => methods,
IDLType::ClassT(_, inner) => {
if let IDLType::ServT(methods) = inner.as_ref() {
methods
} else {
&[]
}
}
IDLTypeKind::ServT(methods) => methods,
IDLTypeKind::ClassT(_, inner) => match inner.as_ref() {
IDLTypeKind::ServT(methods) => methods,
_ => &[],
},
_ => &[],
}
}
Expand Down Expand Up @@ -924,22 +919,20 @@ impl<'b> NominalState<'_, 'b> {
let res = match t.as_ref() {
TypeInner::Opt(ty) => {
path.push(TypePath::Opt);
let syntax_ty = if let Some(IDLType::OptT(inner)) = syntax {
Some(inner.as_ref())
} else {
None
};
let syntax_ty = syntax.and_then(|s| match s {
IDLTypeKind::OptT(inner) => Some(inner.as_ref()),
_ => None,
});
let ty = self.nominalize(env, path, ty, syntax_ty);
path.pop();
TypeInner::Opt(ty)
}
TypeInner::Vec(ty) => {
path.push(TypePath::Vec);
let syntax_ty = if let Some(IDLType::VecT(inner)) = syntax {
Some(inner.as_ref())
} else {
None
};
let syntax_ty = syntax.and_then(|s| match s {
IDLTypeKind::VecT(inner) => Some(inner.as_ref()),
_ => None,
});
let ty = self.nominalize(env, path, ty, syntax_ty);
path.pop();
TypeInner::Vec(ty)
Expand Down Expand Up @@ -1129,11 +1122,10 @@ impl<'b> NominalState<'_, 'b> {
}
},
TypeInner::Class(args, ty) => {
let syntax_ty = if let Some(IDLType::ClassT(_, syntax_ty)) = syntax {
Some(syntax_ty.as_ref())
} else {
None
};
let syntax_ty = syntax.and_then(|s| match s {
IDLTypeKind::ClassT(_, syntax_ty) => Some(syntax_ty.as_ref()),
_ => None,
});
TypeInner::Class(
args.iter()
.map(|arg| {
Expand Down
48 changes: 31 additions & 17 deletions rust/candid_parser/src/bindings/typescript.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::javascript::{ident, is_tuple_fields};
use crate::syntax::{self, IDLMergedProg, IDLType};
use crate::syntax::{self, IDLMergedProg, IDLType, IDLTypeKind};
use candid::pretty::utils::*;
use candid::types::{Field, Function, Label, SharedLabel, Type, TypeEnv, TypeInner};
use pretty::RcDoc;
Expand Down Expand Up @@ -29,23 +29,38 @@ fn pp_ty_rich<'a>(
syntax: Option<&'a IDLType>,
is_ref: bool,
) -> RcDoc<'a> {
match (ty.as_ref(), syntax) {
(TypeInner::Record(ref fields), Some(IDLType::RecordT(syntax_fields))) => {
pp_record(env, fields, Some(syntax_fields), is_ref)
match ty.as_ref() {
TypeInner::Record(ref fields) => {
if let Some(IDLTypeKind::RecordT(syntax_fields)) = syntax {
return pp_record(env, fields, Some(syntax_fields), is_ref);
}
pp_record(env, fields, None, is_ref)
}
(TypeInner::Variant(ref fields), Some(IDLType::VariantT(syntax_fields))) => {
pp_variant(env, fields, Some(syntax_fields), is_ref)
TypeInner::Variant(ref fields) => {
if let Some(IDLTypeKind::VariantT(syntax_fields)) = syntax {
return pp_variant(env, fields, Some(syntax_fields), is_ref);
}
pp_variant(env, fields, None, is_ref)
}
(TypeInner::Service(ref serv), Some(IDLType::ServT(syntax_serv))) => {
pp_service(env, serv, Some(syntax_serv))
TypeInner::Service(ref serv) => {
if let Some(IDLTypeKind::ServT(syntax_serv)) = syntax {
return pp_service(env, serv, Some(syntax_serv));
}
pp_service(env, serv, None)
}
(TypeInner::Opt(ref t), Some(IDLType::OptT(syntax_inner))) => {
pp_opt(env, t, Some(syntax_inner), is_ref)
TypeInner::Opt(ref t) => {
if let Some(IDLTypeKind::OptT(syntax_inner)) = syntax {
return pp_opt(env, t, Some(syntax_inner), is_ref);
}
pp_opt(env, t, None, is_ref)
}
(TypeInner::Vec(ref t), Some(IDLType::VecT(syntax_inner))) => {
pp_vec(env, t, Some(syntax_inner), is_ref)
TypeInner::Vec(ref t) => {
if let Some(IDLTypeKind::VecT(syntax_inner)) = syntax {
return pp_vec(env, t, Some(syntax_inner), is_ref);
}
pp_vec(env, t, None, is_ref)
}
(_, _) => pp_ty(env, ty, is_ref),
_ => pp_ty(env, ty, is_ref),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the typing.rs file, I would avoid refactoring code that is not in scope with the PR's goal

}
}

Expand Down Expand Up @@ -308,11 +323,10 @@ fn pp_actor<'a>(env: &'a TypeEnv, ty: &'a Type, syntax: Option<&'a IDLType>) ->
.append(str(id))
.append(str(" {}")),
TypeInner::Class(_, t) => {
if let Some(IDLType::ClassT(_, syntax_t)) = syntax {
pp_actor(env, t, Some(syntax_t))
} else {
pp_actor(env, t, None)
if let Some(IDLTypeKind::ClassT(_, syntax_t)) = syntax {
return pp_actor(env, t, Some(syntax_t));
}
pp_actor(env, t, None)
}
_ => unreachable!(),
}
Expand Down
Loading
Loading