Przeglądaj źródła

Format code with cargo fmt

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 5 lat temu
rodzic
commit
ad2ee99ef0

+ 4 - 1
build.rs

@@ -8,7 +8,10 @@ fn main() {
         .unwrap();
 
     // note: add error checking yourself.
-    let output = Command::new("git").args(&["rev-parse", "HEAD"]).output().unwrap();
+    let output = Command::new("git")
+        .args(&["rev-parse", "HEAD"])
+        .output()
+        .unwrap();
     let git_hash = String::from_utf8(output.stdout).unwrap();
     println!("cargo:rustc-env=GIT_HASH={}", git_hash);
 }

+ 55 - 32
src/abi/ethereum.rs

@@ -36,7 +36,9 @@ pub fn gen_abi(contract: &Contract) -> Vec<ABI> {
         }
     }
 
-    contract.constructors.iter()
+    contract
+        .constructors
+        .iter()
         .map(|f| ABI {
             name: "".to_owned(),
             constant: match &f.cfg {
@@ -52,37 +54,58 @@ pub fn gen_abi(contract: &Contract) -> Vec<ABI> {
                 _ => false,
             },
             ty: "constructor".to_owned(),
-            inputs: f.params.iter().map(|p| parameter_to_abi(p, contract)).collect(),
-            outputs: f.returns.iter().map(|p| parameter_to_abi(p, contract)).collect(),
+            inputs: f
+                .params
+                .iter()
+                .map(|p| parameter_to_abi(p, contract))
+                .collect(),
+            outputs: f
+                .returns
+                .iter()
+                .map(|p| parameter_to_abi(p, contract))
+                .collect(),
         })
-        .chain(contract.functions.iter()
-            .filter(|f| if let ast::Visibility::Public(_) = f.visibility {
-                true
-            } else {
-                false
-            })
-            .map(|f| ABI {
-                name: f.name.to_owned(),
-                constant: match &f.cfg {
-                    Some(cfg) => !cfg.writes_contract_storage,
-                    None => false,
-                },
-                mutability: match &f.mutability {
-                    Some(n) => n.to_string(),
-                    None => "nonpayable",
-                },
-                payable: match &f.mutability {
-                    Some(ast::StateMutability::Payable(_)) => true,
-                    _ => false,
-                },
-                ty: if f.name == "" {
-                    "fallback".to_owned()
-                } else {
-                    "function".to_owned()
-                },
-                inputs: f.params.iter().map(|p| parameter_to_abi(p, contract)).collect(),
-                outputs: f.returns.iter().map(|p| parameter_to_abi(p, contract)).collect(),
-            })
+        .chain(
+            contract
+                .functions
+                .iter()
+                .filter(|f| {
+                    if let ast::Visibility::Public(_) = f.visibility {
+                        true
+                    } else {
+                        false
+                    }
+                })
+                .map(|f| ABI {
+                    name: f.name.to_owned(),
+                    constant: match &f.cfg {
+                        Some(cfg) => !cfg.writes_contract_storage,
+                        None => false,
+                    },
+                    mutability: match &f.mutability {
+                        Some(n) => n.to_string(),
+                        None => "nonpayable",
+                    },
+                    payable: match &f.mutability {
+                        Some(ast::StateMutability::Payable(_)) => true,
+                        _ => false,
+                    },
+                    ty: if f.name == "" {
+                        "fallback".to_owned()
+                    } else {
+                        "function".to_owned()
+                    },
+                    inputs: f
+                        .params
+                        .iter()
+                        .map(|p| parameter_to_abi(p, contract))
+                        .collect(),
+                    outputs: f
+                        .returns
+                        .iter()
+                        .map(|p| parameter_to_abi(p, contract))
+                        .collect(),
+                }),
         )
         .collect()
-}
+}

+ 11 - 7
src/abi/mod.rs

@@ -1,4 +1,3 @@
-
 use resolver::Contract;
 use Target;
 
@@ -7,19 +6,24 @@ pub mod substrate;
 
 pub fn generate_abi(contract: &Contract, verbose: bool) -> (String, &'static str) {
     match contract.target {
-        Target::Ewasm |
-        Target::Burrow => {
+        Target::Ewasm | Target::Burrow => {
             if verbose {
-                eprintln!("info: Generating Ethereum ABI for contract {}", contract.name);
+                eprintln!(
+                    "info: Generating Ethereum ABI for contract {}",
+                    contract.name
+                );
             }
 
             let abi = ethereum::gen_abi(contract);
 
             (serde_json::to_string(&abi).unwrap(), "abi")
-        },
+        }
         Target::Substrate => {
             if verbose {
-                eprintln!("info: Generating Substrate ABI for contract {}", contract.name);
+                eprintln!(
+                    "info: Generating Substrate ABI for contract {}",
+                    contract.name
+                );
             }
 
             let abi = substrate::gen_abi(contract);
@@ -27,4 +31,4 @@ pub fn generate_abi(contract: &Contract, verbose: bool) -> (String, &'static str
             (serde_json::to_string_pretty(&abi).unwrap(), "json")
         }
     }
-}
+}

+ 135 - 105
src/abi/substrate.rs

