Skip to content

Commit

Permalink
[lang] Initial commit for the actual eDSL
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbepop committed Mar 7, 2019
1 parent b1e0e72 commit ee17938
Show file tree
Hide file tree
Showing 11 changed files with 814 additions and 0 deletions.
43 changes: 43 additions & 0 deletions lang/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[package]
name = "pdsl_lang"
version = "0.1.0"
authors = ["Herobird <robbepop@web.de>"]
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 = "[pDSL: Parity eDSL] 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]
pdsl_core = { path = "../core/" }
parity-codec = { version = "3.1", 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 = "0.7"
either = "1.5"

[lib]
name = "pdsl_lang"
proc-macro = true

[features]
default = ["std"]
std = [
"pdsl_core/std",
"parity-codec/std",
]
test-env = [
"pdsl_core/test-env",
]
1 change: 1 addition & 0 deletions lang/LICENSE
1 change: 1 addition & 0 deletions lang/README.md
110 changes: 110 additions & 0 deletions lang/src/ast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use crate::parser::keywords;

use proc_macro2::Ident;
// use quote::ToTokens;
use syn::{
token,
punctuated::Punctuated,
ReturnType,
Type,
};

#[derive(Debug)]
pub struct Contract {
pub items: Vec<Item>,
}

impl Contract {
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 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,
})
}
}

#[derive(Debug)]
pub enum Item {
State(ItemState),
Impl(ItemImpl),
}

#[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 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,
}

#[derive(Debug, Clone)]
pub enum FnArg {
SelfRef(syn::ArgSelfRef),
SelfValue(syn::ArgSelf),
Captured(syn::ArgCaptured),
}
61 changes: 61 additions & 0 deletions lang/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use proc_macro2::TokenStream;
use quote::ToTokens;
use std::result::Result as StdResult;
pub use syn::parse::Error as SynError;

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)*))
}
}
}
}

/// A collection of errors.
///
/// # Note
///
/// This is used to allow for reporting multiple errors at the same time.
#[derive(Debug)]
pub struct Errors {
errors: Vec<SynError>,
}

impl From<SynError> for Errors {
fn from(err: SynError) -> Errors {
Errors{
errors: vec![err],
}
}
}

impl From<Vec<Errors>> for Errors {
fn from(err: Vec<Errors>) -> Errors {
let result = err
.into_iter()
.flat_map(|v| v.errors)
.collect::<Vec<_>>();
assert!(result.len() > 0);
Errors{ errors: result }
}
}

/// Used to create a TokenStream from a list of errors
impl ToTokens for Errors {
fn to_tokens(&self, tokens: &mut TokenStream) {
for item in self.errors.iter() {
item.to_compile_error().to_tokens(tokens);
}
}
}

/// Result type alias for an error type which allows for accumulating errors.
pub type Result<T> = StdResult<T, Errors>;

0 comments on commit ee17938

Please sign in to comment.