Skip to content

Commit

Permalink
Merge pull request #62 from ikehara/feature/generate-preamble
Browse files Browse the repository at this point in the history
Generate preamble code
  • Loading branch information
bluele authored Oct 15, 2019
2 parents 69729e7 + fc7fc46 commit 063d961
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 12 deletions.
4 changes: 2 additions & 2 deletions example/token/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ deploy: build
$(eval CONTRACT_ADDRESS := $(shell $(HMCLI) contract deploy --path=$(CONTRACT_CODE) --address=${ADDR1} --gas=1 --password=password --node=tcp://$(NODE_ADDR)))
@echo "contract address is ${CONTRACT_ADDRESS}"

call:
$(HMCLI) contract call --address=${ADDR1} --contract=$(CONTRACT_ADDRESS) --gas=1 --func="app_main" --password=password --node=tcp://$(NODE_ADDR)
transfer:
$(HMCLI) contract call --address=${ADDR1} --contract=$(CONTRACT_ADDRESS) --gas=1 --func="transfer" --args ${ADDR2} --args 10 --argtypes=address,int64 --password=password --node=tcp://$(NODE_ADDR)

build:
cargo build --target=wasm32-unknown-unknown
Expand Down
4 changes: 1 addition & 3 deletions example/token/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ fn get_balance_from_addr(addr: &Address) -> Result<i64, Error> {
}

#[contract]
pub fn transfer() -> R<i64> {
let to: Address = get_arg(0)?;
let amount: i64 = get_arg(1)?;
pub fn transfer(to: Address, amount: i64) -> R<i64> {
let sender = get_sender()?;

let from_balance = get_balance_from_addr(&sender)?;
Expand Down
39 changes: 37 additions & 2 deletions hmcdk/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions hmcdk/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ authors = ["Jun Kimura <[email protected]>"]
edition = "2018"

[dependencies]
syn = { version = "0.15.18", features = ["full", "extra-traits"] }
quote = "0.6.9"
syn = { version = "1.0", features = ["full", "extra-traits"] }
quote = "1.0"

[lib]
proc-macro = true
59 changes: 56 additions & 3 deletions hmcdk/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,74 @@ extern crate proc_macro;

use crate::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};
use syn::{parse_macro_input, parse_quote, ItemFn, FnArg, Type, Stmt, Pat, Ident};
use std::ops::Deref;

fn get_assignment_from_name_and_type(name: &Ident, ty: &Type, index: usize) -> Result<Stmt, String> {
match ty {
Type::Path(type_path) => {
let pair = type_path.path.segments.last().ok_or("internal error")?;
let ident = &pair.ident;
let a = parse_quote! {
let #name: #ident = get_arg(#index).unwrap();
};
Ok(a)
}
_ => Err("invalid arg type".to_string())
}
}

fn get_assignment_from_arg(arg: &FnArg, index: usize) -> Result<(&Ident, Stmt), String> {
match arg {
FnArg::Typed(pat_type) => {
match &pat_type.pat.deref() {
Pat::Ident(pat) => {
let pat = &pat.ident;
match get_assignment_from_name_and_type(pat, pat_type.ty.deref(), index) {
Ok(stmt) => Ok((pat, stmt)),
Err(err) => Err(err)
}
}
_ => Err("no parameter name".to_string())
}
}
FnArg::Receiver(_receiver) => Err("receiver not supported".to_string())
}
}

#[proc_macro_attribute]
pub fn contract(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(item as ItemFn);
let org_name = &ast.ident;
let org_name = &ast.sig.ident;
let export_name = format!("{}", org_name);
let fn_name = syn::Ident::new(format!("__{}", org_name).as_str(), org_name.span());

let decl = &ast.sig;
let inputs = &decl.inputs;
let mut c = 0;
let mut assignments = Vec::new();
let mut arguments = Vec::new();
for arg in inputs {
let a = get_assignment_from_arg(&arg, c);
c += 1;
match a {
Ok((ident, stmt)) => {
assignments.push(stmt);
arguments.push(ident);
}
Err(e) => {
eprintln!("{:?}", e);
}
}
}

let pre = quote! {
#[cfg_attr(not(feature = "emulation"), export_name = #export_name)]
pub fn #fn_name() -> i32 {
use hmcdk::prelude::*;
use hmcdk::api::{return_value, log};
match #org_name() {
#(#assignments);*
match #org_name(#(#arguments),*) {
Ok(Some(v)) => {
match return_value(&v.to_bytes()) {
0 => 0,
Expand Down

0 comments on commit 063d961

Please sign in to comment.