@@ -5,72 +5,65 @@ use resolver;
 use serde::{Deserialize, Serialize};
 
 /// Substrate contracts abi consists of a a registry of strings and types, the contract itself
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 pub struct Metadata {
     pub registry: Registry,
     storage: Storage,
-    pub contract: Contract
+    pub contract: Contract,
 }
 
 impl Metadata {
     pub fn get_function(&self, name: &str) -> Option<&Message> {
-        self.contract.messages.iter()
+        self.contract
+            .messages
+            .iter()
             .find(|m| name == self.registry.get_str(m.name))
     }
 }
 
 /// The registry holds strings and types. Presumably this is to avoid duplication
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 pub struct Registry {
     strings: Vec<String>,
-    types: Vec<Type>
+    types: Vec<Type>,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 pub struct Array {
     #[serde(rename = "array.len")]
     len: usize,
     #[serde(rename = "array.type")]
-    ty: usize
+    ty: usize,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 #[serde(untagged)]
 enum Type {
-    Builtin {
-        id: String,
-        def: String
-    },
-    BuiltinArray {
-        id: Array,
-        def: String
-    },
-    Struct {
-        id: CustomID,
-        def: StructDef
-    }
+    Builtin { id: String, def: String },
+    BuiltinArray { id: Array, def: String },
+    Struct { id: CustomID, def: StructDef },
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 pub struct Contract {
     pub name: usize,
     pub constructors: Vec<Constructor>,
     pub messages: Vec<Message>,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct BuiltinType {
     id: String,
-    def: String
+    def: String,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct StructType {
     id: CustomID,
-    def: StructDef
+    def: StructDef,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct CustomID {
     #[serde(rename = "custom.name")]
     name: usize,
@@ -80,28 +73,28 @@ struct CustomID {
     params: Vec<usize>,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct StructDef {
     #[serde(rename = "struct.fields")]
-    fields: Vec<StructField>
+    fields: Vec<StructField>,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct StructField {
     name: usize,
     #[serde(rename = "type")]
-    ty: usize
+    ty: usize,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 pub struct Constructor {
     pub name: usize,
     pub selector: u32,
     pub docs: Vec<String>,
-    args: Vec<Param>
+    args: Vec<Param>,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 pub struct Message {
     pub name: usize,
     pub selector: u32,
@@ -111,55 +104,55 @@ pub struct Message {
     return_type: Option<ParamType>,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct Param {
     name: usize,
     #[serde(rename = "type")]
     ty: ParamType,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct ParamType {
     ty: usize,
-    display_name: Vec<usize>
+    display_name: Vec<usize>,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct Storage {
     #[serde(rename = "struct.type")]
     ty: usize,
     #[serde(rename = "struct.fields")]
-    fields: Vec<StorageLayout>
+    fields: Vec<StorageLayout>,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct LayoutField {
     #[serde(rename = "range.offset")]
     offset: String,
     #[serde(rename = "range.len")]
     len: usize,
     #[serde(rename = "range.elem_type")]
-    ty: usize
+    ty: usize,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 struct StorageLayout {
     name: usize,
-    layout: StorageFieldLayout
+    layout: StorageFieldLayout,
 }
 
-#[derive(Deserialize,Serialize)]
+#[derive(Deserialize, Serialize)]
 #[serde(untagged)]
 enum StorageFieldLayout {
     Field(LayoutField),
-    Storage(Box<Storage>)
+    Storage(Box<Storage>),
 }
 
 /// Create a new registry and create new entries. Note that the registry is
 /// accessed by number, and the first entry is 1, not 0.
 impl Registry {
     fn new() -> Self {
-        Registry{
+        Registry {
             strings: Vec::new(),
             types: Vec::new(),
         }
@@ -191,8 +184,8 @@ impl Registry {
             match s {
                 Type::Builtin { id, .. } if id == ty => {
                     return i + 1;
-                },
-                _ => ()
+                }
+                _ => (),
             }
         }
 
@@ -212,10 +205,13 @@ impl Registry {
 
         for (i, s) in self.types.iter().enumerate() {
             match s {
-                Type::BuiltinArray { id: Array { len, ty }, .. } if *len == array_len && *ty == elem => {
+                Type::BuiltinArray {
+                    id: Array { len, ty },
+                    ..
+                } if *len == array_len && *ty == elem => {
                     return i + 1;
-                },
-                _ => ()
+                }
+                _ => (),
             }
         }
 
@@ -243,9 +239,7 @@ impl Registry {
                 namespace: Vec::new(),
                 params: Vec::new(),
             },
-            def: StructDef {
-                fields
-            }
+            def: StructDef { fields },
         });
 
         length + 1
@@ -259,83 +253,112 @@ pub fn load(bs: &str) -> Result<Metadata, serde_json::error::Error> {
 pub fn gen_abi(resolver_contract: &resolver::Contract) -> Metadata {
     let mut registry = Registry::new();
 
-    let fields = resolver_contract.variables.iter()
+    let fields = resolver_contract
+        .variables
+        .iter()
         .filter(|v| !v.is_storage())
         .map(|v| {
             let (scalety, _) = solty_to_scalety(&v.ty, resolver_contract);
 
             StructField {
                 name: registry.string(&v.name),
-                ty: registry.builtin_type(&scalety)
+                ty: registry.builtin_type(&scalety),
             }
-        }).collect();
+        })
+        .collect();
 
     let storagety = registry.struct_type("storage", fields);
 
-    let fields = resolver_contract.variables.iter()
-        .filter_map(|v|  {
+    let fields = resolver_contract
+        .variables
+        .iter()
+        .filter_map(|v| {
             if let resolver::ContractVariableType::Storage(storage) = v.var {
                 let (scalety, len) = solty_to_scalety(&v.ty, resolver_contract);
 
                 Some(StorageLayout {
                     name: registry.string(&v.name),
-                    layout: StorageFieldLayout::Field(LayoutField{
+                    layout: StorageFieldLayout::Field(LayoutField {
                         offset: format!("0x{:064X}", storage),
                         len,
-                        ty: registry.builtin_type(&scalety)
-                    })
+                        ty: registry.builtin_type(&scalety),
+                    }),
                 })
             } else {
                 None
             }
-        }).collect();
+        })
+        .collect();
 
     let storage = Storage {
         ty: storagety,
-        fields: vec!(StorageLayout {
+        fields: vec![StorageLayout {
             name: registry.string("Storage"),
-            layout: StorageFieldLayout::Storage(Box::new(
-                Storage {
-                    ty: storagety,
-                    fields
-                }
-            ))
-        })
+            layout: StorageFieldLayout::Storage(Box::new(Storage {
+                ty: storagety,
+                fields,
+            })),
+        }],
     };
 
-    let constructors = resolver_contract.constructors.iter().map(|f| Constructor{
-        name: registry.string("new"),
-        selector: f.selector(),
-        args: f.params.iter().map(|p| parameter_to_abi(p, resolver_contract, &mut registry)).collect(),
-        docs: f.doc.clone()
-    }).collect();
+    let constructors = resolver_contract
+        .constructors
+        .iter()
+        .map(|f| Constructor {
+            name: registry.string("new"),
+            selector: f.selector(),
+            args: f
+                .params
+                .iter()
+                .map(|p| parameter_to_abi(p, resolver_contract, &mut registry))
+                .collect(),
+            docs: f.doc.clone(),
+        })
+        .collect();
 
-    let messages = resolver_contract.functions.iter()
-        .filter(|f| if let ast::Visibility::Public(_) = f.visibility {
+    let messages = resolver_contract
+        .functions
+        .iter()
+        .filter(|f| {
+            if let ast::Visibility::Public(_) = f.visibility {
                 true
             } else {
                 false
-            })
-        .map(|f| Message{
+            }
+        })
+        .map(|f| Message {
             name: registry.string(&f.name),
             mutates: f.mutability.is_none(),
             return_type: match f.returns.len() {
                 0 => None,
-                1 => Some(ty_to_abi(&f.returns[0].ty, resolver_contract, &mut registry)),
-                _ => unreachable!()
+                1 => Some(ty_to_abi(
+                    &f.returns[0].ty,
+                    resolver_contract,
+                    &mut registry,
+                )),
+                _ => unreachable!(),
             },
             selector: f.selector(),
-            args: f.params.iter().map(|p| parameter_to_abi(p, resolver_contract, &mut registry)).collect(),
-            docs: f.doc.clone()
-        }).collect();
+            args: f
+                .params
+                .iter()
+                .map(|p| parameter_to_abi(p, resolver_contract, &mut registry))
+                .collect(),
+            docs: f.doc.clone(),
+        })
+        .collect();
 
-    let contract = Contract{
+    let contract = Contract {
         name: registry.string(&resolver_contract.name),
         constructors: constructors,
         messages: messages,
     };
 
-    Metadata{registry, storage, contract}
+    Metadata {
+        registry,
+        storage,
+        contract,
+    }
 }
 
 fn solty_to_scalety(ty: &resolver::Type, contract: &resolver::Contract) -> (String, usize) {
@@ -345,39 +368,42 @@ fn solty_to_scalety(ty: &resolver::Type, contract: &resolver::Contract) -> (Stri
         ast::PrimitiveType::Int(n) => (format!("i{}", n), (n / 8).into()),
         ast::PrimitiveType::Bytes(n) => (format!("bytes{}", n), *n as usize),
         ast::PrimitiveType::Address => ("address".into(), 20),
-        _ => unreachable!()
+        _ => unreachable!(),
     }
 }
 
-fn ty_to_abi(ty: &resolver::Type, contract: &resolver::Contract, registry: &mut Registry) -> ParamType {
+fn ty_to_abi(
+    ty: &resolver::Type,
+    contract: &resolver::Contract,
+    registry: &mut Registry,
+) -> ParamType {
     let primitive = ty_to_primitive(ty, contract);
 
     match primitive {
-        ast::PrimitiveType::Bytes(n) => {
-            ParamType{
-                ty: registry.builtin_bytes_type(*n as usize),
-                display_name: vec!(),
-            }
+        ast::PrimitiveType::Bytes(n) => ParamType {
+            ty: registry.builtin_bytes_type(*n as usize),
+            display_name: vec![],
         },
-        ast::PrimitiveType::Address => {
-            ParamType{
-                ty: registry.builtin_bytes_type(160 as usize),
-                display_name: vec!(),
-            }
+        ast::PrimitiveType::Address => ParamType {
+            ty: registry.builtin_bytes_type(160 as usize),
+            display_name: vec![],
         },
-        _ =>  {
+        _ => {
             let scalety = primitive_to_string(&primitive);
 
             ParamType {
                 ty: registry.builtin_type(&scalety),
-                display_name: vec![ registry.string(&scalety.to_string()) ],
+                display_name: vec![registry.string(&scalety.to_string())],
             }
         }
     }
 }
 
 // For a given resolved type, return the underlying primitive
-fn ty_to_primitive<'a>(ty: &'a resolver::Type, resolved_contract: &'a resolver::Contract) -> &'a ast::PrimitiveType {
+fn ty_to_primitive<'a>(
+    ty: &'a resolver::Type,
+    resolved_contract: &'a resolver::Contract,
+) -> &'a ast::PrimitiveType {
     match ty {
         resolver::Type::Primitive(e) => e,
         resolver::Type::Enum(ref i) => &resolved_contract.enums[*i].ty,
@@ -395,13 +421,17 @@ fn primitive_to_string(ty: &ast::PrimitiveType) -> String {
         ast::PrimitiveType::Int(n) => format!("i{}", n),
         ast::PrimitiveType::Bytes(n) => format!("bytes{}", n),
         ast::PrimitiveType::Address => "address".into(),
-        _ => unreachable!()
+        _ => unreachable!(),
     }
 }
 
-fn parameter_to_abi(param: &resolver::Parameter, contract: &resolver::Contract, registry: &mut Registry) -> Param {
+fn parameter_to_abi(
+    param: &resolver::Parameter,
+    contract: &resolver::Contract,
+    registry: &mut Registry,
+) -> Param {
     Param {
         name: registry.string(&param.name),
-        ty: ty_to_abi(&param.ty, contract, registry)
+        ty: ty_to_abi(&param.ty, contract, registry),
     }
 }

+ 55 - 17
src/bin/solang.rs

@@ -9,9 +9,9 @@ use std::fs::File;
 use std::io::prelude::*;
 use std::path::{Path, PathBuf};
 
-use solang::output;
-use solang::link;
 use solang::abi;
+use solang::link;
+use solang::output;
 
 #[derive(Serialize)]
 pub struct EwasmContract {
@@ -62,12 +62,12 @@ fn main() {
                 .long("target")
                 .takes_value(true)
                 .possible_values(&["substrate", "burrow", "ewasm"])
-                .default_value("substrate")
+                .default_value("substrate"),
         )
         .arg(
             Arg::with_name("STD-JSON")
                 .help("mimic solidity json output on stdout")
-                .long("standard-json")
+                .long("standard-json"),
         )
         .arg(
             Arg::with_name("VERBOSE")
@@ -91,8 +91,7 @@ fn main() {
     };
 
     let output_file = |stem: &str, ext: &str| -> PathBuf {
-        Path::new(matches.value_of("OUTPUT").unwrap_or("."))
-            .join(format!("{}.{}", stem, ext))
+        Path::new(matches.value_of("OUTPUT").unwrap_or(".")).join(format!("{}.{}", stem, ext))
     };
 
     let context = inkwell::context::Context::create();
@@ -104,7 +103,7 @@ fn main() {
             Some("substrate") => solang::Target::Substrate,
             Some("burrow") => solang::Target::Burrow,
             Some("ewasm") => solang::Target::Ewasm,
-            _ => unreachable!()
+            _ => unreachable!(),
         }
     };
     let verbose = matches.is_present("VERBOSE");
@@ -146,7 +145,10 @@ fn main() {
             }
 
             if verbose {
-                eprintln!("info: Generating LLVM IR for contract {} with target {}", resolved_contract.name, resolved_contract.target);
+                eprintln!(
+                    "info: Generating LLVM IR for contract {} with target {}",
+                    resolved_contract.name, resolved_contract.target
+                );
             }
 
             let contract = resolved_contract.emit(&context, &filename, &opt);
@@ -158,7 +160,11 @@ fn main() {
                     let llvm_filename = output_file(&format!("{}_deploy", contract.name), "ll");
 
                     if verbose {
-                        eprintln!("info: Saving deployer LLVM {} for contract {}", llvm_filename.display(), contract.name);
+                        eprintln!(
+                            "info: Saving deployer LLVM {} for contract {}",
+                            llvm_filename.display(),
+                            contract.name
+                        );
                     }
 
                     contract.dump_llvm(&llvm_filename).unwrap();
@@ -166,7 +172,11 @@ fn main() {
                     let llvm_filename = output_file(&format!("{}_runtime", contract.name), "ll");
 
                     if verbose {
-                        eprintln!("info: Saving runtime LLVM {} for contract {}", llvm_filename.display(), contract.name);
+                        eprintln!(
+                            "info: Saving runtime LLVM {} for contract {}",
+                            llvm_filename.display(),
+                            contract.name
+                        );
                     }
 
                     runtime.dump_llvm(&llvm_filename).unwrap();
@@ -174,7 +184,11 @@ fn main() {
                     let llvm_filename = output_file(&contract.name, "ll");
 
                     if verbose {
-                        eprintln!("info: Saving LLVM {} for contract {}", llvm_filename.display(), contract.name);
+                        eprintln!(
+                            "info: Saving LLVM {} for contract {}",
+                            llvm_filename.display(),
+                            contract.name
+                        );
                     }
 
                     contract.dump_llvm(&llvm_filename).unwrap();
@@ -189,7 +203,11 @@ fn main() {
                     let bc_filename = output_file(&format!("{}_deploy", contract.name), "bc");
 
                     if verbose {
-                        eprintln!("info: Saving deploy LLVM BC {} for contract {}", bc_filename.display(), contract.name);
+                        eprintln!(
+                            "info: Saving deploy LLVM BC {} for contract {}",
+                            bc_filename.display(),
+                            contract.name
+                        );
                     }
 
                     contract.bitcode(&bc_filename);
@@ -197,7 +215,11 @@ fn main() {
                     let bc_filename = output_file(&format!("{}_runtime", contract.name), "bc");
 
                     if verbose {
-                        eprintln!("info: Saving runtime LLVM BC {} for contract {}", bc_filename.display(), contract.name);
+                        eprintln!(
+                            "info: Saving runtime LLVM BC {} for contract {}",
+                            bc_filename.display(),
+                            contract.name
+                        );
                     }
 
                     runtime.bitcode(&bc_filename);
@@ -205,7 +227,11 @@ fn main() {
                     let bc_filename = output_file(&contract.name, "bc");
 
                     if verbose {
-                        eprintln!("info: Saving LLVM BC {} for contract {}", bc_filename.display(), contract.name);
+                        eprintln!(
+                            "info: Saving LLVM BC {} for contract {}",
+                            bc_filename.display(),
+                            contract.name
+                        );
                     }
 
                     contract.bitcode(&bc_filename);
@@ -225,7 +251,11 @@ fn main() {
                 let obj_filename = output_file(&contract.name, "o");
 
                 if verbose {
-                    eprintln!("info: Saving Object {} for contract {}", obj_filename.display(), contract.name);
+                    eprintln!(
+                        "info: Saving Object {} for contract {}",
+                        obj_filename.display(),
+                        contract.name
+                    );
                 }
 
                 let mut file = File::create(obj_filename).unwrap();
@@ -249,7 +279,11 @@ fn main() {
                 let wasm_filename = output_file(&contract.name, "wasm");
 
                 if verbose {
-                    eprintln!("info: Saving WebAssembly {} for contract {}", wasm_filename.display(), contract.name);
+                    eprintln!(
+                        "info: Saving WebAssembly {} for contract {}",
+                        wasm_filename.display(),
+                        contract.name
+                    );
                 }
 
                 let mut file = File::create(wasm_filename).unwrap();
@@ -259,7 +293,11 @@ fn main() {
                 let abi_filename = output_file(&contract.name, abi_ext);
 
                 if verbose {
-                    eprintln!("info: Saving ABI {} for contract {}", abi_filename.display(), contract.name);
+                    eprintln!(
+                        "info: Saving ABI {} for contract {}",
+                        abi_filename.display(),
+                        contract.name
+                    );
                 }
 
                 file = File::create(abi_filename).unwrap();

+ 430 - 176
src/emit/burrow.rs

@@ -1,24 +1,26 @@
-
 use parser::ast;
 use resolver;
 use std::str;
 
-use inkwell::types::BasicTypeEnum;
 use inkwell::context::Context;
 use inkwell::module::Linkage;
+use inkwell::types::BasicTypeEnum;
+use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue};
 use inkwell::AddressSpace;
-use inkwell::values::{PointerValue, IntValue, FunctionValue, BasicValueEnum};
 use inkwell::IntPredicate;
 
-use super::{TargetRuntime, Contract};
+use super::{Contract, TargetRuntime};
 
-pub struct BurrowTarget {
-}
+pub struct BurrowTarget {}
 
 impl BurrowTarget {
-    pub fn build<'a>(context: &'a Context, contract: &'a resolver::Contract, filename: &'a str) -> Contract<'a> {
+    pub fn build<'a>(
+        context: &'a Context,
+        contract: &'a resolver::Contract,
+        filename: &'a str,
+    ) -> Contract<'a> {
         let mut c = Contract::new(context, contract, filename, None);
-        let b = BurrowTarget{};
+        let b = BurrowTarget {};
 
         // externals
         b.declare_externals(&mut c);
@@ -35,14 +37,22 @@ impl BurrowTarget {
         let ret = contract.context.void_type();
         let args: Vec<BasicTypeEnum> = vec![
             contract.context.i32_type().into(),
-            contract.context.i8_type().ptr_type(AddressSpace::Generic).into(),
+            contract
+                .context
+                .i8_type()
+                .ptr_type(AddressSpace::Generic)
+                .into(),
             contract.context.i32_type().into(),
         ];
 
         let ftype = ret.fn_type(&args, false);
 
-        contract.module.add_function("get_storage32", ftype, Some(Linkage::External));
-        contract.module.add_function("set_storage32", ftype, Some(Linkage::External));
+        contract
+            .module
+            .add_function("get_storage32", ftype, Some(Linkage::External));
+        contract
+            .module
+            .add_function("set_storage32", ftype, Some(Linkage::External));
     }
 
     fn emit_constructor_dispatch(&self, contract: &Contract) {
@@ -50,7 +60,14 @@ impl BurrowTarget {
 
         // create start function
         let ret = contract.context.void_type();
-        let ftype = ret.fn_type(&[contract.context.i32_type().ptr_type(AddressSpace::Generic).into()], false);
+        let ftype = ret.fn_type(
+            &[contract
+                .context
+                .i32_type()
+                .ptr_type(AddressSpace::Generic)
+                .into()],
+            false,
+        );
         let function = contract.module.add_function("constructor", ftype, None);
 
         let entry = contract.context.append_basic_block(function, "entry");
@@ -61,7 +78,8 @@ impl BurrowTarget {
         contract.builder.build_call(
             contract.module.get_function("__init_heap").unwrap(),
             &[],
-            "");
+            "",
+        );
 
         // init our storage vars
         contract.builder.build_call(initializer, &[], "");
@@ -74,9 +92,11 @@ impl BurrowTarget {
 
             // step over length
             let args_ptr = unsafe {
-                contract.builder.build_gep(arg,
+                contract.builder.build_gep(
+                    arg,
                     &[contract.context.i32_type().const_int(1, false).into()],
-                    "args_ptr")
+                    "args_ptr",
+                )
             };
 
             // insert abi decode
@@ -89,7 +109,9 @@ impl BurrowTarget {
                 con,
             );
 
-            contract.builder.build_call(contract.constructors[0], &args, "");
+            contract
+                .builder
+                .build_call(contract.constructors[0], &args, "");
         }
 
         contract.builder.build_return(None);
@@ -98,7 +120,14 @@ impl BurrowTarget {
     fn emit_function_dispatch(&self, contract: &Contract) {
         // create start function
         let ret = contract.context.i32_type().ptr_type(AddressSpace::Generic);
-        let ftype = ret.fn_type(&[contract.context.i32_type().ptr_type(AddressSpace::Generic).into()], false);
+        let ftype = ret.fn_type(
+            &[contract
+                .context
+                .i32_type()
+                .ptr_type(AddressSpace::Generic)
+                .into()],
+            false,
+        );
         let function = contract.module.add_function("function", ftype, None);
 
         let entry = contract.context.append_basic_block(function, "entry");
@@ -113,26 +142,32 @@ impl BurrowTarget {
             contract.builder.build_gep(
                 data,
                 &[contract.context.i32_type().const_int(1, false).into()],
-                "argsdata")
+                "argsdata",
+            )
         };
 
-        contract.emit_function_dispatch(&contract.ns.functions, &contract.functions, argsdata, argslen, function, &fallback_block, self);
+        contract.emit_function_dispatch(
+            &contract.ns.functions,
+            &contract.functions,
+            argsdata,
+            argslen,
+            function,
+            &fallback_block,
+            self,
+        );
 
         // emit fallback code
         contract.builder.position_at_end(&fallback_block);
 
         match contract.ns.fallback_function() {
             Some(f) => {
-                contract.builder.build_call(
-                    contract.functions[f],
-                    &[],
-                    "");
+                contract.builder.build_call(contract.functions[f], &[], "");
 
                 contract.builder.build_return(None);
             }
             None => {
                 contract.builder.build_unreachable();
-            },
+            }
         }
     }
 
@@ -146,95 +181,134 @@ impl BurrowTarget {
         match ty {
             ast::PrimitiveType::Bool => {
                 // first clear
-                let dest8 = contract.builder.build_pointer_cast(dest,
+                let dest8 = contract.builder.build_pointer_cast(
+                    dest,
                     contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                    "destvoid");
+                    "destvoid",
+                );
 
                 contract.builder.build_call(
                     contract.module.get_function("__bzero8").unwrap(),
-                    &[ dest8.into(),
-                       contract.context.i32_type().const_int(4, false).into() ],
-                    "");
+                    &[
+                        dest8.into(),
+                        contract.context.i32_type().const_int(4, false).into(),
+                    ],
+                    "",
+                );
 
-                let value = contract.builder.build_select(val.into_int_value(),
+                let value = contract.builder.build_select(
+                    val.into_int_value(),
                     contract.context.i8_type().const_int(1, false),
                     contract.context.i8_type().const_zero(),
-                    "bool_val");
+                    "bool_val",
+                );
 
                 let dest = unsafe {
                     contract.builder.build_gep(
                         dest8,
-                        &[ contract.context.i32_type().const_int(31, false).into() ],
-                        "")
+                        &[contract.context.i32_type().const_int(31, false).into()],
+                        "",
+                    )
                 };
 
                 contract.builder.build_store(dest, value);
             }
             ast::PrimitiveType::Int(8) | ast::PrimitiveType::Uint(8) => {
                 let signval = if let ast::PrimitiveType::Int(8) = ty {
-                    let negative = contract.builder.build_int_compare(IntPredicate::SLT,
-                            val.into_int_value(), contract.context.i8_type().const_zero(), "neg");
+                    let negative = contract.builder.build_int_compare(
+                        IntPredicate::SLT,
+                        val.into_int_value(),
+                        contract.context.i8_type().const_zero(),
+                        "neg",
+                    );
 
-                            contract.builder.build_select(negative,
-                        contract.context.i64_type().const_zero(),
-                        contract.context.i64_type().const_int(std::u64::MAX, true),
-                        "val").into_int_value()
+                    contract
+                        .builder
+                        .build_select(
+                            negative,
+                            contract.context.i64_type().const_zero(),
+                            contract.context.i64_type().const_int(std::u64::MAX, true),
+                            "val",
+                        )
+                        .into_int_value()
                 } else {
                     contract.context.i64_type().const_zero()
                 };
 
-                let dest8 = contract.builder.build_pointer_cast(dest,
+                let dest8 = contract.builder.build_pointer_cast(
+                    dest,
                     contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                    "destvoid");
+                    "destvoid",
+                );
 
-                    contract.builder.build_call(
+                contract.builder.build_call(
                     contract.module.get_function("__memset8").unwrap(),
-                    &[ dest8.into(), signval.into(),
-                       contract.context.i32_type().const_int(4, false).into() ],
-                    "");
+                    &[
+                        dest8.into(),
+                        signval.into(),
+                        contract.context.i32_type().const_int(4, false).into(),
+                    ],
+                    "",
+                );
 
                 let dest = unsafe {
                     contract.builder.build_gep(
                         dest8,
-                        &[ contract.context.i32_type().const_int(31, false).into() ],
-                        "")
+                        &[contract.context.i32_type().const_int(31, false).into()],
+                        "",
+                    )
                 };
 
                 contract.builder.build_store(dest, val);
             }
-            ast::PrimitiveType::Address |
-            ast::PrimitiveType::Uint(_) |
-            ast::PrimitiveType::Int(_) => {
+            ast::PrimitiveType::Address
+            | ast::PrimitiveType::Uint(_)
+            | ast::PrimitiveType::Int(_) => {
                 let n = match ty {
                     ast::PrimitiveType::Address => 160,
                     ast::PrimitiveType::Uint(b) => *b,
                     ast::PrimitiveType::Int(b) => *b,
-                    _ => unreachable!()
+                    _ => unreachable!(),
                 };
 
                 // first clear/set the upper bits
                 if n < 256 {
                     let signval = if let ast::PrimitiveType::Int(8) = ty {
-                        let negative = contract.builder.build_int_compare(IntPredicate::SLT,
-                                val.into_int_value(), contract.context.i8_type().const_zero(), "neg");
-
-                        contract.builder.build_select(negative,
-                            contract.context.i64_type().const_zero(),
-                            contract.context.i64_type().const_int(std::u64::MAX, true),
-                            "val").into_int_value()
+                        let negative = contract.builder.build_int_compare(
+                            IntPredicate::SLT,
+                            val.into_int_value(),
+                            contract.context.i8_type().const_zero(),
+                            "neg",
+                        );
+
+                        contract
+                            .builder
+                            .build_select(
+                                negative,
+                                contract.context.i64_type().const_zero(),
+                                contract.context.i64_type().const_int(std::u64::MAX, true),
+                                "val",
+                            )
+                            .into_int_value()
                     } else {
                         contract.context.i64_type().const_zero()
                     };
 
-                    let dest8 = contract.builder.build_pointer_cast(dest,
+                    let dest8 = contract.builder.build_pointer_cast(
+                        dest,
                         contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                        "destvoid");
+                        "destvoid",
+                    );
 
                     contract.builder.build_call(
                         contract.module.get_function("__memset8").unwrap(),
-                        &[ dest8.into(), signval.into(),
-                            contract.context.i32_type().const_int(4, false).into() ],
-                        "");
+                        &[
+                            dest8.into(),
+                            signval.into(),
+                            contract.context.i32_type().const_int(4, false).into(),
+                        ],
+                        "",
+                    );
                 }
 
                 // no need to allocate space for each uint64
@@ -255,40 +329,65 @@ impl BurrowTarget {
                 contract.builder.build_call(
                     contract.module.get_function("__leNtobe32").unwrap(),
                     &[
-                        contract.builder.build_pointer_cast(store,
-                            contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                            "store").into(),
-                        contract.builder.build_pointer_cast(dest,
-                            contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                            "dest").into(),
-                        contract.builder.build_int_truncate(type_size,
-                            contract.context.i32_type(), "").into()
+                        contract
+                            .builder
+                            .build_pointer_cast(
+                                store,
+                                contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                "store",
+                            )
+                            .into(),
+                        contract
+                            .builder
+                            .build_pointer_cast(
+                                dest,
+                                contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                "dest",
+                            )
+                            .into(),
+                        contract
+                            .builder
+                            .build_int_truncate(type_size, contract.context.i32_type(), "")
+                            .into(),
                     ],
-                    "");
+                    "",
+                );
             }
             ast::PrimitiveType::Bytes(1) => {
-                let dest8 = contract.builder.build_pointer_cast(dest,
+                let dest8 = contract.builder.build_pointer_cast(
+                    dest,
                     contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                    "destvoid");
+                    "destvoid",
+                );
 
                 contract.builder.build_call(
                     contract.module.get_function("__bzero8").unwrap(),
-                    &[ dest8.into(), contract.context.i32_type().const_int(4, false).into() ],
-                    "");
+                    &[
+                        dest8.into(),
+                        contract.context.i32_type().const_int(4, false).into(),
+                    ],
+                    "",
+                );
 
                 contract.builder.build_store(dest8, val);
-            },
+            }
             ast::PrimitiveType::Bytes(b) => {
                 // first clear/set the upper bits
                 if *b < 32 {
-                    let dest8 = contract.builder.build_pointer_cast(dest,
+                    let dest8 = contract.builder.build_pointer_cast(
+                        dest,
                         contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                        "destvoid");
+                        "destvoid",
+                    );
 
                     contract.builder.build_call(
                         contract.module.get_function("__bzero8").unwrap(),
-                        &[ dest8.into(), contract.context.i32_type().const_int(4, false).into() ],
-                        "");
+                        &[
+                            dest8.into(),
+                            contract.context.i32_type().const_int(4, false).into(),
+                        ],
+                        "",
+                    );
                 }
 
                 // no need to allocate space for each uint64
@@ -309,62 +408,121 @@ impl BurrowTarget {
                 contract.builder.build_call(
                     contract.module.get_function("__leNtobeN").unwrap(),
                     &[
-                        contract.builder.build_pointer_cast(store,
-                            contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                            "store").into(),
-                        contract.builder.build_pointer_cast(dest,
-                            contract.context.i8_type().ptr_type(AddressSpace::Generic),
-                            "dest").into(),
-                        contract.builder.build_int_truncate(type_size,
-                            contract.context.i32_type(), "").into()
+                        contract
+                            .builder
+                            .build_pointer_cast(
+                                store,
+                                contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                "store",
+                            )
+                            .into(),
+                        contract
+                            .builder
+                            .build_pointer_cast(
+                                dest,
+                                contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                "dest",
+                            )
+                            .into(),
+                        contract
+                            .builder
+                            .build_int_truncate(type_size, contract.context.i32_type(), "")
+                            .into(),
                     ],
-                    "");
+                    "",
+                );
             }
             _ => unimplemented!(),
         }
     }
-
 }
 
 impl TargetRuntime for BurrowTarget {
-    fn set_storage<'a>(&self, contract: &'a Contract, _function: FunctionValue, slot: u32, dest: inkwell::values::PointerValue<'a>) {
+    fn set_storage<'a>(
+        &self,
+        contract: &'a Contract,
+        _function: FunctionValue,
+        slot: u32,
+        dest: inkwell::values::PointerValue<'a>,
+    ) {
         contract.builder.build_call(
             contract.module.get_function("set_storage32").unwrap(),
             &[
-                contract.context.i32_type().const_int(slot as u64, false).into(),
-                contract.builder.build_pointer_cast(dest,
-                    contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                dest.get_type().size_of().const_cast(
-                    contract.context.i32_type(), false).into()
+                contract
+                    .context
+                    .i32_type()
+                    .const_int(slot as u64, false)
+                    .into(),
+                contract
+                    .builder
+                    .build_pointer_cast(
+                        dest,
+                        contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                        "",
+                    )
+                    .into(),
+                dest.get_type()
+                    .size_of()
+                    .const_cast(contract.context.i32_type(), false)
+                    .into(),
             ],
-            "");
+            "",
+        );
     }
 
-    fn get_storage<'a>(&self, contract: &'a Contract, _function: FunctionValue, slot: u32, dest: inkwell::values::PointerValue<'a>) {
+    fn get_storage<'a>(
+        &self,
+        contract: &'a Contract,
+        _function: FunctionValue,
+        slot: u32,
+        dest: inkwell::values::PointerValue<'a>,
+    ) {
         contract.builder.build_call(
             contract.module.get_function("get_storage32").unwrap(),
             &[
-                contract.context.i32_type().const_int(slot as u64, false).into(),
-                contract.builder.build_pointer_cast(dest,
-                    contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                dest.get_type().size_of().const_cast(
-                    contract.context.i32_type(), false).into()
+                contract
+                    .context
+                    .i32_type()
+                    .const_int(slot as u64, false)
+                    .into(),
+                contract
+                    .builder
+                    .build_pointer_cast(
+                        dest,
+                        contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                        "",
+                    )
+                    .into(),
+                dest.get_type()
+                    .size_of()
+                    .const_cast(contract.context.i32_type(), false)
+                    .into(),
             ],
-            "");
+            "",
+        );
     }
 
     fn return_empty_abi(&self, contract: &Contract) {
-        let dest = contract.builder.build_call(
-            contract.module.get_function("__malloc").unwrap(),
-            &[contract.context.i32_type().const_int(4, false).into()],
-            ""
-        ).try_as_basic_value().left().unwrap().into_pointer_value();
+        let dest = contract
+            .builder
+            .build_call(
+                contract.module.get_function("__malloc").unwrap(),
+                &[contract.context.i32_type().const_int(4, false).into()],
+                "",
+            )
+            .try_as_basic_value()
+            .left()
+            .unwrap()
+            .into_pointer_value();
 
         contract.builder.build_store(
-            contract.builder.build_pointer_cast(dest,
+            contract.builder.build_pointer_cast(
+                dest,
                 contract.context.i32_type().ptr_type(AddressSpace::Generic),
-                ""),
-            contract.context.i32_type().const_zero());
+                "",
+            ),
+            contract.context.i32_type().const_zero(),
+        );
 
         contract.builder.build_return(Some(&dest));
     }
@@ -376,29 +534,46 @@ impl TargetRuntime for BurrowTarget {
     fn abi_encode<'b>(
         &self,
         contract: &'b Contract,
-        args: &[ BasicValueEnum<'b> ],
+        args: &[BasicValueEnum<'b>],
         spec: &resolver::FunctionDecl,
     ) -> (PointerValue<'b>, IntValue<'b>) {
-        let length = contract.context.i32_type().const_int(32 * args.len() as u64, false);
-        let data = contract.builder.build_call(
-            contract.module.get_function("__malloc").unwrap(),
-            &[contract.context.i32_type().const_int(4 + 32 * args.len() as u64, false).into()],
-            ""
-        ).try_as_basic_value().left().unwrap().into_pointer_value();
+        let length = contract
+            .context
+            .i32_type()
+            .const_int(32 * args.len() as u64, false);
+        let data = contract
+            .builder
+            .build_call(
+                contract.module.get_function("__malloc").unwrap(),
+                &[contract
+                    .context
+                    .i32_type()
+                    .const_int(4 + 32 * args.len() as u64, false)
+                    .into()],
+                "",
+            )
+            .try_as_basic_value()
+            .left()
+            .unwrap()
+            .into_pointer_value();
 
         // write length
         contract.builder.build_store(
-            contract.builder.build_pointer_cast(data,
+            contract.builder.build_pointer_cast(
+                data,
                 contract.context.i32_type().ptr_type(AddressSpace::Generic),
-                ""),
-            length);
+                "",
+            ),
+            length,
+        );
 
         // malloc returns u8*
         let abi_ptr = unsafe {
             contract.builder.build_gep(
                 data,
-                &[ contract.context.i32_type().const_int(4, false).into()],
-                "abi_ptr")
+                &[contract.context.i32_type().const_int(4, false).into()],
+                "abi_ptr",
+            )
         };
 
         for (i, arg) in spec.returns.iter().enumerate() {
@@ -427,13 +602,23 @@ impl TargetRuntime for BurrowTarget {
     ) {
         let mut data = data;
         let decode_block = contract.context.append_basic_block(function, "abi_decode");
-        let wrong_length_block = contract.context.append_basic_block(function, "wrong_abi_length");
-
-        let is_ok = contract.builder.build_int_compare(IntPredicate::EQ, length,
-            contract.context.i32_type().const_int(32  * spec.params.len() as u64, false),
-            "correct_length");
-
-        contract.builder.build_conditional_branch(is_ok, &decode_block, &wrong_length_block);
+        let wrong_length_block = contract
+            .context
+            .append_basic_block(function, "wrong_abi_length");
+
+        let is_ok = contract.builder.build_int_compare(
+            IntPredicate::EQ,
+            length,
+            contract
+                .context
+                .i32_type()
+                .const_int(32 * spec.params.len() as u64, false),
+            "correct_length",
+        );
+
+        contract
+            .builder
+            .build_conditional_branch(is_ok, &decode_block, &wrong_length_block);
 
         contract.builder.position_at_end(&decode_block);
 
@@ -450,27 +635,46 @@ impl TargetRuntime for BurrowTarget {
                     // solidity checks all the 32 bytes for being non-zero; we will just look at the upper 8 bytes, else we would need four loads
                     // which is unneeded (hopefully)
                     // cast to 64 bit pointer
-                    let bool_ptr = contract.builder.build_pointer_cast(data,
-                        contract.context.i64_type().ptr_type(AddressSpace::Generic), "");
+                    let bool_ptr = contract.builder.build_pointer_cast(
+                        data,
+                        contract.context.i64_type().ptr_type(AddressSpace::Generic),
+                        "",
+                    );
 
                     let bool_ptr = unsafe {
-                        contract.builder.build_gep(bool_ptr,
-                            &[ contract.context.i32_type().const_int(3, false) ],
-                            "bool_ptr")
+                        contract.builder.build_gep(
+                            bool_ptr,
+                            &[contract.context.i32_type().const_int(3, false)],
+                            "bool_ptr",
+                        )
                     };
 
-                    contract.builder.build_int_compare(IntPredicate::NE,
-                        contract.builder.build_load(bool_ptr, "abi_bool").into_int_value(),
-                        contract.context.i64_type().const_zero(), "bool").into()
+                    contract
+                        .builder
+                        .build_int_compare(
+                            IntPredicate::NE,
+                            contract
+                                .builder
+                                .build_load(bool_ptr, "abi_bool")
+                                .into_int_value(),
+                            contract.context.i64_type().const_zero(),
+                            "bool",
+                        )
+                        .into()
                 }
                 ast::PrimitiveType::Uint(8) | ast::PrimitiveType::Int(8) => {
-                    let int8_ptr = contract.builder.build_pointer_cast(data,
-                        contract.context.i8_type().ptr_type(AddressSpace::Generic), "");
+                    let int8_ptr = contract.builder.build_pointer_cast(
+                        data,
+                        contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                        "",
+                    );
 
                     let int8_ptr = unsafe {
-                        contract.builder.build_gep(int8_ptr,
-                        &[ contract.context.i32_type().const_int(31, false) ],
-                        "bool_ptr")
+                        contract.builder.build_gep(
+                            int8_ptr,
+                            &[contract.context.i32_type().const_int(31, false)],
+                            "bool_ptr",
+                        )
                     };
 
                     contract.builder.build_load(int8_ptr, "abi_int8")
@@ -484,14 +688,28 @@ impl TargetRuntime for BurrowTarget {
                     contract.builder.build_call(
                         contract.module.get_function("__be32toleN").unwrap(),
                         &[
-                            contract.builder.build_pointer_cast(data,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            contract.builder.build_pointer_cast(store,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            contract.builder.build_int_truncate(type_size,
-                                contract.context.i32_type(), "size").into()
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    data,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    store,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
+                            contract
+                                .builder
+                                .build_int_truncate(type_size, contract.context.i32_type(), "size")
+                                .into(),
                         ],
-                        ""
+                        "",
                     );
 
                     store.into()
@@ -505,29 +723,49 @@ impl TargetRuntime for BurrowTarget {
                     contract.builder.build_call(
                         contract.module.get_function("__be32toleN").unwrap(),
                         &[
-                            contract.builder.build_pointer_cast(data,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            contract.builder.build_pointer_cast(store,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            contract.builder.build_int_truncate(type_size,
-                                contract.context.i32_type(), "size").into()
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    data,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    store,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
+                            contract
+                                .builder
+                                .build_int_truncate(type_size, contract.context.i32_type(), "size")
+                                .into(),
                         ],
-                        ""
+                        "",
                     );
 
                     if *n <= 64 {
-                        contract.builder.build_load(store, &format!("abi_int{}", *n))
+                        contract
+                            .builder
+                            .build_load(store, &format!("abi_int{}", *n))
                     } else {
                         store.into()
                     }
                 }
-                ast::PrimitiveType::Bytes(1) => {
-                    contract.builder.build_load(
-                        contract.builder.build_pointer_cast(
+                ast::PrimitiveType::Bytes(1) => contract.builder.build_load(
+                    contract
+                        .builder
+                        .build_pointer_cast(
                             data,
-                            contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                        "bytes1")
-                },
+                            contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                            "",
+                        )
+                        .into(),
+                    "bytes1",
+                ),
                 ast::PrimitiveType::Bytes(b) => {
                     let int_type = contract.context.custom_width_int_type(*b as u32 * 8);
                     let type_size = int_type.size_of();
@@ -537,14 +775,28 @@ impl TargetRuntime for BurrowTarget {
                     contract.builder.build_call(
                         contract.module.get_function("__beNtoleN").unwrap(),
                         &[
-                            contract.builder.build_pointer_cast(data,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            contract.builder.build_pointer_cast(store,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            contract.builder.build_int_truncate(type_size,
-                                contract.context.i32_type(), "size").into()
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    data,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    store,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
+                            contract
+                                .builder
+                                .build_int_truncate(type_size, contract.context.i32_type(), "size")
+                                .into(),
                         ],
-                        ""
+                        "",
                     );
 
                     if *b <= 8 {
@@ -557,9 +809,11 @@ impl TargetRuntime for BurrowTarget {
             });
 
             data = unsafe {
-                contract.builder.build_gep(data,
-                    &[ contract.context.i32_type().const_int(8, false)],
-                    "data_next")
+                contract.builder.build_gep(
+                    data,
+                    &[contract.context.i32_type().const_int(8, false)],
+                    "data_next",
+                )
             };
         }
 

Plik diff jest za duży
+ 496 - 214
src/emit/ewasm.rs


Plik diff jest za duży
+ 402 - 148
src/emit/mod.rs


+ 399 - 159
src/emit/substrate.rs

@@ -1,29 +1,32 @@
-
-use resolver;
 use parser::ast;
+use resolver;
 
 use inkwell::context::Context;
 use inkwell::module::Linkage;
+use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue};
 use inkwell::AddressSpace;
-use inkwell::values::{BasicValueEnum, IntValue, PointerValue, FunctionValue};
 use inkwell::IntPredicate;
 
 use std::collections::HashMap;
 
-use super::{TargetRuntime, Contract};
+use super::{Contract, TargetRuntime};
 
 pub struct SubstrateTarget {
     /// This field maps a storage slot to llvm global
-    slot_mapping: HashMap<usize, usize>
+    slot_mapping: HashMap<usize, usize>,
 }
 
 const ADDRESS_LENGTH: u64 = 20;
 
 impl SubstrateTarget {
-    pub fn build<'a>(context: &'a Context, contract: &'a resolver::Contract, filename: &'a str) -> Contract<'a> {
+    pub fn build<'a>(
+        context: &'a Context,
+        contract: &'a resolver::Contract,
+        filename: &'a str,
+    ) -> Contract<'a> {
         let mut c = Contract::new(context, contract, filename, None);
-        let mut b = SubstrateTarget{
-            slot_mapping: HashMap::new()
+        let mut b = SubstrateTarget {
+            slot_mapping: HashMap::new(),
         };
 
         b.storage_keys(&mut c);
@@ -51,7 +54,11 @@ impl SubstrateTarget {
         }
     }
 
-    fn public_function_prelude<'a>(&self, contract: &'a Contract, function: FunctionValue) -> (PointerValue<'a>, IntValue<'a>) {
+    fn public_function_prelude<'a>(
+        &self,
+        contract: &'a Contract,
+        function: FunctionValue,
+    ) -> (PointerValue<'a>, IntValue<'a>) {
         let entry = contract.context.append_basic_block(function, "entry");
 
         contract.builder.position_at_end(&entry);
@@ -60,19 +67,32 @@ impl SubstrateTarget {
         contract.builder.build_call(
             contract.module.get_function("__init_heap").unwrap(),
             &[],
-            "");
+            "",
+        );
 
         // copy arguments from scratch buffer
-        let args_length = contract.builder.build_call(
-            contract.module.get_function("ext_scratch_size").unwrap(),
-            &[],
-            "scratch_size").try_as_basic_value().left().unwrap();
-
-        let args = contract.builder.build_call(
-            contract.module.get_function("__malloc").unwrap(),
-            &[args_length],
-            ""
-        ).try_as_basic_value().left().unwrap().into_pointer_value();
+        let args_length = contract
+            .builder
+            .build_call(
+                contract.module.get_function("ext_scratch_size").unwrap(),
+                &[],
+                "scratch_size",
+            )
+            .try_as_basic_value()
+            .left()
+            .unwrap();
+
+        let args = contract
+            .builder
+            .build_call(
+                contract.module.get_function("__malloc").unwrap(),
+                &[args_length],
+                "",
+            )
+            .try_as_basic_value()
+            .left()
+            .unwrap()
+            .into_pointer_value();
 
         contract.builder.build_call(
             contract.module.get_function("ext_scratch_read").unwrap(),
@@ -81,11 +101,17 @@ impl SubstrateTarget {
                 contract.context.i32_type().const_zero().into(),
                 args_length.into(),
             ],
-            ""
+            "",
         );
 
-        let args = contract.builder.build_pointer_cast(args,
-            contract.context.i32_type().ptr_type(AddressSpace::Generic), "").into();
+        let args = contract
+            .builder
+            .build_pointer_cast(
+                args,
+                contract.context.i32_type().ptr_type(AddressSpace::Generic),
+                "",
+            )
+            .into();
 
         (args, args_length.into_int_value())
     }
@@ -95,54 +121,93 @@ impl SubstrateTarget {
         contract.module.add_function(
             "ext_scratch_size",
             contract.context.i32_type().fn_type(&[], false),
-            Some(Linkage::External)
+            Some(Linkage::External),
         );
 
         contract.module.add_function(
             "ext_scratch_read",
-            contract.context.void_type().fn_type(&[
-                contract.context.i8_type().ptr_type(AddressSpace::Generic).into(),  // dest_ptr
-                contract.context.i32_type().into(), // offset
-                contract.context.i32_type().into(), // len
-            ], false),
-            Some(Linkage::External)
+            contract.context.void_type().fn_type(
+                &[
+                    contract
+                        .context
+                        .i8_type()
+                        .ptr_type(AddressSpace::Generic)
+                        .into(), // dest_ptr
+                    contract.context.i32_type().into(), // offset
+                    contract.context.i32_type().into(), // len
+                ],
+                false,
+            ),
+            Some(Linkage::External),
         );
 
         contract.module.add_function(
             "ext_scratch_write",
-            contract.context.void_type().fn_type(&[
-                contract.context.i8_type().ptr_type(AddressSpace::Generic).into(),  // dest_ptr
-                contract.context.i32_type().into(), // len
-            ], false),
-            Some(Linkage::External)
+            contract.context.void_type().fn_type(
+                &[
+                    contract
+                        .context
+                        .i8_type()
+                        .ptr_type(AddressSpace::Generic)
+                        .into(), // dest_ptr
+                    contract.context.i32_type().into(), // len
+                ],
+                false,
+            ),
+            Some(Linkage::External),
         );
 
         contract.module.add_function(
             "ext_set_storage",
-            contract.context.void_type().fn_type(&[
-                contract.context.i8_type().ptr_type(AddressSpace::Generic).into(), // key_ptr
-                contract.context.i32_type().into(), // value_non_null
-                contract.context.i8_type().ptr_type(AddressSpace::Generic).into(), // value_ptr
-                contract.context.i32_type().into(), // value_len
-            ], false),
-            Some(Linkage::External)
+            contract.context.void_type().fn_type(
+                &[
+                    contract
+                        .context
+                        .i8_type()
+                        .ptr_type(AddressSpace::Generic)
+                        .into(), // key_ptr
+                    contract.context.i32_type().into(), // value_non_null
+                    contract
+                        .context
+                        .i8_type()
+                        .ptr_type(AddressSpace::Generic)
+                        .into(), // value_ptr
+                    contract.context.i32_type().into(), // value_len
+                ],
+                false,
+            ),
+            Some(Linkage::External),
         );
 
         contract.module.add_function(
             "ext_get_storage",
-            contract.context.i32_type().fn_type(&[
-                contract.context.i8_type().ptr_type(AddressSpace::Generic).into(), // key_ptr
-            ], false),
-            Some(Linkage::External)
+            contract.context.i32_type().fn_type(
+                &[
+                    contract
+                        .context
+                        .i8_type()
+                        .ptr_type(AddressSpace::Generic)
+                        .into(), // key_ptr
+                ],
+                false,
+            ),
+            Some(Linkage::External),
         );
 
         contract.module.add_function(
             "ext_return",
-            contract.context.void_type().fn_type(&[
-                contract.context.i8_type().ptr_type(AddressSpace::Generic).into(), // data_ptr
-                contract.context.i32_type().into(), // data_len
-            ], false),
-            Some(Linkage::External)
+            contract.context.void_type().fn_type(
+                &[
+                    contract
+                        .context
+                        .i8_type()
+                        .ptr_type(AddressSpace::Generic)
+                        .into(), // data_ptr
+                    contract.context.i32_type().into(), // data_len
+                ],
+                false,
+            ),
+            Some(Linkage::External),
         );
     }
 
@@ -153,7 +218,8 @@ impl SubstrateTarget {
         let function = contract.module.add_function(
             "deploy",
             contract.context.i32_type().fn_type(&[], false),
-            None);
+            None,
+        );
 
         let (deploy_args, deploy_args_length) = self.public_function_prelude(contract, function);
 
@@ -162,7 +228,15 @@ impl SubstrateTarget {
 
         let fallback_block = contract.context.append_basic_block(function, "fallback");
 
-        contract.emit_function_dispatch(&contract.ns.constructors, &contract.constructors, deploy_args, deploy_args_length, function, &fallback_block, self);
+        contract.emit_function_dispatch(
+            &contract.ns.constructors,
+            &contract.constructors,
+            deploy_args,
+            deploy_args_length,
+            function,
+            &fallback_block,
+            self,
+        );
 
         // emit fallback code
         contract.builder.position_at_end(&fallback_block);
@@ -174,24 +248,34 @@ impl SubstrateTarget {
         let function = contract.module.add_function(
             "call",
             contract.context.i32_type().fn_type(&[], false),
-            None);
+            None,
+        );
 
         let (call_args, call_args_length) = self.public_function_prelude(contract, function);
 
         let fallback_block = contract.context.append_basic_block(function, "fallback");
 
-        contract.emit_function_dispatch(&contract.ns.functions, &contract.functions, call_args, call_args_length, function, &fallback_block, self);
+        contract.emit_function_dispatch(
+            &contract.ns.functions,
+            &contract.functions,
+            call_args,
+            call_args_length,
+            function,
+            &fallback_block,
+            self,
+        );
 
         // emit fallback code
         contract.builder.position_at_end(&fallback_block);
 
         if let Some(fallback) = contract.ns.fallback_function() {
-            contract.builder.build_call(
-                contract.functions[fallback],
-                &[],
-                "");
+            contract
+                .builder
+                .build_call(contract.functions[fallback], &[], "");
 
-            contract.builder.build_return(Some(&contract.context.i32_type().const_zero()));
+            contract
+                .builder
+                .build_return(Some(&contract.context.i32_type().const_zero()));
         } else {
             contract.builder.build_unreachable();
         }
@@ -199,67 +283,129 @@ impl SubstrateTarget {
 }
 
 impl TargetRuntime for SubstrateTarget {
-    fn set_storage<'a>(&self, contract: &'a Contract, _function: FunctionValue, slot: u32, dest: inkwell::values::PointerValue<'a>) {
+    fn set_storage<'a>(
+        &self,
+        contract: &'a Contract,
+        _function: FunctionValue,
+        slot: u32,
+        dest: inkwell::values::PointerValue<'a>,
+    ) {
         // TODO: check for non-zero
         let key = contract.globals[self.slot_mapping[&(slot as usize)]];
 
         contract.builder.build_call(
             contract.module.get_function("ext_set_storage").unwrap(),
             &[
-                contract.builder.build_pointer_cast(key.as_pointer_value(),
-                    contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
+                contract
+                    .builder
+                    .build_pointer_cast(
+                        key.as_pointer_value(),
+                        contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                        "",
+                    )
+                    .into(),
                 contract.context.i32_type().const_int(1, false).into(),
-                contract.builder.build_pointer_cast(dest,
-                    contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                dest.get_type().get_element_type().into_int_type().size_of().const_cast(
-                    contract.context.i32_type(), false).into()
+                contract
+                    .builder
+                    .build_pointer_cast(
+                        dest,
+                        contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                        "",
+                    )
+                    .into(),
+                dest.get_type()
+                    .get_element_type()
+                    .into_int_type()
+                    .size_of()
+                    .const_cast(contract.context.i32_type(), false)
+                    .into(),
             ],
-            "");
+            "",
+        );
     }
 
     /// Read from substrate storage
-    fn get_storage<'a>(&self, contract: &'a Contract, function: FunctionValue, slot: u32, dest: inkwell::values::PointerValue<'a>) {
+    fn get_storage<'a>(
+        &self,
+        contract: &'a Contract,
+        function: FunctionValue,
+        slot: u32,
+        dest: inkwell::values::PointerValue<'a>,
+    ) {
         let key = contract.globals[self.slot_mapping[&(slot as usize)]];
 
-        let exists = contract.builder.build_call(
-            contract.module.get_function("ext_get_storage").unwrap(),
-            &[
-                contract.builder.build_pointer_cast(key.as_pointer_value(),
-                    contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-            ],
-            "").try_as_basic_value().left().unwrap();
+        let exists = contract
+            .builder
+            .build_call(
+                contract.module.get_function("ext_get_storage").unwrap(),
+                &[contract
+                    .builder
+                    .build_pointer_cast(
+                        key.as_pointer_value(),
+                        contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                        "",
+                    )
+                    .into()],
+                "",
+            )
+            .try_as_basic_value()
+            .left()
+            .unwrap();
 
         let exists = contract.builder.build_int_compare(
             IntPredicate::EQ,
             exists.into_int_value(),
             contract.context.i32_type().const_zero(),
-            "storage_exists");
+            "storage_exists",
+        );
 
-        let clear_block = contract.context.append_basic_block(function, "not_in_storage");
+        let clear_block = contract
+            .context
+            .append_basic_block(function, "not_in_storage");
         let retrieve_block = contract.context.append_basic_block(function, "in_storage");
-        let done_storage = contract.context.append_basic_block(function, "done_storage");
+        let done_storage = contract
+            .context
+            .append_basic_block(function, "done_storage");
 
-        contract.builder.build_conditional_branch(exists, &retrieve_block, &clear_block);
+        contract
+            .builder
+            .build_conditional_branch(exists, &retrieve_block, &clear_block);
 
         contract.builder.position_at_end(&retrieve_block);
 
         contract.builder.build_call(
             contract.module.get_function("ext_scratch_read").unwrap(),
             &[
-                contract.builder.build_pointer_cast(dest,
-                    contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
+                contract
+                    .builder
+                    .build_pointer_cast(
+                        dest,
+                        contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                        "",
+                    )
+                    .into(),
                 contract.context.i32_type().const_zero().into(),
-                dest.get_type().get_element_type().into_int_type().size_of().const_cast(
-                    contract.context.i32_type(), false).into()
+                dest.get_type()
+                    .get_element_type()
+                    .into_int_type()
+                    .size_of()
+                    .const_cast(contract.context.i32_type(), false)
+                    .into(),
             ],
-            ""
+            "",
         );
 
         contract.builder.build_unconditional_branch(&done_storage);
 
         contract.builder.position_at_end(&clear_block);
 
-        contract.builder.build_store(dest, dest.get_type().get_element_type().into_int_type().const_zero());
+        contract.builder.build_store(
+            dest,
+            dest.get_type()
+                .get_element_type()
+                .into_int_type()
+                .const_zero(),
+        );
 
         contract.builder.build_unconditional_branch(&done_storage);
 
@@ -287,30 +433,39 @@ impl TargetRuntime for SubstrateTarget {
 
             match ty {
                 ast::PrimitiveType::Bool => length += 1,
-                ast::PrimitiveType::Uint(n) |
-                ast::PrimitiveType::Int(n) => length += n as u64 / 8,
+                ast::PrimitiveType::Uint(n) | ast::PrimitiveType::Int(n) => length += n as u64 / 8,
                 ast::PrimitiveType::Bytes(n) => length += n as u64,
                 ast::PrimitiveType::Address => length += ADDRESS_LENGTH,
-                _ => unimplemented!()
+                _ => unimplemented!(),
             }
         }
 
         let decode_block = contract.context.append_basic_block(function, "abi_decode");
-        let wrong_length_block = contract.context.append_basic_block(function, "wrong_abi_length");
+        let wrong_length_block = contract
+            .context
+            .append_basic_block(function, "wrong_abi_length");
 
-        let is_ok = contract.builder.build_int_compare(IntPredicate::EQ, datalength,
+        let is_ok = contract.builder.build_int_compare(
+            IntPredicate::EQ,
+            datalength,
             contract.context.i32_type().const_int(length, false),
-            "correct_length");
+            "correct_length",
+        );
 
-        contract.builder.build_conditional_branch(is_ok, &decode_block, &wrong_length_block);
+        contract
+            .builder
+            .build_conditional_branch(is_ok, &decode_block, &wrong_length_block);
 
         contract.builder.position_at_end(&wrong_length_block);
         contract.builder.build_unreachable();
 
         contract.builder.position_at_end(&decode_block);
 
-        let mut argsdata = contract.builder.build_pointer_cast(data,
-            contract.context.i8_type().ptr_type(AddressSpace::Generic), "");
+        let mut argsdata = contract.builder.build_pointer_cast(
+            data,
+            contract.context.i8_type().ptr_type(AddressSpace::Generic),
+            "",
+        );
 
         for arg in spec.params.iter() {
             let ty = match arg.ty {
@@ -324,23 +479,38 @@ impl TargetRuntime for SubstrateTarget {
 
             match ty {
                 ast::PrimitiveType::Bool => {
-                    args.push(contract.builder.build_int_compare(IntPredicate::EQ,
-                        contract.builder.build_load(argsdata, "abi_bool").into_int_value(),
-                        contract.context.i8_type().const_int(1, false), "bool").into());
+                    args.push(
+                        contract
+                            .builder
+                            .build_int_compare(
+                                IntPredicate::EQ,
+                                contract
+                                    .builder
+                                    .build_load(argsdata, "abi_bool")
+                                    .into_int_value(),
+                                contract.context.i8_type().const_int(1, false),
+                                "bool",
+                            )
+                            .into(),
+                    );
                     arglen = 1;
-                },
-                ast::PrimitiveType::Uint(n) |
-                ast::PrimitiveType::Int(n) => {
+                }
+                ast::PrimitiveType::Uint(n) | ast::PrimitiveType::Int(n) => {
                     let int_type = contract.context.custom_width_int_type(n as u32);
 
                     let val = contract.builder.build_load(
-                        contract.builder.build_pointer_cast(argsdata,
+                        contract.builder.build_pointer_cast(
+                            argsdata,
                             int_type.ptr_type(AddressSpace::Generic),
-                            ""),
-                        "");
+                            "",
+                        ),
+                        "",
+                    );
 
                     if ty.stack_based() {
-                        let m = contract.builder.build_alloca(ty.LLVMType(&contract.context), "");
+                        let m = contract
+                            .builder
+                            .build_alloca(ty.LLVMType(&contract.context), "");
 
                         contract.builder.build_store(m, val);
 
@@ -349,20 +519,32 @@ impl TargetRuntime for SubstrateTarget {
                         args.push(val);
                     }
                     arglen = n as u64 / 8;
-                },
+                }
                 ast::PrimitiveType::Bytes(n) => {
-                    let m = contract.builder.build_alloca(ty.LLVMType(&contract.context), "");
+                    let m = contract
+                        .builder
+                        .build_alloca(ty.LLVMType(&contract.context), "");
 
                     // byte order needs to be reversed. e.g. hex"11223344" should be 0x10 0x11 0x22 0x33 0x44
                     contract.builder.build_call(
                         contract.module.get_function("__beNtoleN").unwrap(),
                         &[
                             argsdata.into(),
-                            contract.builder.build_pointer_cast(m,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            contract.context.i32_type().const_int(n as u64, false).into()
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    m,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
+                            contract
+                                .context
+                                .i32_type()
+                                .const_int(n as u64, false)
+                                .into(),
                         ],
-                        ""
+                        "",
                     );
 
                     if ty.stack_based() {
@@ -374,32 +556,45 @@ impl TargetRuntime for SubstrateTarget {
                     arglen = n as u64;
                 }
                 ast::PrimitiveType::Address => {
-                    let address = contract.builder.build_alloca(ty.LLVMType(&contract.context), "address");
+                    let address = contract
+                        .builder
+                        .build_alloca(ty.LLVMType(&contract.context), "address");
 
                     // byte order needs to be reversed
                     contract.builder.build_call(
                         contract.module.get_function("__beNtoleN").unwrap(),
                         &[
                             argsdata.into(),
-                            contract.builder.build_pointer_cast(address,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
-                            contract.context.i32_type().const_int(ADDRESS_LENGTH, false).into()
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    address,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
+                            contract
+                                .context
+                                .i32_type()
+                                .const_int(ADDRESS_LENGTH, false)
+                                .into(),
                         ],
-                        ""
+                        "",
                     );
 
                     args.push(address.into());
 
                     arglen = ADDRESS_LENGTH;
                 }
-                _ => unimplemented!()
+                _ => unimplemented!(),
             }
 
             argsdata = unsafe {
                 contract.builder.build_gep(
                     argsdata,
-                    &[ contract.context.i32_type().const_int(arglen, false).into()],
-                    "abi_ptr")
+                    &[contract.context.i32_type().const_int(arglen, false).into()],
+                    "abi_ptr",
+                )
             };
         }
     }
@@ -422,21 +617,26 @@ impl TargetRuntime for SubstrateTarget {
 
             match ty {
                 ast::PrimitiveType::Bool => length += 1,
-                ast::PrimitiveType::Uint(n) |
-                ast::PrimitiveType::Int(n) => length += n as u64 / 8,
+                ast::PrimitiveType::Uint(n) | ast::PrimitiveType::Int(n) => length += n as u64 / 8,
                 ast::PrimitiveType::Bytes(n) => length += n as u64,
                 ast::PrimitiveType::Address => length += ADDRESS_LENGTH,
-                _ => unimplemented!()
+                _ => unimplemented!(),
             }
         }
 
         let length = contract.context.i32_type().const_int(length, false);
 
-        let data = contract.builder.build_call(
-            contract.module.get_function("__malloc").unwrap(),
-            &[ length.into() ],
-            ""
-        ).try_as_basic_value().left().unwrap().into_pointer_value();
+        let data = contract
+            .builder
+            .build_call(
+                contract.module.get_function("__malloc").unwrap(),
+                &[length.into()],
+                "",
+            )
+            .try_as_basic_value()
+            .left()
+            .unwrap()
+            .into_pointer_value();
 
         let mut argsdata = data;
 
@@ -452,34 +652,47 @@ impl TargetRuntime for SubstrateTarget {
 
             match ty {
                 ast::PrimitiveType::Bool => {
-                    contract.builder.build_store(argsdata,
-                        contract.builder.build_int_z_extend(args[i].into_int_value(), contract.context.i8_type(), "bool")
+                    contract.builder.build_store(
+                        argsdata,
+                        contract.builder.build_int_z_extend(
+                            args[i].into_int_value(),
+                            contract.context.i8_type(),
+                            "bool",
+                        ),
                     );
                     arglen = 1;
-                },
-                ast::PrimitiveType::Uint(n) |
-                ast::PrimitiveType::Int(n) => {
+                }
+                ast::PrimitiveType::Uint(n) | ast::PrimitiveType::Int(n) => {
                     let val = if args[i].is_pointer_value() {
                         // Value is a pointer to e.g i256. First we have to load the value
-                        contract.builder.build_load(args[i].into_pointer_value(), "")
+                        contract
+                            .builder
+                            .build_load(args[i].into_pointer_value(), "")
                     } else {
                         args[i]
                     };
 
                     contract.builder.build_store(
-                        contract.builder.build_pointer_cast(argsdata,
-                            val.into_int_value().get_type().ptr_type(AddressSpace::Generic),
-                            ""),
-                        val.into_int_value()
+                        contract.builder.build_pointer_cast(
+                            argsdata,
+                            val.into_int_value()
+                                .get_type()
+                                .ptr_type(AddressSpace::Generic),
+                            "",
+                        ),
+                        val.into_int_value(),
                     );
 
                     arglen = n as u64 / 8;
-                },
+                }
                 ast::PrimitiveType::Bytes(n) => {
                     let val = if args[i].is_pointer_value() {
                         args[i].into_pointer_value()
                     } else {
-                        let val = contract.builder.build_alloca(args[i].into_int_value().get_type(), &format!("bytes{}", n));
+                        let val = contract.builder.build_alloca(
+                            args[i].into_int_value().get_type(),
+                            &format!("bytes{}", n),
+                        );
 
                         contract.builder.build_store(val, args[i].into_int_value());
 
@@ -490,12 +703,22 @@ impl TargetRuntime for SubstrateTarget {
                     contract.builder.build_call(
                         contract.module.get_function("__leNtobeN").unwrap(),
                         &[
-                            contract.builder.build_pointer_cast(val,
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    val,
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
                             argsdata.into(),
-                            contract.context.i32_type().const_int(n as u64, false).into()
+                            contract
+                                .context
+                                .i32_type()
+                                .const_int(n as u64, false)
+                                .into(),
                         ],
-                        ""
+                        "",
                     );
 
                     arglen = n as u64
@@ -505,24 +728,35 @@ impl TargetRuntime for SubstrateTarget {
                     contract.builder.build_call(
                         contract.module.get_function("__leNtobeN").unwrap(),
                         &[
-                            contract.builder.build_pointer_cast(args[i].into_pointer_value(),
-                                contract.context.i8_type().ptr_type(AddressSpace::Generic), "").into(),
+                            contract
+                                .builder
+                                .build_pointer_cast(
+                                    args[i].into_pointer_value(),
+                                    contract.context.i8_type().ptr_type(AddressSpace::Generic),
+                                    "",
+                                )
+                                .into(),
                             argsdata.into(),
-                            contract.context.i32_type().const_int(ADDRESS_LENGTH, false).into()
+                            contract
+                                .context
+                                .i32_type()
+                                .const_int(ADDRESS_LENGTH, false)
+                                .into(),
                         ],
-                        ""
+                        "",
                     );
 
                     arglen = ADDRESS_LENGTH
                 }
-                _ => unimplemented!()
+                _ => unimplemented!(),
             }
 
             argsdata = unsafe {
                 contract.builder.build_gep(
                     argsdata,
-                    &[ contract.context.i32_type().const_int(arglen, false).into()],
-                    "abi_ptr")
+                    &[contract.context.i32_type().const_int(arglen, false).into()],
+                    "abi_ptr",
+                )
             };
         }
 
@@ -534,26 +768,32 @@ impl TargetRuntime for SubstrateTarget {
         contract.builder.build_call(
             contract.module.get_function("ext_scratch_write").unwrap(),
             &[
-                contract.context.i8_type().ptr_type(AddressSpace::Generic).const_zero().into(),
+                contract
+                    .context
+                    .i8_type()
+                    .ptr_type(AddressSpace::Generic)
+                    .const_zero()
+                    .into(),
                 contract.context.i32_type().const_zero().into(),
             ],
-            ""
+            "",
         );
 
-        contract.builder.build_return(Some(&contract.context.i32_type().const_zero()));
+        contract
+            .builder
+            .build_return(Some(&contract.context.i32_type().const_zero()));
     }
 
     fn return_abi<'b>(&self, contract: &'b Contract, data: PointerValue<'b>, length: IntValue) {
         contract.builder.build_call(
             contract.module.get_function("ext_scratch_write").unwrap(),
-            &[
-                data.into(),
-                length.into(),
-            ],
-            ""
+            &[data.into(), length.into()],
+            "",
         );
 
-        contract.builder.build_return(Some(&contract.context.i32_type().const_zero()));
+        contract
+            .builder
+            .build_return(Some(&contract.context.i32_type().const_zero()));
     }
 
     fn assert_failure<'b>(&self, contract: &'b Contract) {

+ 27 - 16
src/lib.rs

@@ -1,20 +1,20 @@
 extern crate clap;
 extern crate hex;
+extern crate inkwell;
 extern crate lalrpop_util;
 extern crate lazy_static;
 extern crate num_bigint;
+extern crate num_derive;
 extern crate num_traits;
 extern crate parity_wasm;
 extern crate serde;
+extern crate serde_derive;
 extern crate tiny_keccak;
 extern crate unescape;
-extern crate inkwell;
-extern crate num_derive;
-extern crate serde_derive;
 
+pub mod abi;
 pub mod link;
 pub mod output;
-pub mod abi;
 
 mod emit;
 mod parser;
@@ -30,7 +30,7 @@ pub enum Target {
     /// Hyperledger Burrow, see https://github.com/hyperledger/burrow/
     Burrow,
     /// Ethereum ewasm, see https://github.com/ewasm/design
-    Ewasm
+    Ewasm,
 }
 
 impl fmt::Display for Target {
@@ -38,7 +38,7 @@ impl fmt::Display for Target {
         match self {
             Target::Substrate => write!(f, "Substrate"),
             Target::Burrow => write!(f, "Burrow"),
-            Target::Ewasm => write!(f, "ewasm")
+            Target::Ewasm => write!(f, "ewasm"),
         }
     }
 }
@@ -50,7 +50,12 @@ impl fmt::Display for Target {
 /// compiler warnings, errors and informational messages are also provided.
 ///
 /// The ctx is the inkwell llvm context.
-pub fn compile(src: &str, filename: &str, opt: &str, target: &Target) -> (Vec<(Vec<u8>, String)>, Vec<output::Output>) {
+pub fn compile(
+    src: &str,
+    filename: &str,
+    opt: &str,
+    target: &Target,
+) -> (Vec<(Vec<u8>, String)>, Vec<output::Output>) {
     let ctx = inkwell::context::Context::create();
 
     let ast = match parser::parse(src) {
@@ -63,18 +68,21 @@ pub fn compile(src: &str, filename: &str, opt: &str, target: &Target) -> (Vec<(V
     // resolve
     let (contracts, errors) = resolver::resolver(ast, target);
 
-    let results = contracts.iter().map(|c| {
-        let (abistr, _) = abi::generate_abi(c, false);
+    let results = contracts
+        .iter()
+        .map(|c| {
+            let (abistr, _) = abi::generate_abi(c, false);
 
-        // codegen
-        let contract = emit::Contract::build(&ctx, c, filename, opt);
+            // codegen
+            let contract = emit::Contract::build(&ctx, c, filename, opt);
 
-        let obj = contract.wasm(opt).expect("llvm wasm emit should work");
+            let obj = contract.wasm(opt).expect("llvm wasm emit should work");
 
-        let bc = link::link(&obj, target);
+            let bc = link::link(&obj, target);
 
-        (bc, abistr)
-    }).collect();
+            (bc, abistr)
+        })
+        .collect();
 
     (results, errors)
 }
@@ -84,7 +92,10 @@ pub fn compile(src: &str, filename: &str, opt: &str, target: &Target) -> (Vec<(V
 /// informational messages like `found contact N`.
 ///
 /// Note that multiple contracts can be specified in on solidity source file.
-pub fn parse_and_resolve(src: &str, target: &Target) -> (Vec<resolver::Contract>, Vec<output::Output>) {
+pub fn parse_and_resolve(
+    src: &str,
+    target: &Target,
+) -> (Vec<resolver::Contract>, Vec<output::Output>) {
     let ast = match parser::parse(src) {
         Ok(s) => s,
         Err(errors) => {

+ 6 - 9
src/link.rs

@@ -1,10 +1,9 @@
-
-use Target;
 use parity_wasm;
 use parity_wasm::builder;
 use parity_wasm::elements::{
     ExportEntry, GlobalEntry, GlobalType, InitExpr, Internal, Module, ValueType,
 };
+use Target;
 
 use parity_wasm::elements;
 use parity_wasm::elements::{Deserialize, ImportEntry, VarUint32, VarUint7};
@@ -28,12 +27,10 @@ pub fn link(input: &[u8], target: &Target) -> Vec<u8> {
     // FIXME: rather than filtering out functions which should not be exported, we should
     // rely on LLVM to optimize them away, with e.g. LLVMAddInternalizePassWithMustPreservePredicate()
     // or something like that.
-    let allowed_externs = |name: &str| {
-        match target {
-            Target::Ewasm => name == "main",
-            Target::Burrow => name == "constructor" || name == "function",
-            Target::Substrate => name == "deploy" || name == "call"
-        }
+    let allowed_externs = |name: &str| match target {
+        Target::Ewasm => name == "main",
+        Target::Burrow => name == "constructor" || name == "function",
+        Target::Substrate => name == "deploy" || name == "call",
     };
 
     for c in module.custom_sections() {
@@ -80,7 +77,7 @@ pub fn link(input: &[u8], target: &Target) -> Vec<u8> {
             } else {
                 if let Target::Ewasm = target {
                     let module = imports[ind].module_mut();
-                    
+
                     *module = "ethereum".to_string();
                 }
 

+ 2 - 2
src/parser/ast.rs

@@ -164,13 +164,13 @@ pub struct ContractVariableDefinition {
 #[derive(Debug, PartialEq)]
 pub struct StringLiteral {
     pub loc: Loc,
-    pub string: String
+    pub string: String,
 }
 
 #[derive(Debug, PartialEq)]
 pub struct HexLiteral {
     pub loc: Loc,
-    pub hex: String
+    pub hex: String,
 }
 
 #[derive(Debug, PartialEq)]

+ 341 - 239
src/parser/lexer.rs

@@ -3,10 +3,10 @@
 //  - comments and doc comments
 //  - pragma value is [^;]+
 //
-use std::iter::Peekable;
-use std::str::CharIndices;
 use std::collections::HashMap;
 use std::fmt;
+use std::iter::Peekable;
+use std::str::CharIndices;
 
 use super::ast::Loc;
 
@@ -15,7 +15,7 @@ pub type Spanned<Token, Loc, Error> = Result<(Loc, Token, Loc), Error>;
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum CommentType {
     Line,
-    Block
+    Block,
 }
 
 #[derive(Copy, Clone, PartialEq, Debug)]
@@ -249,10 +249,10 @@ pub struct Lexer<'input> {
     input: &'input str,
     chars: Peekable<CharIndices<'input>>,
     keywords: HashMap<String, Token<'input>>,
-    pragma_state: PragmaParserState
+    pragma_state: PragmaParserState,
 }
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub enum LexicalError {
     EndOfFileInComment(usize, usize),
     EndOfFileInString(usize, usize),
@@ -267,12 +267,20 @@ impl LexicalError {
     pub fn to_string(&self) -> String {
         match self {
             LexicalError::EndOfFileInComment(_, _) => "end of file found in comment".to_string(),
-            LexicalError::EndOfFileInString(_, _) => "end of file found in string literal".to_string(),
-            LexicalError::EndofFileInHex(_, _) => "end of file found in hex literal string".to_string(),
+            LexicalError::EndOfFileInString(_, _) => {
+                "end of file found in string literal".to_string()
+            }
+            LexicalError::EndofFileInHex(_, _) => {
+                "end of file found in hex literal string".to_string()
+            }
             LexicalError::MissingNumber(_, _) => "missing number".to_string(),
-            LexicalError::InvalidCharacterInHexLiteral(_, ch) => format!("invalid character ‘{}’ in hex literal string", ch),
+            LexicalError::InvalidCharacterInHexLiteral(_, ch) => {
+                format!("invalid character ‘{}’ in hex literal string", ch)
+            }
             LexicalError::UnrecognisedToken(_, _, t) => format!("unrecognised token ‘{}’", t),
-            LexicalError::PragmaMissingSemiColon(_, _) => "pragma is missing terminating ‘;’".to_string(),
+            LexicalError::PragmaMissingSemiColon(_, _) => {
+                "pragma is missing terminating ‘;’".to_string()
+            }
         }
     }
 
@@ -295,7 +303,7 @@ impl LexicalError {
 pub enum PragmaParserState {
     NotParsingPragma,
     SeenPragma,
-    SeenPragmaIdentifier
+    SeenPragmaIdentifier,
 }
 
 impl<'input> Lexer<'input> {
@@ -369,11 +377,16 @@ impl<'input> Lexer<'input> {
             input: input,
             chars: input.char_indices().peekable(),
             keywords: keywords,
-            pragma_state: PragmaParserState::NotParsingPragma
+            pragma_state: PragmaParserState::NotParsingPragma,
         }
     }
 
-    fn parse_number(&mut self, start: usize, end: usize, ch: char) -> Option<Result<(usize, Token<'input>, usize), LexicalError>> {
+    fn parse_number(
+        &mut self,
+        start: usize,
+        end: usize,
+        ch: char,
+    ) -> Option<Result<(usize, Token<'input>, usize), LexicalError>> {
         if ch == '0' {
             if let Some((_, 'x')) = self.chars.peek() {
                 // hex number
@@ -383,7 +396,7 @@ impl<'input> Lexer<'input> {
                     Some((end, ch)) if ch.is_ascii_hexdigit() => end,
                     Some((_, _)) => {
                         return Some(Err(LexicalError::MissingNumber(start, start + 1)));
-                    },
+                    }
                     None => {
                         return Some(Err(LexicalError::EndofFileInHex(start, self.input.len())));
                     }
@@ -397,7 +410,11 @@ impl<'input> Lexer<'input> {
                     self.chars.next();
                 }
 
-                return Some(Ok((start, Token::HexNumber(&self.input[start..=end]), end+1)));
+                return Some(Ok((
+                    start,
+                    Token::HexNumber(&self.input[start..=end]),
+                    end + 1,
+                )));
             }
         }
 
@@ -410,7 +427,11 @@ impl<'input> Lexer<'input> {
             self.chars.next();
         }
 
-        return Some(Ok((start, Token::Number(&self.input[start..=end]), end+1)));
+        return Some(Ok((
+            start,
+            Token::Number(&self.input[start..=end]),
+            end + 1,
+        )));
     }
 
     fn next(&mut self) -> Option<Result<(usize, Token<'input>, usize), LexicalError>> {
@@ -435,7 +456,11 @@ impl<'input> Lexer<'input> {
 
                             while let Some((i, ch)) = self.chars.next() {
                                 if ch == '"' {
-                                    return Some(Ok((start, Token::HexLiteral(&self.input[start..=i]), i+1)));
+                                    return Some(Ok((
+                                        start,
+                                        Token::HexLiteral(&self.input[start..=i]),
+                                        i + 1,
+                                    )));
                                 }
 
                                 if !ch.is_ascii_hexdigit() && ch != '_' {
@@ -446,20 +471,25 @@ impl<'input> Lexer<'input> {
                                         }
                                     }
 
-                                    return Some(Err(LexicalError::InvalidCharacterInHexLiteral(i, ch)));
+                                    return Some(Err(LexicalError::InvalidCharacterInHexLiteral(
+                                        i, ch,
+                                    )));
                                 }
                             }
 
-                            return Some(Err(LexicalError::EndOfFileInString(start, self.input.len())));
+                            return Some(Err(LexicalError::EndOfFileInString(
+                                start,
+                                self.input.len(),
+                            )));
                         }
                     }
 
                     return if let Some(w) = self.keywords.get(id) {
-                        Some(Ok((start, *w, end+1)))
+                        Some(Ok((start, *w, end + 1)))
                     } else {
-                        Some(Ok((start, Token::Identifier(id), end+1)))
+                        Some(Ok((start, Token::Identifier(id), end + 1)))
                     };
-                },
+                }
                 Some((start, '"')) => {
                     let mut end;
 
@@ -477,17 +507,24 @@ impl<'input> Lexer<'input> {
                                 last_was_escape = false;
                             }
                         } else {
-                            return Some(Err(LexicalError::EndOfFileInString(start, self.input.len())));
+                            return Some(Err(LexicalError::EndOfFileInString(
+                                start,
+                                self.input.len(),
+                            )));
                         }
                     }
 
-                    return Some(Ok((start, Token::StringLiteral(&self.input[start+1..=end-1]), end+1)));
-                },
+                    return Some(Ok((
+                        start,
+                        Token::StringLiteral(&self.input[start + 1..=end - 1]),
+                        end + 1,
+                    )));
+                }
                 Some((start, '/')) => {
                     match self.chars.peek() {
                         Some((_, '=')) => {
                             self.chars.next();
-                            return Some(Ok((start, Token::DivideAssign, start+2)));
+                            return Some(Ok((start, Token::DivideAssign, start + 2)));
                         }
                         Some((_, '/')) => {
                             // line comment
@@ -495,7 +532,7 @@ impl<'input> Lexer<'input> {
 
                             let doc_comment_start = match self.chars.peek() {
                                 Some((i, '/')) => Some(i + 1),
-                                _ => None
+                                _ => None,
                             };
 
                             let mut last = start + 3;
@@ -509,19 +546,24 @@ impl<'input> Lexer<'input> {
 
                             if let Some(doc_start) = doc_comment_start {
                                 if last > doc_start {
-                                    return Some(Ok((start + 3,
-                                        Token::DocComment(CommentType::Line, &self.input[doc_start..=last]),
-                                        last + 1)));
+                                    return Some(Ok((
+                                        start + 3,
+                                        Token::DocComment(
+                                            CommentType::Line,
+                                            &self.input[doc_start..=last],
+                                        ),
+                                        last + 1,
+                                    )));
                                 }
                             }
-                        },
+                        }
                         Some((_, '*')) => {
                             // multiline comment
                             self.chars.next();
 
                             let doc_comment_start = match self.chars.peek() {
                                 Some((i, '*')) => Some(i + 1),
-                                _ => None
+                                _ => None,
                             };
 
                             let mut last = start + 3;
@@ -535,148 +577,144 @@ impl<'input> Lexer<'input> {
                                     seen_star = ch == '*';
                                     last = i;
                                 } else {
-                                    return Some(Err(LexicalError::EndOfFileInComment(start, self.input.len())));
+                                    return Some(Err(LexicalError::EndOfFileInComment(
+                                        start,
+                                        self.input.len(),
+                                    )));
                                 }
                             }
 
                             if let Some(doc_start) = doc_comment_start {
                                 if last > doc_start {
-                                    return Some(Ok((start + 3,
-                                        Token::DocComment(CommentType::Block, &self.input[doc_start..last]),
-                                        last)));
+                                    return Some(Ok((
+                                        start + 3,
+                                        Token::DocComment(
+                                            CommentType::Block,
+                                            &self.input[doc_start..last],
+                                        ),
+                                        last,
+                                    )));
                                 }
                             }
-                       },
+                        }
                         _ => {
-                            return Some(Ok((start, Token::Divide, start+1)));
+                            return Some(Ok((start, Token::Divide, start + 1)));
                         }
                     }
                 }
-                Some((start, ch)) if ch.is_ascii_digit() => return self.parse_number(start, start, ch),
-                Some((i, ';')) => return Some(Ok((i, Token::Semicolon, i+1))),
-                Some((i, ',')) => return Some(Ok((i, Token::Comma, i+1))),
-                Some((i, '(')) => return Some(Ok((i, Token::OpenParenthesis, i+1))),
-                Some((i, ')')) => return Some(Ok((i, Token::CloseParenthesis, i+1))),
-                Some((i, '{')) => return Some(Ok((i, Token::OpenCurlyBrace, i+1))),
-                Some((i, '}')) => return Some(Ok((i, Token::CloseCurlyBrace, i+1))),
-                Some((i, '~')) => return Some(Ok((i, Token::Complement, i+1))),
+                Some((start, ch)) if ch.is_ascii_digit() => {
+                    return self.parse_number(start, start, ch)
+                }
+                Some((i, ';')) => return Some(Ok((i, Token::Semicolon, i + 1))),
+                Some((i, ',')) => return Some(Ok((i, Token::Comma, i + 1))),
+                Some((i, '(')) => return Some(Ok((i, Token::OpenParenthesis, i + 1))),
+                Some((i, ')')) => return Some(Ok((i, Token::CloseParenthesis, i + 1))),
+                Some((i, '{')) => return Some(Ok((i, Token::OpenCurlyBrace, i + 1))),
+                Some((i, '}')) => return Some(Ok((i, Token::CloseCurlyBrace, i + 1))),
+                Some((i, '~')) => return Some(Ok((i, Token::Complement, i + 1))),
                 Some((i, '=')) => {
                     if let Some((_, '=')) = self.chars.peek() {
                         self.chars.next();
-                        return Some(Ok((i, Token::Equal, i+2)));
+                        return Some(Ok((i, Token::Equal, i + 2)));
                     } else {
-                        return Some(Ok((i, Token::Assign, i+1)));
+                        return Some(Ok((i, Token::Assign, i + 1)));
                     }
                 }
                 Some((i, '!')) => {
                     if let Some((_, '=')) = self.chars.peek() {
                         self.chars.next();
-                        return Some(Ok((i, Token::NotEqual, i+2)));
+                        return Some(Ok((i, Token::NotEqual, i + 2)));
                     } else {
-                        return Some(Ok((i, Token::Not, i+1)));
+                        return Some(Ok((i, Token::Not, i + 1)));
                     }
                 }
                 Some((i, '|')) => {
                     return match self.chars.peek() {
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::BitwiseOrAssign, i+2)))
-                        },
+                            Some(Ok((i, Token::BitwiseOrAssign, i + 2)))
+                        }
                         Some((_, '|')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::Or, i+2)))
-                        },
-                        _ => {
-                            Some(Ok((i, Token::BitwiseOr, i+1)))
+                            Some(Ok((i, Token::Or, i + 2)))
                         }
+                        _ => Some(Ok((i, Token::BitwiseOr, i + 1))),
                     };
                 }
                 Some((i, '&')) => {
                     return match self.chars.peek() {
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::BitwiseAndAssign, i+2)))
-                        },
+                            Some(Ok((i, Token::BitwiseAndAssign, i + 2)))
+                        }
                         Some((_, '&')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::And, i+2)))
-                        },
-                        _ => {
-                            Some(Ok((i, Token::BitwiseAnd, i+1)))
+                            Some(Ok((i, Token::And, i + 2)))
                         }
+                        _ => Some(Ok((i, Token::BitwiseAnd, i + 1))),
                     };
                 }
                 Some((i, '^')) => {
                     return match self.chars.peek() {
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::BitwiseXorAssign, i+2)))
-                        },
-                        _ => {
-                            Some(Ok((i, Token::BitwiseXor, i+1)))
+                            Some(Ok((i, Token::BitwiseXorAssign, i + 2)))
                         }
+                        _ => Some(Ok((i, Token::BitwiseXor, i + 1))),
                     };
                 }
                 Some((i, '+')) => {
                     return match self.chars.peek() {
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::AddAssign, i+2)))
-                        },
+                            Some(Ok((i, Token::AddAssign, i + 2)))
+                        }
                         Some((_, '+')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::Increment, i+2)))
-                        },
-                        _ => {
-                            Some(Ok((i, Token::Add, i+1)))
+                            Some(Ok((i, Token::Increment, i + 2)))
                         }
+                        _ => Some(Ok((i, Token::Add, i + 1))),
                     };
                 }
                 Some((i, '-')) => {
                     return match self.chars.peek() {
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::SubtractAssign, i+2)))
-                        },
+                            Some(Ok((i, Token::SubtractAssign, i + 2)))
+                        }
                         Some((_, '-')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::Decrement, i+2)))
-                        },
+                            Some(Ok((i, Token::Decrement, i + 2)))
+                        }
                         Some((end, ch)) if ch.is_ascii_digit() => {
                             let ch = *ch;
                             let end = *end;
                             self.chars.next();
                             self.parse_number(i, end, ch)
-                        },
-                        _ => {
-                            Some(Ok((i, Token::Subtract, i+1)))
                         }
+                        _ => Some(Ok((i, Token::Subtract, i + 1))),
                     };
                 }
                 Some((i, '*')) => {
                     return match self.chars.peek() {
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::MulAssign, i+2)))
-                        },
+                            Some(Ok((i, Token::MulAssign, i + 2)))
+                        }
                         Some((_, '*')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::Power, i+2)))
-                        },
-                        _ => {
-                            Some(Ok((i, Token::Mul, i+1)))
+                            Some(Ok((i, Token::Power, i + 2)))
                         }
+                        _ => Some(Ok((i, Token::Mul, i + 1))),
                     };
                 }
                 Some((i, '%')) => {
                     return match self.chars.peek() {
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::ModuloAssign, i+2)))
-                        },
-                        _ => {
-                            Some(Ok((i, Token::Modulo, i+1)))
+                            Some(Ok((i, Token::ModuloAssign, i + 2)))
                         }
+                        _ => Some(Ok((i, Token::Modulo, i + 1))),
                     };
                 }
                 Some((i, '<')) => {
@@ -685,18 +723,16 @@ impl<'input> Lexer<'input> {
                             self.chars.next();
                             if let Some((_, '=')) = self.chars.peek() {
                                 self.chars.next();
-                                Some(Ok((i, Token::ShiftLeftAssign, i+3)))
+                                Some(Ok((i, Token::ShiftLeftAssign, i + 3)))
                             } else {
-                                Some(Ok((i, Token::ShiftLeft, i+2)))
+                                Some(Ok((i, Token::ShiftLeft, i + 2)))
                             }
-                        },
+                        }
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token::LessEqual, i+2)))
-                        }
-                        _ => {
-                           Some(Ok((i, Token::Less, i+1)))
+                            Some(Ok((i, Token::LessEqual, i + 2)))
                         }
