浏览代码

Move enum definitions to namespace

This will allow us to define enums outside of contract definitions.

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 5 年之前
父节点
当前提交
a4f3f974be

+ 1 - 1
clippy.toml

@@ -1,2 +1,2 @@
-too-many-arguments-threshold = 10
+too-many-arguments-threshold = 11
 cognitive-complexity-threshold = 37

+ 10 - 10
src/abi/ethereum.rs

@@ -1,7 +1,7 @@
 // ethereum style ABIs
 
 use parser::ast;
-use resolver::{Contract, Type};
+use resolver::{Contract, Namespace, Type};
 use serde::Serialize;
 
 #[derive(Serialize)]
@@ -28,13 +28,13 @@ pub struct ABI {
     pub mutability: &'static str,
 }
 
-pub fn gen_abi(contract: &Contract) -> Vec<ABI> {
-    fn parameter_to_abi(name: &str, ty: &Type, contract: &Contract) -> ABIParam {
+pub fn gen_abi(contract: &Contract, ns: &Namespace) -> Vec<ABI> {
+    fn parameter_to_abi(name: &str, ty: &Type, contract: &Contract, ns: &Namespace) -> ABIParam {
         let components = if let Type::Struct(n) = ty {
             contract.structs[*n]
                 .fields
                 .iter()
-                .map(|f| parameter_to_abi(&f.name, &f.ty, contract))
+                .map(|f| parameter_to_abi(&f.name, &f.ty, contract, ns))
                 .collect::<Vec<ABIParam>>()
         } else {
             Vec::new()
@@ -42,8 +42,8 @@ pub fn gen_abi(contract: &Contract) -> Vec<ABI> {
 
         ABIParam {
             name: name.to_string(),
-            ty: ty.to_signature_string(contract),
-            internal_ty: ty.to_string(contract),
+            ty: ty.to_signature_string(contract, ns),
+            internal_ty: ty.to_string(contract, ns),
             components,
         }
     }
@@ -69,12 +69,12 @@ pub fn gen_abi(contract: &Contract) -> Vec<ABI> {
             inputs: f
                 .params
                 .iter()
-                .map(|p| parameter_to_abi(&p.name, &p.ty, contract))
+                .map(|p| parameter_to_abi(&p.name, &p.ty, contract, ns))
                 .collect(),
             outputs: f
                 .returns
                 .iter()
-                .map(|p| parameter_to_abi(&p.name, &p.ty, contract))
+                .map(|p| parameter_to_abi(&p.name, &p.ty, contract, ns))
                 .collect(),
         })
         .chain(
@@ -110,12 +110,12 @@ pub fn gen_abi(contract: &Contract) -> Vec<ABI> {
                     inputs: f
                         .params
                         .iter()
-                        .map(|p| parameter_to_abi(&p.name, &p.ty, contract))
+                        .map(|p| parameter_to_abi(&p.name, &p.ty, contract, ns))
                         .collect(),
                     outputs: f
                         .returns
                         .iter()
-                        .map(|p| parameter_to_abi(&p.name, &p.ty, contract))
+                        .map(|p| parameter_to_abi(&p.name, &p.ty, contract, ns))
                         .collect(),
                 }),
         )

+ 4 - 4
src/abi/mod.rs

@@ -1,11 +1,11 @@
-use resolver::Contract;
+use resolver::{Contract, Namespace};
 use Target;
 
 pub mod ethereum;
 pub mod substrate;
 
-pub fn generate_abi(contract: &Contract, target: Target, verbose: bool) -> (String, &'static str) {
-    match target {
+pub fn generate_abi(contract: &Contract, ns: &Namespace, verbose: bool) -> (String, &'static str) {
+    match ns.target {
         Target::Ewasm | Target::Sabre => {
             if verbose {
                 eprintln!(
@@ -14,7 +14,7 @@ pub fn generate_abi(contract: &Contract, target: Target, verbose: bool) -> (Stri
                 );
             }
 
-            let abi = ethereum::gen_abi(contract);
+            let abi = ethereum::gen_abi(contract, ns);
 
             (serde_json::to_string(&abi).unwrap(), "abi")
         }

+ 3 - 3
src/bin/solang.rs

@@ -164,7 +164,7 @@ fn process_filename(
     // emit phase
     for resolved_contract in &ns.contracts {
         if let Some("cfg") = matches.value_of("EMIT") {
-            println!("{}", resolved_contract.to_string());
+            println!("{}", resolved_contract.print_to_string(&ns));
             continue;
         }
 
@@ -293,7 +293,7 @@ fn process_filename(
             json_contracts.insert(
                 contract.name.to_owned(),
                 JsonContract {
-                    abi: abi::ethereum::gen_abi(&resolved_contract),
+                    abi: abi::ethereum::gen_abi(&resolved_contract, &ns),
                     ewasm: EwasmContract {
                         wasm: hex::encode_upper(wasm),
                     },
@@ -313,7 +313,7 @@ fn process_filename(
             let mut file = File::create(wasm_filename).unwrap();
             file.write_all(&wasm).unwrap();
 
-            let (abi_bytes, abi_ext) = resolved_contract.abi(ns.target, verbose);
+            let (abi_bytes, abi_ext) = resolved_contract.abi(&ns, verbose);
             let abi_filename = output_file(&contract.name, abi_ext);
 
             if verbose {

+ 3 - 3
src/emit/ethabiencoder.rs

@@ -74,7 +74,7 @@ impl EthAbiEncoder {
                 }
             }
             resolver::Type::Struct(n) => {
-                for (i, field) in contract.ns.structs[*n].fields.iter().enumerate() {
+                for (i, field) in contract.contract.structs[*n].fields.iter().enumerate() {
                     let elem = unsafe {
                         contract.builder.build_gep(
                             arg.into_pointer_value(),
@@ -654,7 +654,7 @@ impl EthAbiEncoder {
                 let to =
                     to.unwrap_or_else(|| contract.builder.build_alloca(contract.llvm_type(ty), ""));
 
-                for (i, field) in contract.ns.structs[*n].fields.iter().enumerate() {
+                for (i, field) in contract.contract.structs[*n].fields.iter().enumerate() {
                     let elem = unsafe {
                         contract.builder.build_gep(
                             to,
@@ -716,7 +716,7 @@ impl EthAbiEncoder {
         let expected_length = spec
             .params
             .iter()
-            .map(|arg| self.encoded_length(&arg.ty, contract.ns))
+            .map(|arg| self.encoded_length(&arg.ty, contract.contract))
             .sum();
         let mut data = data;
         let decode_block = contract.context.append_basic_block(function, "abi_decode");

+ 5 - 5
src/emit/ewasm.rs

@@ -263,7 +263,7 @@ impl EwasmTarget {
         // init our storage vars
         contract.builder.build_call(initializer, &[], "");
 
-        if let Some(con) = contract.ns.constructors.get(0) {
+        if let Some(con) = contract.contract.constructors.get(0) {
             let mut args = Vec::new();
 
             // insert abi decode
@@ -307,7 +307,7 @@ impl EwasmTarget {
         let fallback_block = contract.context.append_basic_block(function, "fallback");
 
         contract.emit_function_dispatch(
-            &contract.ns.functions,
+            &contract.contract.functions,
             &contract.functions,
             argsdata,
             argslen,
@@ -319,7 +319,7 @@ impl EwasmTarget {
         // emit fallback code
         contract.builder.position_at_end(fallback_block);
 
-        match contract.ns.fallback_function() {
+        match contract.contract.fallback_function() {
             Some(f) => {
                 contract.builder.build_call(contract.functions[f], &[], "");
 
@@ -660,7 +660,7 @@ impl TargetRuntime for EwasmTarget {
             contract.context.i32_type().const_int(4, false),
             contract.context.i32_type().const_int(
                 self.abi
-                    .encoded_length(&resolver::Type::String, contract.ns),
+                    .encoded_length(&resolver::Type::String, contract.contract),
                 false,
             ),
             "length",
@@ -724,7 +724,7 @@ impl TargetRuntime for EwasmTarget {
         let length = contract.context.i32_type().const_int(
             spec.returns
                 .iter()
-                .map(|arg| self.abi.encoded_length(&arg.ty, contract.ns))
+                .map(|arg| self.abi.encoded_length(&arg.ty, contract.contract))
                 .sum(),
             false,
         );

+ 28 - 20
src/emit/mod.rs

@@ -171,7 +171,8 @@ pub struct Contract<'a> {
     builder: Builder<'a>,
     context: &'a Context,
     triple: TargetTriple,
-    ns: &'a resolver::Contract,
+    contract: &'a resolver::Contract,
+    ns: &'a resolver::Namespace,
     constructors: Vec<FunctionValue<'a>>,
     functions: Vec<FunctionValue<'a>>,
 }
@@ -289,7 +290,8 @@ impl<'a> Contract<'a> {
             builder: context.create_builder(),
             triple,
             context,
-            ns: contract,
+            contract,
+            ns,
             constructors: Vec::new(),
             functions: Vec::new(),
         }
@@ -518,9 +520,12 @@ impl<'a> Contract<'a> {
     fn emit_functions(&mut self, runtime: &dyn TargetRuntime) {
         let mut defines = Vec::new();
 
-        for resolver_func in &self.ns.functions {
+        for resolver_func in &self.contract.functions {
             let name = if resolver_func.name != "" {
-                format!("sol::function::{}", resolver_func.wasm_symbol(&self.ns))
+                format!(
+                    "sol::function::{}",
+                    resolver_func.wasm_symbol(self.contract, self.ns)
+                )
             } else {
                 "sol::fallback".to_owned()
             };
@@ -531,9 +536,12 @@ impl<'a> Contract<'a> {
             defines.push((func_decl, resolver_func));
         }
 
-        for resolver_func in &self.ns.constructors {
+        for resolver_func in &self.contract.constructors {
             let func_decl = self.declare_function(
-                &format!("sol::constructor{}", resolver_func.wasm_symbol(&self.ns)),
+                &format!(
+                    "sol::constructor{}",
+                    resolver_func.wasm_symbol(self.contract, self.ns)
+                ),
                 resolver_func,
             );
 
@@ -1764,7 +1772,7 @@ impl<'a> Contract<'a> {
                     "dest",
                 );
 
-                for (i, field) in self.ns.structs[*n].fields.iter().enumerate() {
+                for (i, field) in self.contract.structs[*n].fields.iter().enumerate() {
                     let val = self.storage_load(&field.ty, slot, slot_ptr, function, runtime);
 
                     let elem = unsafe {
@@ -1857,7 +1865,7 @@ impl<'a> Contract<'a> {
                             if !ty.is_reference_type() {
                                 *slot = self.builder.build_int_add(
                                     *slot,
-                                    self.number_literal(256, &ty.storage_slots(self.ns)),
+                                    self.number_literal(256, &ty.storage_slots(self.contract)),
                                     "",
                                 );
                             }
@@ -1968,7 +1976,7 @@ impl<'a> Contract<'a> {
                             if !ty.is_reference_type() {
                                 *slot = self.builder.build_int_add(
                                     *slot,
-                                    self.number_literal(256, &ty.storage_slots(self.ns)),
+                                    self.number_literal(256, &ty.storage_slots(self.contract)),
                                     "",
                                 );
                             }
@@ -1988,7 +1996,7 @@ impl<'a> Contract<'a> {
                             if !ty.is_reference_type() {
                                 *slot = self.builder.build_int_add(
                                     *slot,
-                                    self.number_literal(256, &ty.storage_slots(self.ns)),
+                                    self.number_literal(256, &ty.storage_slots(self.contract)),
                                     "",
                                 );
                             }
@@ -1997,7 +2005,7 @@ impl<'a> Contract<'a> {
                 }
             }
             resolver::Type::Struct(n) => {
-                for (i, field) in self.ns.structs[*n].fields.iter().enumerate() {
+                for (i, field) in self.contract.structs[*n].fields.iter().enumerate() {
                     let mut elem = unsafe {
                         self.builder.build_gep(
                             dest.into_pointer_value(),
@@ -2021,7 +2029,7 @@ impl<'a> Contract<'a> {
                     if !field.ty.is_reference_type() {
                         *slot = self.builder.build_int_add(
                             *slot,
-                            self.number_literal(256, &field.ty.storage_slots(self.ns)),
+                            self.number_literal(256, &field.ty.storage_slots(self.contract)),
                             &field.name,
                         );
                     }
@@ -2077,7 +2085,7 @@ impl<'a> Contract<'a> {
                             if !ty.is_reference_type() {
                                 *slot = self.builder.build_int_add(
                                     *slot,
-                                    self.number_literal(256, &ty.storage_slots(self.ns)),
+                                    self.number_literal(256, &ty.storage_slots(self.contract)),
                                     "",
                                 );
                             }
@@ -2120,7 +2128,7 @@ impl<'a> Contract<'a> {
                             if !ty.is_reference_type() {
                                 *slot = self.builder.build_int_add(
                                     *slot,
-                                    self.number_literal(256, &ty.storage_slots(self.ns)),
+                                    self.number_literal(256, &ty.storage_slots(self.contract)),
                                     "",
                                 );
                             }
@@ -2138,13 +2146,13 @@ impl<'a> Contract<'a> {
                 }
             }
             resolver::Type::Struct(n) => {
-                for (_, field) in self.ns.structs[*n].fields.iter().enumerate() {
+                for (_, field) in self.contract.structs[*n].fields.iter().enumerate() {
                     self.storage_clear(&field.ty, slot, slot_ptr, function, runtime);
 
                     if !field.ty.is_reference_type() {
                         *slot = self.builder.build_int_add(
                             *slot,
-                            self.number_literal(256, &field.ty.storage_slots(self.ns)),
+                            self.number_literal(256, &field.ty.storage_slots(self.contract)),
                             &field.name,
                         );
                     }
@@ -2169,7 +2177,7 @@ impl<'a> Contract<'a> {
             Some(Linkage::Internal),
         );
 
-        self.emit_cfg(&self.ns.initializer, None, function, runtime);
+        self.emit_cfg(&self.contract.initializer, None, function, runtime);
 
         function
     }
@@ -2355,7 +2363,7 @@ impl<'a> Contract<'a> {
                         self.expression(expr, &w.vars, function, runtime);
                     }
                     cfg::Instr::Constant { res, constant } => {
-                        let const_expr = &self.ns.constants[*constant];
+                        let const_expr = &self.contract.constants[*constant];
                         let value_ref = self.expression(const_expr, &w.vars, function, runtime);
                         if w.vars[*res].stack {
                             self.builder
@@ -2549,7 +2557,7 @@ impl<'a> Contract<'a> {
                     }
                     cfg::Instr::Call { res, func, args } => {
                         let mut parms: Vec<BasicValueEnum> = Vec::new();
-                        let f = &self.ns.functions[*func];
+                        let f = &self.contract.functions[*func];
 
                         for (i, a) in args.iter().enumerate() {
                             let ty = &f.params[i].ty;
@@ -3477,7 +3485,7 @@ impl<'a> Contract<'a> {
             resolver::Type::Struct(n) => self
                 .context
                 .struct_type(
-                    &self.ns.structs[*n]
+                    &self.contract.structs[*n]
                         .fields
                         .iter()
                         .map(|f| self.llvm_var(&f.ty))

+ 4 - 4
src/emit/sabre.rs

@@ -170,7 +170,7 @@ impl SabreTarget {
         // init our storage vars
         contract.builder.build_call(initializer, &[], "");
 
-        if let Some(con) = contract.ns.constructors.get(0) {
+        if let Some(con) = contract.contract.constructors.get(0) {
             let mut args = Vec::new();
 
             // insert abi decode
@@ -192,7 +192,7 @@ impl SabreTarget {
         let fallback_block = contract.context.append_basic_block(function, "fallback");
 
         contract.emit_function_dispatch(
-            &contract.ns.functions,
+            &contract.contract.functions,
             &contract.functions,
             argsdata,
             argslen,
@@ -204,7 +204,7 @@ impl SabreTarget {
         // emit fallback code
         contract.builder.position_at_end(fallback_block);
 
-        match contract.ns.fallback_function() {
+        match contract.contract.fallback_function() {
             Some(f) => {
                 contract.builder.build_call(contract.functions[f], &[], "");
 
@@ -598,7 +598,7 @@ impl TargetRuntime for SabreTarget {
         let length = contract.context.i32_type().const_int(
             spec.returns
                 .iter()
-                .map(|arg| self.abi.encoded_length(&arg.ty, contract.ns))
+                .map(|arg| self.abi.encoded_length(&arg.ty, contract.contract))
                 .sum(),
             false,
         );

+ 7 - 7
src/emit/substrate.rs

@@ -271,7 +271,7 @@ impl SubstrateTarget {
         let fallback_block = contract.context.append_basic_block(function, "fallback");
 
         contract.emit_function_dispatch(
-            &contract.ns.constructors,
+            &contract.contract.constructors,
             &contract.constructors,
             deploy_args,
             deploy_args_length,
@@ -300,7 +300,7 @@ impl SubstrateTarget {
         let fallback_block = contract.context.append_basic_block(function, "fallback");
 
         contract.emit_function_dispatch(
-            &contract.ns.functions,
+            &contract.contract.functions,
             &contract.functions,
             call_args,
             call_args_length,
@@ -312,7 +312,7 @@ impl SubstrateTarget {
         // emit fallback code
         contract.builder.position_at_end(fallback_block);
 
-        if let Some(fallback) = contract.ns.fallback_function() {
+        if let Some(fallback) = contract.contract.fallback_function() {
             contract
                 .builder
                 .build_call(contract.functions[fallback], &[], "");
@@ -478,7 +478,7 @@ impl SubstrateTarget {
                 let to =
                     to.unwrap_or_else(|| contract.builder.build_alloca(contract.llvm_type(ty), ""));
 
-                for (i, field) in contract.ns.structs[*n].fields.iter().enumerate() {
+                for (i, field) in contract.contract.structs[*n].fields.iter().enumerate() {
                     let elem = unsafe {
                         contract.builder.build_gep(
                             to,
@@ -909,7 +909,7 @@ impl SubstrateTarget {
                 }
             }
             resolver::Type::Struct(n) => {
-                for (i, field) in contract.ns.structs[*n].fields.iter().enumerate() {
+                for (i, field) in contract.contract.structs[*n].fields.iter().enumerate() {
                     let elem = unsafe {
                         contract.builder.build_gep(
                             arg.into_pointer_value(),
@@ -970,7 +970,7 @@ impl SubstrateTarget {
             resolver::Type::Struct(n) => {
                 let mut sum = contract.context.i32_type().const_zero();
 
-                for (i, field) in contract.ns.structs[*n].fields.iter().enumerate() {
+                for (i, field) in contract.contract.structs[*n].fields.iter().enumerate() {
                     let mut elem = unsafe {
                         contract.builder.build_gep(
                             arg.into_pointer_value(),
@@ -1023,7 +1023,7 @@ impl SubstrateTarget {
                 let elem_ty = ty.array_elem();
                 let llvm_elem_ty = contract.llvm_var(&elem_ty);
 
-                if elem_ty.is_dynamic(contract.ns) {
+                if elem_ty.is_dynamic(contract.contract) {
                     let mut sum = contract.context.i32_type().const_zero();
 
                     contract.emit_static_loop_with_int(

+ 1 - 1
src/lib.rs

@@ -73,7 +73,7 @@ pub fn compile(
         .contracts
         .iter()
         .map(|c| {
-            let (abistr, _) = abi::generate_abi(c, target, false);
+            let (abistr, _) = abi::generate_abi(c, &ns, false);
 
             // codegen
             let contract = emit::Contract::build(&ctx, c, &ns, filename, opt);

+ 5 - 0
src/resolver/builtin.rs

@@ -36,6 +36,7 @@ fn add_assert(contract: &mut Contract, ns: &Namespace) {
         }],
         vec![],
         &contract,
+        ns,
     );
 
     let mut errors = Vec::new();
@@ -109,6 +110,7 @@ fn add_print(contract: &mut Contract, ns: &Namespace) {
         }],
         vec![],
         &contract,
+        ns,
     );
 
     let mut errors = Vec::new();
@@ -177,6 +179,7 @@ fn add_require(contract: &mut Contract, ns: &Namespace) {
         ],
         vec![],
         &contract,
+        ns,
     );
 
     let mut errors = Vec::new();
@@ -267,6 +270,7 @@ fn add_revert(contract: &mut Contract, ns: &Namespace) {
         }],
         vec![],
         &contract,
+        ns,
     );
 
     let mut errors = Vec::new();
@@ -313,6 +317,7 @@ fn add_revert(contract: &mut Contract, ns: &Namespace) {
         vec![],
         vec![],
         &contract,
+        ns,
     );
 
     let mut errors = Vec::new();

+ 158 - 121
src/resolver/cfg.rs

@@ -145,7 +145,12 @@ impl ControlFlowGraph {
         self.bb[self.current].add(ins);
     }
 
-    pub fn expr_to_string(&self, ns: &resolver::Contract, expr: &Expression) -> String {
+    pub fn expr_to_string(
+        &self,
+        contract: &resolver::Contract,
+        ns: &resolver::Namespace,
+        expr: &Expression,
+    ) -> String {
         match expr {
             Expression::BoolLiteral(_, false) => "false".to_string(),
             Expression::BoolLiteral(_, true) => "true".to_string(),
@@ -154,7 +159,7 @@ impl ControlFlowGraph {
             Expression::StructLiteral(_, _, expr) => format!(
                 "struct {{ {} }}",
                 expr.iter()
-                    .map(|e| self.expr_to_string(ns, e))
+                    .map(|e| self.expr_to_string(contract, ns, e))
                     .collect::<Vec<String>>()
                     .join(", ")
             ),
@@ -163,7 +168,7 @@ impl ControlFlowGraph {
                 dims.iter().map(|d| format!("[{}]", d)).collect::<String>(),
                 exprs
                     .iter()
-                    .map(|e| self.expr_to_string(ns, e))
+                    .map(|e| self.expr_to_string(contract, ns, e))
                     .collect::<Vec<String>>()
                     .join(", ")
             ),
@@ -172,223 +177,238 @@ impl ControlFlowGraph {
                 dims.iter().map(|d| format!("[{}]", d)).collect::<String>(),
                 exprs
                     .iter()
-                    .map(|e| self.expr_to_string(ns, e))
+                    .map(|e| self.expr_to_string(contract, ns, e))
                     .collect::<Vec<String>>()
                     .join(", ")
             ),
             Expression::Add(_, l, r) => format!(
                 "({} + {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::Subtract(_, l, r) => format!(
                 "({} - {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::BitwiseOr(_, l, r) => format!(
                 "({} | {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::BitwiseAnd(_, l, r) => format!(
                 "({} & {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::BitwiseXor(_, l, r) => format!(
                 "({} ^ {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::ShiftLeft(_, l, r) => format!(
                 "({} << {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::ShiftRight(_, l, r, _) => format!(
                 "({} >> {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::Multiply(_, l, r) => format!(
                 "({} * {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::UDivide(_, l, r) | Expression::SDivide(_, l, r) => format!(
                 "({} / {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::UModulo(_, l, r) | Expression::SModulo(_, l, r) => format!(
                 "({} % {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::Power(_, l, r) => format!(
                 "({} ** {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::Variable(_, res) => format!("%{}", self.vars[*res].id.name),
-            Expression::Load(_, expr) => format!("(load {})", self.expr_to_string(ns, expr)),
+            Expression::Load(_, expr) => {
+                format!("(load {})", self.expr_to_string(contract, ns, expr))
+            }
             Expression::StorageLoad(_, ty, expr) => format!(
                 "({} storage[{}])",
-                ty.to_string(ns),
-                self.expr_to_string(ns, expr)
+                ty.to_string(contract, ns),
+                self.expr_to_string(contract, ns, expr)
+            ),
+            Expression::ZeroExt(_, ty, e) => format!(
+                "(zext {} {})",
+                ty.to_string(contract, ns),
+                self.expr_to_string(contract, ns, e)
+            ),
+            Expression::SignExt(_, ty, e) => format!(
+                "(sext {} {})",
+                ty.to_string(contract, ns),
+                self.expr_to_string(contract, ns, e)
             ),
-            Expression::ZeroExt(_, ty, e) => {
-                format!("(zext {} {})", ty.to_string(ns), self.expr_to_string(ns, e))
-            }
-            Expression::SignExt(_, ty, e) => {
-                format!("(sext {} {})", ty.to_string(ns), self.expr_to_string(ns, e))
-            }
             Expression::Trunc(_, ty, e) => format!(
                 "(trunc {} {})",
-                ty.to_string(ns),
-                self.expr_to_string(ns, e)
+                ty.to_string(contract, ns),
+                self.expr_to_string(contract, ns, e)
             ),
             Expression::SMore(_, l, r) => format!(
                 "({} >(s) {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::SLess(_, l, r) => format!(
                 "({} <(s) {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::SMoreEqual(_, l, r) => format!(
                 "({} >=(s) {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::SLessEqual(_, l, r) => format!(
                 "({} <=(s) {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::UMore(_, l, r) => format!(
                 "({} >(u) {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::ULess(_, l, r) => format!(
                 "({} <(u) {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::UMoreEqual(_, l, r) => format!(
                 "({} >=(u) {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::ULessEqual(_, l, r) => format!(
                 "({} <=(u) {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::Equal(_, l, r) => format!(
                 "({} == {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::NotEqual(_, l, r) => format!(
                 "({} != {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::ArraySubscript(_, a, i) => format!(
                 "(array index {}[{}])",
-                self.expr_to_string(ns, a),
-                self.expr_to_string(ns, i)
+                self.expr_to_string(contract, ns, a),
+                self.expr_to_string(contract, ns, i)
             ),
             Expression::DynamicArraySubscript(_, a, _, i) => format!(
                 "(darray index {}[{}])",
-                self.expr_to_string(ns, a),
-                self.expr_to_string(ns, i)
+                self.expr_to_string(contract, ns, a),
+                self.expr_to_string(contract, ns, i)
             ),
             Expression::StorageBytesSubscript(_, a, i) => format!(
                 "(storage bytes index {}[{}])",
-                self.expr_to_string(ns, a),
-                self.expr_to_string(ns, i)
+                self.expr_to_string(contract, ns, a),
+                self.expr_to_string(contract, ns, i)
             ),
             Expression::StorageBytesPush(_, a, i) => format!(
                 "(storage bytes push {} {})",
-                self.expr_to_string(ns, a),
-                self.expr_to_string(ns, i)
+                self.expr_to_string(contract, ns, a),
+                self.expr_to_string(contract, ns, i)
+            ),
+            Expression::StorageBytesPop(_, a) => format!(
+                "(storage bytes pop {})",
+                self.expr_to_string(contract, ns, a),
+            ),
+            Expression::StorageBytesLength(_, a) => format!(
+                "(storage bytes length {})",
+                self.expr_to_string(contract, ns, a),
+            ),
+            Expression::StructMember(_, a, f) => format!(
+                "(struct {} field {})",
+                self.expr_to_string(contract, ns, a),
+                f
             ),
-            Expression::StorageBytesPop(_, a) => {
-                format!("(storage bytes pop {})", self.expr_to_string(ns, a),)
-            }
-            Expression::StorageBytesLength(_, a) => {
-                format!("(storage bytes length {})", self.expr_to_string(ns, a),)
-            }
-            Expression::StructMember(_, a, f) => {
-                format!("(struct {} field {})", self.expr_to_string(ns, a), f)
-            }
             Expression::Or(_, l, r) => format!(
                 "({} || {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::And(_, l, r) => format!(
                 "({} && {})",
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
             Expression::Ternary(_, c, l, r) => format!(
                 "({} ? {} : {})",
-                self.expr_to_string(ns, c),
-                self.expr_to_string(ns, l),
-                self.expr_to_string(ns, r)
+                self.expr_to_string(contract, ns, c),
+                self.expr_to_string(contract, ns, l),
+                self.expr_to_string(contract, ns, r)
             ),
-            Expression::Not(_, e) => format!("!{}", self.expr_to_string(ns, e)),
-            Expression::Complement(_, e) => format!("~{}", self.expr_to_string(ns, e)),
-            Expression::UnaryMinus(_, e) => format!("-{}", self.expr_to_string(ns, e)),
+            Expression::Not(_, e) => format!("!{}", self.expr_to_string(contract, ns, e)),
+            Expression::Complement(_, e) => format!("~{}", self.expr_to_string(contract, ns, e)),
+            Expression::UnaryMinus(_, e) => format!("-{}", self.expr_to_string(contract, ns, e)),
             Expression::Poison => "☠".to_string(),
             Expression::AllocDynamicArray(_, ty, size, None) => format!(
                 "(alloc {} len {})",
-                ty.to_string(ns),
-                self.expr_to_string(ns, size)
+                ty.to_string(contract, ns),
+                self.expr_to_string(contract, ns, size)
             ),
             Expression::AllocDynamicArray(_, ty, size, Some(init)) => format!(
                 "(alloc {} {} {})",
-                ty.to_string(ns),
-                self.expr_to_string(ns, size),
+                ty.to_string(contract, ns),
+                self.expr_to_string(contract, ns, size),
                 match str::from_utf8(init) {
                     Ok(s) => format!("\"{}\"", s.to_owned()),
                     Err(_) => format!("hex\"{}\"", hex::encode(init)),
                 }
             ),
             Expression::DynamicArrayLength(_, a) => {
-                format!("(array {} len)", self.expr_to_string(ns, a))
+                format!("(array {} len)", self.expr_to_string(contract, ns, a))
             }
             Expression::StringCompare(_, l, r) => format!(
                 "(strcmp ({}) ({}))",
-                self.location_to_string(ns, l),
-                self.location_to_string(ns, r)
+                self.location_to_string(contract, ns, l),
+                self.location_to_string(contract, ns, r)
             ),
             Expression::StringConcat(_, l, r) => format!(
                 "(concat ({}) ({}))",
-                self.location_to_string(ns, l),
-                self.location_to_string(ns, r)
+                self.location_to_string(contract, ns, l),
+                self.location_to_string(contract, ns, r)
             ),
             Expression::Keccak256(_, exprs) => format!(
                 "(keccak256 {})",
                 exprs
                     .iter()
-                    .map(|e| self.expr_to_string(ns, &e.0))
+                    .map(|e| self.expr_to_string(contract, ns, &e.0))
                     .collect::<Vec<String>>()
                     .join(", ")
             ),
         }
     }
 
-    fn location_to_string(&self, ns: &resolver::Contract, l: &StringLocation) -> String {
+    fn location_to_string(
+        &self,
+        contract: &resolver::Contract,
+        ns: &resolver::Namespace,
+        l: &StringLocation,
+    ) -> String {
         match l {
-            StringLocation::RunTime(e) => self.expr_to_string(ns, e),
+            StringLocation::RunTime(e) => self.expr_to_string(contract, ns, e),
             StringLocation::CompileTime(literal) => match str::from_utf8(literal) {
                 Ok(s) => format!("\"{}\"", s.to_owned()),
                 Err(_) => format!("hex\"{}\"", hex::encode(literal)),
@@ -396,7 +416,12 @@ impl ControlFlowGraph {
         }
     }
 
-    pub fn instr_to_string(&self, ns: &resolver::Contract, instr: &Instr) -> String {
+    pub fn instr_to_string(
+        &self,
+        contract: &resolver::Contract,
+        ns: &resolver::Namespace,
+        instr: &Instr,
+    ) -> String {
         match instr {
             Instr::Return { value } => {
                 let mut s = String::from("return ");
@@ -407,22 +432,22 @@ impl ControlFlowGraph {
                         s.push_str(", ");
                     }
                     first = false;
-                    s.push_str(&self.expr_to_string(ns, arg));
+                    s.push_str(&self.expr_to_string(contract, ns, arg));
                 }
 
                 s
             }
             Instr::Set { res, expr } => format!(
                 "ty:{} %{} = {}",
-                self.vars[*res].ty.to_string(ns),
+                self.vars[*res].ty.to_string(contract, ns),
                 self.vars[*res].id.name,
-                self.expr_to_string(ns, expr)
+                self.expr_to_string(contract, ns, expr)
             ),
-            Instr::Eval { expr } => format!("_ = {}", self.expr_to_string(ns, expr)),
+            Instr::Eval { expr } => format!("_ = {}", self.expr_to_string(contract, ns, expr)),
             Instr::Constant { res, constant } => format!(
                 "%{} = const {}",
                 self.vars[*res].id.name,
-                self.expr_to_string(ns, &ns.constants[*constant])
+                self.expr_to_string(contract, ns, &contract.constants[*constant])
             ),
             Instr::Branch { bb } => format!("branch bb{}", bb),
             Instr::BranchCond {
@@ -431,7 +456,7 @@ impl ControlFlowGraph {
                 false_,
             } => format!(
                 "branchcond {}, bb{}, bb{}",
-                self.expr_to_string(ns, cond),
+                self.expr_to_string(contract, ns, cond),
                 true_,
                 false_
             ),
@@ -440,13 +465,13 @@ impl ControlFlowGraph {
             }
             Instr::ClearStorage { ty, storage } => format!(
                 "clear storage slot({}) ty:{}",
-                self.expr_to_string(ns, storage),
-                ty.to_string(ns),
+                self.expr_to_string(contract, ns, storage),
+                ty.to_string(contract, ns),
             ),
             Instr::SetStorage { ty, local, storage } => format!(
                 "set storage slot({}) ty:{} = %{}",
-                self.expr_to_string(ns, storage),
-                ty.to_string(ns),
+                self.expr_to_string(contract, ns, storage),
+                ty.to_string(contract, ns),
                 self.vars[*local].id.name
             ),
             Instr::SetStorageBytes {
@@ -455,13 +480,13 @@ impl ControlFlowGraph {
                 offset,
             } => format!(
                 "set storage slot({}) offset:{} = %{}",
-                self.expr_to_string(ns, storage),
-                self.expr_to_string(ns, offset),
+                self.expr_to_string(contract, ns, storage),
+                self.expr_to_string(contract, ns, offset),
                 self.vars[*local].id.name
             ),
             Instr::AssertFailure { expr: None } => "assert-failure".to_string(),
             Instr::AssertFailure { expr: Some(expr) } => {
-                format!("assert-failure:{}", self.expr_to_string(ns, expr))
+                format!("assert-failure:{}", self.expr_to_string(contract, ns, expr))
             }
             Instr::Call { res, func, args } => format!(
                 "{} = call {} {} {}",
@@ -474,11 +499,11 @@ impl ControlFlowGraph {
                     s.join(", ")
                 },
                 *func,
-                ns.functions[*func].name.to_owned(),
+                contract.functions[*func].name.to_owned(),
                 {
                     let s: Vec<String> = args
                         .iter()
-                        .map(|expr| self.expr_to_string(ns, expr))
+                        .map(|expr| self.expr_to_string(contract, ns, expr))
                         .collect();
 
                     s.join(", ")
@@ -486,14 +511,19 @@ impl ControlFlowGraph {
             ),
             Instr::Store { dest, pos } => format!(
                 "store {}, {}",
-                self.expr_to_string(ns, dest),
+                self.expr_to_string(contract, ns, dest),
                 self.vars[*pos].id.name
             ),
-            Instr::Print { expr } => format!("print {}", self.expr_to_string(ns, expr)),
+            Instr::Print { expr } => format!("print {}", self.expr_to_string(contract, ns, expr)),
         }
     }
 
-    pub fn basic_block_to_string(&self, ns: &resolver::Contract, pos: usize) -> String {
+    pub fn basic_block_to_string(
+        &self,
+        contract: &resolver::Contract,
+        ns: &resolver::Namespace,
+        pos: usize,
+    ) -> String {
         let mut s = format!("bb{}: # {}\n", pos, self.bb[pos].name);
 
         if let Some(ref phis) = self.bb[pos].phis {
@@ -510,17 +540,17 @@ impl ControlFlowGraph {
         }
 
         for ins in &self.bb[pos].instr {
-            s.push_str(&format!("\t{}\n", self.instr_to_string(ns, ins)));
+            s.push_str(&format!("\t{}\n", self.instr_to_string(contract, ns, ins)));
         }
 
         s
     }
 
-    pub fn to_string(&self, ns: &resolver::Contract) -> String {
+    pub fn to_string(&self, contract: &resolver::Contract, ns: &resolver::Namespace) -> String {
         let mut s = String::from("");
 
         for i in 0..self.bb.len() {
-            s.push_str(&self.basic_block_to_string(ns, i));
+            s.push_str(&self.basic_block_to_string(contract, ns, i));
         }
 
         s
@@ -566,7 +596,7 @@ pub fn generate_cfg(
                         &mut vartab,
                         Instr::Set {
                             res: pos,
-                            expr: resolve_f.returns[i].ty.default(contract),
+                            expr: resolve_f.returns[i].ty.default(ns),
                         },
                     );
 
@@ -590,7 +620,7 @@ pub fn generate_cfg(
                     &mut vartab,
                     Instr::Set {
                         res: pos,
-                        expr: resolve_f.returns[i].ty.default(contract),
+                        expr: resolve_f.returns[i].ty.default(ns),
                     },
                 );
 
@@ -723,6 +753,7 @@ fn statement(
                     &var_ty,
                     true,
                     contract,
+                    ns,
                     errors,
                 )?)
             } else {
@@ -830,6 +861,7 @@ fn statement(
                     &f.returns[i].ty,
                     true,
                     contract,
+                    ns,
                     errors,
                 )?);
             }
@@ -924,6 +956,7 @@ fn statement(
                             &resolver::Type::Bool,
                             true,
                             contract,
+                            ns,
                             errors,
                         )?,
                         true_: body,
@@ -963,6 +996,7 @@ fn statement(
                         &resolver::Type::Bool,
                         true,
                         contract,
+                        ns,
                         errors,
                     )?,
                     true_: body,
@@ -1086,6 +1120,7 @@ fn statement(
                         &resolver::Type::Bool,
                         true,
                         contract,
+                        ns,
                         errors,
                     )?,
                     true_: body,
@@ -1180,6 +1215,7 @@ fn if_then(
                 &resolver::Type::Bool,
                 true,
                 contract,
+                ns,
                 errors,
             )?,
             true_: then,
@@ -1235,6 +1271,7 @@ fn if_then_else(
                 &resolver::Type::Bool,
                 true,
                 contract,
+                ns,
                 errors,
             )?,
             true_: then,
@@ -1520,7 +1557,7 @@ impl LoopScopes {
 }
 
 impl resolver::Type {
-    fn default(&self, ns: &resolver::Contract) -> Expression {
+    fn default(&self, ns: &resolver::Namespace) -> Expression {
         match self {
             resolver::Type::Uint(b) | resolver::Type::Int(b) => {
                 Expression::NumberLiteral(ast::Loc(0, 0), *b, BigInt::from(0))

文件差异内容过多而无法显示
+ 155 - 70
src/resolver/expression.rs


+ 4 - 2
src/resolver/functions.rs

@@ -227,6 +227,7 @@ pub fn function_decl(
         params,
         returns,
         &contract,
+        ns,
     );
 
     if f.constructor {
@@ -350,10 +351,10 @@ pub fn function_decl(
 fn signatures() {
     use super::*;
 
-    let ns = Contract {
+    let ns = Namespace::new(Target::Ewasm);
+    let contract = Contract {
         doc: vec![],
         name: String::from("foo"),
-        enums: Vec::new(),
         structs: Vec::new(),
         constructors: Vec::new(),
         functions: Vec::new(),
@@ -383,6 +384,7 @@ fn signatures() {
             },
         ],
         Vec::new(),
+        &contract,
         &ns,
     );
 

+ 63 - 47
src/resolver/mod.rs

@@ -6,7 +6,6 @@ use num_traits::{One, Zero};
 use output::{Note, Output};
 use parser::ast;
 use std::collections::HashMap;
-use std::fmt;
 use std::ops::Mul;
 use tiny_keccak::keccak256;
 use Target;
@@ -47,7 +46,7 @@ pub enum Type {
 }
 
 impl Type {
-    pub fn to_string(&self, ns: &Contract) -> String {
+    pub fn to_string(&self, contract: &Contract, ns: &Namespace) -> String {
         match self {
             Type::Bool => "bool".to_string(),
             Type::Address => "address".to_string(),
@@ -56,11 +55,11 @@ impl Type {
             Type::Bytes(n) => format!("bytes{}", n),
             Type::String => "string".to_string(),
             Type::DynamicBytes => "bytes".to_string(),
-            Type::Enum(n) => format!("enum {}.{}", ns.name, ns.enums[*n].name),
-            Type::Struct(n) => format!("struct {}.{}", ns.name, ns.structs[*n].name),
+            Type::Enum(n) => format!("enum {}", ns.enums[*n].print_to_string()),
+            Type::Struct(n) => format!("struct {}.{}", contract.name, contract.structs[*n].name),
             Type::Array(ty, len) => format!(
                 "{}{}",
-                ty.to_string(ns),
+                ty.to_string(contract, ns),
                 len.iter()
                     .map(|l| match l {
                         None => "[]".to_string(),
@@ -68,9 +67,13 @@ impl Type {
                     })
                     .collect::<String>()
             ),
-            Type::Mapping(k, v) => format!("mapping({} => {})", k.to_string(ns), v.to_string(ns)),
-            Type::Ref(r) => r.to_string(ns),
-            Type::StorageRef(ty) => format!("storage {}", ty.to_string(ns)),
+            Type::Mapping(k, v) => format!(
+                "mapping({} => {})",
+                k.to_string(contract, ns),
+                v.to_string(contract, ns)
+            ),
+            Type::Ref(r) => r.to_string(contract, ns),
+            Type::StorageRef(ty) => format!("storage {}", ty.to_string(contract, ns)),
             Type::Undef => "undefined".to_owned(),
         }
     }
@@ -89,7 +92,7 @@ impl Type {
         }
     }
 
-    pub fn to_signature_string(&self, ns: &Contract) -> String {
+    pub fn to_signature_string(&self, contract: &Contract, ns: &Namespace) -> String {
         match self {
             Type::Bool => "bool".to_string(),
             Type::Address => "address".to_string(),
@@ -98,10 +101,10 @@ impl Type {
             Type::Bytes(n) => format!("bytes{}", n),
             Type::DynamicBytes => "bytes".to_string(),
             Type::String => "string".to_string(),
-            Type::Enum(n) => ns.enums[*n].ty.to_signature_string(ns),
+            Type::Enum(n) => ns.enums[*n].ty.to_signature_string(contract, ns),
             Type::Array(ty, len) => format!(
                 "{}{}",
-                ty.to_signature_string(ns),
+                ty.to_signature_string(contract, ns),
                 len.iter()
                     .map(|l| match l {
                         None => "[]".to_string(),
@@ -109,8 +112,8 @@ impl Type {
                     })
                     .collect::<String>()
             ),
-            Type::Ref(r) => r.to_string(ns),
-            Type::StorageRef(r) => r.to_string(ns),
+            Type::Ref(r) => r.to_string(contract, ns),
+            Type::StorageRef(r) => r.to_string(contract, ns),
             Type::Struct(_) => "tuple".to_owned(),
             Type::Mapping(_, _) => unreachable!(),
             Type::Undef => "undefined".to_owned(),
@@ -373,10 +376,22 @@ pub struct StructDecl {
 
 pub struct EnumDecl {
     pub name: String,
+    pub contract: Option<String>,
     pub ty: Type,
     pub values: HashMap<String, (ast::Loc, usize)>,
 }
 
+impl EnumDecl {
+    /// Make the enum name into a string for printing. The enum can be declared either
+    /// inside or outside a contract.
+    pub fn print_to_string(&self) -> String {
+        match &self.contract {
+            Some(c) => format!("{}.{}", c, self.name),
+            None => self.name.to_owned(),
+        }
+    }
+}
+
 pub struct Parameter {
     pub name: String,
     pub ty: Type,
@@ -407,14 +422,15 @@ impl FunctionDecl {
         visibility: ast::Visibility,
         params: Vec<Parameter>,
         returns: Vec<Parameter>,
-        ns: &Contract,
+        contract: &Contract,
+        ns: &Namespace,
     ) -> Self {
         let signature = format!(
             "{}({})",
             name,
             params
                 .iter()
-                .map(|p| p.ty.to_signature_string(ns))
+                .map(|p| p.ty.to_signature_string(contract, ns))
                 .collect::<Vec<String>>()
                 .join(",")
         );
@@ -442,7 +458,7 @@ impl FunctionDecl {
     }
 
     /// Return a unique string for this function which is a valid wasm symbol
-    pub fn wasm_symbol(&self, ns: &Contract) -> String {
+    pub fn wasm_symbol(&self, contract: &Contract, ns: &Namespace) -> String {
         let mut sig = self.name.to_owned();
 
         if !self.params.is_empty() {
@@ -453,7 +469,7 @@ impl FunctionDecl {
                     sig.push('_');
                 }
 
-                fn type_to_wasm_name(ty: &Type, ns: &Contract) -> String {
+                fn type_to_wasm_name(ty: &Type, contract: &Contract, ns: &Namespace) -> String {
                     match ty {
                         Type::Bool => "bool".to_string(),
                         Type::Address => "address".to_string(),
@@ -462,11 +478,11 @@ impl FunctionDecl {
                         Type::Bytes(n) => format!("bytes{}", n),
                         Type::DynamicBytes => "bytes".to_string(),
                         Type::String => "string".to_string(),
-                        Type::Enum(i) => ns.enums[*i].name.to_owned(),
-                        Type::Struct(i) => ns.structs[*i].name.to_owned(),
+                        Type::Enum(i) => ns.enums[*i].print_to_string(),
+                        Type::Struct(i) => contract.structs[*i].name.to_owned(),
                         Type::Array(ty, len) => format!(
                             "{}{}",
-                            ty.to_string(ns),
+                            ty.to_string(contract, ns),
                             len.iter()
                                 .map(|r| match r {
                                     None => ":".to_string(),
@@ -476,16 +492,16 @@ impl FunctionDecl {
                         ),
                         Type::Mapping(k, v) => format!(
                             "mapping:{}:{}",
-                            type_to_wasm_name(k, ns),
-                            type_to_wasm_name(v, ns)
+                            type_to_wasm_name(k, contract, ns),
+                            type_to_wasm_name(v, contract, ns)
                         ),
                         Type::Undef => unreachable!(),
-                        Type::Ref(r) => type_to_wasm_name(r, ns),
-                        Type::StorageRef(r) => type_to_wasm_name(r, ns),
+                        Type::Ref(r) => type_to_wasm_name(r, contract, ns),
+                        Type::StorageRef(r) => type_to_wasm_name(r, contract, ns),
                     }
                 }
 
-                sig.push_str(&type_to_wasm_name(&p.ty, ns));
+                sig.push_str(&type_to_wasm_name(&p.ty, contract, ns));
             }
         }
 
@@ -541,6 +557,7 @@ pub enum Symbol {
 /// When resolving a Solidity file, this holds all the resolved items
 pub struct Namespace {
     pub target: Target,
+    pub enums: Vec<EnumDecl>,
     pub contracts: Vec<Contract>,
     symbols: HashMap<String, Symbol>,
 }
@@ -549,6 +566,7 @@ impl Namespace {
     pub fn new(target: Target) -> Self {
         Namespace {
             target,
+            enums: Vec::new(),
             contracts: Vec::new(),
             symbols: HashMap::new(),
         }
@@ -588,7 +606,6 @@ impl Namespace {
 pub struct Contract {
     pub doc: Vec<String>,
     pub name: String,
-    pub enums: Vec<EnumDecl>,
     // events
     pub structs: Vec<StructDecl>,
     pub constructors: Vec<FunctionDecl>,
@@ -1016,8 +1033,8 @@ impl Contract {
         None
     }
 
-    pub fn abi(&self, target: Target, verbose: bool) -> (String, &'static str) {
-        abi::generate_abi(self, target, verbose)
+    pub fn abi(&self, ns: &Namespace, verbose: bool) -> (String, &'static str) {
+        abi::generate_abi(self, ns, verbose)
     }
 
     pub fn emit<'a>(
@@ -1029,36 +1046,35 @@ impl Contract {
     ) -> emit::Contract {
         emit::Contract::build(context, self, ns, filename, opt)
     }
-}
 
-impl fmt::Display for Contract {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "#\n# Contract: {}\n#\n\n", self.name)?;
+    /// Print the entire contract; storage initializers, constructors and functions and their CFGs
+    pub fn print_to_string(&self, ns: &Namespace) -> String {
+        let mut out = format!("#\n# Contract: {}\n#\n\n", self.name);
 
-        writeln!(f, "# storage initializer")?;
-        writeln!(f, "{}", &self.initializer.to_string(self))?;
+        out += "# storage initializer\n";
+        out += &self.initializer.to_string(self, ns);
 
         for func in &self.constructors {
-            writeln!(f, "# constructor {}", func.signature)?;
+            out += &format!("# constructor {}\n", func.signature);
 
             if let Some(ref cfg) = func.cfg {
-                write!(f, "{}", &cfg.to_string(self))?;
+                out += &cfg.to_string(self, ns);
             }
         }
 
         for (i, func) in self.functions.iter().enumerate() {
             if func.name != "" {
-                writeln!(f, "# function({}) {}", i, func.signature)?;
+                out += &format!("# function({}) {}", i, func.signature);
             } else {
-                writeln!(f, "# fallback({})", i)?;
+                out += &format!("# fallback({})", i);
             }
 
             if let Some(ref cfg) = func.cfg {
-                writeln!(f, "{}", &cfg.to_string(self))?;
+                out += &cfg.to_string(self, ns);
             }
         }
 
-        Ok(())
+        out
     }
 }
 
@@ -1105,7 +1121,6 @@ fn resolve_contract(
     let mut contract = Contract {
         name: def.name.name.to_string(),
         doc: def.doc.clone(),
-        enums: Vec::new(),
         structs: Vec::new(),
         constructors: Vec::new(),
         functions: Vec::new(),
@@ -1188,6 +1203,7 @@ fn resolve_contract(
             Vec::new(),
             Vec::new(),
             &contract,
+            ns,
         );
 
         let mut vartab = Vartable::new();
@@ -1323,13 +1339,14 @@ fn enum_decl(
 
     let decl = EnumDecl {
         name: enum_.name.name.to_string(),
+        contract: Some(contract.name.to_owned()),
         ty: Type::Uint(bits as u16),
         values: entries,
     };
 
-    let pos = contract.enums.len();
+    let pos = ns.enums.len();
 
-    contract.enums.push(decl);
+    ns.enums.push(decl);
 
     if !contract.add_symbol(&enum_.name, Symbol::Enum(enum_.name.loc, pos), ns, errors) {
         valid = false;
@@ -1354,7 +1371,6 @@ fn enum_256values_is_uint8() {
     let mut contract = Contract {
         name: "foo".to_string(),
         doc: Vec::new(),
-        enums: Vec::new(),
         structs: Vec::new(),
         constructors: Vec::new(),
         functions: Vec::new(),
@@ -1371,7 +1387,7 @@ fn enum_256values_is_uint8() {
     });
 
     assert!(enum_decl(&e, &mut contract, &mut ns, &mut Vec::new()));
-    assert_eq!(contract.enums.last().unwrap().ty, Type::Uint(8));
+    assert_eq!(ns.enums.last().unwrap().ty, Type::Uint(8));
 
     for i in 1..256 {
         e.values.push(ast::Identifier {
@@ -1384,7 +1400,7 @@ fn enum_256values_is_uint8() {
 
     e.name.name = "foo2".to_owned();
     assert!(enum_decl(&e, &mut contract, &mut ns, &mut Vec::new()));
-    assert_eq!(contract.enums.last().unwrap().ty, Type::Uint(8));
+    assert_eq!(ns.enums.last().unwrap().ty, Type::Uint(8));
 
     e.values.push(ast::Identifier {
         loc: ast::Loc(0, 0),
@@ -1393,5 +1409,5 @@ fn enum_256values_is_uint8() {
 
     e.name.name = "foo3".to_owned();
     assert!(enum_decl(&e, &mut contract, &mut ns, &mut Vec::new()));
-    assert_eq!(contract.enums.last().unwrap().ty, Type::Uint(16));
+    assert_eq!(ns.enums.last().unwrap().ty, Type::Uint(16));
 }

+ 4 - 1
src/resolver/storage.rs

@@ -183,6 +183,7 @@ pub fn array_push(
                     &elem_ty.deref(),
                     true,
                     contract,
+                    ns,
                     errors,
                 )?,
             },
@@ -399,6 +400,7 @@ pub fn bytes_push(
                 &resolver::Type::Bytes(1),
                 true,
                 contract,
+                ns,
                 errors,
             )?
         }
@@ -475,13 +477,14 @@ pub fn mapping_subscript(
         key_ty,
         true,
         contract,
+        ns,
         errors,
     )?;
 
     let slot_ty = resolver::Type::Uint(256);
 
     let index_ty = if let resolver::Type::Enum(n) = index_ty {
-        contract.enums[n].ty.clone()
+        ns.enums[n].ty.clone()
     } else {
         index_ty
     };

+ 1 - 1
src/resolver/variables.rs

@@ -110,7 +110,7 @@ fn var_decl(
         };
 
         // implicityly conversion to correct ty
-        let res = match cast(&s.loc, res, &resty, &ty, true, &contract, errors) {
+        let res = match cast(&s.loc, res, &resty, &ty, true, &contract, ns, errors) {
             Ok(res) => res,
             Err(_) => return false,
         };

部分文件因为文件数量过多而无法显示