Skip to content
Merged
33 changes: 32 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,42 @@
### Candid

* Breaking changes:
+ `pp_args` and `pp_init_args` noew require a `&[ArgType]` parameter. The `pp_rets` function has been added, with the signature of the old `pp_args`.
+ `pp_args` and `pp_init_args` now require a `&[ArgType]` parameter. The `pp_rets` function has been added, with the signature of the old `pp_args`.

* Non-breaking changes:
+ The following structs have been moved from the `candid_parser` crate to the `candid::types::syntax` module:
- `IDLType`
- `IDLTypes`
- `PrimType`
- `FuncType`
- `IDLArgType`
- `TypeField`
- `Dec`
- `Binding`
- `IDLProg`
- `IDLInitArgs`

### candid_parser

* Breaking changes:
+ The following structs have been moved to the `candid` crate:
- `IDLType`
- `IDLTypes`
- `PrimType`
- `FuncType`
- `IDLArgType`
- `TypeField`
- `Dec`
- `Binding`
- `IDLProg`
- `IDLInitArgs`
As a consequence, the `FromStr` trait is no longer implemented for the following types:
- `IDLProg`
- `IDLInitArgs`
- `IDLType`
- `IDLTypes`
You must now use the `parse_idl_prog`, `parse_idl_init_args`, `parse_idl_type` and `parse_idl_types` functions to parse these types, respectively.
+ `pretty_parse` doesn't work anymore with the `IDLProg` and `IDLTypes` types. Use `pretty_parse_idl_prog` and `pretty_parse_idl_types` instead.
+ The `args` field in both `FuncType` and `IDLInitArgs` now have type `Vec<IDLArgType>`.