+                        _ => Some(Ok((i, Token::Less, i + 1))),
                     };
                 }
                 Some((i, '>')) => {
@@ -705,29 +741,24 @@ impl<'input> Lexer<'input> {
                             self.chars.next();
                             if let Some((_, '=')) = self.chars.peek() {
                                 self.chars.next();
-                                Some(Ok((i, Token::ShiftRightAssign, i+3)))
+                                Some(Ok((i, Token::ShiftRightAssign, i + 3)))
                             } else {
-                                Some(Ok((i, Token::ShiftRight, i+2)))
+                                Some(Ok((i, Token::ShiftRight, i + 2)))
                             }
-                        },
+                        }
                         Some((_, '=')) => {
                             self.chars.next();
-                            Some(Ok((i, Token:: MoreEqual, i+2)))
-                        }
-                        _ => {
-                           Some(Ok((i, Token::More, i+1)))
+                            Some(Ok((i, Token::MoreEqual, i + 2)))
                         }
+                        _ => Some(Ok((i, Token::More, i + 1))),
                     };
                 }
-                Some((i, '.')) => return Some(Ok((i, Token::Member, i+1))),
-                Some((i, '[')) => return Some(Ok((i, Token::OpenBracket, i+1))),
-                Some((i, ']')) => return Some(Ok((i, Token::CloseBracket, i+1))),
-                Some((i, ':')) => return Some(Ok((i, Token::Colon, i+1))),
-                Some((i, '?')) => return Some(Ok((i, Token::Question, i+1))),
-                Some((_, '\t')) |
-                Some((_, '\r')) |
-                Some((_, ' ')) |
-                Some((_, '\n')) => (),
+                Some((i, '.')) => return Some(Ok((i, Token::Member, i + 1))),
+                Some((i, '[')) => return Some(Ok((i, Token::OpenBracket, i + 1))),
+                Some((i, ']')) => return Some(Ok((i, Token::CloseBracket, i + 1))),
+                Some((i, ':')) => return Some(Ok((i, Token::Colon, i + 1))),
+                Some((i, '?')) => return Some(Ok((i, Token::Question, i + 1))),
+                Some((_, '\t')) | Some((_, '\r')) | Some((_, ' ')) | Some((_, '\n')) => (),
                 Some((start, _)) => {
                     let mut end;
 
@@ -744,7 +775,11 @@ impl<'input> Lexer<'input> {
                         }
                     }
 
