[*] remove ink_lang and ink_model sub crates

parent fe093478
Pipeline #56436 failed with stages
in 24 seconds
......@@ -3,8 +3,6 @@
members = [
"utils",
"core",
"model",
"lang",
"lang2",
"cli",
"abi",
......
[package]
name = "ink_lang"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "MIT/Apache-2.0"
readme = "README.md"
# repository = "https://github.com/robbepop/substrate-contract"
# homepage = "https://github.com/robbepop/substrate-contract"
# documentation = "https://robbepop.github.io/pwasm-abi/substrate-contract/"
description = "[ink!] Rust based eDSL for writing smart contracts for Substrate"
keywords = ["wasm", "parity", "webassembly", "blockchain", "edsl"]
categories = ["no-std", "embedded"]
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
[dependencies]
ink_utils = { path = "../utils/", default-features = false }
ink_model = { path = "../model/", default-features = false }
scale = { package = "parity-scale-codec", version = "1.0", default-features = false, features = ["derive"] }
quote = "0.6"
syn = { version = "0.15", features = ["parsing", "full", "extra-traits"] }
proc-macro2 = "0.4"
heck = "0.3"
itertools = { version = "0.8", default-features = false }
either = { version = "1.5", default-features = false }
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde_json = "1.0"
[dev-dependencies]
pretty_assertions = "0.6.1"
[lib]
name = "ink_lang"
proc-macro = true
[features]
default = ["test-env"]
std = [
"ink_utils/std",
"ink_model/std",
"scale/std",
"itertools/use_std",
"either/use_std",
"serde/std",
]
test-env = [
"std",
"ink_model/test-env",
]
ink-generate-abi = [
"std",
]
../LICENSE
\ No newline at end of file
../README.md
\ No newline at end of file
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use crate::parser::keywords;
use proc_macro2::{
Ident,
TokenStream as TokenStream2,
};
use syn::{
punctuated::Punctuated,
token,
ReturnType,
Token,
};
#[derive(Debug)]
pub struct Contract {
pub items: Vec<Item>,
}
impl Contract {
pub fn env_metas<'a>(&'a self) -> impl Iterator<Item = &'a ItemEnvMeta> + 'a {
self.items.iter().filter_map(|item| {
match *item {
Item::EnvMeta(ref t) => Some(t),
_ => None,
}
})
}
pub fn states<'a>(&'a self) -> impl Iterator<Item = &'a ItemState> + 'a {
self.items.iter().filter_map(|item| {
match *item {
Item::State(ref c) => Some(c),
_ => None,
}
})
}
pub fn deploy_impl_blocks<'a>(
&'a self,
) -> impl Iterator<Item = &'a ItemDeployImpl> + 'a {
self.items.iter().filter_map(|item| {
match *item {
Item::DeployImpl(ref d) => Some(d),
_ => None,
}
})
}
pub fn impl_blocks<'a>(&'a self) -> impl Iterator<Item = &'a ItemImpl> + 'a {
self.items.iter().filter_map(|item| {
match *item {
Item::Impl(ref i) => Some(i),
_ => None,
}
})
}
pub fn events<'a>(&'a self) -> impl Iterator<Item = &'a ItemEvent> + 'a {
self.items.iter().filter_map(|item| {
match *item {
Item::Event(ref event) => Some(event),
_ => None,
}
})
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum Item {
EnvMeta(ItemEnvMeta),
State(ItemState),
DeployImpl(ItemDeployImpl),
Impl(ItemImpl),
Event(ItemEvent),
}
#[derive(Debug, Clone)]
pub struct ItemEnvMeta {
pub env_types_metas: Vec<ItemEnvTypesMeta>,
}
#[derive(Debug, Clone)]
pub struct ItemEnvTypesMeta {
pub ident: Ident,
pub eq_token: Token![=],
pub ty: syn::Type,
}
/// An event declaration.
///
/// # Example
///
/// This mirrors the syntax for: `event Foo { bar: Bar };`
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ItemEvent {
pub attrs: Vec<syn::Attribute>,
pub event_tok: crate::parser::keywords::event,
pub ident: Ident,
pub brace_tok: token::Brace,
pub args: Punctuated<EventArg, token::Comma>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct EventArg {
pub attrs: Vec<syn::Attribute>,
pub ident: Ident,
pub colon_tok: Token![:],
pub ty: syn::Type,
}
impl EventArg {
/// Returns `true` if the event argument is indexed.
pub fn is_indexed(&self) -> bool {
self.attrs.iter().any(|attr| {
attr.style == syn::AttrStyle::Outer
&& attr.path.is_ident("indexed")
&& attr.tts.is_empty()
})
}
}
#[derive(Debug)]
pub struct ItemState {
pub attrs: Vec<syn::Attribute>,
pub struct_tok: token::Struct,
pub ident: Ident,
pub fields: syn::FieldsNamed,
}
#[derive(Debug)]
pub struct ItemDeployImpl {
pub attrs: Vec<syn::Attribute>,
pub impl_tok: Token![impl],
pub deploy_tok: keywords::Deploy,
pub for_tok: Token![for],
pub self_ty: Ident,
pub brace_tok: token::Brace,
pub item: DeployItemMethod,
}
#[derive(Debug)]
pub struct DeployItemMethod {
pub attrs: Vec<syn::Attribute>,
pub deploy_tok: keywords::deploy,
pub decl: FnDecl,
pub block: syn::Block,
}
#[derive(Debug)]
pub struct ItemImpl {
pub attrs: Vec<syn::Attribute>,
pub impl_tok: token::Impl,
pub self_ty: Ident,
pub brace_tok: token::Brace,
pub items: Vec<ItemImplMethod>,
}
#[derive(Debug)]
pub struct ItemImplMethod {
pub attrs: Vec<syn::Attribute>,
pub vis: MethodVisibility,
pub sig: MethodSig,
pub block: syn::Block,
}
#[derive(Debug, Clone)]
pub enum MethodVisibility {
External(ExternalVisibility),
Inherited,
}
impl MethodVisibility {
/// Returns `true` if this is an external visibility.
///
/// # Note
///
/// The `pub(external)` visibility is only used for contract messages.
pub fn is_external(&self) -> bool {
match self {
MethodVisibility::External(_) => true,
_ => false,
}
}
}
#[derive(Debug, Clone)]
pub struct ExternalVisibility {
pub pub_tok: token::Pub,
pub paren_tok: token::Paren,
pub external_tok: keywords::external,
}
#[derive(Debug, Clone)]
pub struct MethodSig {
pub ident: Ident,
pub decl: FnDecl,
}
#[derive(Debug, Clone)]
pub struct FnDecl {
pub fn_tok: token::Fn,
pub paren_tok: token::Paren,
pub inputs: Punctuated<FnArg, token::Comma>,
pub output: ReturnType,
pub generics: syn::Generics,
}
pub struct FnInputs {
punct: Punctuated<FnArg, Token![,]>,
}
impl FnInputs {
pub fn to_actual_params(&self) -> Punctuated<syn::Pat, Token![,]> {
let mut params: Punctuated<syn::Pat, Token![,]> = Default::default();
for captured in self.punct.iter().filter_map(|fn_arg| {
if let FnArg::Captured(captured) = fn_arg {
Some(captured)
} else {
None
}
}) {
params.push(captured.pat.clone())
}
params
}
}
impl quote::ToTokens for FnInputs {
fn to_tokens(&self, tokens: &mut TokenStream2) {
self.punct.to_tokens(tokens)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum FnDeclKind {
SelfRef,
SelfRefMut,
SelfVal,
Static,
}
impl FnDecl {
pub fn kind(&self) -> FnDeclKind {
match self.inputs.iter().next().unwrap() {
FnArg::SelfRef(self_ref) => {
if self_ref.mutability.is_some() {
FnDeclKind::SelfRefMut
} else {
FnDeclKind::SelfRef
}
}
FnArg::SelfValue(_) => FnDeclKind::SelfVal,
_ => FnDeclKind::Static,
}
}
pub fn is_self_ref(&self) -> bool {
if let FnDeclKind::SelfRef | FnDeclKind::SelfRefMut = self.kind() {
return true
}
false
}
pub fn inputs(&self) -> FnInputs {
assert!(self.is_self_ref());
FnInputs {
punct: self.inputs.clone(),
}
}
pub fn inputs_without_self(&self) -> FnInputs {
assert!(self.is_self_ref());
let mut inputs_without_self: Punctuated<FnArg, Token![,]> = Default::default();
for input in self.inputs.iter().skip(1) {
inputs_without_self.push(input.clone())
}
FnInputs {
punct: inputs_without_self,
}
}
pub fn inputs_with_env(&self, env_handler: &syn::Type) -> FnInputs {
assert!(self.is_self_ref());
let mut inputs_with_env: Punctuated<FnArg, Token![,]> = Default::default();
let mut inputs_iter = self.inputs.iter();
let self_arg = inputs_iter.next().unwrap();
inputs_with_env.push_value(self_arg.clone());
inputs_with_env.push_punct(Default::default());
let custom_arg_captured: ArgCaptured = if self.kind() == FnDeclKind::SelfRefMut {
syn::parse_quote! { env: &mut #env_handler }
} else {
syn::parse_quote! { env: &#env_handler }
};
inputs_with_env.push(FnArg::Captured(custom_arg_captured.into_arg_captured()));
for input in inputs_iter {
inputs_with_env.push(input.clone())
}
FnInputs {
punct: inputs_with_env,
}
}
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone)]
pub enum FnArg {
SelfRef(syn::ArgSelfRef),
SelfValue(syn::ArgSelf),
Captured(syn::ArgCaptured),
}
impl FnArg {
/// Returns the ident if available.
pub fn ident(&self) -> Option<proc_macro2::Ident> {
match self {
FnArg::SelfRef(_) | FnArg::SelfValue(_) => None,
FnArg::Captured(captured) => {
match &captured.pat {
syn::Pat::Ident(pat_ident) => Some(pat_ident.ident.clone()),
_ => None,
}
}
}
}
/// Returns `true` if the fn argument is captured.
pub fn is_captured(&self) -> Option<&syn::ArgCaptured> {
match self {
FnArg::Captured(capt) => Some(capt),
_ => None,
}
}
}
impl quote::ToTokens for FnArg {
fn to_tokens(&self, tokens: &mut TokenStream2) {
match self {
FnArg::SelfRef(arg_self_ref) => arg_self_ref.to_tokens(tokens),
FnArg::SelfValue(arg_self_value) => arg_self_value.to_tokens(tokens),
FnArg::Captured(arg_captured) => arg_captured.to_tokens(tokens),
}
}
}
#[derive(Debug)]
pub struct ArgCaptured {
pub pat: syn::Pat,
pub colon_token: Token![:],
pub ty: syn::Type,
}
impl syn::parse::Parse for ArgCaptured {
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
let pat = input.parse()?;
let colon_token = input.parse()?;
let ty = input.parse()?;
Ok(Self {
pat,
colon_token,
ty,
})
}
}
impl ArgCaptured {
pub fn into_arg_captured(self) -> syn::ArgCaptured {
syn::ArgCaptured {
pat: self.pat,
colon_token: self.colon_token,
ty: self.ty,
}
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use proc_macro2::TokenStream as TokenStream2;
use syn::Result;
#[cfg(feature = "ink-generate-abi")]
use crate::old_abi;
use crate::{
gen,
hir,
parser,
};
pub fn generate(input: TokenStream2) -> TokenStream2 {
match generate_or_err(input) {
Ok(tokens) => tokens,
Err(err) => err.to_compile_error(),
}
}
pub fn generate_or_err(input: TokenStream2) -> Result<TokenStream2> {
let ast_contract = parser::parse_contract(input)?;
let hir_contract = hir::Contract::from_ast(&ast_contract)?;
#[cfg(feature = "ink-generate-abi")]
old_abi::generate_old_abi(&hir_contract)?;
let tokens = gen::generate_code(&hir_contract);
Ok(tokens)
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
macro_rules! bail {
($($args:tt)*) => {
return Err(format_err!($($args)*).into())
}
}
macro_rules! format_err {
($tokens:expr, $($msg:tt)*) => {
match &$tokens {
t => {
syn::parse::Error::new_spanned(t, format_args!($($msg)*))
}
}
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
//! Code generation for smart contract ABI and metadata generation.
//!
//! This two-steps process is required because Rust macros (and thus `ink_lang`)
//! are not able to access type information or anything that is related to that.
use crate::{
ast,
gen::selector_to_expr,
hir,
};
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{
self,
punctuated::Punctuated,
Token,
};
/// Trims a doc string obtained from an attribute token stream into the actual doc string.
///
/// Practically speaking this method removes the trailing start `" = \""` and end `\"`
/// of documentation strings coming from Syn attribute token streams.
fn trim_doc_string(attr: &syn::Attribute) -> String {
attr.tts
.to_string()
.trim_start_matches('=')
.trim_start()
.trim_start_matches('r')
.trim_start_matches('\"')
.trim_end_matches('\"')
.trim()
.into()
}
pub fn generate_code(tokens: &mut TokenStream2, contract: &hir::Contract) {
let abi_mod_body = generate_abi_mod_body(contract);
tokens.extend(abi_mod_body);
}
fn generate_abi_mod_body(contract: &hir::Contract) -> TokenStream2 {
let ink_generate_abi_contract = generate_abi_contract(contract);
let ink_generate_abi_layout = generate_abi_layout(contract);
quote! {
#[cfg(not(feature = "ink-as-dependency"))]
#[cfg(feature = "ink-generate-abi")]
pub fn ink_generate_abi() -> ink_abi::InkProject {
let contract = {
#ink_generate_abi_contract
};
let layout = {
#ink_generate_abi_layout
};
ink_abi::InkProject::new(layout, contract)
}
}
}
fn generate_abi_constructor(contract: &hir::Contract) -> TokenStream2 {
let constructor = &contract.on_deploy;
let args = constructor
.decl
.inputs
.iter()
.filter_map(ast::FnArg::is_captured)
.map(|capt| {
let name = match &capt.pat {
syn::Pat::Ident(pat_ident) => {
if pat_ident.by_ref.is_none()
&& pat_ident.mutability.is_none()
&& pat_ident.subpat.is_none()
{
pat_ident.ident.to_string()
} else {
unreachable!("encountered invalid deploy argument")
}
}
syn::Pat::Path(pat_path) => {
if pat_path.qself.is_none()
&& pat_path.path.leading_colon.is_none()
&& pat_path.path.segments.len() == 1