* Non-breaking changes:
Expand Down
1 change: 1 addition & 0 deletions rust/candid/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use serde::ser::Error;
mod impls;
pub mod internal;
pub mod subtype;
pub mod syntax;
pub mod type_env;
#[cfg_attr(docsrs, doc(cfg(feature = "value")))]
#[cfg(feature = "value")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::Result;
use candid::types::{FuncMode, Label};
use crate::types::{FuncMode, Label};

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IDLType {
PrimT(PrimType),
VarT(String),
Expand Down Expand Up @@ -60,14 +59,14 @@ pub enum PrimType {
Empty,
}}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FuncType {
pub modes: Vec<FuncMode>,
pub args: Vec<IDLArgType>,
pub rets: Vec<IDLType>,
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IDLArgType {
pub typ: IDLType,
pub name: Option<String>,
Expand All @@ -91,7 +90,7 @@ impl IDLArgType {
}
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TypeField {
pub label: Label,
pub typ: IDLType,
Expand All @@ -104,13 +103,13 @@ pub enum Dec {
ImportServ(String),
}

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Binding {
pub id: String,
pub typ: IDLType,
}

#[derive(Debug)]
#[derive(Debug, Default)]
pub struct IDLProg {
pub decs: Vec<Dec>,
pub actor: Option<IDLType>,
Expand All @@ -121,34 +120,3 @@ pub struct IDLInitArgs {
pub decs: Vec<Dec>,
pub args: Vec<IDLArgType>,
}

impl std::str::FromStr for IDLProg {
type Err = crate::Error;
fn from_str(str: &str) -> Result<Self> {
let lexer = super::token::Tokenizer::new(str);
Ok(super::grammar::IDLProgParser::new().parse(lexer)?)
}
}
impl std::str::FromStr for IDLInitArgs {
type Err = crate::Error;
fn from_str(str: &str) -> Result<Self> {
let lexer = super::token::Tokenizer::new(str);
Ok(super::grammar::IDLInitArgsParser::new().parse(lexer)?)
}
}

impl std::str::FromStr for IDLType {
type Err = crate::Error;
fn from_str(str: &str) -> Result<Self> {
let lexer = super::token::Tokenizer::new(str);
Ok(super::grammar::TypParser::new().parse(lexer)?)
}
}

impl std::str::FromStr for IDLTypes {
type Err = crate::Error;
fn from_str(str: &str) -> Result<Self> {
let lexer = super::token::Tokenizer::new(str);
Ok(super::grammar::TypsParser::new().parse(lexer)?)
}
}
4 changes: 2 additions & 2 deletions rust/candid_parser/src/bindings/motoko.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

use candid::pretty::candid::is_valid_as_id;
use candid::pretty::utils::*;
use candid::types::{ArgType, FuncMode};
use candid::types::{Field, Function, Label, SharedLabel, Type, TypeEnv, TypeInner};
use candid::types::{ArgType, Field, FuncMode, Function, Label, SharedLabel, Type, TypeInner};
use candid::TypeEnv;
use pretty::RcDoc;

// The definition of tuple is language specific.
Expand Down
27 changes: 18 additions & 9 deletions rust/candid_parser/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
//! When serializing or deserializing Candid goes wrong.

use candid::types::syntax::{IDLProg, IDLTypes};
use codespan_reporting::diagnostic::Label;
use std::io;
use thiserror::Error;

use crate::token;
use crate::{parse_idl_prog, parse_idl_types, token};
use codespan_reporting::{
diagnostic::Diagnostic,
files::{Error as ReportError, SimpleFile},
Expand Down Expand Up @@ -105,14 +106,20 @@ impl From<toml::de::Error> for Error {
}
}

/// Does not work for parsing [IDLProg] and [IDLTypes], use [pretty_parse_idl_prog] and [pretty_parse_idl_types] instead.
pub fn pretty_parse<T>(name: &str, str: &str) -> Result<T>
where
T: std::str::FromStr<Err = Error>,
{
str.parse::<T>().or_else(|e| {
pretty_diagnose(name, str, &e)?;
Err(e)
})
str.parse::<T>().or_else(|e| pretty_print_err(name, str, e))
}

pub fn pretty_parse_idl_prog(name: &str, str: &str) -> Result<IDLProg> {
parse_idl_prog(str).or_else(|e| pretty_print_err(name, str, e))
}

pub fn pretty_parse_idl_types(name: &str, str: &str) -> Result<IDLTypes> {
parse_idl_types(str).or_else(|e| pretty_print_err(name, str, e))
}

/// Wrap the parser error and pretty print the error message.
Expand All @@ -122,10 +129,12 @@ where
/// # Ok::<(), candid_parser::Error>(())
/// ```
pub fn pretty_wrap<T>(name: &str, str: &str, f: impl FnOnce(&str) -> Result<T>) -> Result<T> {
f(str).or_else(|e| {
pretty_diagnose(name, str, &e)?;
Err(e)
})
f(str).or_else(|e| pretty_print_err(name, str, e))
}

fn pretty_print_err<T>(name: &str, source: &str, e: Error) -> Result<T> {
pretty_diagnose(name, source, &e)?;
Err(e)
}

pub fn pretty_diagnose(file_name: &str, source: &str, e: &Error) -> Result<()> {
Expand Down
2 changes: 1 addition & 1 deletion rust/candid_parser/src/grammar.lalrpop
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::types::{IDLType, PrimType, TypeField, FuncType, Binding, Dec, IDLProg, IDLTypes, IDLInitArgs, IDLArgType};
use super::test::{Assert, Input, Test};
use super::token::{Token, error, error2, LexicalError, Span};
use candid::{Principal, types::Label};
use candid::types::syntax::{IDLType, PrimType, TypeField, FuncType, Binding, Dec, IDLProg, IDLTypes, IDLInitArgs, IDLArgType};
use candid::types::value::{IDLField, IDLValue, IDLArgs, VariantValue};
use candid::types::{TypeEnv, FuncMode};
use candid::utils::check_unique;
Expand Down
36 changes: 28 additions & 8 deletions rust/candid_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
//! ```
//! # fn f() -> anyhow::Result<()> {
//! use candid::{TypeEnv, types::{Type, TypeInner}};
//! use candid_parser::{IDLProg, check_prog};
//! use candid_parser::{check_prog, parse_idl_prog};
//! let did_file = r#"
//! type List = opt record { head: int; tail: List };
//! type byte = nat8;
Expand All @@ -58,7 +58,7 @@
//! "#;
//!
//! // Parse did file into an AST
//! let ast: IDLProg = did_file.parse()?;
//! let ast = parse_idl_prog(did_file)?;
//!
//! // Type checking a given .did file
//! // let (env, opt_actor) = check_file("a.did")?;
Expand Down Expand Up @@ -86,7 +86,7 @@
//! use candid::{IDLArgs, types::value::IDLValue};
//! use candid_parser::parse_idl_args;
//! # use candid::TypeEnv;
//! # use candid_parser::{IDLProg, check_prog};
//! # use candid_parser::{check_prog, parse_idl_prog};
//! # let did_file = r#"
//! # type List = opt record { head: int; tail: List };
//! # type byte = nat8;
Expand All @@ -95,7 +95,7 @@
//! # g : (List) -> (int) query;
//! # }
//! # "#;
//! # let ast = did_file.parse::<IDLProg>()?;
//! # let ast = parse_idl_prog(did_file)?;
//! # let mut env = TypeEnv::new();
//! # let actor = check_prog(&mut env, &ast)?.unwrap();
//! // Get method type f : (byte, int, nat, int8) -> (List)
Expand All @@ -119,15 +119,15 @@
#![cfg_attr(docsrs, feature(doc_cfg))]

pub mod error;
pub use error::{pretty_parse, pretty_wrap, Error, Result};
pub use error::{
pretty_parse, pretty_parse_idl_prog, pretty_parse_idl_types, pretty_wrap, Error, Result,
};

pub mod bindings;
pub mod grammar;
pub mod token;
pub mod types;
pub mod utils;
pub use types::IDLProg;
pub mod typing;
pub mod utils;
pub use typing::{check_file, check_prog, pretty_check_file};

pub use candid;
Expand All @@ -142,6 +142,26 @@ pub mod configs;
pub mod random;
pub mod test;

pub fn parse_idl_prog(str: &str) -> Result<candid::types::syntax::IDLProg> {
let lexer = token::Tokenizer::new(str);
Ok(grammar::IDLProgParser::new().parse(lexer)?)
}

pub fn parse_idl_init_args(str: &str) -> Result<candid::types::syntax::IDLInitArgs> {
let lexer = token::Tokenizer::new(str);
Ok(grammar::IDLInitArgsParser::new().parse(lexer)?)
}

pub fn parse_idl_type(str: &str) -> Result<candid::types::syntax::IDLType> {
let lexer = token::Tokenizer::new(str);
Ok(grammar::TypParser::new().parse(lexer)?)
}

pub fn parse_idl_types(str: &str) -> Result<candid::types::syntax::IDLTypes> {
let lexer = token::Tokenizer::new(str);
Ok(grammar::TypsParser::new().parse(lexer)?)
}

pub fn parse_idl_args(s: &str) -> crate::Result<candid::IDLArgs> {
let lexer = token::Tokenizer::new(s);
Ok(grammar::ArgsParser::new().parse(lexer)?)
Expand Down
2 changes: 1 addition & 1 deletion rust/candid_parser/src/test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::types::{Dec, IDLProg, IDLType};
use super::typing::check_prog;
use crate::{Error, Result};
use candid::types::syntax::{Dec, IDLProg, IDLType};
use candid::types::value::IDLArgs;
use candid::types::{Type, TypeEnv};
use candid::DecoderConfig;
Expand Down
20 changes: 11 additions & 9 deletions rust/candid_parser/src/typing.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use super::types::*;
use crate::{pretty_parse, Error, Result};
use candid::types::{ArgType, Field, Function, Type, TypeEnv, TypeInner};
use crate::{parse_idl_prog, pretty_parse_idl_prog, Error, Result};
use candid::types::{
syntax::{Binding, Dec, IDLArgType, IDLInitArgs, IDLProg, IDLType, PrimType, TypeField},
ArgType, Field, Function, Type, TypeEnv, TypeInner,
};
use candid::utils::check_unique;
use std::collections::{BTreeMap, BTreeSet};
use std::path::{Path, PathBuf};
Expand All @@ -11,7 +13,7 @@ pub struct Env<'a> {
}

/// Convert candid AST to internal Type
pub fn ast_to_type(env: &TypeEnv, ast: &super::types::IDLType) -> Result<Type> {
pub fn ast_to_type(env: &TypeEnv, ast: &IDLType) -> Result<Type> {
let env = Env {
te: &mut env.clone(),
pre: false,
Expand Down Expand Up @@ -237,9 +239,9 @@ fn load_imports(
let code = std::fs::read_to_string(&path)
.map_err(|_| Error::msg(format!("Cannot import {file:?}")))?;
let code = if is_pretty {
pretty_parse::<IDLProg>(path.to_str().unwrap(), &code)?
pretty_parse_idl_prog(path.to_str().unwrap(), &code)?
} else {
code.parse::<IDLProg>()?
parse_idl_prog(&code)?
};
let base = path.parent().unwrap();
load_imports(is_pretty, base, visited, &code, list)?;
Expand Down Expand Up @@ -324,9 +326,9 @@ fn check_file_(file: &Path, is_pretty: bool) -> Result<(TypeEnv, Option<Type>)>
let prog =
std::fs::read_to_string(file).map_err(|_| Error::msg(format!("Cannot open {file:?}")))?;
let prog = if is_pretty {
pretty_parse::<IDLProg>(file.to_str().unwrap(), &prog)?
pretty_parse_idl_prog(file.to_str().unwrap(), &prog)?
} else {
prog.parse::<IDLProg>()?
parse_idl_prog(&prog)?
};
let mut visited = BTreeMap::new();
let mut imports = Vec::new();
Expand All @@ -346,7 +348,7 @@ fn check_file_(file: &Path, is_pretty: bool) -> Result<(TypeEnv, Option<Type>)>
let mut actor: Option<Type> = None;
for (include_serv, path, name) in imports.iter() {
let code = std::fs::read_to_string(path)?;
let code = code.parse::<IDLProg>()?;
let code = parse_idl_prog(&code)?;
check_decs(&mut env, &code.decs)?;
if *include_serv {
let t = check_actor(&env, &code.actor)?;
Expand Down
Loading