-                    return Some(Err(LexicalError::UnrecognisedToken(start, end, self.input[start..end].to_owned())));
+                    return Some(Err(LexicalError::UnrecognisedToken(
+                        start,
+                        end,
+                        self.input[start..end].to_owned(),
+                    )));
                 }
                 None => return None, // End of file
             }
@@ -776,11 +811,18 @@ impl<'input> Iterator for Lexer<'input> {
             loop {
                 match self.chars.next() {
                     Some((i, ';')) => {
-                        return Some(Ok((start, Token::StringLiteral(&self.input[start..i]), i-1)));
-                    },
+                        return Some(Ok((
+                            start,
+                            Token::StringLiteral(&self.input[start..i]),
+                            i - 1,
+                        )));
+                    }
                     Some(_) => (),
                     None => {
-                        return Some(Err(LexicalError::PragmaMissingSemiColon(start, self.input.len())));
+                        return Some(Err(LexicalError::PragmaMissingSemiColon(
+                            start,
+                            self.input.len(),
+                        )));
                     }
                 }
             }
@@ -795,14 +837,14 @@ impl<'input> Iterator for Lexer<'input> {
                 } else {
                     PragmaParserState::NotParsingPragma
                 }
-            },
+            }
             PragmaParserState::SeenPragma => {
                 if let Some(Ok((_, Token::Identifier(_), _))) = token {
                     PragmaParserState::SeenPragmaIdentifier
                 } else {
                     PragmaParserState::NotParsingPragma
                 }
-            },
+            }
             PragmaParserState::SeenPragmaIdentifier => {
                 unreachable!();
             }
@@ -824,24 +866,29 @@ pub fn fold_doc_comments(docs: Vec<(CommentType, &str)>) -> Vec<String> {
         match d {
             (CommentType::Block, s) => {
                 return if comment.is_empty() {
-                    s.lines().filter_map(|s| {
-                        if let Some((i, _)) = s.char_indices().find(|(_, ch)| !ch.is_whitespace() && *ch != '*') {
-                            return Some(s[i..].to_string());
-                        }
+                    s.lines()
+                        .filter_map(|s| {
+                            if let Some((i, _)) = s
+                                .char_indices()
+                                .find(|(_, ch)| !ch.is_whitespace() && *ch != '*')
+                            {
+                                return Some(s[i..].to_string());
+                            }
 
-                        None
-                    }).collect()
+                            None
+                        })
+                        .collect()
                 } else {
                     comment
                 };
-            },
+            }
             (CommentType::Line, s) => {
                 let s = s.trim();
 
                 if !s.is_empty() {
                     comment.insert(0, s.to_string());
                 }
-            },
+            }
         }
     }
 
@@ -862,148 +909,203 @@ fn lexertest() {
 
     assert_eq!(tokens, vec!(Ok((0, Token::Identifier("hex"), 3))));
 
-    let tokens = Lexer::new("hex\"cafe_dead\" /* adad*** */").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(Ok((0, Token::HexLiteral("hex\"cafe_dead\""), 14))));
-
-    let tokens = Lexer::new("// foo bar\n0x00fead0_12 00090 0_0").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((11, Token::HexNumber("0x00fead0_12"), 23)),
-        Ok((24, Token::Number("00090"), 29)),
-        Ok((30, Token::Number("0_0"), 33))
-    ));
-
-    let tokens = Lexer::new("\"foo\"").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((0, Token::StringLiteral("foo"), 5)),
-    ));
-
-    let tokens = Lexer::new("pragma solidity >=0.5.0 <0.7.0;").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((0, Token::Pragma, 6)),
-        Ok((7, Token::Identifier("solidity"), 15)),
-        Ok((16, Token::StringLiteral(">=0.5.0 <0.7.0"), 29)),
-    ));
-
-    let tokens = Lexer::new(">>= >> >= >").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((0, Token::ShiftRightAssign, 3)),
-        Ok((4, Token::ShiftRight, 6)),
-        Ok((7, Token::MoreEqual, 9)),
-        Ok((10, Token::More, 11)),
-    ));
-
-    let tokens = Lexer::new("<<= << <= <").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((0, Token::ShiftLeftAssign, 3)),
-        Ok((4, Token::ShiftLeft, 6)),
-        Ok((7, Token::LessEqual, 9)),
-        Ok((10, Token::Less, 11)),
-    ));
-
-    let tokens = Lexer::new("-16 -- - -=").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((0, Token::Number("-16"), 3)),
-        Ok((4, Token::Decrement, 6)),
-        Ok((7, Token::Subtract, 8)),
-        Ok((9, Token::SubtractAssign, 11)),
-    ));
+    let tokens = Lexer::new("hex\"cafe_dead\" /* adad*** */")
+        .collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(Ok((0, Token::HexLiteral("hex\"cafe_dead\""), 14)))
+    );
+
+    let tokens = Lexer::new("// foo bar\n0x00fead0_12 00090 0_0")
+        .collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(
+            Ok((11, Token::HexNumber("0x00fead0_12"), 23)),
+            Ok((24, Token::Number("00090"), 29)),
+            Ok((30, Token::Number("0_0"), 33))
+        )
+    );
+
+    let tokens =
+        Lexer::new("\"foo\"").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(tokens, vec!(Ok((0, Token::StringLiteral("foo"), 5)),));
+
+    let tokens = Lexer::new("pragma solidity >=0.5.0 <0.7.0;")
+        .collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(
+            Ok((0, Token::Pragma, 6)),
+            Ok((7, Token::Identifier("solidity"), 15)),
+            Ok((16, Token::StringLiteral(">=0.5.0 <0.7.0"), 29)),
+        )
+    );
+
+    let tokens =
+        Lexer::new(">>= >> >= >").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(
+            Ok((0, Token::ShiftRightAssign, 3)),
+            Ok((4, Token::ShiftRight, 6)),
+            Ok((7, Token::MoreEqual, 9)),
+            Ok((10, Token::More, 11)),
+        )
+    );
+
+    let tokens =
+        Lexer::new("<<= << <= <").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(
+            Ok((0, Token::ShiftLeftAssign, 3)),
+            Ok((4, Token::ShiftLeft, 6)),
+            Ok((7, Token::LessEqual, 9)),
+            Ok((10, Token::Less, 11)),
+        )
+    );
+
+    let tokens =
+        Lexer::new("-16 -- - -=").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(
+            Ok((0, Token::Number("-16"), 3)),
+            Ok((4, Token::Decrement, 6)),
+            Ok((7, Token::Subtract, 8)),
+            Ok((9, Token::SubtractAssign, 11)),
+        )
+    );
 
     let tokens = Lexer::new("-4 ").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
 
-    assert_eq!(tokens, vec!(
-        Ok((0, Token::Number("-4"), 2)),
-    ));
+    assert_eq!(tokens, vec!(Ok((0, Token::Number("-4"), 2)),));
 
-    let tokens = Lexer::new(r#"hex"abcdefg""#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+    let tokens =
+        Lexer::new(r#"hex"abcdefg""#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
 
-    assert_eq!(tokens, vec!(
-        Err(LexicalError::InvalidCharacterInHexLiteral(10, 'g'))
-    ));
+    assert_eq!(
+        tokens,
+        vec!(Err(LexicalError::InvalidCharacterInHexLiteral(10, 'g')))
+    );
 
     let tokens = Lexer::new(r#" € "#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
 
-    assert_eq!(tokens, vec!(
-        Err(LexicalError::UnrecognisedToken(1, 4, "€".to_owned()))
-    ));
+    assert_eq!(
+        tokens,
+        vec!(Err(LexicalError::UnrecognisedToken(1, 4, "€".to_owned())))
+    );
 
     let tokens = Lexer::new(r#"€"#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
 
-    assert_eq!(tokens, vec!(
-        Err(LexicalError::UnrecognisedToken(0, 3, "€".to_owned()))
-    ));
-
-    let tokens = Lexer::new(r#"pragma foo bar"#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((0, Token::Pragma, 6)),
-        Ok((7, Token::Identifier("foo"), 10)),
-        Err(LexicalError::PragmaMissingSemiColon(11, 14))
-    ));
-
-    let tokens = Lexer::new(r#"/// foo"#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((3, Token::DocComment(CommentType::Line, " foo"), 7))
-    ));
-
-    let tokens = Lexer::new("/// jadajadadjada\n// bar").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((3, Token::DocComment(CommentType::Line, " jadajadadjada"), 17))
-    ));
-
-    let tokens = Lexer::new(r#"/** foo */"#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((3, Token::DocComment(CommentType::Block, " foo "), 8))
-    ));
-
-    let tokens = Lexer::new("/** jadajadadjada */\n/* bar */").collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
-
-    assert_eq!(tokens, vec!(
-        Ok((3, Token::DocComment(CommentType::Block, " jadajadadjada "), 18))
-    ));
+    assert_eq!(
+        tokens,
+        vec!(Err(LexicalError::UnrecognisedToken(0, 3, "€".to_owned())))
+    );
+
+    let tokens = Lexer::new(r#"pragma foo bar"#)
+        .collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(
+            Ok((0, Token::Pragma, 6)),
+            Ok((7, Token::Identifier("foo"), 10)),
+            Err(LexicalError::PragmaMissingSemiColon(11, 14))
+        )
+    );
+
+    let tokens =
+        Lexer::new(r#"/// foo"#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(Ok((3, Token::DocComment(CommentType::Line, " foo"), 7)))
+    );
+
+    let tokens = Lexer::new("/// jadajadadjada\n// bar")
+        .collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(Ok((
+            3,
+            Token::DocComment(CommentType::Line, " jadajadadjada"),
+            17
+        )))
+    );
+
+    let tokens =
+        Lexer::new(r#"/** foo */"#).collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(Ok((3, Token::DocComment(CommentType::Block, " foo "), 8)))
+    );
+
+    let tokens = Lexer::new("/** jadajadadjada */\n/* bar */")
+        .collect::<Vec<Result<(usize, Token, usize), LexicalError>>>();
+
+    assert_eq!(
+        tokens,
+        vec!(Ok((
+            3,
+            Token::DocComment(CommentType::Block, " jadajadadjada "),
+            18
+        )))
+    );
 }
 
 #[test]
 fn doc_comment_lexer() {
-    let tokens = Lexer::new("/** jadajadad\njada */\n/* bar */").map(|e| match e {
-        Ok((_, Token::DocComment(t, s), _)) => (t, s),
-        _ => unreachable!()
-    }).collect();
+    let tokens = Lexer::new("/** jadajadad\njada */\n/* bar */")
+        .map(|e| match e {
+            Ok((_, Token::DocComment(t, s), _)) => (t, s),
+            _ => unreachable!(),
+        })
+        .collect();
 
     assert_eq!(fold_doc_comments(tokens), vec!("jadajadad", "jada "));
 
-    let tokens = Lexer::new("/** bar *//** jadajadad\njada */\n/* bar */").map(|e| match e {
-        Ok((_, Token::DocComment(t, s), _)) => (t, s),
-        _ => unreachable!()
-    }).collect();
+    let tokens = Lexer::new("/** bar *//** jadajadad\njada */\n/* bar */")
+        .map(|e| match e {
+            Ok((_, Token::DocComment(t, s), _)) => (t, s),
+            _ => unreachable!(),
+        })
+        .collect();
 
     assert_eq!(fold_doc_comments(tokens), vec!("jadajadad", "jada "));
 
-    let tokens = Lexer::new("/// bar   \n///    jadajadad\n\n/* bar */").map(|e| match e {
-        Ok((_, Token::DocComment(t, s), _)) => (t, s),
-        _ => unreachable!()
-    }).collect();
+    let tokens = Lexer::new("/// bar   \n///    jadajadad\n\n/* bar */")
+        .map(|e| match e {
+            Ok((_, Token::DocComment(t, s), _)) => (t, s),
+            _ => unreachable!(),
+        })
+        .collect();
 
     assert_eq!(fold_doc_comments(tokens), vec!("bar", "jadajadad"));
 
-    let tokens = Lexer::new(r#"
+    let tokens = Lexer::new(
+        r#"
     /**
      * bar
      * 
      * foo 
-     */"#).map(|e| match e {
+     */"#,
+    )
+    .map(|e| match e {
         Ok((_, Token::DocComment(t, s), _)) => (t, s),
-        _ => unreachable!()
-    }).collect();
+        _ => unreachable!(),
+    })
+    .collect();
 
     assert_eq!(fold_doc_comments(tokens), vec!("bar", "foo "));
-}
+}

+ 8 - 9
src/parser/mod.rs

@@ -1,6 +1,6 @@
 pub mod ast;
-pub mod solidity;
 pub mod lexer;
+pub mod solidity;
 
 use lalrpop_util::ParseError;
 use output::Output;
@@ -56,13 +56,12 @@ pub fn box_option<T>(o: Option<T>) -> Option<Box<T>> {
 #[cfg(test)]
 mod test {
     use parser::ast::*;
-    use parser::solidity;
     use parser::lexer;
+    use parser::solidity;
 
     #[test]
     fn parse_test() {
-        let src =
-                "contract foo {
+        let src = "contract foo {
                     struct Jurisdiction {
                         bool exists;
                         uint keyIdx;
@@ -79,7 +78,7 @@ mod test {
 
         let a = SourceUnit(vec![SourceUnitPart::ContractDefinition(Box::new(
             ContractDefinition {
-                doc: vec!(),
+                doc: vec![],
                 loc: Loc(0, 325),
                 ty: ContractType::Contract,
                 name: Identifier {
@@ -88,7 +87,7 @@ mod test {
                 },
                 parts: vec![
                     ContractPart::StructDefinition(Box::new(StructDefinition {
-                        doc: vec!(),
+                        doc: vec![],
                         name: Identifier {
                             loc: Loc(42, 54),
                             name: "Jurisdiction".to_string(),
@@ -130,7 +129,7 @@ mod test {
                     })),
                     ContractPart::ContractVariableDefinition(Box::new(
                         ContractVariableDefinition {
-                            doc: vec!(),
+                            doc: vec![],
                             ty: Type::Primitive(PrimitiveType::String),
                             attrs: vec![],
                             name: Identifier {
@@ -143,7 +142,7 @@ mod test {
                     )),
                     ContractPart::ContractVariableDefinition(Box::new(
                         ContractVariableDefinition {
-                            doc: vec!(),
+                            doc: vec![],
                             ty: Type::Primitive(PrimitiveType::Int(64)),
                             attrs: vec![],
                             name: Identifier {
@@ -160,4 +159,4 @@ mod test {
 
         assert_eq!(e, a);
     }
-}
+}

Plik diff jest za duży
+ 229 - 551
src/parser/solidity.rs


+ 34 - 23
src/resolver/address.rs

@@ -8,30 +8,33 @@ pub fn to_hexstr_eip55(src: &str) -> String {
     assert!(src.starts_with("0x"));
     assert!(src.chars().skip(2).all(|c| c.is_ascii_hexdigit()));
 
-    let address : String = src.chars().skip(2).map(|c| c.to_ascii_lowercase()).collect();
+    let address: String = src
+        .chars()
+        .skip(2)
+        .map(|c| c.to_ascii_lowercase())
+        .collect();
 
     let hash = keccak256(address.as_bytes());
 
-    return "0x".chars().chain(address.chars().enumerate().map(|(i,c)| {
-        match c {
-            '0'..='9' => c,
-            'a'..='f' => {
-                // hash is 32 bytes; find the i'th "nibble"
-                let nibble = hash[i >> 1] >> if (i & 1) != 0 {
-                    0
-                } else {
-                    4
-                };
+    return "0x"
+        .chars()
+        .chain(address.chars().enumerate().map(|(i, c)| {
+            match c {
+                '0'..='9' => c,
+                'a'..='f' => {
+                    // hash is 32 bytes; find the i'th "nibble"
+                    let nibble = hash[i >> 1] >> if (i & 1) != 0 { 0 } else { 4 };
 
-                if (nibble & 8) != 0 {
-                    c.to_ascii_uppercase()
-                } else {
-                    c
+                    if (nibble & 8) != 0 {
+                        c.to_ascii_uppercase()
+                    } else {
+                        c
+                    }
                 }
-            },
-            _ => unreachable!()
-        }
-    })).collect();
+                _ => unreachable!(),
+            }
+        }))
+        .collect();
 }
 
 #[test]
@@ -40,8 +43,16 @@ fn test_is_hexstr_eip55() {
         to_hexstr_eip55(s) == s
     }
 
-    assert!(is_hexstr_eip55("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"));
-    assert!(is_hexstr_eip55("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"));
-    assert!(is_hexstr_eip55("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"));
-    assert!(is_hexstr_eip55("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"));
+    assert!(is_hexstr_eip55(
+        "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
+    ));
+    assert!(is_hexstr_eip55(
+        "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"
+    ));
+    assert!(is_hexstr_eip55(
+        "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"
+    ));
+    assert!(is_hexstr_eip55(
+        "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"
+    ));
 }

+ 44 - 23
src/resolver/builtin.rs

@@ -1,23 +1,31 @@
-
+use super::cfg::{ControlFlowGraph, Expression, Instr, Vartable};
 use parser::ast;
-use super::cfg::{ControlFlowGraph, Vartable, Instr, Expression};
 use resolver;
 
 use super::{Contract, FunctionDecl, Parameter};
 
 pub fn add_builtin_function(ns: &mut Contract) {
     let argty = resolver::Type::Primitive(ast::PrimitiveType::Bool);
-    let id = ast::Identifier{
+    let id = ast::Identifier {
         loc: ast::Loc(0, 0),
-        name: "assert".to_owned()
+        name: "assert".to_owned(),
     };
 
-    let mut assert = FunctionDecl::new(ast::Loc(0, 0), "assert".to_owned(),
-        vec!(), false, None, None, ast::Visibility::Private(ast::Loc(0, 0)),
-        vec!( Parameter {
+    let mut assert = FunctionDecl::new(
+        ast::Loc(0, 0),
+        "assert".to_owned(),
+        vec![],
+        false,
+        None,
+        None,
+        ast::Visibility::Private(ast::Loc(0, 0)),
+        vec![Parameter {
             name: "arg0".to_owned(),
-            ty: resolver::Type::Primitive(ast::PrimitiveType::Bool)
-        } ), vec!(), &ns);
+            ty: resolver::Type::Primitive(ast::PrimitiveType::Bool),
+        }],
+        vec![],
+        &ns,
+    );
 
     let mut errors = Vec::new();
     let mut vartab = Vartable::new();
@@ -26,22 +34,32 @@ pub fn add_builtin_function(ns: &mut Contract) {
     let true_ = cfg.new_basic_block("noassert".to_owned());
     let false_ = cfg.new_basic_block("doassert".to_owned());
 
-    let cond = vartab.add(&ast::Identifier{
-        loc: ast::Loc(0, 0),
-        name: "arg0".to_owned()
-    }, argty, &mut errors).unwrap();
-
-    cfg.add(&mut vartab, Instr::FuncArg{ res: cond, arg: 0 });
-    cfg.add(&mut vartab, Instr::BranchCond{
-        cond: Expression::Variable(ast::Loc(0, 0), cond),
-        true_, false_
-    });
+    let cond = vartab
+        .add(
+            &ast::Identifier {
+                loc: ast::Loc(0, 0),
+                name: "arg0".to_owned(),
+            },
+            argty,
+            &mut errors,
+        )
+        .unwrap();
+
+    cfg.add(&mut vartab, Instr::FuncArg { res: cond, arg: 0 });
+    cfg.add(
+        &mut vartab,
+        Instr::BranchCond {
+            cond: Expression::Variable(ast::Loc(0, 0), cond),
+            true_,
+            false_,
+        },
+    );
 
     cfg.set_basic_block(true_);
-    cfg.add(&mut vartab, Instr::Return{ value: Vec::new() });
+    cfg.add(&mut vartab, Instr::Return { value: Vec::new() });
 
     cfg.set_basic_block(false_);
-    cfg.add(&mut vartab, Instr::AssertFailure{  });
+    cfg.add(&mut vartab, Instr::AssertFailure {});
 
     cfg.vars = vartab.drain();
 
@@ -51,6 +69,9 @@ pub fn add_builtin_function(ns: &mut Contract) {
 
     ns.functions.push(assert);
 
-    ns.add_symbol(&id, resolver::Symbol::Function(vec![(id.loc, pos)]), &mut errors);
-
+    ns.add_symbol(
+        &id,
+        resolver::Symbol::Function(vec![(id.loc, pos)]),
+        &mut errors,
+    );
 }

Plik diff jest za duży
+ 356 - 152
src/resolver/cfg.rs


+ 35 - 18
src/resolver/functions.rs

@@ -1,7 +1,7 @@
-use parser::ast;
+use super::{Contract, FunctionDecl, Parameter, Symbol};
 use output::Output;
+use parser::ast;
 use Target;
-use super::{Contract, Parameter, FunctionDecl, Symbol};
 
 pub fn function_decl(
     f: &ast::FunctionDefinition,
@@ -102,10 +102,7 @@ pub fn function_decl(
     }
 
     if visibility == None {
-        errors.push(Output::error(
-            f.loc,
-            format!("no visibility specified"),
-        ));
+        errors.push(Output::error(f.loc, format!("no visibility specified")));
         success = false;
     }
 
@@ -118,7 +115,18 @@ pub fn function_decl(
         None => ("".to_owned(), !f.constructor),
     };
 
-    let fdecl = FunctionDecl::new(f.loc, name, f.doc.clone(), fallback, Some(i), mutability, visibility.unwrap(), params, returns, &ns);
+    let fdecl = FunctionDecl::new(
+        f.loc,
+        name,
+        f.doc.clone(),
+        fallback,
+        Some(i),
+        mutability,
+        visibility.unwrap(),
+        params,
+        returns,
+        &ns,
+    );
 
     if f.constructor {
         // In the eth solidity, only one constructor is allowed
@@ -139,7 +147,7 @@ pub fn function_decl(
             _ => {
                 errors.push(Output::error(
                     f.loc,
-                    "constructor function must be declared public".to_owned()
+                    "constructor function must be declared public".to_owned(),
                 ));
                 return false;
             }
@@ -152,15 +160,15 @@ pub fn function_decl(
                     format!("constructor cannot be declared pure"),
                 ));
                 return false;
-            },
+            }
             Some(ast::StateMutability::View(loc)) => {
                 errors.push(Output::error(
                     loc,
                     format!("constructor cannot be declared view"),
                 ));
                 return false;
-            },
-            _ => ()
+            }
+            _ => (),
         }
 
         for v in ns.constructors.iter() {
@@ -226,7 +234,7 @@ pub fn function_decl(
         } else {
             errors.push(Output::error(
                 f.loc,
-                "fallback function must be declared external".to_owned()
+                "fallback function must be declared external".to_owned(),
             ));
             return false;
         }
@@ -242,7 +250,7 @@ fn signatures() {
     use super::*;
 
     let ns = Contract {
-        doc: vec!(),
+        doc: vec![],
         name: String::from("foo"),
         enums: Vec::new(),
         constructors: Vec::new(),
@@ -256,17 +264,26 @@ fn signatures() {
     };
 
     let fdecl = FunctionDecl::new(
-        ast::Loc(0, 0), "foo".to_owned(), vec!(), false, Some(0), None, ast::Visibility::Public(ast::Loc(0, 0)),
-        vec!(
+        ast::Loc(0, 0),
+        "foo".to_owned(),
+        vec![],
+        false,
+        Some(0),
+        None,
+        ast::Visibility::Public(ast::Loc(0, 0)),
+        vec![
             Parameter {
                 name: "".to_string(),
-                ty: Type::Primitive(ast::PrimitiveType::Uint(8))
+                ty: Type::Primitive(ast::PrimitiveType::Uint(8)),
             },
             Parameter {
                 name: "".to_string(),
-                ty: Type::Primitive(ast::PrimitiveType::Address)
+                ty: Type::Primitive(ast::PrimitiveType::Address),
             },
-        ), Vec::new(), &ns);
+        ],
+        Vec::new(),
+        &ns,
+    );
 
     assert_eq!(fdecl.signature, "foo(uint8,address)");
 }

+ 88 - 31
src/resolver/mod.rs

@@ -1,19 +1,18 @@
-
-use parser::ast;
+use abi;
+use emit;
 use output::{Note, Output};
+use parser::ast;
 use std::collections::HashMap;
 use tiny_keccak::keccak256;
 use Target;
-use abi;
-use emit;
 
+mod address;
+mod builtin;
 pub mod cfg;
 mod functions;
 mod variables;
-mod builtin;
-mod address;
 
-use resolver::cfg::{ControlFlowGraph, Vartable, Instr};
+use resolver::cfg::{ControlFlowGraph, Instr, Vartable};
 
 #[derive(PartialEq, Clone, Debug)]
 pub enum Type {
@@ -28,7 +27,11 @@ impl Type {
         match self {
             Type::Primitive(e) => e.to_string(),
             Type::Enum(n) => format!("enum {}.{}", ns.name, ns.enums[*n].name),
-            Type::FixedArray(ty, len) => format!("{}[{}]", ty.to_string(ns), len.iter().map(|l| format!("[{}]", l)).collect::<String>()),
+            Type::FixedArray(ty, len) => format!(
+                "{}[{}]",
+                ty.to_string(ns),
+                len.iter().map(|l| format!("[{}]", l)).collect::<String>()
+            ),
             Type::Noreturn => "no return".to_owned(),
         }
     }
@@ -37,7 +40,11 @@ impl Type {
         match self {
             Type::Primitive(e) => e.to_string(),
             Type::Enum(n) => ns.enums[*n].ty.to_string(),
-            Type::FixedArray(ty, len) => format!("{}{}", ty.to_primitive_string(ns), len.iter().map(|l| format!("[{}]", l)).collect::<String>()),
+            Type::FixedArray(ty, len) => format!(
+                "{}{}",
+                ty.to_primitive_string(ns),
+                len.iter().map(|l| format!("[{}]", l)).collect::<String>()
+            ),
             Type::Noreturn => "no return".to_owned(),
         }
     }
@@ -99,8 +106,18 @@ pub struct FunctionDecl {
 }
 
 impl FunctionDecl {
-    fn new(loc: ast::Loc, name: String, doc: Vec<String>, fallback: bool, ast_index: Option<usize>, mutability: Option<ast::StateMutability>,
-        visibility: ast::Visibility, params: Vec<Parameter>, returns: Vec<Parameter>, ns: &Contract) -> Self {
+    fn new(
+        loc: ast::Loc,
+        name: String,
+        doc: Vec<String>,
+        fallback: bool,
+        ast_index: Option<usize>,
+        mutability: Option<ast::StateMutability>,
+        visibility: ast::Visibility,
+        params: Vec<Parameter>,
+        returns: Vec<Parameter>,
+        ns: &Contract,
+    ) -> Self {
         let mut signature = name.to_owned();
 
         signature.push('(');
@@ -117,8 +134,19 @@ impl FunctionDecl {
 
         let wasm_return = returns.len() == 1 && !returns[0].ty.stack_based();
 
-        FunctionDecl{
-            doc, loc, name, fallback, signature, ast_index, mutability, visibility, params, returns, wasm_return, cfg: None
+        FunctionDecl {
+            doc,
+            loc,
+            name,
+            fallback,
+            signature,
+            ast_index,
+            mutability,
+            visibility,
+            params,
+            returns,
+            wasm_return,
+            cfg: None,
         }
     }
 
@@ -142,7 +170,11 @@ impl FunctionDecl {
                 sig.push_str(&match &p.ty {
                     Type::Primitive(e) => e.to_string(),
                     Type::Enum(i) => ns.enums[*i].name.to_owned(),
-                    Type::FixedArray(ty, len) => format!("{}{}", ty.to_string(ns), len.iter().map(|r| format!(":{}", r)).collect::<String>()),
+                    Type::FixedArray(ty, len) => format!(
+                        "{}{}",
+                        ty.to_string(ns),
+                        len.iter().map(|r| format!(":{}", r)).collect::<String>()
+                    ),
                     Type::Noreturn => unreachable!(),
                 });
             }
@@ -154,7 +186,7 @@ impl FunctionDecl {
 
 pub enum ContractVariableType {
     Storage(usize),
-    Constant(usize)
+    Constant(usize),
 }
 
 pub struct ContractVariable {
@@ -162,7 +194,7 @@ pub struct ContractVariable {
     pub name: String,
     pub ty: Type,
     pub visibility: ast::Visibility,
-    pub var: ContractVariableType
+    pub var: ContractVariableType,
 }
 
 impl ContractVariable {
@@ -280,7 +312,11 @@ impl Contract {
         }
     }
 
-    pub fn resolve_func(&self, id: &ast::Identifier, errors: &mut Vec<Output>) -> Result<&Vec<(ast::Loc, usize)>, ()> {
+    pub fn resolve_func(
+        &self,
+        id: &ast::Identifier,
+        errors: &mut Vec<Output>,
+    ) -> Result<&Vec<(ast::Loc, usize)>, ()> {
         match self.symbols.get(&id.name) {
             Some(Symbol::Function(v)) => Ok(v),
             _ => {
@@ -400,7 +436,12 @@ impl Contract {
         abi::generate_abi(self, verbose)
     }
 
-    pub fn emit<'a>(&'a self, context: &'a inkwell::context::Context, filename: &'a str, opt: &str) -> emit::Contract {
+    pub fn emit<'a>(
+        &'a self,
+        context: &'a inkwell::context::Context,
+        filename: &'a str,
+        opt: &str,
+    ) -> emit::Contract {
         emit::Contract::build(context, self, filename, opt)
     }
 }
@@ -415,7 +456,7 @@ pub fn resolver(s: ast::SourceUnit, target: &Target) -> (Vec<Contract>, Vec<Outp
                 if let Some(c) = resolve_contract(def, &target, &mut errors) {
                     contracts.push(c)
                 }
-            },
+            }
             ast::SourceUnitPart::PragmaDirective(name, _) => {
                 if name.name == "solidity" {
                     errors.push(Output::info(
@@ -428,8 +469,8 @@ pub fn resolver(s: ast::SourceUnit, target: &Target) -> (Vec<Contract>, Vec<Outp
                         format!("unknown pragma {} ignored", name.name),
                     ));
                 }
-            },
-            _ => unimplemented!()
+            }
+            _ => unimplemented!(),
         }
     }
 
@@ -498,8 +539,8 @@ fn resolve_contract(
         if let Some(ast_index) = ns.constructors[f].ast_index {
             if let ast::ContractPart::FunctionDefinition(ref ast_f) = def.parts[ast_index] {
                 match cfg::generate_cfg(ast_f, &ns.constructors[f], &ns, errors) {
-                    Ok(c) =>  ns.constructors[f].cfg = Some(c),
-                    Err(_) => broken = true
+                    Ok(c) => ns.constructors[f].cfg = Some(c),
+                    Err(_) => broken = true,
                 }
             }
         }
@@ -508,12 +549,22 @@ fn resolve_contract(
     // Substrate requires one constructor
     if ns.constructors.is_empty() && target == &Target::Substrate {
         let mut fdecl = FunctionDecl::new(
-            ast::Loc(0, 0), "".to_owned(), vec!(), false, None, None, ast::Visibility::Public(ast::Loc(0, 0)), Vec::new(), Vec::new(), &ns);
+            ast::Loc(0, 0),
+            "".to_owned(),
+            vec![],
+            false,
+            None,
+            None,
+            ast::Visibility::Public(ast::Loc(0, 0)),
+            Vec::new(),
+            Vec::new(),
+            &ns,
+        );
 
         let mut vartab = Vartable::new();
         let mut cfg = ControlFlowGraph::new();
 
-        cfg.add(&mut vartab, Instr::Return{ value: Vec::new() });
+        cfg.add(&mut vartab, Instr::Return { value: Vec::new() });
         cfg.vars = vartab.drain();
 
         fdecl.cfg = Some(Box::new(cfg));
@@ -532,13 +583,17 @@ fn resolve_contract(
                                 if c.writes_contract_storage {
                                     errors.push(Output::error(
                                         loc.clone(),
-                                        format!("function declared pure but writes contract storage"),
+                                        format!(
+                                            "function declared pure but writes contract storage"
+                                        ),
                                     ));
                                     broken = true;
                                 } else if c.reads_contract_storage {
                                     errors.push(Output::error(
                                         loc.clone(),
-                                        format!("function declared pure but reads contract storage"),
+                                        format!(
+                                            "function declared pure but reads contract storage"
+                                        ),
                                     ));
                                     broken = true;
                                 }
@@ -547,7 +602,9 @@ fn resolve_contract(
                                 if c.writes_contract_storage {
                                     errors.push(Output::error(
                                         loc.clone(),
-                                        format!("function declared view but writes contract storage"),
+                                        format!(
+                                            "function declared view but writes contract storage"
+                                        ),
                                     ));
                                     broken = true;
                                 } else if !c.reads_contract_storage {
@@ -578,7 +635,7 @@ fn resolve_contract(
                         }
                         ns.functions[f].cfg = Some(c);
                     }
-                    Err(_) => broken = true
+                    Err(_) => broken = true,
                 }
             }
         }
@@ -630,7 +687,7 @@ fn enum_decl(enum_: &ast::EnumDefinition, errors: &mut Vec<Output>) -> EnumDecl
 #[test]
 fn enum_256values_is_uint8() {
     let mut e = ast::EnumDefinition {
-        doc: vec!(),
+        doc: vec![],
         name: ast::Identifier {
             loc: ast::Loc(0, 0),
             name: "foo".into(),
@@ -665,4 +722,4 @@ fn enum_256values_is_uint8() {
 
     let r2 = enum_decl(&e, &mut Vec::new());
     assert_eq!(r2.ty, ast::PrimitiveType::Uint(16));
-}
+}

+ 16 - 11
src/resolver/variables.rs

@@ -1,14 +1,13 @@
-
-use parser::ast;
-use output::Output;
 use super::{Contract, ContractVariable, Symbol};
-use resolver::cfg::{ControlFlowGraph, Vartable, Instr, set_contract_storage, expression, cast};
+use output::Output;
+use parser::ast;
+use resolver::cfg::{cast, expression, set_contract_storage, ControlFlowGraph, Instr, Vartable};
 use resolver::ContractVariableType;
 
 pub fn contract_variables(
     def: &ast::ContractDefinition,
     ns: &mut Contract,
-    errors: &mut Vec<Output>
+    errors: &mut Vec<Output>,
 ) -> bool {
     let mut broken = false;
     let mut vartab = Vartable::new();
@@ -22,7 +21,7 @@ pub fn contract_variables(
         }
     }
 
-    cfg.add(&mut vartab, Instr::Return{ value: Vec::new() });
+    cfg.add(&mut vartab, Instr::Return { value: Vec::new() });
 
     cfg.vars = vartab.drain();
 
@@ -104,13 +103,13 @@ fn var_decl(
 
         let (res, resty) = match expr {
             Ok((res, ty)) => (res, ty),
-            Err(()) => return false
+            Err(()) => return false,
         };
 
         // implicityly conversion to correct ty
         let res = match cast(&s.loc, res, &resty, &ty, true, &ns, errors) {
             Ok(res) => res,
-            Err(_) => return false
+            Err(_) => return false,
         };
 
         Some(res)
@@ -131,7 +130,7 @@ fn var_decl(
         doc: s.doc.clone(),
         visibility,
         ty,
-        var
+        var,
     };
 
     let pos = ns.variables.len();
@@ -139,7 +138,7 @@ fn var_decl(
     ns.variables.push(sdecl);
 
     if !ns.add_symbol(&s.name, Symbol::Variable(s.loc, pos), errors) {
-        return false
+        return false;
     }
 
     if let Some(res) = initializer {
@@ -148,7 +147,13 @@ fn var_decl(
         } else {
             let var = vartab.find(&s.name, ns, errors).unwrap();
 
-            cfg.add(vartab, Instr::Set{ res: var.pos, expr: res });
+            cfg.add(
+                vartab,
+                Instr::Set {
+                    res: var.pos,
+                    expr: res,
+                },
+            );
 
             set_contract_storage(&s.name, &var, cfg, vartab, errors).unwrap();
         }

+ 134 - 58
tests/burrow.rs

@@ -1,16 +1,16 @@
-extern crate solang;
-extern crate wasmi;
 extern crate ethabi;
 extern crate ethereum_types;
+extern crate solang;
+extern crate wasmi;
 
+use ethabi::Token;
 use std::collections::HashMap;
 use std::mem;
 use wasmi::memory_units::Pages;
 use wasmi::*;
-use ethabi::Token;
 
-use solang::{compile, Target};
 use solang::output;
+use solang::{compile, Target};
 
 struct ContractStorage {
     memory: MemoryRef,
@@ -90,7 +90,7 @@ impl ModuleImportResolver for ContractStorage {
 
 struct TestRuntime {
     module: ModuleRef,
-    abi: ethabi::Contract
+    abi: ethabi::Contract,
 }
 
 impl TestRuntime {
@@ -98,16 +98,23 @@ impl TestRuntime {
         let calldata = self.abi.functions[name].encode_input(args).unwrap();
         // need to prepend length
         store.memory.set_value(0, calldata.len() as u32).unwrap();
-        store.memory.set(mem::size_of::<u32>() as u32, &calldata).unwrap();
+        store
+            .memory
+            .set(mem::size_of::<u32>() as u32, &calldata)
+            .unwrap();
 
-        let ret = self.module
+        let ret = self
+            .module
             .invoke_export("function", &[RuntimeValue::I32(0)], store)
             .expect("failed to call function");
 
         match ret {
             Some(RuntimeValue::I32(offset)) => {
                 let offset = offset as u32;
-                let returndata = store.memory.get(offset + mem::size_of::<u32>() as u32, 32).unwrap();
+                let returndata = store
+                    .memory
+                    .get(offset + mem::size_of::<u32>() as u32, 32)
+                    .unwrap();
 
                 println!("RETURNDATA: {}", hex::encode(&returndata));
 
@@ -123,9 +130,13 @@ impl TestRuntime {
 
             // need to prepend length
             store.memory.set_value(0, calldata.len() as u32).unwrap();
-            store.memory.set(mem::size_of::<u32>() as u32, &calldata).unwrap();
+            store
+                .memory
+                .set(mem::size_of::<u32>() as u32, &calldata)
+                .unwrap();
 
-            let ret = self.module
+            let ret = self
+                .module
                 .invoke_export("constructor", &[RuntimeValue::I32(0)], store)
                 .expect("failed to call constructor");
 
@@ -152,14 +163,17 @@ fn build_solidity(src: &'static str) -> (TestRuntime, ContractStorage) {
     let store = ContractStorage::new();
 
     (
-        TestRuntime{
-            module: ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &store))
-                .expect("Failed to instantiate module")
-                .run_start(&mut NopExternals)
-                .expect("Failed to run start function in module"),
+        TestRuntime {
+            module: ModuleInstance::new(
+                &module,
+                &ImportsBuilder::new().with_resolver("env", &store),
+            )
+            .expect("Failed to instantiate module")
+            .run_start(&mut NopExternals)
+            .expect("Failed to run start function in module"),
             abi: ethabi::Contract::load(abi.as_bytes()).unwrap(),
         },
-        store
+        store,
     )
 }
 
@@ -177,7 +191,10 @@ fn simple_solidiy_compile_and_run() {
 
     let returns = runtime.function(&mut store, "foo", &[]);
 
-    assert_eq!(returns, vec![ethabi::Token::Uint(ethereum_types::U256::from(2))]);
+    assert_eq!(
+        returns,
+        vec![ethabi::Token::Uint(ethereum_types::U256::from(2))]
+    );
 }
 
 #[test]
@@ -228,21 +245,34 @@ contract test3 {
     for i in 0..=50 {
         let res = ((50 - i) * 100 + 5) + i * 1000;
 
-        let returns = runtime.function(&mut store, "foo", &[ethabi::Token::Uint(ethereum_types::U256::from(i))]);
+        let returns = runtime.function(
+            &mut store,
+            "foo",
+            &[ethabi::Token::Uint(ethereum_types::U256::from(i))],
+        );
 
-        assert_eq!(returns, vec![ethabi::Token::Uint(ethereum_types::U256::from(res))]);
+        assert_eq!(
+            returns,
+            vec![ethabi::Token::Uint(ethereum_types::U256::from(res))]
+        );
     }
 
     for i in 0..=50 {
         let res = (i + 1) * 10 + 1;
 
-        let returns = runtime.function(&mut store, "bar",
+        let returns = runtime.function(
+            &mut store,
+            "bar",
             &[
                 ethabi::Token::Uint(ethereum_types::U256::from(i)),
-                ethabi::Token::Bool(true)
-            ]);
-
-        assert_eq!(returns, vec![ethabi::Token::Uint(ethereum_types::U256::from(res))]);
+                ethabi::Token::Bool(true),
+            ],
+        );
+
+        assert_eq!(
+            returns,
+            vec![ethabi::Token::Uint(ethereum_types::U256::from(res))]
+        );
     }
 
     for i in 0..=50 {
@@ -252,13 +282,19 @@ contract test3 {
             res *= 3;
         }
 
-        let returns = runtime.function(&mut store, "bar",
+        let returns = runtime.function(
+            &mut store,
+            "bar",
             &[
                 ethabi::Token::Uint(ethereum_types::U256::from(i)),
-                ethabi::Token::Bool(false)
-            ]);
-
-        assert_eq!(returns, vec![ethabi::Token::Uint(ethereum_types::U256::from(res))]);
+                ethabi::Token::Bool(false),
+            ],
+        );
+
+        assert_eq!(
+            returns,
+            vec![ethabi::Token::Uint(ethereum_types::U256::from(res))]
+        );
     }
 
     for i in 1..=50 {
@@ -272,12 +308,16 @@ contract test3 {
             res += 1;
         }
 
-        let returns = runtime.function(&mut store, "baz",
-            &[
-                ethabi::Token::Uint(ethereum_types::U256::from(i)),
-            ]);
+        let returns = runtime.function(
+            &mut store,
+            "baz",
+            &[ethabi::Token::Uint(ethereum_types::U256::from(i))],
+        );
 
-        assert_eq!(returns, vec![ethabi::Token::Uint(ethereum_types::U256::from(res))]);
+        assert_eq!(
+            returns,
+            vec![ethabi::Token::Uint(ethereum_types::U256::from(res))]
+        );
     }
 }
 
@@ -313,7 +353,10 @@ contract test {
 
     let returns = runtime.function(&mut store, "foo", &[]);
 
-    assert_eq!(returns, vec![ethabi::Token::Uint(ethereum_types::U256::from(102))]);
+    assert_eq!(
+        returns,
+        vec![ethabi::Token::Uint(ethereum_types::U256::from(102))]
+    );
 }
 
 #[test]
@@ -328,12 +371,16 @@ contract test {
     );
 
     for val in [102i32, 255, 256, 0x7fffffff].iter() {
-        let returns = runtime.function(&mut store, "foo",
-            &[
-                ethabi::Token::Uint(ethereum_types::U256::from(*val)),
-            ]);
-
-        assert_eq!(returns, vec![ethabi::Token::Uint(ethereum_types::U256::from(*val))]);
+        let returns = runtime.function(
+            &mut store,
+            "foo",
+            &[ethabi::Token::Uint(ethereum_types::U256::from(*val))],
+        );
+
+        assert_eq!(
+            returns,
+            vec![ethabi::Token::Uint(ethereum_types::U256::from(*val))]
+        );
     }
 }
 
@@ -411,7 +458,8 @@ fn large_ints_encoded() {
 
 #[test]
 fn address() {
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract address_tester {
             function encode_const() public returns (address) {
                 return 0x52908400098527886E0F7030069857D2E4169EE7;
@@ -428,19 +476,34 @@ fn address() {
             function allones() public returns (address) {
                 return address(1);
             }
-        }");
+        }",
+    );
 
     let ret = runtime.function(&mut store, "encode_const", &[]);
 
-    assert_eq!(ret, [ ethabi::Token::Address(ethereum_types::Address::from_slice(&hex::decode("52908400098527886E0F7030069857D2E4169EE7").unwrap())) ]);
+    assert_eq!(
+        ret,
+        [ethabi::Token::Address(ethereum_types::Address::from_slice(
+            &hex::decode("52908400098527886E0F7030069857D2E4169EE7").unwrap()
+        ))]
+    );
 
-    runtime.function(&mut store, "test_arg", &[
-        ethabi::Token::Address(ethereum_types::Address::from_slice(&hex::decode("27b1fdb04752bbc536007a920d24acb045561c26").unwrap()))
-    ]);
+    runtime.function(
+        &mut store,
+        "test_arg",
+        &[ethabi::Token::Address(ethereum_types::Address::from_slice(
+            &hex::decode("27b1fdb04752bbc536007a920d24acb045561c26").unwrap(),
+        ))],
+    );
 
     let ret = runtime.function(&mut store, "allones", &[]);
 
-    assert_eq!(ret, [ ethabi::Token::Address(ethereum_types::Address::from_slice(&hex::decode("0000000000000000000000000000000000000001").unwrap())) ]);
+    assert_eq!(
+        ret,
+        [ethabi::Token::Address(ethereum_types::Address::from_slice(
+            &hex::decode("0000000000000000000000000000000000000001").unwrap()
+        ))]
+    );
 
     // no arithmetic/bitwise allowed on address
     // no ordered comparison allowed
@@ -449,7 +512,8 @@ fn address() {
 
 #[test]
 fn bytes() {
-    let (runtime, mut store) = build_solidity(r##"
+    let (runtime, mut store) = build_solidity(
+        r##"
         contract bar {
             bytes4 constant foo = hex"11223344";
 
@@ -484,33 +548,45 @@ fn bytes() {
             function shiftedright() public view returns (bytes4) {
                 return foo >> 8;
             }
-        }"##);
+        }"##,
+    );
 
     runtime.constructor(&mut store, &[]);
 
     let ret = runtime.function(&mut store, "get_foo", &[]);
 
-    assert_eq!(ret, [ ethabi::Token::FixedBytes(vec!( 0x11, 0x22, 0x33, 0x44 )) ]);
+    assert_eq!(
+        ret,
+        [ethabi::Token::FixedBytes(vec!(0x11, 0x22, 0x33, 0x44))]
+    );
 
     let ret = runtime.function(&mut store, "bytes4asuint32", &[]);
 
-    assert_eq!(ret, [ ethabi::Token::Uint(ethereum_types::U256::from(0x11223344)) ]);
+    assert_eq!(
+        ret,
+        [ethabi::Token::Uint(ethereum_types::U256::from(0x11223344))]
+    );
 
     let ret = runtime.function(&mut store, "bytes4asuint64", &[]);
 
-    assert_eq!(ret, [ ethabi::Token::Uint(ethereum_types::U256::from(0x11223344_0000_0000u64)) ]);
+    assert_eq!(
+        ret,
+        [ethabi::Token::Uint(ethereum_types::U256::from(
+            0x11223344_0000_0000u64
+        ))]
+    );
 
     let ret = runtime.function(&mut store, "bytes4asbytes2", &[]);
 
-    assert_eq!(ret, [ ethabi::Token::FixedBytes(vec!(0x11, 0x22)) ]);
+    assert_eq!(ret, [ethabi::Token::FixedBytes(vec!(0x11, 0x22))]);
 
-    let val = vec!(ethabi::Token::FixedBytes(vec!(0x41, 0x42, 0x43, 0x44)));
+    let val = vec![ethabi::Token::FixedBytes(vec![0x41, 0x42, 0x43, 0x44])];
 
     assert_eq!(runtime.function(&mut store, "passthrough", &val), val);
 
-    let val = vec!(ethabi::Token::Uint(ethereum_types::U256::from(1)));
+    let val = vec![ethabi::Token::Uint(ethereum_types::U256::from(1))];
 
     let ret = runtime.function(&mut store, "entry", &val);
 
-    assert_eq!(ret, [ ethabi::Token::FixedBytes(vec!(0x22)) ]);
-}
+    assert_eq!(ret, [ethabi::Token::FixedBytes(vec!(0x22))]);
+}

+ 4 - 3
tests/loops.rs

@@ -1,8 +1,7 @@
-
 extern crate solang;
 
-use solang::{parse_and_resolve, Target};
 use solang::output;
+use solang::{parse_and_resolve, Target};
 
 fn first_error(errors: Vec<output::Output>) -> String {
     for m in errors.iter().filter(|m| m.level == output::Level::Error) {
@@ -24,7 +23,9 @@ fn test_infinite_loop() {
                 }
                 return 0;
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     assert_eq!(first_error(errors), "unreachable statement");
 }

+ 56 - 33
tests/substrate.rs

@@ -1,31 +1,31 @@
 // Create WASM virtual machine like substrate
-extern crate solang;
-extern crate wasmi;
 extern crate ethabi;
 extern crate ethereum_types;
-extern crate parity_scale_codec_derive;
-extern crate parity_scale_codec;
+extern crate num_bigint;
 extern crate num_derive;
-extern crate serde_derive;
 extern crate num_traits;
-extern crate num_bigint;
+extern crate parity_scale_codec;
+extern crate parity_scale_codec_derive;
 extern crate rand;
+extern crate serde_derive;
+extern crate solang;
+extern crate wasmi;
 
+use num_derive::FromPrimitive;
+use num_traits::FromPrimitive;
 use std::collections::HashMap;
 use wasmi::memory_units::Pages;
 use wasmi::*;
-use num_derive::FromPrimitive;
-use num_traits::FromPrimitive;
 
-use solang::{compile, Target};
-use solang::output;
 use solang::abi;
+use solang::output;
+use solang::{compile, Target};
 
-mod substrate_first;
-mod substrate_primitives;
-mod substrate_expressions;
 mod substrate_enums;
+mod substrate_expressions;
+mod substrate_first;
 mod substrate_functions;
+mod substrate_primitives;
 
 type StorageKey = [u8; 32];
 
@@ -37,7 +37,7 @@ enum SubstrateExternal {
     ext_scratch_write,
     ext_set_storage,
     ext_get_storage,
-    ext_return
+    ext_return,
 }
 
 pub struct ContractStorage {
@@ -62,22 +62,24 @@ impl Externals for ContractStorage {
         index: usize,
         args: RuntimeArgs,
     ) -> Result<Option<RuntimeValue>, Trap> {
-
         match FromPrimitive::from_usize(index) {
             Some(SubstrateExternal::ext_scratch_size) => {
                 Ok(Some(RuntimeValue::I32(self.scratch.len() as i32)))
-            },
+            }
             Some(SubstrateExternal::ext_scratch_read) => {
                 let dest: u32 = args.nth_checked(0)?;
                 let offset: u32 = args.nth_checked(1)?;
                 let len: u32 = args.nth_checked(2)?;
 
-                if let Err(e) = self.memory.set(dest, &self.scratch[offset as usize..(offset + len) as usize]) {
+                if let Err(e) = self.memory.set(
+                    dest,
+                    &self.scratch[offset as usize..(offset + len) as usize],
+                ) {
                     panic!("ext_set_storage: {}", e);
                 }
 
                 Ok(None)
-            },
+            }
             Some(SubstrateExternal::ext_scratch_write) => {
                 let dest: u32 = args.nth_checked(0)?;
                 let len: u32 = args.nth_checked(1)?;
@@ -89,7 +91,7 @@ impl Externals for ContractStorage {
                 }
 
                 Ok(None)
-            },
+            }
             Some(SubstrateExternal::ext_get_storage) => {
                 assert_eq!(args.len(), 1);
 
@@ -108,7 +110,7 @@ impl Externals for ContractStorage {
                     self.scratch.clear();
                     Ok(Some(RuntimeValue::I32(1)))
                 }
-            },
+            }
             Some(SubstrateExternal::ext_set_storage) => {
                 assert_eq!(args.len(), 4);
 
@@ -137,7 +139,7 @@ impl Externals for ContractStorage {
                 }
 
                 Ok(None)
-            },
+            }
             Some(SubstrateExternal::ext_return) => {
                 let data_ptr: u32 = args.nth_checked(0)?;
                 let len: u32 = args.nth_checked(1)?;
@@ -149,7 +151,7 @@ impl Externals for ContractStorage {
                 }
 
                 Ok(None)
-            },
+            }
             _ => panic!("external {} unknown", index),
         }
     }
@@ -183,14 +185,20 @@ impl ModuleImportResolver for ContractStorage {
 
 pub struct TestRuntime {
     module: ModuleRef,
-    abi: abi::substrate::Metadata
+    abi: abi::substrate::Metadata,
 }
 
 impl TestRuntime {
     pub fn constructor<'a>(&self, store: &mut ContractStorage, index: usize, args: Vec<u8>) {
         let m = &self.abi.contract.constructors[index];
 
-        store.scratch = m.selector.to_le_bytes().to_vec().into_iter().chain(args).collect();
+        store.scratch = m
+            .selector
+            .to_le_bytes()
+            .to_vec()
+            .into_iter()
+            .chain(args)
+            .collect();
 
         self.module
             .invoke_export("deploy", &[], store)
@@ -200,7 +208,13 @@ impl TestRuntime {
     pub fn function<'a>(&self, store: &mut ContractStorage, name: &str, args: Vec<u8>) {
         let m = self.abi.get_function(name).unwrap();
 
-        store.scratch = m.selector.to_le_bytes().to_vec().into_iter().chain(args).collect();
+        store.scratch = m
+            .selector
+            .to_le_bytes()
+            .to_vec()
+            .into_iter()
+            .chain(args)
+            .collect();
 
         self.module
             .invoke_export("call", &[], store)
@@ -231,14 +245,17 @@ pub fn build_solidity(src: &'static str) -> (TestRuntime, ContractStorage) {
     let store = ContractStorage::new();
 
     (
-        TestRuntime{
-            module: ModuleInstance::new(&module, &ImportsBuilder::new().with_resolver("env", &store))
-                .expect("Failed to instantiate module")
-                .run_start(&mut NopExternals)
-                .expect("Failed to run start function in module"),
-            abi: abi::substrate::load(&abistr).unwrap()
+        TestRuntime {
+            module: ModuleInstance::new(
+                &module,
+                &ImportsBuilder::new().with_resolver("env", &store),
+            )
+            .expect("Failed to instantiate module")
+            .run_start(&mut NopExternals)
+            .expect("Failed to run start function in module"),
+            abi: abi::substrate::load(&abistr).unwrap(),
         },
-        store
+        store,
     )
 }
 
@@ -259,5 +276,11 @@ pub fn first_warning(errors: Vec<output::Output>) -> String {
 }
 
 pub fn no_errors(errors: Vec<output::Output>) {
-    assert!(errors.iter().filter(|m| m.level == output::Level::Error).count() == 0);
+    assert!(
+        errors
+            .iter()
+            .filter(|m| m.level == output::Level::Error)
+            .count()
+            == 0
+    );
 }

+ 16 - 8
tests/substrate_enums/mod.rs

@@ -1,6 +1,5 @@
-
 use parity_scale_codec::Encode;
-use parity_scale_codec_derive::{Encode, Decode};
+use parity_scale_codec_derive::{Decode, Encode};
 
 use super::{build_solidity, first_error, no_errors};
 use solang::{parse_and_resolve, Target};
@@ -11,7 +10,8 @@ fn weekdays() {
     struct Val(u8);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract enum_example {
             enum Weekday { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
 
@@ -38,7 +38,8 @@ fn weekdays() {
                 x = Weekday(2);
                 assert(x == Weekday.Wednesday);
             }
-        }");
+        }",
+    );
 
     runtime.function(&mut store, "is_weekend", Val(4).encode());
 
@@ -59,9 +60,14 @@ fn test_cast_errors() {
             function foo() public pure returns (uint8) {
                 return state.foo;
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "conversion from enum test.state to uint8 not possible");
+    assert_eq!(
+        first_error(errors),
+        "conversion from enum test.state to uint8 not possible"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
@@ -69,7 +75,9 @@ fn test_cast_errors() {
             function foo() public pure returns (uint8) {
                 return uint8(state.foo);
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     no_errors(errors);
-}
+}

+ 235 - 71
tests/substrate_expressions/mod.rs

@@ -1,11 +1,11 @@
-use parity_scale_codec::{Encode, Decode};
-use parity_scale_codec_derive::{Encode, Decode};
+use parity_scale_codec::{Decode, Encode};
+use parity_scale_codec_derive::{Decode, Encode};
 
 use super::{build_solidity, first_error, no_errors};
-use solang::{parse_and_resolve, Target};
 use num_bigint::BigInt;
 use num_bigint::Sign;
 use rand::Rng;
+use solang::{parse_and_resolve, Target};
 
 #[test]
 fn celcius_and_fahrenheit() {
@@ -13,7 +13,8 @@ fn celcius_and_fahrenheit() {
     struct Val(u32);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function celcius2fahrenheit(int32 celcius) pure public returns (int32) {
                 int32 fahrenheit = celcius * 9 / 5 + 32;
@@ -44,7 +45,8 @@ fn digits() {
     struct Val64(u64);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function digitslen(uint64 val) pure public returns (uint32) {
                 uint32 count = 0;
@@ -88,7 +90,8 @@ fn large_loops() {
     struct Val64(u64);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function foo(uint val) pure public returns (uint) {
                 for (uint i =0 ; i < 100; i++ ) {
@@ -245,18 +248,28 @@ fn test_cast_errors() {
             function foo(uint bar) public {
                 bool is_nonzero = bar;
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "conversion from uint256 to bool not possible");
+    assert_eq!(
+        first_error(errors),
+        "conversion from uint256 to bool not possible"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             function foobar(uint foo, int bar) public returns (bool) {
                 return (foo < bar);
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion would change sign from uint256 to int256");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion would change sign from uint256 to int256"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
@@ -264,7 +277,9 @@ fn test_cast_errors() {
                 foo = bar;
                 return false;
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     no_errors(errors);
 
@@ -275,9 +290,14 @@ fn test_cast_errors() {
                 foo = bar;
                 return false;
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion would change sign from int16 to uint32");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion would change sign from int16 to uint32"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract foo {
@@ -307,7 +327,9 @@ fn test_cast_errors() {
             function set_enum_x(X b) public {
                 set_x(uint32(b));
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     no_errors(errors);
 }
@@ -316,7 +338,8 @@ fn test_cast_errors() {
 #[should_panic]
 fn divisions_by_zero() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function do_test() public returns (uint){
                 uint256 val = 100;
@@ -332,7 +355,8 @@ fn divisions_by_zero() {
 #[test]
 fn divisions() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint constant large = 101213131318098987934191741;
             function do_test() public returns (uint) {
@@ -355,7 +379,8 @@ fn divisions() {
 #[test]
 fn divisions64() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint64 constant large = 101213131318098987;
             function do_test() public returns (uint) {
@@ -384,7 +409,8 @@ fn divisions128() {
     struct Rets(i128);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint128 constant large = 101213131318098987;
             uint128 constant small = 99;
@@ -478,7 +504,11 @@ fn divisions128() {
         assert!(false);
     }
 
-    runtime.function(&mut store, "do_div", Args(-101213131318098987, -100000).encode());
+    runtime.function(
+        &mut store,
+        "do_div",
+        Args(-101213131318098987, -100000).encode(),
+    );
 
     if let Ok(Rets(r)) = Rets::decode(&mut &store.scratch[..]) {
         assert_eq!(r, 1012131313180);
@@ -492,7 +522,8 @@ fn divisions128() {
 #[test]
 fn divisions256() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint256 constant large = 101213131318098987;
             uint256 constant small = 99;
@@ -522,7 +553,8 @@ fn divisions256() {
 #[test]
 fn complement() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function do_test() public {
                 uint8 x1 = 0;
@@ -553,7 +585,8 @@ fn complement() {
 #[test]
 fn bitwise() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function do_test() public {
                 uint8 x1 = 0xf0;
@@ -620,7 +653,8 @@ fn bitwise() {
 #[test]
 fn shift() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function do_test() public {
                 uint8 x1 = 0xf0;
@@ -647,7 +681,8 @@ fn shift() {
 #[test]
 fn assign_bitwise() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function do_test() public {
                 uint8 x1 = 0xf0;
@@ -725,7 +760,8 @@ fn assign_bitwise() {
 #[test]
 fn assign_shift() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function do_test() public {
                 uint8 x1 = 0xf0;
@@ -756,7 +792,8 @@ fn assign_shift() {
 #[test]
 fn ternary() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function do_test() public {
                 uint8 x1 = 0xf0;
@@ -774,7 +811,8 @@ fn ternary() {
 #[test]
 fn short_circuit() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint32 counter;
 
@@ -811,36 +849,54 @@ fn power() {
     struct Val(u64);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract c {
             function power(uint64 base, uint64 exp) public returns (uint64) {
                 return base ** exp;
             }
-        }");
+        }",
+    );
 
     // 4**5 = 1024
-    let args = Val(4).encode().into_iter().chain(Val(5).encode().into_iter()).collect();
+    let args = Val(4)
+        .encode()
+        .into_iter()
+        .chain(Val(5).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
     assert_eq!(store.scratch, Val(1024).encode());
 
     // n ** 1 = n
-    let args = Val(2345).encode().into_iter().chain(Val(1).encode().into_iter()).collect();
+    let args = Val(2345)
+        .encode()
+        .into_iter()
+        .chain(Val(1).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
     assert_eq!(store.scratch, Val(2345).encode());
 
     // n ** 0 = 0
-    let args = Val(0xdeadbeef).encode().into_iter().chain(Val(0).encode().into_iter()).collect();
+    let args = Val(0xdeadbeef)
+        .encode()
+        .into_iter()
+        .chain(Val(0).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
     assert_eq!(store.scratch, Val(1).encode());
 
     // 0 ** n = 0
-    let args = Val(0).encode().into_iter().chain(Val(0xdeadbeef).encode().into_iter()).collect();
+    let args = Val(0)
+        .encode()
+        .into_iter()
+        .chain(Val(0xdeadbeef).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
@@ -851,27 +907,42 @@ fn power() {
             function power(uint64 base, int64 exp) public returns (uint64) {
                 return base ** exp;
             }
-       }", &Target::Substrate);
+       }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "exponation (**) is not allowed with signed types");
+    assert_eq!(
+        first_error(errors),
+        "exponation (**) is not allowed with signed types"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             function power(int64 base, uint64 exp) public returns (int64) {
                 return base ** exp;
             }
-       }", &Target::Substrate);
+       }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "exponation (**) is not allowed with signed types");
+    assert_eq!(
+        first_error(errors),
+        "exponation (**) is not allowed with signed types"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             function power(int64 base, int64 exp) public returns (int64) {
                 return base ** exp;
             }
-       }", &Target::Substrate);
+       }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "exponation (**) is not allowed with signed types");
+    assert_eq!(
+        first_error(errors),
+        "exponation (**) is not allowed with signed types"
+    );
 }
 
 #[test]
@@ -880,47 +951,72 @@ fn large_power() {
     struct Val(u128);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract c {
             function power(uint128 base, uint128 exp) public returns (uint128) {
                 return base ** exp;
             }
-        }");
+        }",
+    );
 
     // 4**5 = 1024
-    let args = Val(4).encode().into_iter().chain(Val(5).encode().into_iter()).collect();
+    let args = Val(4)
+        .encode()
+        .into_iter()
+        .chain(Val(5).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
     assert_eq!(store.scratch, Val(1024).encode());
 
     // n ** 1 = n
-    let args = Val(2345).encode().into_iter().chain(Val(1).encode().into_iter()).collect();
+    let args = Val(2345)
+        .encode()
+        .into_iter()
+        .chain(Val(1).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
     assert_eq!(store.scratch, Val(2345).encode());
 
     // n ** 0 = 0
-    let args = Val(0xdeadbeef).encode().into_iter().chain(Val(0).encode().into_iter()).collect();
+    let args = Val(0xdeadbeef)
+        .encode()
+        .into_iter()
+        .chain(Val(0).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
     assert_eq!(store.scratch, Val(1).encode());
 
     // 0 ** n = 0
-    let args = Val(0).encode().into_iter().chain(Val(0xdeadbeef).encode().into_iter()).collect();
+    let args = Val(0)
+        .encode()
+        .into_iter()
+        .chain(Val(0xdeadbeef).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
     assert_eq!(store.scratch, Val(0).encode());
 
     // 10 ** 36 = 1000000000000000000000000000000000000
-    let args = Val(10).encode().into_iter().chain(Val(36).encode().into_iter()).collect();
+    let args = Val(10)
+        .encode()
+        .into_iter()
+        .chain(Val(36).encode().into_iter())
+        .collect();
 
     runtime.function(&mut store, "power", args);
 
-    assert_eq!(store.scratch, Val(1000000000000000000000000000000000000).encode());
+    assert_eq!(
+        store.scratch,
+        Val(1000000000000000000000000000000000000).encode()
+    );
 }
 
 #[test]
@@ -928,12 +1024,14 @@ fn multiply() {
     let mut rng = rand::thread_rng();
     let size = 32;
 
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract c {
             function multiply(uint a, uint b) public returns (uint) {
                 return a * b;
             }
-        }");
+        }",
+    );
 
     let mut rand = || -> (BigInt, Vec<u8>) {
         let length = rng.gen::<usize>() % size;
@@ -953,7 +1051,11 @@ fn multiply() {
 
         println!("in: a:{:?} b:{:?}", a_data, b_data);
 
-        runtime.function(&mut store, "multiply", a_data.into_iter().chain(b_data.into_iter()).collect());
+        runtime.function(
+            &mut store,
+            "multiply",
+            a_data.into_iter().chain(b_data.into_iter()).collect(),
+        );
 
         println!("out: res:{:?}", store.scratch);
 
@@ -980,7 +1082,8 @@ fn bytes_bitwise() {
     struct BytesArray([u8; 7], u32);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract c {
             function or(bytes5 x) public returns (bytes5 y) {
                 y = x | hex\"80808080\";
@@ -1027,43 +1130,94 @@ fn bytes_bitwise() {
             function bytes_array(bytes7 foo, uint32 index) public returns (bytes1) {
                 return foo[index];
             }
-        }");
+        }",
+    );
 
-    runtime.function(&mut store, "or", Bytes5([ 0x01, 0x01, 0x01, 0x01, 0x01]).encode());
+    runtime.function(
+        &mut store,
+        "or",
+        Bytes5([0x01, 0x01, 0x01, 0x01, 0x01]).encode(),
+    );
 
-    assert_eq!(store.scratch, Bytes5([0x81, 0x81, 0x81, 0x81, 0x01]).encode());
+    assert_eq!(
+        store.scratch,
+        Bytes5([0x81, 0x81, 0x81, 0x81, 0x01]).encode()
+    );
 
-    runtime.function(&mut store, "and", Bytes5([ 0x01, 0x01, 0x01, 0x01, 0x01]).encode());
+    runtime.function(
+        &mut store,
+        "and",
+        Bytes5([0x01, 0x01, 0x01, 0x01, 0x01]).encode(),
+    );
 
     assert_eq!(store.scratch, Bytes5([0x01, 0x01, 0, 0, 0]).encode());
 
-    runtime.function(&mut store, "xor", Bytes5([0x01, 0x01, 0x01, 0x01, 0x01]).encode());
+    runtime.function(
+        &mut store,
+        "xor",
+        Bytes5([0x01, 0x01, 0x01, 0x01, 0x01]).encode(),
+    );
 
-    assert_eq!(store.scratch, Bytes5([0xfe, 0x01, 0x01, 0x01, 0x01]).encode());
+    assert_eq!(
+        store.scratch,
+        Bytes5([0xfe, 0x01, 0x01, 0x01, 0x01]).encode()
+    );
 
     // shifty-shift
-    runtime.function(&mut store, "shift_left", Bytes3([0xf3, 0x7d, 0x03]).encode());
+    runtime.function(
+        &mut store,
+        "shift_left",
+        Bytes3([0xf3, 0x7d, 0x03]).encode(),
+    );
 
-    assert_eq!(store.scratch, Bytes5([0x7d, 0x03, 0x00, 0x00, 0x00]).encode());
+    assert_eq!(
+        store.scratch,
+        Bytes5([0x7d, 0x03, 0x00, 0x00, 0x00]).encode()
+    );
 
-    runtime.function(&mut store, "shift_right", Bytes3([0xf3, 0x7d, 0x03]).encode());
+    runtime.function(
+        &mut store,
+        "shift_right",
+        Bytes3([0xf3, 0x7d, 0x03]).encode(),
+    );
 
-    assert_eq!(store.scratch, Bytes5([0x00, 0xf3, 0x7d, 0x03, 0x00]).encode());
+    assert_eq!(
+        store.scratch,
+        Bytes5([0x00, 0xf3, 0x7d, 0x03, 0x00]).encode()
+    );
 
     // assignment versions
-    runtime.function(&mut store, "shift_left2", Bytes3([0xf3, 0x7d, 0x03]).encode());
+    runtime.function(
+        &mut store,
+        "shift_left2",
+        Bytes3([0xf3, 0x7d, 0x03]).encode(),
+    );
 
-    assert_eq!(store.scratch, Bytes5([0x7d, 0x03, 0x00, 0x00, 0x00]).encode());
+    assert_eq!(
+        store.scratch,
+        Bytes5([0x7d, 0x03, 0x00, 0x00, 0x00]).encode()
+    );
 
-    runtime.function(&mut store, "shift_right2", Bytes3([0xf3, 0x7d, 0x03]).encode());
+    runtime.function(
+        &mut store,
+        "shift_right2",
+        Bytes3([0xf3, 0x7d, 0x03]).encode(),
+    );
 
-    assert_eq!(store.scratch, Bytes5([0x00, 0xf3, 0x7d, 0x03, 0x00]).encode());
+    assert_eq!(
+        store.scratch,
+        Bytes5([0x00, 0xf3, 0x7d, 0x03, 0x00]).encode()
+    );
 
     // check length
     runtime.function(&mut store, "bytes_length", Vec::new());
 
     // complement
-    runtime.function(&mut store, "complement", Bytes3([0xf3, 0x7d, 0x03]).encode());
+    runtime.function(
+        &mut store,
+        "complement",
+        Bytes3([0xf3, 0x7d, 0x03]).encode(),
+    );
 
     assert_eq!(store.scratch, Bytes3([0x0c, 0x82, 0xfc]).encode());
 
@@ -1072,7 +1226,7 @@ fn bytes_bitwise() {
     for i in 0..6 {
         runtime.function(&mut store, "bytes_array", BytesArray(bytes7, i).encode());
 
-        assert_eq!(store.scratch, [ bytes7[i as usize] ]);
+        assert_eq!(store.scratch, [bytes7[i as usize]]);
     }
 }
 
@@ -1083,7 +1237,8 @@ fn bytesn_underflow_index_acccess() {
     struct BytesArray([u8; 7], i32);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function bytes_array(bytes7 foo, int32 index) public returns (bytes1) {
                 return foo[index];
@@ -1091,7 +1246,11 @@ fn bytesn_underflow_index_acccess() {
         }",
     );
 
-    runtime.function(&mut store, "bytes_array", BytesArray(*b"nawabra", -1).encode());
+    runtime.function(
+        &mut store,
+        "bytes_array",
+        BytesArray(*b"nawabra", -1).encode(),
+    );
 }
 
 #[test]
@@ -1101,7 +1260,8 @@ fn bytesn_overflow_index_acccess() {
     struct BytesArray([u8; 7], i32);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function bytes_array(bytes7 foo, int32 index) public returns (byte) {
                 return foo[index];
@@ -1109,5 +1269,9 @@ fn bytesn_overflow_index_acccess() {
         }",
     );
 
-    runtime.function(&mut store, "bytes_array", BytesArray(*b"nawabra", 7).encode());
+    runtime.function(
+        &mut store,
+        "bytes_array",
+        BytesArray(*b"nawabra", 7).encode(),
+    );
 }

+ 19 - 14
tests/substrate_first/mod.rs

@@ -1,6 +1,5 @@
-
 use parity_scale_codec::Encode;
-use parity_scale_codec_derive::{Encode, Decode};
+use parity_scale_codec_derive::{Decode, Encode};
 
 use super::build_solidity;
 
@@ -8,11 +7,12 @@ use super::build_solidity;
 fn simple_solidiy_compile_and_run() {
     #[derive(Debug, PartialEq, Encode, Decode)]
     struct FooReturn {
-        value: u32
+        value: u32,
     }
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function foo() public returns (uint32) {
                 return 2;
@@ -22,7 +22,7 @@ fn simple_solidiy_compile_and_run() {
 
     runtime.function(&mut store, "foo", Vec::new());
 
-    let ret = FooReturn{ value: 2 };
+    let ret = FooReturn { value: 2 };
 
     assert_eq!(store.scratch, ret.encode());
 }
@@ -30,7 +30,8 @@ fn simple_solidiy_compile_and_run() {
 #[test]
 fn flipper() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract flipper {
             bool private value;
 
@@ -69,11 +70,12 @@ fn flipper() {
 fn contract_storage_initializers() {
     #[derive(Debug, PartialEq, Encode, Decode)]
     struct FooReturn {
-        value: u32
+        value: u32,
     }
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint32 a = 100;
             uint32 b = 200;
@@ -92,7 +94,7 @@ fn contract_storage_initializers() {
 
     runtime.function(&mut store, "foo", Vec::new());
 
-    let ret = FooReturn{ value: 400 };
+    let ret = FooReturn { value: 400 };
 
     assert_eq!(store.scratch, ret.encode());
 }
@@ -101,11 +103,12 @@ fn contract_storage_initializers() {
 fn contract_constants() {
     #[derive(Debug, PartialEq, Encode, Decode)]
     struct FooReturn {
-        value: u32
+        value: u32,
     }
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint32 constant a = 300 + 100;
 
@@ -120,7 +123,7 @@ fn contract_constants() {
 
     runtime.function(&mut store, "foo", Vec::new());
 
-    let ret = FooReturn{ value: 400 };
+    let ret = FooReturn { value: 400 };
 
     assert_eq!(store.scratch, ret.encode());
 }
@@ -152,7 +155,8 @@ fn large_contract_variables() {
 #[test]
 fn assert_ok() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function foo() public pure returns (uint32) {
                 assert(true);
@@ -170,7 +174,8 @@ fn assert_ok() {
 #[should_panic]
 fn assert_not_ok() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function foo() public pure returns (uint32) {
                 assert(false);

+ 51 - 25
tests/substrate_functions/mod.rs

@@ -1,6 +1,5 @@
-
 use parity_scale_codec::Encode;
-use parity_scale_codec_derive::{Encode, Decode};
+use parity_scale_codec_derive::{Decode, Encode};
 
 use super::{build_solidity, first_error, first_warning};
 use solang::{parse_and_resolve, Target};
@@ -11,7 +10,8 @@ fn constructors() {
     struct Val(u64);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint64 result;
 
@@ -26,15 +26,17 @@ fn constructors() {
             function get() public returns (uint64) {
                 return result;
             }
-        }");
+        }",
+    );
 
     runtime.constructor(&mut store, 0, Vec::new());
     runtime.function(&mut store, "get", Vec::new());
 
     assert_eq!(store.scratch, Val(1).encode());
 
-        // parse
-        let (runtime, mut store) = build_solidity("
+    // parse
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint64 result;
 
@@ -49,7 +51,8 @@ fn constructors() {
             function get() public returns (uint64) {
                 return result;
             }
-        }");
+        }",
+    );
 
     runtime.constructor(&mut store, 1, Val(0xaabbccdd).encode());
     runtime.function(&mut store, "get", Vec::new());
@@ -63,7 +66,8 @@ fn fallback() {
     struct Val(u64);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             int64 result = 102;
 
@@ -74,9 +78,10 @@ fn fallback() {
             function() external {
                 result = 356;
             }
-        }");
+        }",
+    );
 
-    runtime.raw_function(&mut store, [ 0xaa, 0xbb, 0xcc, 0xdd, 0xff ].to_vec());
+    runtime.raw_function(&mut store, [0xaa, 0xbb, 0xcc, 0xdd, 0xff].to_vec());
     runtime.function(&mut store, "get", Vec::new());
 
     assert_eq!(store.scratch, Val(356).encode());
@@ -89,16 +94,18 @@ fn nofallback() {
     struct Val(u64);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             int64 result = 102;
 
             function get() public returns (int64) {
                 return result;
             }
-        }");
+        }",
+    );
 
-    runtime.raw_function(&mut store, [ 0xaa, 0xbb, 0xcc, 0xdd, 0xff ].to_vec());
+    runtime.raw_function(&mut store, [0xaa, 0xbb, 0xcc, 0xdd, 0xff].to_vec());
     runtime.function(&mut store, "get", Vec::new());
 
     assert_eq!(store.scratch, Val(356).encode());
@@ -107,7 +114,8 @@ fn nofallback() {
 #[test]
 fn test_overloading() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint32 result = 1;
 
@@ -127,7 +135,8 @@ fn test_overloading() {
             function foo(uint32 x) private {
                 result = x + 10;
             }
-        }");
+        }",
+    );
 
     runtime.constructor(&mut store, 0, Vec::new());
 }
@@ -141,9 +150,14 @@ fn mutability() {
             function bar() public pure returns (int64) {
                 return foo;
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "function declared pure but reads contract storage");
+    assert_eq!(
+        first_error(errors),
+        "function declared pure but reads contract storage"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
@@ -152,9 +166,14 @@ fn mutability() {
             function bar() public view {
                 foo = 102;
             }
-        }", &Target::Substrate);
-
-    assert_eq!(first_error(errors), "function declared view but writes contract storage");
+        }",
+        &Target::Substrate,
+    );
+
+    assert_eq!(
+        first_error(errors),
+        "function declared view but writes contract storage"
+    );
 }
 
 #[test]
@@ -181,7 +200,10 @@ fn shadowing() {
 
     let (_, errors) = parse_and_resolve(&src, &Target::Substrate);
 
-    assert_eq!(first_warning(errors), "declaration of `result\' shadows state variable");
+    assert_eq!(
+        first_warning(errors),
+        "declaration of `result\' shadows state variable"
+    );
 
     // parse
     let (runtime, mut store) = build_solidity(src);
@@ -255,7 +277,8 @@ fn for_forever() {
 #[test]
 fn test_loops() {
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             uint32 result = 1;
 
@@ -302,7 +325,8 @@ fn test_loops() {
 
                 assert(n == 9);
             }
-        }");
+        }",
+    );
 
     runtime.constructor(&mut store, 0, Vec::new());
 }
@@ -395,7 +419,8 @@ fn args_and_returns() {
 
     assert_eq!(first_error(errors), "missing return statement");
 
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract foobar {
             function foo1() public returns (int32 a) {
                 a = -102;
@@ -405,7 +430,8 @@ fn args_and_returns() {
                 a = -102;
                 return 553;
             }
-        }");
+        }",
+    );
 
     runtime.function(&mut store, "foo1", Vec::new());
 

+ 118 - 39
tests/substrate_primitives/mod.rs

@@ -1,6 +1,5 @@
-
 use parity_scale_codec::Encode;
-use parity_scale_codec_derive::{Encode, Decode};
+use parity_scale_codec_derive::{Decode, Encode};
 
 use super::{build_solidity, first_error, no_errors};
 use solang::{parse_and_resolve, Target};
@@ -13,7 +12,8 @@ fn various_constants() {
     struct Foo64Return(i64);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function foo() public returns (uint32) {
                 return 2;
@@ -26,7 +26,8 @@ fn various_constants() {
     assert_eq!(store.scratch, FooReturn(2).encode());
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function foo() public returns (uint32) {
                 return 0xdeadcafe;
@@ -39,7 +40,8 @@ fn various_constants() {
     assert_eq!(store.scratch, FooReturn(0xdeadcafe).encode());
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function foo() public returns (int64) {
                 return -0x7afedeaddeedcafe;
@@ -57,58 +59,89 @@ fn test_literal_overflow() {
     let (_, errors) = parse_and_resolve(
         "contract test {
             uint8 foo = 300;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion would truncate from uint16 to uint8");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion would truncate from uint16 to uint8"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             uint16 foo = 0x10000;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion would truncate from uint24 to uint16");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion would truncate from uint24 to uint16"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             int8 foo = 0x8_0;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion would truncate from uint8 to int8");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion would truncate from uint8 to int8"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             int8 foo = 127;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     no_errors(errors);
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             int8 foo = -128;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     no_errors(errors);
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             uint8 foo = 255;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     no_errors(errors);
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             uint8 foo = -1_30;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion cannot change negative number to uint8");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion cannot change negative number to uint8"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             int64 foo = 1844674_4073709551616;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion would truncate from uint72 to int64");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion would truncate from uint72 to int64"
+    );
 }
 
 #[test]
@@ -125,7 +158,8 @@ fn bytes() {
     struct Test4args(u32, [u8; 4]);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function const3() public returns (bytes3) {
                 return hex\"112233\";
@@ -159,7 +193,7 @@ fn bytes() {
             function test7trunc(bytes7 foo) public returns (bytes3) {
                 return bytes3(foo);
             }
-        }"
+        }",
     );
 
     runtime.function(&mut store, "const3", Vec::new());
@@ -172,14 +206,20 @@ fn bytes() {
 
     runtime.function(&mut store, "const32", Vec::new());
 
-    assert_eq!(store.scratch, Bytes32(*b"The quick brown fox jumped over ").encode());
+    assert_eq!(
+        store.scratch,
+        Bytes32(*b"The quick brown fox jumped over ").encode()
+    );
 
     runtime.function(&mut store, "test4", Test4args(1, *b"abcd").encode());
     runtime.function(&mut store, "test4", Test4args(2, *b"ABCD").encode());
 
     // Casting to larger bytesN should insert stuff on the right
     runtime.function(&mut store, "test7", Bytes7(*b"1234567").encode());
-    assert_eq!(store.scratch, Bytes32(*b"1234567\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0").encode());
+    assert_eq!(
+        store.scratch,
+        Bytes32(*b"1234567\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0").encode()
+    );
 
     runtime.function(&mut store, "test3", Bytes3(*b"XYZ").encode());
     assert_eq!(store.scratch, Bytes7(*b"XYZ\0\0\0\0").encode());
@@ -187,7 +227,6 @@ fn bytes() {
     // truncating should drop values on the right
     runtime.function(&mut store, "test7trunc", Bytes7(*b"XYWOLEH").encode());
     assert_eq!(store.scratch, Bytes3(*b"XYW").encode());
-
 }
 
 #[test]
@@ -195,23 +234,35 @@ fn address() {
     let (_, errors) = parse_and_resolve(
         "contract test {
             address  foo = 0x1844674_4073709551616;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion from uint80 to address not allowed");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion from uint80 to address not allowed"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             address foo = 0x8617E340B3D01FA5F11F306F4090FD50E238070d;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     assert_eq!(first_error(errors), "address literal has incorrect checksum, expected ‘0x8617E340B3D01FA5F11F306F4090FD50E238070D’");
 
     let (_, errors) = parse_and_resolve(
         "contract test {
             uint160 foo = 0x8617E340B3D01FA5F11F306F4090FD50E238070D;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "implicit conversion would truncate from address to uint160");
+    assert_eq!(
+        first_error(errors),
+        "implicit conversion would truncate from address to uint160"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
@@ -220,9 +271,14 @@ fn address() {
             function bar() private returns (bool) {
                 return foo > address(0);
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "expression of type address not allowed");
+    assert_eq!(
+        first_error(errors),
+        "expression of type address not allowed"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
@@ -231,9 +287,14 @@ fn address() {
             function bar() private returns (address) {
                 return foo + address(1);
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "expression of type address not allowed");
+    assert_eq!(
+        first_error(errors),
+        "expression of type address not allowed"
+    );
 
     let (_, errors) = parse_and_resolve(
         "contract test {
@@ -242,15 +303,21 @@ fn address() {
             function bar() private returns (address) {
                 return foo | address(1);
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "expression of type address not allowed");
+    assert_eq!(
+        first_error(errors),
+        "expression of type address not allowed"
+    );
 
     #[derive(Debug, PartialEq, Encode, Decode)]
     struct Address([u8; 20]);
 
     // parse
-    let (runtime, mut store) = build_solidity("
+    let (runtime, mut store) = build_solidity(
+        "
         contract test {
             function check_return() public returns (address) {
                 return 0xde709f2102306220921060314715629080e2fb77;
@@ -259,13 +326,25 @@ fn address() {
             function check_param(address a) public {
                 assert(a == 0xE9430d8C01C4E4Bb33E44fd7748942085D82fC91);
             }
-        }");
+        }",
+    );
 
     runtime.function(&mut store, "check_return", Vec::new());
 
-    assert_eq!(store.scratch, Address([ 0xde, 0x70, 0x9f, 0x21, 0x02, 0x30, 0x62, 0x20, 0x92, 0x10, 0x60, 0x31, 0x47, 0x15, 0x62, 0x90, 0x80, 0xe2, 0xfb, 0x77 ]).encode());
+    assert_eq!(
+        store.scratch,
+        Address([
+            0xde, 0x70, 0x9f, 0x21, 0x02, 0x30, 0x62, 0x20, 0x92, 0x10, 0x60, 0x31, 0x47, 0x15,
+            0x62, 0x90, 0x80, 0xe2, 0xfb, 0x77
+        ])
+        .encode()
+    );
 
-    let val = Address([ 0xE9, 0x43, 0x0d, 0x8C, 0x01, 0xC4, 0xE4, 0xBb, 0x33, 0xE4, 0x4f, 0xd7, 0x74, 0x89, 0x42, 0x08, 0x5D, 0x82, 0xfC, 0x91 ]).encode();
+    let val = Address([
+        0xE9, 0x43, 0x0d, 0x8C, 0x01, 0xC4, 0xE4, 0xBb, 0x33, 0xE4, 0x4f, 0xd7, 0x74, 0x89, 0x42,
+        0x08, 0x5D, 0x82, 0xfC, 0x91,
+    ])
+    .encode();
 
     runtime.function(&mut store, "check_param", val);
-}
+}

+ 28 - 11
tests/variables.rs

@@ -1,8 +1,7 @@
-
 extern crate solang;
 
-use solang::{parse_and_resolve, Target};
 use solang::output;
+use solang::{parse_and_resolve, Target};
 
 fn first_error(errors: Vec<output::Output>) -> String {
     for m in errors.iter().filter(|m| m.level == output::Level::Error) {
@@ -23,7 +22,9 @@ fn test_variable_errors() {
 
                 return a * b;
             }
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     assert_eq!(first_error(errors), "`b' is not declared");
 }
@@ -35,9 +36,14 @@ fn test_variable_initializer_errors() {
         "contract test {
             uint x = 102;
             uint constant y = x + 5;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "cannot read variable x in constant expression");
+    assert_eq!(
+        first_error(errors),
+        "cannot read variable x in constant expression"
+    );
 
     // cannot read contract storage in constant
     let (_, errors) = parse_and_resolve(
@@ -46,16 +52,23 @@ fn test_variable_initializer_errors() {
                 return 102;
             }
             uint constant y = foo() + 5;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
-    assert_eq!(first_error(errors), "cannot call function in constant expression");
+    assert_eq!(
+        first_error(errors),
+        "cannot call function in constant expression"
+    );
 
     // cannot refer to variable declared later
     let (_, errors) = parse_and_resolve(
         "contract test {
             uint x = y + 102;
             uint y = 102;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     assert_eq!(first_error(errors), "`y' is not declared");
 
@@ -64,7 +77,9 @@ fn test_variable_initializer_errors() {
         "contract test {
             uint x = y + 102;
             uint constant y = 102;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     assert_eq!(first_error(errors), "`y' is not declared");
 
@@ -72,7 +87,9 @@ fn test_variable_initializer_errors() {
     let (_, errors) = parse_and_resolve(
         "contract test {
             uint x = x + 102;
-        }", &Target::Substrate);
+        }",
+        &Target::Substrate,
+    );
 
     assert_eq!(first_error(errors), "`x' is not declared");
-}
+}

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików