From e34f93bfc06dbebd1b90cdb599f829047ed037db Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Fri, 29 Oct 2021 10:58:21 -1000 Subject: [PATCH 01/25] first commit --- Cargo.lock | 1 + core_lang/Cargo.toml | 1 + forc/src/abi_spec/type_info.rs | 7 +++++++ 3 files changed, 9 insertions(+) create mode 100644 forc/src/abi_spec/type_info.rs diff --git a/Cargo.lock b/Cargo.lock index 52576e78b03..02238f8388c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -771,6 +771,7 @@ dependencies = [ "either", "fuel-asm", "fuel-vm", + "fuels-rs", "hex", "line-col", "pest 2.1.3 (git+https://github.com/sezna/pest.git?rev=8aa58791f759daf4caee26e8560e862df5a6afb7)", diff --git a/core_lang/Cargo.toml b/core_lang/Cargo.toml index 2eeecd163ae..839a40fd13d 100644 --- a/core_lang/Cargo.toml +++ b/core_lang/Cargo.toml @@ -24,6 +24,7 @@ thiserror = "1.0" uuid-b64 = "0.1" line-col = "0.2" source-span = "2.4" +fuels-rs = {path = "../fuels-rs"} [[bin]] name = "selector-debug" diff --git a/forc/src/abi_spec/type_info.rs b/forc/src/abi_spec/type_info.rs new file mode 100644 index 00000000000..204aafdb4ac --- /dev/null +++ b/forc/src/abi_spec/type_info.rs @@ -0,0 +1,7 @@ +use core_lang::{CompileResult, TypeInfo}; + +use serde_json::Value; + +pub fn generate_abi_spec<'sc>(typ: TypeInfo<'sc>) -> CompileResult<'sc, Value> { + unimplemented!() +} \ No newline at end of file From c24ea42f151b669efc37aa37d16079017bfc720c Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Fri, 29 Oct 2021 11:37:58 -1000 Subject: [PATCH 02/25] Pass around a JsonABI object. --- core_lang/src/lib.rs | 5 ++ .../semantic_analysis/ast_node/code_block.rs | 4 ++ .../semantic_analysis/ast_node/declaration.rs | 5 +- .../ast_node/expression/enum_instantiation.rs | 6 +- .../ast_node/expression/typed_expression.rs | 61 +++++++++++++++---- .../typed_expression/method_application.rs | 6 +- .../semantic_analysis/ast_node/impl_trait.rs | 16 +++-- .../src/semantic_analysis/ast_node/mod.rs | 50 ++++++++++----- .../src/semantic_analysis/syntax_tree.rs | 9 ++- 9 files changed, 126 insertions(+), 36 deletions(-) diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index 4ed853fee5d..ce59f0ff4f9 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -234,6 +234,7 @@ pub(crate) fn compile_inner_dependency<'sc>( &build_config.clone(), dead_code_graph, dependency_graph, + &vec![], ) .ok(&mut warnings, &mut errors) .map(|value| (name, value)) @@ -295,6 +296,8 @@ pub fn compile_to_asm<'sc>( namespace: Default::default(), }; + let mut json_abi = vec![]; + let mut type_check_ast = |ast: Option<_>, tree_type| { ast.map(|tree| { TypedParseTree::type_check( @@ -304,6 +307,7 @@ pub fn compile_to_asm<'sc>( &build_config.clone(), &mut dead_code_graph, dependency_graph, + &mut json_abi, ) .ok(&mut warnings, &mut errors) }) @@ -326,6 +330,7 @@ pub fn compile_to_asm<'sc>( &build_config.clone(), &mut dead_code_graph, dependency_graph, + &mut json_abi, ) .ok(&mut warnings, &mut errors) .map(|value| (name, value)) diff --git a/core_lang/src/semantic_analysis/ast_node/code_block.rs b/core_lang/src/semantic_analysis/ast_node/code_block.rs index 8930634408b..3b3bc80d24d 100644 --- a/core_lang/src/semantic_analysis/ast_node/code_block.rs +++ b/core_lang/src/semantic_analysis/ast_node/code_block.rs @@ -1,3 +1,5 @@ +use fuels_rs::types::JsonABI; + use super::*; use crate::build_config::BuildConfig; use crate::control_flow_analysis::ControlFlowGraph; @@ -26,6 +28,7 @@ impl<'sc> TypedCodeBlock<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, (Self, Option>)> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -46,6 +49,7 @@ impl<'sc> TypedCodeBlock<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ) .ok(&mut warnings, &mut errors) }) diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index 83be1018c1a..bdc7e306e0e 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -12,6 +12,7 @@ use crate::{ Ident, }; use crate::{control_flow_analysis::ControlFlowGraph, types::TypeInfo}; +use fuels_rs::types::JsonABI; use sha2::{Digest, Sha256}; use std::collections::{HashMap, HashSet}; @@ -511,6 +512,7 @@ impl<'sc> TypedFunctionDeclaration<'sc> { dead_code_graph: &mut ControlFlowGraph<'sc>, mode: Mode, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedFunctionDeclaration<'sc>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -559,7 +561,8 @@ impl<'sc> TypedFunctionDeclaration<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), ( TypedCodeBlock { diff --git a/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs b/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs index e91921bcbe9..d90a8ec3588 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs @@ -1,3 +1,5 @@ +use fuels_rs::types::JsonABI; + use crate::build_config::BuildConfig; use crate::control_flow_analysis::ControlFlowGraph; use crate::error::*; @@ -16,6 +18,7 @@ pub(crate) fn instantiate_enum<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -70,7 +73,8 @@ pub(crate) fn instantiate_enum<'sc>( self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs index 5748274a72b..86e8c5e8c6b 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -4,6 +4,8 @@ use crate::control_flow_analysis::ControlFlowGraph; use crate::semantic_analysis::ast_node::*; use crate::types::{IntegerBits, MaybeResolvedType, ResolvedType}; use either::Either; +use fuels_rs::json_abi; +use fuels_rs::types::JsonABI; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; @@ -39,6 +41,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, Self> { let expr_span = other.span(); let res = match other { @@ -60,6 +63,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), Expression::LazyOperator { op, lhs, rhs, span } => Self::type_check_lazy_operator( op, @@ -71,6 +75,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), Expression::MatchExpression { span, .. } => { let errors = vec![CompileError::Unimplemented( @@ -89,6 +94,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), // TODO if _condition_ is constant, evaluate it and compile this to an // expression with only one branch @@ -108,6 +114,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), Expression::AsmExpression { asm, span, .. } => Self::type_check_asm_expression( asm, @@ -117,6 +124,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), Expression::StructExpression { span, @@ -131,6 +139,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), Expression::SubfieldExpression { prefix, @@ -145,6 +154,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), Expression::MethodApplication { method_name, @@ -159,6 +169,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), Expression::Unit { span } => { let exp = TypedExpression { @@ -184,6 +195,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), Expression::AbiCast { abi_name, @@ -198,6 +210,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ), a => { let mut errors = vec![]; @@ -331,6 +344,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -403,7 +417,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ) .unwrap_or_else( &mut warnings, @@ -452,6 +467,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -465,7 +481,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(lhs.span()), warnings, @@ -481,7 +498,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(rhs.span()), warnings, @@ -571,6 +589,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -583,7 +602,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), ( TypedCodeBlock { @@ -632,6 +652,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -644,7 +665,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(condition.span()), warnings, @@ -659,7 +681,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(then.span()), warnings, @@ -675,7 +698,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(expr.span()), warnings, @@ -716,6 +740,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -743,7 +768,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(initializer.span()), warnings, @@ -777,6 +803,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -838,7 +865,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), continue, warnings, @@ -885,6 +913,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -897,7 +926,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, @@ -955,6 +985,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -1011,7 +1042,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, @@ -1049,6 +1081,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -1064,7 +1097,8 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(err_span), warnings, @@ -1111,7 +1145,8 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, Mode::ImplAbiFn, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index 6cdb7013792..e1b9d181d0c 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -4,6 +4,8 @@ use crate::control_flow_analysis::ControlFlowGraph; use crate::types::{MaybeResolvedType, ResolvedType}; use std::collections::VecDeque; +use fuels_rs::types::JsonABI; + pub(crate) fn type_check_method_application<'sc>( method_name: MethodName<'sc>, arguments: Vec>, @@ -13,6 +15,7 @@ pub(crate) fn type_check_method_application<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -27,7 +30,8 @@ pub(crate) fn type_check_method_application<'sc>( self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(span.clone()), warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/impl_trait.rs b/core_lang/src/semantic_analysis/ast_node/impl_trait.rs index 15a693411f9..05aa97a5c66 100644 --- a/core_lang/src/semantic_analysis/ast_node/impl_trait.rs +++ b/core_lang/src/semantic_analysis/ast_node/impl_trait.rs @@ -1,3 +1,5 @@ +use fuels_rs::types::JsonABI; + use super::{declaration::TypedTraitFn, ERROR_RECOVERY_DECLARATION}; use crate::parse_tree::{FunctionDeclaration, ImplTrait, TypeParameter}; use crate::semantic_analysis::{Namespace, TypedDeclaration, TypedFunctionDeclaration}; @@ -17,6 +19,7 @@ pub(crate) fn implementation_of_trait<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedDeclaration<'sc>> { let mut errors = vec![]; let mut warnings = vec![]; @@ -65,7 +68,8 @@ pub(crate) fn implementation_of_trait<'sc>( &block_span, &type_implementing_for, Mode::NonAbi, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, @@ -117,7 +121,8 @@ pub(crate) fn implementation_of_trait<'sc>( &block_span, &type_implementing_for, Mode::ImplAbiFn, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, @@ -172,6 +177,7 @@ fn type_check_trait_implementation<'sc>( type_implementing_for: &MaybeResolvedType<'sc>, mode: Mode, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, Vec>> { let mut functions_buf: Vec = vec![]; let mut errors = vec![]; @@ -198,7 +204,8 @@ fn type_check_trait_implementation<'sc>( build_config, dead_code_graph, mode, - dependency_graph + dependency_graph, + json_abi ), continue, warnings, @@ -360,7 +367,8 @@ fn type_check_trait_implementation<'sc>( build_config, dead_code_graph, mode, - dependency_graph + dependency_graph, + json_abi ), continue, warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/mod.rs b/core_lang/src/semantic_analysis/ast_node/mod.rs index 420294692a9..16373d7e7e2 100644 --- a/core_lang/src/semantic_analysis/ast_node/mod.rs +++ b/core_lang/src/semantic_analysis/ast_node/mod.rs @@ -7,6 +7,7 @@ use crate::{control_flow_analysis::ControlFlowGraph, parse_tree::*}; use crate::{error::*, types::IntegerBits}; use crate::{AstNode, AstNodeContent, Ident, ReturnStatement}; use declaration::TypedTraitFn; +use fuels_rs::types::JsonABI; pub(crate) use impl_trait::Mode; use std::path::Path; @@ -93,6 +94,7 @@ impl<'sc> TypedAstNode<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedAstNode<'sc>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -121,6 +123,7 @@ impl<'sc> TypedAstNode<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ) }; @@ -223,7 +226,8 @@ impl<'sc> TypedAstNode<'sc> { build_config, dead_code_graph, Mode::NonAbi, - dependency_graph + dependency_graph, + json_abi ), error_recovery_function_declaration(fn_decl), warnings, @@ -271,7 +275,8 @@ impl<'sc> TypedAstNode<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), vec![], warnings, @@ -298,7 +303,8 @@ impl<'sc> TypedAstNode<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, @@ -311,7 +317,8 @@ impl<'sc> TypedAstNode<'sc> { namespace, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, @@ -366,7 +373,8 @@ impl<'sc> TypedAstNode<'sc> { build_config, dead_code_graph, Mode::NonAbi, - dependency_graph + dependency_graph, + json_abi ), continue, warnings, @@ -452,7 +460,8 @@ impl<'sc> TypedAstNode<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), vec![], warnings, @@ -480,7 +489,8 @@ impl<'sc> TypedAstNode<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(a.span()), warnings, @@ -500,7 +510,8 @@ impl<'sc> TypedAstNode<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(expr.span()), warnings, @@ -521,7 +532,8 @@ impl<'sc> TypedAstNode<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(expr.span()), warnings, @@ -539,7 +551,8 @@ impl<'sc> TypedAstNode<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, @@ -556,7 +569,8 @@ impl<'sc> TypedAstNode<'sc> { self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), ( TypedCodeBlock { @@ -702,6 +716,7 @@ fn reassignment<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, TypedDeclaration<'sc>> { let mut errors = vec![]; let mut warnings = vec![]; @@ -758,7 +773,8 @@ fn reassignment<'sc>( self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(span), warnings, @@ -794,7 +810,8 @@ fn reassignment<'sc>( self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(expr.span()), warnings, @@ -858,7 +875,8 @@ fn reassignment<'sc>( self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), error_recovery_expr(span), warnings, @@ -929,6 +947,7 @@ fn type_check_trait_methods<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, Vec>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -1048,7 +1067,8 @@ fn type_check_trait_methods<'sc>( self_type, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), continue, warnings, diff --git a/core_lang/src/semantic_analysis/syntax_tree.rs b/core_lang/src/semantic_analysis/syntax_tree.rs index b31fefe528a..9f8cac3ca47 100644 --- a/core_lang/src/semantic_analysis/syntax_tree.rs +++ b/core_lang/src/semantic_analysis/syntax_tree.rs @@ -9,6 +9,9 @@ use crate::{ types::{MaybeResolvedType, ResolvedType}, }; use crate::{AstNode, AstNodeContent, ParseTree}; + +use fuels_rs::types::JsonABI; + use std::collections::{HashMap, HashSet}; #[derive(Clone, Copy, PartialEq, Eq)] @@ -76,6 +79,7 @@ impl<'sc> TypedParseTree<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, Self> { let mut new_namespace = initial_namespace.clone(); let mut warnings = Vec::new(); @@ -105,7 +109,8 @@ impl<'sc> TypedParseTree<'sc> { &mut new_namespace, build_config, dead_code_graph, - dependency_graph + dependency_graph, + json_abi ), return err(warnings, errors), warnings, @@ -161,6 +166,7 @@ impl<'sc> TypedParseTree<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, + json_abi: &JsonABI, ) -> CompileResult<'sc, Vec>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -178,6 +184,7 @@ impl<'sc> TypedParseTree<'sc> { build_config, dead_code_graph, dependency_graph, + json_abi, ) }) .filter_map(|res| res.ok(&mut warnings, &mut errors)) From 3faff5a605cfc1e8c2be5b037b990fa8e4fac4c3 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Fri, 29 Oct 2021 12:00:53 -1000 Subject: [PATCH 03/25] Creating the JSON abi output. --- core_lang/src/lib.rs | 7 ++- .../semantic_analysis/ast_node/code_block.rs | 2 +- .../semantic_analysis/ast_node/declaration.rs | 2 +- .../ast_node/expression/enum_instantiation.rs | 2 +- .../ast_node/expression/typed_expression.rs | 48 ++++++++++++++----- .../typed_expression/method_application.rs | 2 +- .../semantic_analysis/ast_node/impl_trait.rs | 4 +- .../src/semantic_analysis/ast_node/mod.rs | 6 +-- .../src/semantic_analysis/syntax_tree.rs | 4 +- 9 files changed, 54 insertions(+), 23 deletions(-) diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index ce59f0ff4f9..286b2de168d 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -222,6 +222,9 @@ pub(crate) fn compile_inner_dependency<'sc>( return err(warnings, errors); } } + + let mut json_abi = vec![]; + let library_exports: LibraryExports = { let res: Vec<_> = parse_tree .library_exports @@ -234,7 +237,7 @@ pub(crate) fn compile_inner_dependency<'sc>( &build_config.clone(), dead_code_graph, dependency_graph, - &vec![], + &mut json_abi, ) .ok(&mut warnings, &mut errors) .map(|value| (name, value)) @@ -350,6 +353,8 @@ pub fn compile_to_asm<'sc>( exports }; + println!("{:?}", json_abi); + // If there are errors, display them now before performing control flow analysis. // It is necessary that the syntax tree is well-formed for control flow analysis // to be correct. diff --git a/core_lang/src/semantic_analysis/ast_node/code_block.rs b/core_lang/src/semantic_analysis/ast_node/code_block.rs index 3b3bc80d24d..c80c9282c7c 100644 --- a/core_lang/src/semantic_analysis/ast_node/code_block.rs +++ b/core_lang/src/semantic_analysis/ast_node/code_block.rs @@ -28,7 +28,7 @@ impl<'sc> TypedCodeBlock<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, (Self, Option>)> { let mut warnings = Vec::new(); let mut errors = Vec::new(); diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index bdc7e306e0e..b2840cf56e6 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -512,7 +512,7 @@ impl<'sc> TypedFunctionDeclaration<'sc> { dead_code_graph: &mut ControlFlowGraph<'sc>, mode: Mode, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedFunctionDeclaration<'sc>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); diff --git a/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs b/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs index d90a8ec3588..25e1acecc13 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs @@ -18,7 +18,7 @@ pub(crate) fn instantiate_enum<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; diff --git a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs index 86e8c5e8c6b..41ad44dc39a 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -4,7 +4,7 @@ use crate::control_flow_analysis::ControlFlowGraph; use crate::semantic_analysis::ast_node::*; use crate::types::{IntegerBits, MaybeResolvedType, ResolvedType}; use either::Either; -use fuels_rs::json_abi; +use fuels_rs::types; use fuels_rs::types::JsonABI; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; @@ -41,7 +41,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, Self> { let expr_span = other.span(); let res = match other { @@ -344,7 +344,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -467,7 +467,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -589,7 +589,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -652,7 +652,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -740,7 +740,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -803,7 +803,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -913,7 +913,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -985,7 +985,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -1081,7 +1081,7 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -1122,6 +1122,32 @@ impl<'sc> TypedExpression<'sc> { return err(warnings, errors); } }; + + let mut functions: JsonABI = abi + .methods + .iter() + .map(|function| types::Function { + type_field: "function".to_string(), + inputs: function + .parameters + .iter() + .map(|parameter| types::Property { + name: parameter.name.primary_name.to_string(), + type_field: format!("{:?}", parameter.r#type), + components: None, + }) + .collect(), + name: function.name.primary_name.to_string(), + outputs: vec![types::Property { + name: "".to_string(), + type_field: format!("{:?}", function.return_type), + components: None, + }], + }) + .collect(); + + json_abi.append(&mut functions); + let return_type = MaybeResolvedType::Resolved(ResolvedType::ContractCaller { abi_name: abi_name.clone(), address: Box::new(address.clone()), diff --git a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index e1b9d181d0c..4ca9e71b3ad 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -15,7 +15,7 @@ pub(crate) fn type_check_method_application<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; diff --git a/core_lang/src/semantic_analysis/ast_node/impl_trait.rs b/core_lang/src/semantic_analysis/ast_node/impl_trait.rs index 05aa97a5c66..ac9b6deee04 100644 --- a/core_lang/src/semantic_analysis/ast_node/impl_trait.rs +++ b/core_lang/src/semantic_analysis/ast_node/impl_trait.rs @@ -19,7 +19,7 @@ pub(crate) fn implementation_of_trait<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedDeclaration<'sc>> { let mut errors = vec![]; let mut warnings = vec![]; @@ -177,7 +177,7 @@ fn type_check_trait_implementation<'sc>( type_implementing_for: &MaybeResolvedType<'sc>, mode: Mode, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, Vec>> { let mut functions_buf: Vec = vec![]; let mut errors = vec![]; diff --git a/core_lang/src/semantic_analysis/ast_node/mod.rs b/core_lang/src/semantic_analysis/ast_node/mod.rs index 16373d7e7e2..c7ae7118eb8 100644 --- a/core_lang/src/semantic_analysis/ast_node/mod.rs +++ b/core_lang/src/semantic_analysis/ast_node/mod.rs @@ -94,7 +94,7 @@ impl<'sc> TypedAstNode<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedAstNode<'sc>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -716,7 +716,7 @@ fn reassignment<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedDeclaration<'sc>> { let mut errors = vec![]; let mut warnings = vec![]; @@ -947,7 +947,7 @@ fn type_check_trait_methods<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, Vec>> { let mut warnings = vec![]; let mut errors = vec![]; diff --git a/core_lang/src/semantic_analysis/syntax_tree.rs b/core_lang/src/semantic_analysis/syntax_tree.rs index 9f8cac3ca47..a8f9f5e92e0 100644 --- a/core_lang/src/semantic_analysis/syntax_tree.rs +++ b/core_lang/src/semantic_analysis/syntax_tree.rs @@ -79,7 +79,7 @@ impl<'sc> TypedParseTree<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, Self> { let mut new_namespace = initial_namespace.clone(); let mut warnings = Vec::new(); @@ -166,7 +166,7 @@ impl<'sc> TypedParseTree<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &JsonABI, + json_abi: &mut JsonABI, ) -> CompileResult<'sc, Vec>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); From a81acc81bc69bf8a3b4a74dfff15574a4344e0c8 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 15 Nov 2021 17:53:20 -0600 Subject: [PATCH 04/25] Complete abi json functionality. --- Cargo.lock | 1 + core_lang/src/lib.rs | 282 +++++++++++------- .../src/semantic_analysis/syntax_tree.rs | 2 +- forc/Cargo.toml | 1 + forc/src/cli/commands/json_abi.rs | 25 ++ forc/src/cli/commands/mod.rs | 1 + forc/src/cli/mod.rs | 5 +- forc/src/ops/forc_abi_json.rs | 263 ++++++++++++++++ forc/src/ops/forc_build.rs | 117 +------- forc/src/ops/mod.rs | 1 + forc/src/utils/helpers.rs | 97 ++++++ 11 files changed, 585 insertions(+), 210 deletions(-) create mode 100644 forc/src/cli/commands/json_abi.rs create mode 100644 forc/src/ops/forc_abi_json.rs diff --git a/Cargo.lock b/Cargo.lock index 02238f8388c..0b28e84e8cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1186,6 +1186,7 @@ dependencies = [ "fuel-client", "fuel-tx", "fuel-vm", + "fuels-rs", "hex", "line-col", "pest 2.1.3 (git+https://github.com/sezna/pest.git?rev=8aa58791f759daf4caee26e8560e862df5a6afb7)", diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index 286b2de168d..06274ffb83a 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -20,6 +20,8 @@ use crate::{asm_generation::compile_ast_to_asm, error::*}; pub use asm_generation::{AbstractInstructionSet, FinalizedAsm, HllAsmSet}; pub use build_config::BuildConfig; use control_flow_analysis::{ControlFlowGraph, Graph}; +use fuels_rs::json_abi; +use fuels_rs::types::Function; use pest::iterators::Pair; use pest::Parser; use semantic_analysis::{TreeType, TypedParseTree}; @@ -132,10 +134,12 @@ pub fn parse<'sc>( pub enum CompilationResult<'sc> { Success { asm: FinalizedAsm<'sc>, + json_abi: Vec, warnings: Vec>, }, Library { exports: LibraryExports<'sc>, + json_abi: Vec, warnings: Vec>, }, Failure { @@ -143,6 +147,23 @@ pub enum CompilationResult<'sc> { errors: Vec>, }, } + +pub enum CompileASTsResult<'sc> { + Success { + contract_ast: Option>, + script_ast: Option>, + predicate_ast: Option>, + library_exports: LibraryExports<'sc>, + json_abi: Vec, + dead_code_graph: ControlFlowGraph<'sc>, + warnings: Vec>, + }, + Failure { + warnings: Vec>, + errors: Vec>, + }, +} + pub enum BytecodeCompilationResult<'sc> { Success { bytes: Vec, @@ -279,17 +300,17 @@ pub(crate) fn compile_inner_dependency<'sc>( ) } -pub fn compile_to_asm<'sc>( +fn compile_asts<'sc>( input: &'sc str, initial_namespace: &Namespace<'sc>, - build_config: BuildConfig, + build_config: &BuildConfig, dependency_graph: &mut HashMap>, -) -> CompilationResult<'sc> { +) -> CompileASTsResult<'sc> { let mut warnings = Vec::new(); let mut errors = Vec::new(); let parse_tree = check!( - parse(input, Some(&build_config)), - return CompilationResult::Failure { errors, warnings }, + parse(input, Some(build_config)), + return CompileASTsResult::Failure { errors, warnings }, warnings, errors ); @@ -353,114 +374,163 @@ pub fn compile_to_asm<'sc>( exports }; - println!("{:?}", json_abi); - - // If there are errors, display them now before performing control flow analysis. - // It is necessary that the syntax tree is well-formed for control flow analysis - // to be correct. if !errors.is_empty() { - return CompilationResult::Failure { errors, warnings }; + return CompileASTsResult::Failure { errors, warnings }; } - // perform control flow analysis on each branch - let (script_warnings, script_errors) = - perform_control_flow_analysis(&script_ast, TreeType::Script, &mut dead_code_graph); - let (contract_warnings, contract_errors) = - perform_control_flow_analysis(&contract_ast, TreeType::Contract, &mut dead_code_graph); - let (predicate_warnings, predicate_errors) = - perform_control_flow_analysis(&predicate_ast, TreeType::Predicate, &mut dead_code_graph); - let (library_warnings, library_errors) = - perform_control_flow_analysis_on_library_exports(&library_exports, &mut dead_code_graph); - - let mut l_warnings = [ - script_warnings, - contract_warnings, - predicate_warnings, - library_warnings, - ] - .concat(); - let mut l_errors = [ - script_errors, - contract_errors, - predicate_errors, - library_errors, - ] - .concat(); - - errors.append(&mut l_errors); - warnings.append(&mut l_warnings); - // for each syntax tree, generate assembly. - let predicate_asm = (|| { - if let Some(tree) = predicate_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None - } - })(); - - let contract_asm = (|| { - if let Some(tree) = contract_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None - } - })(); - - let script_asm = (|| { - if let Some(tree) = script_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None + CompileASTsResult::Success { + contract_ast, + predicate_ast, + script_ast, + library_exports, + json_abi, + dead_code_graph, + warnings, + } +} + +pub fn compile_to_asm<'sc>( + input: &'sc str, + initial_namespace: &Namespace<'sc>, + build_config: BuildConfig, + dependency_graph: &mut HashMap>, +) -> CompilationResult<'sc> { + match compile_asts(input, initial_namespace, &build_config, dependency_graph) { + CompileASTsResult::Failure { warnings, errors } => { + CompilationResult::Failure { warnings, errors } } - })(); - - if errors.is_empty() { - // TODO move this check earlier and don't compile all of them if there is only one - match (predicate_asm, contract_asm, script_asm, library_exports) { - (Some(pred), None, None, o) if o.trees.is_empty() => CompilationResult::Success { - asm: pred, - warnings, - }, - (None, Some(contract), None, o) if o.trees.is_empty() => CompilationResult::Success { - asm: contract, - warnings, - }, - (None, None, Some(script), o) if o.trees.is_empty() => CompilationResult::Success { - asm: script, - warnings, - }, - (None, None, None, o) if !o.trees.is_empty() => CompilationResult::Library { - warnings, - exports: o, - }, - (None, None, None, o) if o.trees.is_empty() => { - todo!("do we want empty files to be valid programs?") + CompileASTsResult::Success { + script_ast, + contract_ast, + library_exports, + predicate_ast, + mut dead_code_graph, + mut warnings, + json_abi, + } => { + let mut errors = vec![]; + + // perform control flow analysis on each branch + let (script_warnings, script_errors) = + perform_control_flow_analysis(&script_ast, TreeType::Script, &mut dead_code_graph); + let (contract_warnings, contract_errors) = perform_control_flow_analysis( + &contract_ast, + TreeType::Contract, + &mut dead_code_graph, + ); + let (predicate_warnings, predicate_errors) = perform_control_flow_analysis( + &predicate_ast, + TreeType::Predicate, + &mut dead_code_graph, + ); + let (library_warnings, library_errors) = + perform_control_flow_analysis_on_library_exports( + &library_exports, + &mut dead_code_graph, + ); + + let mut l_warnings = [ + script_warnings, + contract_warnings, + predicate_warnings, + library_warnings, + ] + .concat(); + let mut l_errors = [ + script_errors, + contract_errors, + predicate_errors, + library_errors, + ] + .concat(); + + errors.append(&mut l_errors); + warnings.append(&mut l_warnings); + // for each syntax tree, generate assembly. + let predicate_asm = (|| { + if let Some(tree) = predicate_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None + } + })(); + + let contract_asm = (|| { + if let Some(tree) = contract_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None + } + })(); + + let script_asm = (|| { + if let Some(tree) = script_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None + } + })(); + + if errors.is_empty() { + // TODO move this check earlier and don't compile all of them if there is only one + match (predicate_asm, contract_asm, script_asm, library_exports) { + (Some(pred), None, None, o) if o.trees.is_empty() => { + CompilationResult::Success { + asm: pred, + json_abi, + warnings, + } + } + (None, Some(contract), None, o) if o.trees.is_empty() => { + CompilationResult::Success { + asm: contract, + json_abi, + warnings, + } + } + (None, None, Some(script), o) if o.trees.is_empty() => { + CompilationResult::Success { + asm: script, + json_abi, + warnings, + } + } + (None, None, None, o) if !o.trees.is_empty() => CompilationResult::Library { + warnings, + json_abi, + exports: o, + }, + (None, None, None, o) if o.trees.is_empty() => { + todo!("do we want empty files to be valid programs?") + } + // Default to compiling an empty library if there is no code or invalid state + _ => unimplemented!( + "Multiple contracts, libraries, scripts, or predicates in a single file are \ + unsupported." + ), + } + } else { + CompilationResult::Failure { errors, warnings } } - // Default to compiling an empty library if there is no code or invalid state - _ => unimplemented!( - "Multiple contracts, libraries, scripts, or predicates in a single file are \ - unsupported." - ), } - } else { - CompilationResult::Failure { errors, warnings } } } + pub fn compile_to_bytecode<'sc>( input: &'sc str, initial_namespace: &Namespace<'sc>, @@ -471,6 +541,7 @@ pub fn compile_to_bytecode<'sc>( CompilationResult::Success { mut asm, mut warnings, + json_abi, } => { let mut asm_res = asm.to_bytecode(); warnings.append(&mut asm_res.warnings); @@ -492,6 +563,7 @@ pub fn compile_to_bytecode<'sc>( } CompilationResult::Library { warnings, + json_abi, exports: _exports, } => BytecodeCompilationResult::Library { warnings }, } diff --git a/core_lang/src/semantic_analysis/syntax_tree.rs b/core_lang/src/semantic_analysis/syntax_tree.rs index a8f9f5e92e0..47973f23d6c 100644 --- a/core_lang/src/semantic_analysis/syntax_tree.rs +++ b/core_lang/src/semantic_analysis/syntax_tree.rs @@ -23,7 +23,7 @@ pub(crate) enum TreeType { } #[derive(Debug)] -pub(crate) enum TypedParseTree<'sc> { +pub enum TypedParseTree<'sc> { Script { main_function: TypedFunctionDeclaration<'sc>, namespace: Namespace<'sc>, diff --git a/forc/Cargo.toml b/forc/Cargo.toml index 40a66b8b661..7e5057fedb2 100644 --- a/forc/Cargo.toml +++ b/forc/Cargo.toml @@ -32,6 +32,7 @@ termcolor = "1.1" tokio = {version = "1.8.0", features = ["macros", "rt-multi-thread", "process"]} toml = "0.5" whoami = "1.1" +fuels-rs = {path = "../fuels-rs"} [features] default = [] diff --git a/forc/src/cli/commands/json_abi.rs b/forc/src/cli/commands/json_abi.rs new file mode 100644 index 00000000000..4c883df83d3 --- /dev/null +++ b/forc/src/cli/commands/json_abi.rs @@ -0,0 +1,25 @@ +use crate::ops::forc_abi_json; +use structopt::{self, StructOpt}; + +/// Compile the current or target project. +#[derive(Debug, StructOpt)] +pub struct Command { + /// Path to the project, if not specified, current working directory will be used. + #[structopt(short, long)] + pub path: Option, + /// If set, outputs a json file representing the output json abi. + #[structopt(short = "o")] + pub json_outfile: Option, + /// Offline mode, prevents Forc from using the network when managing dependencies. + /// Meaning it will only try to use previously downloaded dependencies. + #[structopt(long = "offline")] + pub offline_mode: bool, + /// Silent mode. Don't output any warnings or errors to the command line. + #[structopt(long = "silent", short = "s")] + pub silent_mode: bool, +} + +pub(crate) fn exec(command: Command) -> Result<(), String> { + forc_abi_json::build(command)?; + Ok(()) +} diff --git a/forc/src/cli/commands/mod.rs b/forc/src/cli/commands/mod.rs index 6b1eb6861d9..5867333c8ef 100644 --- a/forc/src/cli/commands/mod.rs +++ b/forc/src/cli/commands/mod.rs @@ -1,3 +1,4 @@ +pub mod json_abi; pub mod build; pub mod deploy; pub mod format; diff --git a/forc/src/cli/mod.rs b/forc/src/cli/mod.rs index a7310c3c487..47395e8f683 100644 --- a/forc/src/cli/mod.rs +++ b/forc/src/cli/mod.rs @@ -1,8 +1,9 @@ use structopt::StructOpt; mod commands; -use self::commands::{build, deploy, format, init, parse_bytecode, run, test, update}; +use self::commands::{json_abi, build, deploy, format, init, parse_bytecode, run, test, update}; +pub use json_abi::Command as JsonAbiCommand; pub use build::Command as BuildCommand; pub use deploy::Command as DeployCommand; pub use format::Command as FormatCommand; @@ -31,6 +32,7 @@ enum Forc { Run(RunCommand), Test(TestCommand), Update(UpdateCommand), + JsonAbi(JsonAbiCommand), } pub(crate) async fn run_cli() -> Result<(), String> { @@ -44,6 +46,7 @@ pub(crate) async fn run_cli() -> Result<(), String> { Forc::Run(command) => run::exec(command).await, Forc::Test(command) => test::exec(command), Forc::Update(command) => update::exec(command).await, + Forc::JsonAbi(command) => json_abi::exec(command), }?; Ok(()) diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs new file mode 100644 index 00000000000..0475a9eebd9 --- /dev/null +++ b/forc/src/ops/forc_abi_json.rs @@ -0,0 +1,263 @@ +use crate::utils::dependency::{Dependency, DependencyDetails}; +use crate::{ + cli::JsonAbiCommand, + utils::dependency, + utils::helpers::{ + find_file_name, find_main_path, find_manifest_dir, get_main_file, print_on_failure, + print_on_success_library, print_on_success_script, read_manifest, + }, +}; + +use fuels_rs::types::Function; + +use std::fs::File; +use std::io::Write; + +use anyhow::Result; +use core_lang::{BuildConfig, CompilationResult, LibraryExports, Namespace}; +use std::collections::{HashMap, HashSet}; +use std::path::PathBuf; + +pub fn build(command: JsonAbiCommand) -> Result, String> { + // find manifest directory, even if in subdirectory + let this_dir = if let Some(ref path) = command.path { + PathBuf::from(path) + } else { + std::env::current_dir().map_err(|e| format!("{:?}", e))? + }; + + let JsonAbiCommand { + json_outfile, + offline_mode, + silent_mode, + .. + } = command; + + let manifest_dir = match find_manifest_dir(&this_dir) { + Some(dir) => dir, + None => { + return Err(format!( + "No manifest file found in this directory or any parent directories of it: {:?}", + this_dir + )) + } + }; + let mut manifest = read_manifest(&manifest_dir)?; + let main_path = find_main_path(&manifest_dir, &manifest); + let file_name = find_file_name(&manifest_dir, &main_path)?; + + let build_config = BuildConfig::root_from_file_name_and_manifest_path( + file_name.clone().to_path_buf(), + manifest_dir.clone(), + ); + + let mut dependency_graph = HashMap::new(); + let mut json_abi = vec!(); + + let mut namespace: Namespace = Default::default(); + if let Some(ref mut deps) = manifest.dependencies { + for (dependency_name, dependency_details) in deps.iter_mut() { + // Check if dependency is a git-based dependency. + let dep = match dependency_details { + Dependency::Simple(..) => { + return Err( + "Not yet implemented: Simple version-spec dependencies require a registry." + .into(), + ); + } + Dependency::Detailed(dep_details) => dep_details, + }; + + // Download a non-local dependency if the `git` property is set in this dependency. + if let Some(git) = &dep.git { + let downloaded_dep_path = match dependency::download_github_dep( + dependency_name, + git, + &dep.branch, + &dep.version, + offline_mode.into(), + ) { + Ok(path) => path, + Err(e) => { + return Err(format!( + "Couldn't download dependency ({:?}): {:?}", + dependency_name, e + )) + } + }; + + // Mutate this dependency's path to hold the newly downloaded dependency's path. + dep.path = Some(downloaded_dep_path); + } + + json_abi.append(&mut compile_dependency_lib( + &this_dir, + &dependency_name, + &dependency_details, + &mut namespace, + &mut dependency_graph, + silent_mode, + )?); + } + } + + // now, compile this program with all of its dependencies + let main_file = get_main_file(&manifest, &manifest_dir)?; + + json_abi.append(&mut compile( + main_file, + &manifest.project.name, + &namespace, + build_config, + &mut dependency_graph, + silent_mode, + )?); + if let Some(outfile) = json_outfile { + let mut file = File::create(outfile).map_err(|e| e.to_string())?; + //file.write_all(json_abi).map_err(|e| e.to_string())?; + } else { + println!("{:?}", json_abi); + } + + Ok(json_abi) +} + +/// Takes a dependency and returns a namespace of exported things from that dependency +/// trait implementations are included as well +fn compile_dependency_lib<'source, 'manifest>( + project_file_path: &PathBuf, + dependency_name: &'manifest str, + dependency_lib: &Dependency, + namespace: &mut Namespace<'source>, + dependency_graph: &mut HashMap>, + silent_mode: bool, +) -> Result, String> { + let dep_path = match dependency_lib { + Dependency::Simple(..) => { + return Err( + "Not yet implemented: Simple version-spec dependencies require a registry.".into(), + ) + } + Dependency::Detailed(DependencyDetails { path, .. }) => path, + }; + + let dep_path = + match dep_path { + Some(p) => p, + None => return Err( + "Only simple path imports are supported right now. Please supply a path relative \ + to the manifest file." + .into(), + ), + }; + + // dependency paths are relative to the path of the project being compiled + let mut project_path = project_file_path.clone(); + project_path.push(dep_path); + + // compile the dependencies of this dependency + // this should detect circular dependencies + let manifest_dir = match find_manifest_dir(&project_path) { + Some(o) => o, + None => return Err("Manifest not found for dependency.".into()), + }; + let manifest_of_dep = read_manifest(&manifest_dir)?; + let main_path = find_main_path(&manifest_dir, &manifest_of_dep); + let file_name = find_file_name(&manifest_dir, &main_path)?; + + let build_config = BuildConfig::root_from_file_name_and_manifest_path( + file_name.clone().to_path_buf(), + manifest_dir.clone(), + ); + let mut dep_namespace = namespace.clone(); + + // The part below here is just a massive shortcut to get the standard library working + if let Some(ref deps) = manifest_of_dep.dependencies { + for dep in deps { + // to do this properly, iterate over list of dependencies make sure there are no + // circular dependencies + //return Err("Unimplemented: dependencies that have dependencies".into()); + compile_dependency_lib( + project_file_path, + &dep.0, + &dep.1, + // give it a cloned namespace, which we then merge with this namespace + &mut dep_namespace, + dependency_graph, + silent_mode, + )?; + } + } + + let main_file = get_main_file(&manifest_of_dep, &manifest_dir)?; + + let (compiled, json_abi) = compile_library( + main_file, + &manifest_of_dep.project.name, + &dep_namespace, + build_config.clone(), + dependency_graph, + silent_mode, + )?; + + namespace.insert_dependency_module(dependency_name.to_string(), compiled.namespace); + + // nothing is returned from this method since it mutates the hashmaps it was given + Ok(json_abi) +} + +fn compile_library<'source, 'manifest>( + source: &'source str, + proj_name: &str, + namespace: &Namespace<'source>, + build_config: BuildConfig, + dependency_graph: &mut HashMap>, + silent_mode: bool, +) -> Result<(LibraryExports<'source>, Vec), String> { + let res = core_lang::compile_to_asm(&source, namespace, build_config, dependency_graph); + match res { + CompilationResult::Library { + warnings, + json_abi, + exports, + } => { + print_on_success_library(silent_mode, proj_name, warnings); + Ok((exports, json_abi)) + } + CompilationResult::Success { warnings, .. } => { + print_on_failure(silent_mode, warnings, vec![]); + Err(format!("Failed to compile {}", proj_name)) + } + CompilationResult::Failure { warnings, errors } => { + print_on_failure(silent_mode, warnings, errors); + Err(format!("Failed to compile {}", proj_name)) + } + } +} + +fn compile<'source, 'manifest>( + source: &'source str, + proj_name: &str, + namespace: &Namespace<'source>, + build_config: BuildConfig, + dependency_graph: &mut HashMap>, + silent_mode: bool, +) -> Result, String> { + let res = core_lang::compile_to_asm(&source, namespace, build_config, dependency_graph); + match res { + CompilationResult::Success { + warnings, json_abi, .. + } => { + print_on_success_script(silent_mode, proj_name, warnings); + Ok(json_abi) + } + CompilationResult::Library { warnings, .. } => { + print_on_failure(silent_mode, warnings, vec![]); + Err(format!("Failed to compile {}", proj_name)) + } + CompilationResult::Failure { warnings, errors } => { + print_on_failure(silent_mode, warnings, errors); + Err(format!("Failed to compile {}", proj_name)) + } + } +} diff --git a/forc/src/ops/forc_build.rs b/forc/src/ops/forc_build.rs index 7d42b3f93d5..55ea4b53426 100644 --- a/forc/src/ops/forc_build.rs +++ b/forc/src/ops/forc_build.rs @@ -3,19 +3,19 @@ use crate::{ cli::BuildCommand, utils::dependency, utils::helpers::{ - find_manifest_dir, get_main_file, print_blue_err, println_green_err, println_red_err, - println_yellow_err, read_manifest, + find_manifest_dir, get_main_file, print_on_failure, print_on_success_library, + print_on_success_script, read_manifest, }, }; -use std::fs::File; -use std::io::Write; -use anyhow::Result; use core_lang::{ BuildConfig, BytecodeCompilationResult, CompilationResult, LibraryExports, Namespace, }; -use source_span::fmt::{Color, Formatter}; + +use anyhow::Result; use std::collections::{HashMap, HashSet}; +use std::fs::File; +use std::io::Write; use std::path::PathBuf; pub fn build(command: BuildCommand) -> Result, String> { @@ -242,41 +242,14 @@ fn compile_library<'source, 'manifest>( ) -> Result, String> { let res = core_lang::compile_to_asm(&source, namespace, build_config, dependency_graph); match res { - CompilationResult::Library { exports, warnings } => { - if !silent_mode { - warnings.iter().for_each(|warning| format_warning(warning)); - } - - if warnings.is_empty() { - let _ = println_green_err(&format!(" Compiled library {:?}.", proj_name)); - } else { - let _ = println_yellow_err(&format!( - " Compiled library {:?} with {} {}.", - proj_name, - warnings.len(), - if warnings.len() > 1 { - "warnings" - } else { - "warning" - } - )); - } + CompilationResult::Library { + exports, warnings, .. + } => { + print_on_success_library(silent_mode, proj_name, warnings); Ok(exports) } CompilationResult::Failure { errors, warnings } => { - let e_len = errors.len(); - - if !silent_mode { - warnings.iter().for_each(|warning| format_warning(warning)); - errors.into_iter().for_each(|error| format_err(&error)); - } - - println_red_err(&format!( - " Aborting due to {} {}.", - e_len, - if e_len > 1 { "errors" } else { "error" } - )) - .unwrap(); + print_on_failure(silent_mode, warnings, errors); Err(format!("Failed to compile {}", proj_name)) } _ => { @@ -288,22 +261,6 @@ fn compile_library<'source, 'manifest>( } } -fn format_err(err: &core_lang::CompileError) { - let mut fmt = Formatter::with_margin_color(Color::Blue); - let formatted = err.format(&mut fmt); - print_blue_err(" --> ").unwrap(); - print!("{}", err.path()); - println!("{}", formatted); -} - -fn format_warning(warning: &core_lang::CompileWarning) { - let mut fmt = Formatter::with_margin_color(Color::Blue); - let formatted = warning.format(&mut fmt); - print_blue_err(" --> ").unwrap(); - print!("{}", warning.path()); - println!("{}", formatted); -} - fn compile<'source, 'manifest>( source: &'source str, proj_name: &str, @@ -315,61 +272,15 @@ fn compile<'source, 'manifest>( let res = core_lang::compile_to_bytecode(&source, namespace, build_config, dependency_graph); match res { BytecodeCompilationResult::Success { bytes, warnings } => { - if !silent_mode { - warnings.iter().for_each(|warning| format_warning(warning)); - } - - if warnings.is_empty() { - let _ = println_green_err(&format!(" Compiled script {:?}.", proj_name)); - } else { - let _ = println_yellow_err(&format!( - " Compiled script {:?} with {} {}.", - proj_name, - warnings.len(), - if warnings.len() > 1 { - "warnings" - } else { - "warning" - } - )); - } + print_on_success_script(silent_mode, proj_name, warnings); return Ok(bytes); } BytecodeCompilationResult::Library { warnings } => { - if !silent_mode { - warnings.iter().for_each(|warning| format_warning(warning)); - } - - if warnings.is_empty() { - let _ = println_green_err(&format!(" Compiled library {:?}.", proj_name)); - } else { - let _ = println_yellow_err(&format!( - " Compiled library {:?} with {} {}.", - proj_name, - warnings.len(), - if warnings.len() > 1 { - "warnings" - } else { - "warning" - } - )); - } + print_on_success_library(silent_mode, proj_name, warnings); return Ok(vec![]); } BytecodeCompilationResult::Failure { errors, warnings } => { - let e_len = errors.len(); - - if !silent_mode { - warnings.iter().for_each(|warning| format_warning(warning)); - errors.into_iter().for_each(|error| format_err(&error)); - } - - println_red_err(&format!( - " Aborting due to {} {}.", - e_len, - if e_len > 1 { "errors" } else { "error" } - )) - .unwrap(); + print_on_failure(silent_mode, warnings, errors); return Err(format!("Failed to compile {}", proj_name)); } } diff --git a/forc/src/ops/mod.rs b/forc/src/ops/mod.rs index 72c9f18de0e..86bc785834d 100644 --- a/forc/src/ops/mod.rs +++ b/forc/src/ops/mod.rs @@ -1,3 +1,4 @@ +pub mod forc_abi_json; pub mod forc_build; pub mod forc_dep_check; pub mod forc_deploy; diff --git a/forc/src/utils/helpers.rs b/forc/src/utils/helpers.rs index 5cc269f6685..c1cb1f68405 100644 --- a/forc/src/utils/helpers.rs +++ b/forc/src/utils/helpers.rs @@ -1,5 +1,7 @@ use super::constants::{SRC_DIR, SWAY_EXTENSION}; use super::manifest::Manifest; +use core_lang::{CompileError, CompileWarning}; +use source_span::fmt::{Color, Formatter}; use std::ffi::OsStr; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -53,6 +55,23 @@ pub fn find_manifest_dir(starter_path: &PathBuf) -> Option { None } +pub fn find_main_path(manifest_dir: &PathBuf, manifest: &Manifest) -> PathBuf { + let mut code_dir = manifest_dir.clone(); + code_dir.push(crate::utils::constants::SRC_DIR); + code_dir.push(&manifest.project.entry); + code_dir +} + +pub fn find_file_name<'sc>(manifest_dir: &'sc PathBuf, main_path: &'sc PathBuf) -> Result<&'sc Path, String> { + let mut file_path = manifest_dir.clone(); + file_path.pop(); + let file_name = match main_path.strip_prefix(file_path.clone()) { + Ok(o) => o, + Err(err) => return Err(err.to_string()), + }; + Ok(file_name) +} + pub fn read_manifest(manifest_dir: &PathBuf) -> Result { let manifest_path = { let mut man = manifest_dir.clone(); @@ -93,6 +112,68 @@ pub fn get_main_file( return Ok(main_file); } +pub fn print_on_success_script(silent_mode: bool, proj_name: &str, warnings: Vec) { + if !silent_mode { + warnings.iter().for_each(|warning| format_warning(warning)); + } + + if warnings.is_empty() { + let _ = println_green_err(&format!(" Compiled script {:?}.", proj_name)); + } else { + let _ = println_yellow_err(&format!( + " Compiled script {:?} with {} {}.", + proj_name, + warnings.len(), + if warnings.len() > 1 { + "warnings" + } else { + "warning" + } + )); + } +} + +pub fn print_on_success_library(silent_mode: bool, proj_name: &str, warnings: Vec) { + if !silent_mode { + warnings.iter().for_each(|warning| format_warning(warning)); + } + + if warnings.is_empty() { + let _ = println_green_err(&format!(" Compiled script {:?}.", proj_name)); + } else { + let _ = println_yellow_err(&format!( + " Compiled library {:?} with {} {}.", + proj_name, + warnings.len(), + if warnings.len() > 1 { + "warnings" + } else { + "warning" + } + )); + } +} + +pub fn print_on_failure( + silent_mode: bool, + warnings: Vec, + errors: Vec, +) { + let e_len = errors.len(); + + if !silent_mode { + warnings.iter().for_each(|warning| format_warning(warning)); + errors.into_iter().for_each(|error| format_err(&error)); + } + + println_red_err(&format!( + " Aborting due to {} {}.", + e_len, + if e_len > 1 { "errors" } else { "error" } + )) + .unwrap(); +} + pub fn println_red(txt: &str) -> io::Result<()> { println_std_out(txt, TermColor::Red) } @@ -152,3 +233,19 @@ fn println_with_color(txt: &str, color: TermColor, stream: StandardStream) -> io stream.reset()?; Ok(()) } + +fn format_err(err: &core_lang::CompileError) { + let mut fmt = Formatter::with_margin_color(Color::Blue); + let formatted = err.format(&mut fmt); + print_blue_err(" --> ").unwrap(); + print!("{}", err.path()); + println!("{}", formatted); +} + +fn format_warning(warning: &core_lang::CompileWarning) { + let mut fmt = Formatter::with_margin_color(Color::Blue); + let formatted = warning.format(&mut fmt); + print_blue_err(" --> ").unwrap(); + print!("{}", warning.path()); + println!("{}", formatted); +} From 4c651da90eeda2519ebc99885472eee020922b24 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Tue, 16 Nov 2021 14:26:15 -0600 Subject: [PATCH 05/25] format --- core_lang/src/error.rs | 6 +++--- core_lang/src/semantic_analysis/ast_node/declaration.rs | 8 ++------ .../ast_node/expression/typed_expression.rs | 2 +- core_lang/src/semantic_analysis/ast_node/mod.rs | 2 +- forc/src/cli/commands/mod.rs | 2 +- forc/src/cli/mod.rs | 4 ++-- forc/src/ops/forc_abi_json.rs | 2 +- forc/src/ops/forc_build.rs | 5 +++-- forc/src/utils/helpers.rs | 5 ++++- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core_lang/src/error.rs b/core_lang/src/error.rs index ae6ace5e6ba..861d1590c5f 100644 --- a/core_lang/src/error.rs +++ b/core_lang/src/error.rs @@ -2,13 +2,13 @@ use crate::parser::Rule; use crate::span::Span; use crate::style::{to_screaming_snake_case, to_snake_case, to_upper_camel_case}; use crate::type_engine::{IntegerBits, TypeInfo}; -use std::fmt; -use thiserror::Error; +use line_col::LineColLookup; use source_span::{ fmt::{Formatter, Style}, Position, }; -use line_col::LineColLookup; +use std::fmt; +use thiserror::Error; macro_rules! check { ($fn_expr: expr, $error_recovery: expr, $warnings: ident, $errors: ident) => {{ diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index 0fb7606cf93..c225ce5da36 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -5,13 +5,9 @@ use super::{ use crate::parse_tree::*; use crate::semantic_analysis::Namespace; use crate::span::Span; -use crate::{ - build_config::BuildConfig, - error::*, - Ident, -}; -use crate::ControlFlowGraph; use crate::type_engine::*; +use crate::ControlFlowGraph; +use crate::{build_config::BuildConfig, error::*, Ident}; use core_types::JsonABI; diff --git a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs index 89c966387d5..e830dd338a4 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -4,8 +4,8 @@ use crate::control_flow_analysis::ControlFlowGraph; use crate::semantic_analysis::ast_node::*; use crate::type_engine::{insert_type, IntegerBits}; -use either::Either; use core_types::JsonABI; +use either::Either; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; diff --git a/core_lang/src/semantic_analysis/ast_node/mod.rs b/core_lang/src/semantic_analysis/ast_node/mod.rs index ba4c112d3ef..d98c649241d 100644 --- a/core_lang/src/semantic_analysis/ast_node/mod.rs +++ b/core_lang/src/semantic_analysis/ast_node/mod.rs @@ -6,8 +6,8 @@ use crate::span::Span; use crate::{control_flow_analysis::ControlFlowGraph, parse_tree::*}; use crate::{AstNode, AstNodeContent, Ident, ReturnStatement}; -use declaration::TypedTraitFn; use core_types::JsonABI; +use declaration::TypedTraitFn; pub(crate) use impl_trait::Mode; use std::sync::Arc; diff --git a/forc/src/cli/commands/mod.rs b/forc/src/cli/commands/mod.rs index 5867333c8ef..0e188a7aca9 100644 --- a/forc/src/cli/commands/mod.rs +++ b/forc/src/cli/commands/mod.rs @@ -1,8 +1,8 @@ -pub mod json_abi; pub mod build; pub mod deploy; pub mod format; pub mod init; +pub mod json_abi; pub mod parse_bytecode; pub mod run; pub mod test; diff --git a/forc/src/cli/mod.rs b/forc/src/cli/mod.rs index 47395e8f683..4d33852fcae 100644 --- a/forc/src/cli/mod.rs +++ b/forc/src/cli/mod.rs @@ -1,13 +1,13 @@ use structopt::StructOpt; mod commands; -use self::commands::{json_abi, build, deploy, format, init, parse_bytecode, run, test, update}; +use self::commands::{build, deploy, format, init, json_abi, parse_bytecode, run, test, update}; -pub use json_abi::Command as JsonAbiCommand; pub use build::Command as BuildCommand; pub use deploy::Command as DeployCommand; pub use format::Command as FormatCommand; use init::Command as InitCommand; +pub use json_abi::Command as JsonAbiCommand; use parse_bytecode::Command as ParseBytecodeCommand; pub use run::Command as RunCommand; use test::Command as TestCommand; diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index cd9a205da23..2fd57b199aa 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -52,7 +52,7 @@ pub fn build(command: JsonAbiCommand) -> Result, String> { ); let mut dependency_graph = HashMap::new(); - let mut json_abi = vec!(); + let mut json_abi = vec![]; let mut namespace: Namespace = Default::default(); if let Some(ref mut deps) = manifest.dependencies { diff --git a/forc/src/ops/forc_build.rs b/forc/src/ops/forc_build.rs index bde523f72d0..cce8b874552 100644 --- a/forc/src/ops/forc_build.rs +++ b/forc/src/ops/forc_build.rs @@ -3,7 +3,8 @@ use crate::{ cli::BuildCommand, utils::dependency, utils::helpers::{ - find_manifest_dir, read_manifest, get_main_file, print_on_success_library, print_on_success_script, print_on_failure + find_manifest_dir, get_main_file, print_on_failure, print_on_success_library, + print_on_success_script, read_manifest, }, }; @@ -12,9 +13,9 @@ use core_lang::{ }; use anyhow::Result; +use std::collections::{HashMap, HashSet}; use std::fs::File; use std::io::Write; -use std::collections::{HashMap, HashSet}; use std::path::{Path, PathBuf}; pub fn build(command: BuildCommand) -> Result, String> { diff --git a/forc/src/utils/helpers.rs b/forc/src/utils/helpers.rs index 65096c254fa..e6cb9e935d9 100644 --- a/forc/src/utils/helpers.rs +++ b/forc/src/utils/helpers.rs @@ -58,7 +58,10 @@ pub fn find_main_path(manifest_dir: &PathBuf, manifest: &Manifest) -> PathBuf { code_dir } -pub fn find_file_name<'sc>(manifest_dir: &'sc PathBuf, main_path: &'sc PathBuf) -> Result<&'sc Path, String> { +pub fn find_file_name<'sc>( + manifest_dir: &'sc PathBuf, + main_path: &'sc PathBuf, +) -> Result<&'sc Path, String> { let mut file_path = manifest_dir.clone(); file_path.pop(); let file_name = match main_path.strip_prefix(file_path.clone()) { From 878bf93ddd751ff84e821f7a7f5694e5ff4edb30 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Wed, 17 Nov 2021 16:31:30 -0600 Subject: [PATCH 06/25] Undo the mistakes of past. i.e. type inference means that the JsonABI object cannot be creating during type checking. --- core_lang/src/lib.rs | 267 +++--- .../semantic_analysis/ast_node/code_block.rs | 4 - .../semantic_analysis/ast_node/declaration.rs | 4 - .../ast_node/expression/enum_instantiation.rs | 4 - .../ast_node/expression/typed_expression.rs | 34 - .../typed_expression/method_application.rs | 8 - .../semantic_analysis/ast_node/impl_trait.rs | 6 - .../src/semantic_analysis/ast_node/mod.rs | 801 +++++++++--------- .../src/semantic_analysis/syntax_tree.rs | 4 - forc/src/cli/commands/json_abi.rs | 2 +- forc/src/ops/forc_abi_json.rs | 12 +- 11 files changed, 506 insertions(+), 640 deletions(-) diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index b9ed7286c4f..12d6b867730 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -243,8 +243,6 @@ pub(crate) fn compile_inner_dependency<'sc>( } } - let mut json_abi = vec![]; - let library_exports: LibraryExports = { let res: Vec<_> = parse_tree .library_exports @@ -257,7 +255,6 @@ pub(crate) fn compile_inner_dependency<'sc>( &build_config.clone(), dead_code_graph, dependency_graph, - &mut json_abi, ) .ok(&mut warnings, &mut errors) .map(|value| (name, value)) @@ -276,6 +273,7 @@ pub(crate) fn compile_inner_dependency<'sc>( } exports }; + // look for return path errors for tree in &library_exports.trees { let graph = ControlFlowGraph::construct_return_path_graph(tree); @@ -299,17 +297,17 @@ pub(crate) fn compile_inner_dependency<'sc>( ) } -fn compile_asts<'sc>( +pub fn compile_to_asm<'sc>( input: &'sc str, initial_namespace: &Namespace<'sc>, - build_config: &BuildConfig, + build_config: BuildConfig, dependency_graph: &mut HashMap>, -) -> CompileASTsResult<'sc> { +) -> CompilationResult<'sc> { let mut warnings = Vec::new(); let mut errors = Vec::new(); let parse_tree = check!( - parse(input, Some(build_config)), - return CompileASTsResult::Failure { errors, warnings }, + parse(input, Some(&build_config)), + return CompilationResult::Failure { errors, warnings }, warnings, errors ); @@ -319,8 +317,6 @@ fn compile_asts<'sc>( namespace: Default::default(), }; - let mut json_abi = vec![]; - let mut type_check_ast = |ast: Option<_>, tree_type| { ast.map(|tree| { TypedParseTree::type_check( @@ -330,7 +326,6 @@ fn compile_asts<'sc>( &build_config.clone(), &mut dead_code_graph, dependency_graph, - &mut json_abi, ) .ok(&mut warnings, &mut errors) }) @@ -353,7 +348,6 @@ fn compile_asts<'sc>( &build_config.clone(), &mut dead_code_graph, dependency_graph, - &mut json_abi, ) .ok(&mut warnings, &mut errors) .map(|value| (name, value)) @@ -374,159 +368,112 @@ fn compile_asts<'sc>( }; if !errors.is_empty() { - return CompileASTsResult::Failure { errors, warnings }; + return CompilationResult::Failure { errors, warnings }; } - CompileASTsResult::Success { - contract_ast, - predicate_ast, - script_ast, - library_exports, - json_abi, - dead_code_graph, - warnings, - } -} - -pub fn compile_to_asm<'sc>( - input: &'sc str, - initial_namespace: &Namespace<'sc>, - build_config: BuildConfig, - dependency_graph: &mut HashMap>, -) -> CompilationResult<'sc> { - match compile_asts(input, initial_namespace, &build_config, dependency_graph) { - CompileASTsResult::Failure { warnings, errors } => { - CompilationResult::Failure { warnings, errors } + // perform control flow analysis on each branch + let (script_warnings, script_errors) = + perform_control_flow_analysis(&script_ast, TreeType::Script, &mut dead_code_graph); + let (contract_warnings, contract_errors) = + perform_control_flow_analysis(&contract_ast, TreeType::Contract, &mut dead_code_graph); + let (predicate_warnings, predicate_errors) = + perform_control_flow_analysis(&predicate_ast, TreeType::Predicate, &mut dead_code_graph); + let (library_warnings, library_errors) = + perform_control_flow_analysis_on_library_exports(&library_exports, &mut dead_code_graph); + + let mut l_warnings = [ + script_warnings, + contract_warnings, + predicate_warnings, + library_warnings, + ] + .concat(); + let mut l_errors = [ + script_errors, + contract_errors, + predicate_errors, + library_errors, + ] + .concat(); + + errors.append(&mut l_errors); + warnings.append(&mut l_warnings); + // for each syntax tree, generate assembly. + let predicate_asm = (|| { + if let Some(tree) = predicate_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None } - CompileASTsResult::Success { - script_ast, - contract_ast, - library_exports, - predicate_ast, - mut dead_code_graph, - mut warnings, - json_abi, - } => { - let mut errors = vec![]; - - // perform control flow analysis on each branch - let (script_warnings, script_errors) = - perform_control_flow_analysis(&script_ast, TreeType::Script, &mut dead_code_graph); - let (contract_warnings, contract_errors) = perform_control_flow_analysis( - &contract_ast, - TreeType::Contract, - &mut dead_code_graph, - ); - let (predicate_warnings, predicate_errors) = perform_control_flow_analysis( - &predicate_ast, - TreeType::Predicate, - &mut dead_code_graph, - ); - let (library_warnings, library_errors) = - perform_control_flow_analysis_on_library_exports( - &library_exports, - &mut dead_code_graph, - ); - - let mut l_warnings = [ - script_warnings, - contract_warnings, - predicate_warnings, - library_warnings, - ] - .concat(); - let mut l_errors = [ - script_errors, - contract_errors, - predicate_errors, - library_errors, - ] - .concat(); - - errors.append(&mut l_errors); - warnings.append(&mut l_warnings); - // for each syntax tree, generate assembly. - let predicate_asm = (|| { - if let Some(tree) = predicate_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None - } - })(); - - let contract_asm = (|| { - if let Some(tree) = contract_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None - } - })(); - - let script_asm = (|| { - if let Some(tree) = script_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None - } - })(); - - if errors.is_empty() { - // TODO move this check earlier and don't compile all of them if there is only one - match (predicate_asm, contract_asm, script_asm, library_exports) { - (Some(pred), None, None, o) if o.trees.is_empty() => { - CompilationResult::Success { - asm: pred, - json_abi, - warnings, - } - } - (None, Some(contract), None, o) if o.trees.is_empty() => { - CompilationResult::Success { - asm: contract, - json_abi, - warnings, - } - } - (None, None, Some(script), o) if o.trees.is_empty() => { - CompilationResult::Success { - asm: script, - json_abi, - warnings, - } - } - (None, None, None, o) if !o.trees.is_empty() => CompilationResult::Library { - warnings, - json_abi, - exports: o, - }, - (None, None, None, o) if o.trees.is_empty() => { - todo!("do we want empty files to be valid programs?") - } - // Default to compiling an empty library if there is no code or invalid state - _ => unimplemented!( - "Multiple contracts, libraries, scripts, or predicates in a single file are \ - unsupported." - ), - } - } else { - CompilationResult::Failure { errors, warnings } + })(); + + let contract_asm = (|| { + if let Some(tree) = contract_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None + } + })(); + + let script_asm = (|| { + if let Some(tree) = script_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None + } + })(); + + let json_abi = vec![]; + + if errors.is_empty() { + // TODO move this check earlier and don't compile all of them if there is only one + match (predicate_asm, contract_asm, script_asm, library_exports) { + (Some(pred), None, None, o) if o.trees.is_empty() => CompilationResult::Success { + asm: pred, + json_abi, + warnings, + }, + (None, Some(contract), None, o) if o.trees.is_empty() => CompilationResult::Success { + asm: contract, + json_abi, + warnings, + }, + (None, None, Some(script), o) if o.trees.is_empty() => CompilationResult::Success { + asm: script, + json_abi, + warnings, + }, + (None, None, None, o) if !o.trees.is_empty() => CompilationResult::Library { + warnings, + json_abi, + exports: o, + }, + (None, None, None, o) if o.trees.is_empty() => { + todo!("do we want empty files to be valid programs?") } + // Default to compiling an empty library if there is no code or invalid state + _ => unimplemented!( + "Multiple contracts, libraries, scripts, or predicates in a single file are \ + unsupported." + ), } + } else { + CompilationResult::Failure { errors, warnings } } } diff --git a/core_lang/src/semantic_analysis/ast_node/code_block.rs b/core_lang/src/semantic_analysis/ast_node/code_block.rs index d8b84c4ac2b..ab20df4461f 100644 --- a/core_lang/src/semantic_analysis/ast_node/code_block.rs +++ b/core_lang/src/semantic_analysis/ast_node/code_block.rs @@ -1,5 +1,3 @@ -use core_types::JsonABI; - use super::*; use crate::build_config::BuildConfig; use crate::control_flow_analysis::ControlFlowGraph; @@ -24,7 +22,6 @@ impl<'sc> TypedCodeBlock<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, (Self, TypeId)> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -45,7 +42,6 @@ impl<'sc> TypedCodeBlock<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ) .ok(&mut warnings, &mut errors) }) diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index c225ce5da36..49cbf9c40ee 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -9,8 +9,6 @@ use crate::type_engine::*; use crate::ControlFlowGraph; use crate::{build_config::BuildConfig, error::*, Ident}; -use core_types::JsonABI; - use sha2::{Digest, Sha256}; use std::collections::{HashMap, HashSet}; @@ -581,7 +579,6 @@ impl<'sc> TypedFunctionDeclaration<'sc> { dead_code_graph: &mut ControlFlowGraph<'sc>, mode: Mode, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedFunctionDeclaration<'sc>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -628,7 +625,6 @@ impl<'sc> TypedFunctionDeclaration<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), ( TypedCodeBlock { diff --git a/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs b/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs index 7fa04874e24..873202d25d9 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/enum_instantiation.rs @@ -1,5 +1,3 @@ -use core_types::JsonABI; - use crate::build_config::BuildConfig; use crate::control_flow_analysis::ControlFlowGraph; use crate::error::*; @@ -18,7 +16,6 @@ pub(crate) fn instantiate_enum<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -74,7 +71,6 @@ pub(crate) fn instantiate_enum<'sc>( build_config, dead_code_graph, dependency_graph, - json_abi ), return err(warnings, errors), warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs index e830dd338a4..dd3b84ddd33 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -4,7 +4,6 @@ use crate::control_flow_analysis::ControlFlowGraph; use crate::semantic_analysis::ast_node::*; use crate::type_engine::{insert_type, IntegerBits}; -use core_types::JsonABI; use either::Either; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; @@ -42,7 +41,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, Self> { let expr_span = other.span(); let res = match other { @@ -66,7 +64,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), Expression::LazyOperator { op, lhs, rhs, span } => Self::type_check_lazy_operator( op, @@ -78,7 +75,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), Expression::MatchExpression { span, .. } => { let errors = vec![CompileError::Unimplemented( @@ -97,7 +93,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), // TODO if _condition_ is constant, evaluate it and compile this to an // expression with only one branch @@ -117,7 +112,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), Expression::AsmExpression { asm, span, .. } => Self::type_check_asm_expression( asm, @@ -127,7 +121,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), Expression::StructExpression { span, @@ -142,7 +135,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), Expression::SubfieldExpression { prefix, @@ -157,7 +149,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), Expression::MethodApplication { method_name, @@ -172,7 +163,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), Expression::Unit { span } => { let exp = TypedExpression { @@ -198,7 +188,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), Expression::AbiCast { abi_name, @@ -213,7 +202,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ), a => { let errors = vec![CompileError::Unimplemented( @@ -339,7 +327,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -410,7 +397,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ) .unwrap_or_else( &mut warnings, @@ -459,7 +445,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -474,7 +459,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(lhs.span()), warnings, @@ -491,7 +475,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(rhs.span()), warnings, @@ -581,7 +564,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -596,7 +578,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), ( TypedCodeBlock { @@ -645,7 +626,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -659,7 +639,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(condition.span()), warnings, @@ -675,7 +654,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(then.span()), warnings, @@ -692,7 +670,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(expr.span()), warnings, @@ -731,7 +708,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -760,7 +736,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(initializer.span()), warnings, @@ -794,7 +769,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -856,7 +830,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), continue, warnings, @@ -908,7 +881,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -922,7 +894,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), return err(warnings, errors), warnings, @@ -981,7 +952,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -1036,7 +1006,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), return err(warnings, errors), warnings, @@ -1074,7 +1043,6 @@ impl<'sc> TypedExpression<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -1094,7 +1062,6 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(err_span), warnings, @@ -1142,7 +1109,6 @@ impl<'sc> TypedExpression<'sc> { dead_code_graph, Mode::ImplAbiFn, dependency_graph, - json_abi ), return err(warnings, errors), warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index dc457e72fd2..61950af985b 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -7,8 +7,6 @@ use crate::parser::{HllParser, Rule}; use pest::Parser; use std::collections::{HashMap, VecDeque}; -use core_types::JsonABI; - pub(crate) fn type_check_method_application<'sc>( method_name: MethodName<'sc>, arguments: Vec>, @@ -18,7 +16,6 @@ pub(crate) fn type_check_method_application<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedExpression<'sc>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -34,7 +31,6 @@ pub(crate) fn type_check_method_application<'sc>( build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(span.clone()), warnings, @@ -156,7 +152,6 @@ pub(crate) fn type_check_method_application<'sc>( self_type, dead_code_graph, dependency_graph, - json_abi ), return err(warnings, errors), warnings, @@ -230,7 +225,6 @@ pub(crate) fn type_check_method_application<'sc>( self_type, dead_code_graph, dependency_graph, - json_abi ), return err(warnings, errors), warnings, @@ -264,7 +258,6 @@ fn re_parse_expression<'a>( self_type: TypeId, dead_code_graph: &mut ControlFlowGraph<'a>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'a, TypedExpression<'a>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -311,7 +304,6 @@ fn re_parse_expression<'a>( build_config, dead_code_graph, dependency_graph, - json_abi ), return err(warnings, errors), warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/impl_trait.rs b/core_lang/src/semantic_analysis/ast_node/impl_trait.rs index 3d1d69ff7dd..15be6f5c1b2 100644 --- a/core_lang/src/semantic_analysis/ast_node/impl_trait.rs +++ b/core_lang/src/semantic_analysis/ast_node/impl_trait.rs @@ -19,7 +19,6 @@ pub(crate) fn implementation_of_trait<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedDeclaration<'sc>> { let mut errors = vec![]; let mut warnings = vec![]; @@ -71,7 +70,6 @@ pub(crate) fn implementation_of_trait<'sc>( &type_implementing_for_span, Mode::NonAbi, dependency_graph, - json_abi ), return err(warnings, errors), warnings, @@ -131,7 +129,6 @@ pub(crate) fn implementation_of_trait<'sc>( &type_implementing_for_span, Mode::ImplAbiFn, dependency_graph, - json_abi ), return err(warnings, errors), warnings, @@ -187,7 +184,6 @@ fn type_check_trait_implementation<'sc>( type_implementing_for_span: &Span<'sc>, mode: Mode, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, Vec>> { let mut functions_buf: Vec = vec![]; let mut errors = vec![]; @@ -216,7 +212,6 @@ fn type_check_trait_implementation<'sc>( dead_code_graph, mode, dependency_graph, - json_abi ), continue, warnings, @@ -381,7 +376,6 @@ fn type_check_trait_implementation<'sc>( dead_code_graph, mode, dependency_graph, - json_abi ), continue, warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/mod.rs b/core_lang/src/semantic_analysis/ast_node/mod.rs index d98c649241d..a77d6817f76 100644 --- a/core_lang/src/semantic_analysis/ast_node/mod.rs +++ b/core_lang/src/semantic_analysis/ast_node/mod.rs @@ -6,7 +6,7 @@ use crate::span::Span; use crate::{control_flow_analysis::ControlFlowGraph, parse_tree::*}; use crate::{AstNode, AstNodeContent, Ident, ReturnStatement}; -use core_types::JsonABI; +use core_types::{Function, JsonABI, Property}; use declaration::TypedTraitFn; pub(crate) use impl_trait::Mode; use std::sync::Arc; @@ -102,7 +102,6 @@ impl<'sc> TypedAstNode<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedAstNode<'sc>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -123,459 +122,449 @@ impl<'sc> TypedAstNode<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ) }; - let node = TypedAstNode { - content: match node.content.clone() { - AstNodeContent::UseStatement(a) => { - let mut res = match a.import_type { - ImportType::Star => namespace.star_import(a.call_path, a.is_absolute), - ImportType::Item(s) => { - namespace.item_import(a.call_path, &s, a.is_absolute, a.alias) + let content = match node.content.clone() { + AstNodeContent::UseStatement(a) => { + let mut res = match a.import_type { + ImportType::Star => namespace.star_import(a.call_path, a.is_absolute), + ImportType::Item(s) => { + namespace.item_import(a.call_path, &s, a.is_absolute, a.alias) + } + }; + warnings.append(&mut res.warnings); + errors.append(&mut res.errors); + TypedAstNodeContent::SideEffect + } + AstNodeContent::IncludeStatement(ref a) => { + // Import the file, parse it, put it in the namespace under the module name (alias or + // last part of the import by default) + let _ = check!( + import_new_file( + a, + namespace, + build_config, + dead_code_graph, + dependency_graph + ), + return err(warnings, errors), + warnings, + errors + ); + TypedAstNodeContent::SideEffect + } + AstNodeContent::Declaration(a) => { + TypedAstNodeContent::Declaration(match a { + Declaration::VariableDeclaration(VariableDeclaration { + name, + type_ascription, + body, + is_mutable, + }) => { + let result = type_check_ascribed_expr(type_ascription, body, "Variable"); + let body = check!( + result, + error_recovery_expr(name.span.clone()), + warnings, + errors + ); + let typed_var_decl = + TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { + name: name.clone(), + body, + is_mutable, + }); + namespace.insert(name, typed_var_decl.clone()); + typed_var_decl + } + Declaration::ConstantDeclaration(ConstantDeclaration { + name, + type_ascription, + value, + visibility, + }) => { + let result = type_check_ascribed_expr(type_ascription, value, "Constant"); + let value = check!( + result, + error_recovery_expr(name.span.clone()), + warnings, + errors + ); + let typed_const_decl = + TypedDeclaration::ConstantDeclaration(TypedConstantDeclaration { + name: name.clone(), + value, + visibility, + }); + namespace.insert(name, typed_const_decl.clone()); + typed_const_decl + } + Declaration::EnumDeclaration(e) => { + let span = e.span.clone(); + let primary_name = e.name.primary_name; + let decl = TypedDeclaration::EnumDeclaration( + e.to_typed_decl(namespace, self_type), + ); + + namespace.insert(Ident { primary_name, span }, decl.clone()); + decl + } + Declaration::FunctionDeclaration(fn_decl) => { + let decl = check!( + TypedFunctionDeclaration::type_check( + fn_decl.clone(), + namespace, + crate::type_engine::insert_type(TypeInfo::Unknown), + "", + self_type, + build_config, + dead_code_graph, + Mode::NonAbi, + dependency_graph, + ), + error_recovery_function_declaration(fn_decl), + warnings, + errors + ); + if errors.is_empty() { + // Add this function declaration to the namespace only if it + // fully typechecked without errors. + namespace.insert( + decl.name.clone(), + TypedDeclaration::FunctionDeclaration(decl.clone()), + ); } - }; - warnings.append(&mut res.warnings); - errors.append(&mut res.errors); - TypedAstNodeContent::SideEffect - } - AstNodeContent::IncludeStatement(ref a) => { - // Import the file, parse it, put it in the namespace under the module name (alias or - // last part of the import by default) - let _ = check!( - import_new_file( - a, + TypedDeclaration::FunctionDeclaration(decl) + } + Declaration::TraitDeclaration(TraitDeclaration { + name, + interface_surface, + methods, + type_parameters, + visibility, + }) => { + // type check the interface surface + let interface_surface = + type_check_interface_surface(interface_surface, namespace); + let mut trait_namespace = namespace.clone(); + // insert placeholder functions representing the interface surface + // to allow methods to use those functions + trait_namespace.insert_trait_implementation( + CallPath { + prefixes: vec![], + suffix: name.clone(), + }, + TypeInfo::SelfType, + interface_surface + .iter() + .map(|x| x.to_dummy_func(Mode::NonAbi)) + .collect(), + ); + // check the methods for errors but throw them away and use vanilla [FunctionDeclaration]s + let _methods = check!( + type_check_trait_methods( + methods.clone(), + &trait_namespace, + insert_type(TypeInfo::SelfType), + build_config, + dead_code_graph, + dependency_graph, + ), + vec![], + warnings, + errors + ); + let trait_decl = + TypedDeclaration::TraitDeclaration(TypedTraitDeclaration { + name: name.clone(), + interface_surface, + methods, + type_parameters, + visibility, + }); + namespace.insert(name, trait_decl.clone()); + trait_decl + } + Declaration::Reassignment(Reassignment { lhs, rhs, span }) => { + check!( + reassignment( + lhs, + rhs, + span, + namespace, + self_type, + build_config, + dead_code_graph, + dependency_graph, + ), + return err(warnings, errors), + warnings, + errors + ) + } + Declaration::ImplTrait(impl_trait) => check!( + implementation_of_trait( + impl_trait, namespace, build_config, dead_code_graph, - dependency_graph + dependency_graph, ), return err(warnings, errors), warnings, errors - ); - TypedAstNodeContent::SideEffect - } - AstNodeContent::Declaration(a) => { - TypedAstNodeContent::Declaration(match a { - Declaration::VariableDeclaration(VariableDeclaration { - name, - type_ascription, - body, - is_mutable, - }) => { - let result = - type_check_ascribed_expr(type_ascription, body, "Variable"); - let body = check!( - result, - error_recovery_expr(name.span.clone()), - warnings, - errors - ); - let typed_var_decl = - TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { - name: name.clone(), - body, - is_mutable, - }); - namespace.insert(name, typed_var_decl.clone()); - typed_var_decl - } - Declaration::ConstantDeclaration(ConstantDeclaration { - name, - type_ascription, - value, - visibility, - }) => { - let result = - type_check_ascribed_expr(type_ascription, value, "Constant"); - let value = check!( - result, - error_recovery_expr(name.span.clone()), - warnings, - errors - ); - let typed_const_decl = - TypedDeclaration::ConstantDeclaration(TypedConstantDeclaration { - name: name.clone(), - value, - visibility, - }); - namespace.insert(name, typed_const_decl.clone()); - typed_const_decl + ), + + Declaration::ImplSelf(ImplSelf { + type_arguments, + functions, + type_implementing_for, + block_span, + .. + }) => { + let implementing_for_type_id = + namespace.resolve_type_without_self(&type_implementing_for); + // check, if this is a custom type, if it is in scope or a generic. + let mut functions_buf: Vec = vec![]; + if !type_arguments.is_empty() { + errors.push(CompileError::Internal( + "Where clauses are not supported yet.", + type_arguments[0].clone().name_ident.span, + )); } - Declaration::EnumDeclaration(e) => { - let span = e.span.clone(); - let primary_name = e.name.primary_name; - let decl = TypedDeclaration::EnumDeclaration( - e.to_typed_decl(namespace, self_type), + for mut fn_decl in functions.into_iter() { + let mut type_arguments = type_arguments.clone(); + // add generic params from impl trait into function type params + fn_decl.type_parameters.append(&mut type_arguments); + // ensure this fn decl's parameters and signature lines up with the + // one in the trait + + // replace SelfType with type of implementor + // i.e. fn add(self, other: u64) -> Self becomes fn + // add(self: u64, other: u64) -> u64 + fn_decl.parameters.iter_mut().for_each( + |FunctionParameter { ref mut r#type, .. }| { + if r#type == &TypeInfo::SelfType { + *r#type = type_implementing_for.clone(); + } + }, ); + if fn_decl.return_type == TypeInfo::SelfType { + fn_decl.return_type = type_implementing_for.clone(); + } - namespace.insert(Ident { primary_name, span }, decl.clone()); - decl - } - Declaration::FunctionDeclaration(fn_decl) => { - let decl = check!( + functions_buf.push(check!( TypedFunctionDeclaration::type_check( - fn_decl.clone(), + fn_decl, namespace, crate::type_engine::insert_type(TypeInfo::Unknown), "", - self_type, + implementing_for_type_id, build_config, dead_code_graph, Mode::NonAbi, dependency_graph, - json_abi ), - error_recovery_function_declaration(fn_decl), + continue, warnings, errors - ); - if errors.is_empty() { - // Add this function declaration to the namespace only if it - // fully typechecked without errors. - namespace.insert( - decl.name.clone(), - TypedDeclaration::FunctionDeclaration(decl.clone()), - ); - } - TypedDeclaration::FunctionDeclaration(decl) + )); } - Declaration::TraitDeclaration(TraitDeclaration { - name, - interface_surface, - methods, - type_parameters, - visibility, - }) => { - // type check the interface surface - let interface_surface = - type_check_interface_surface(interface_surface, namespace); - let mut trait_namespace = namespace.clone(); - // insert placeholder functions representing the interface surface - // to allow methods to use those functions - trait_namespace.insert_trait_implementation( - CallPath { - prefixes: vec![], - suffix: name.clone(), - }, - TypeInfo::SelfType, - interface_surface - .iter() - .map(|x| x.to_dummy_func(Mode::NonAbi)) - .collect(), - ); - // check the methods for errors but throw them away and use vanilla [FunctionDeclaration]s - let _methods = check!( - type_check_trait_methods( - methods.clone(), - &trait_namespace, - insert_type(TypeInfo::SelfType), - build_config, - dead_code_graph, - dependency_graph, - json_abi - ), - vec![], - warnings, - errors - ); - let trait_decl = - TypedDeclaration::TraitDeclaration(TypedTraitDeclaration { - name: name.clone(), - interface_surface, - methods, - type_parameters, - visibility, - }); - namespace.insert(name, trait_decl.clone()); - trait_decl - } - Declaration::Reassignment(Reassignment { lhs, rhs, span }) => { - check!( - reassignment( - lhs, - rhs, - span, - namespace, - self_type, - build_config, - dead_code_graph, - dependency_graph, - json_abi - ), - return err(warnings, errors), - warnings, - errors - ) + let trait_name = CallPath { + prefixes: vec![], + suffix: Ident { + primary_name: "r#Self", + span: block_span.clone(), + }, + }; + namespace.insert_trait_implementation( + trait_name.clone(), + look_up_type_id(implementing_for_type_id), + functions_buf.clone(), + ); + TypedDeclaration::ImplTrait { + trait_name, + span: block_span, + methods: functions_buf, + type_implementing_for, } - Declaration::ImplTrait(impl_trait) => check!( - implementation_of_trait( - impl_trait, + } + Declaration::StructDeclaration(decl) => { + // look up any generic or struct types in the namespace + let fields = decl + .fields + .into_iter() + .map(|StructField { name, r#type, span }| TypedStructField { + name, + r#type: namespace.resolve_type_with_self(r#type, self_type), + span, + }) + .collect::>(); + let decl = TypedStructDeclaration { + name: decl.name.clone(), + type_parameters: decl.type_parameters.clone(), + fields, + visibility: decl.visibility, + }; + + // insert struct into namespace + namespace.insert( + decl.name.clone(), + TypedDeclaration::StructDeclaration(decl.clone()), + ); + + TypedDeclaration::StructDeclaration(decl) + } + Declaration::AbiDeclaration(AbiDeclaration { + name, + interface_surface, + methods, + span, + }) => { + // type check the interface surface and methods + // We don't want the user to waste resources by contract calling + // themselves, and we don't want to do more work in the compiler, + // so we don't support the case of calling a contract's own interface + // from itself. This is by design. + let interface_surface = + type_check_interface_surface(interface_surface, namespace); + // type check these for errors but don't actually use them yet -- the real + // ones will be type checked with proper symbols when the ABI is implemented + let methodz = check!( + type_check_trait_methods( + methods.clone(), namespace, + self_type, build_config, dead_code_graph, dependency_graph, - json_abi ), - return err(warnings, errors), + vec![], warnings, errors - ), - - Declaration::ImplSelf(ImplSelf { - type_arguments, - functions, - type_implementing_for, - block_span, - .. - }) => { - let implementing_for_type_id = - namespace.resolve_type_without_self(&type_implementing_for); - // check, if this is a custom type, if it is in scope or a generic. - let mut functions_buf: Vec = vec![]; - if !type_arguments.is_empty() { - errors.push(CompileError::Internal( - "Where clauses are not supported yet.", - type_arguments[0].clone().name_ident.span, - )); - } - for mut fn_decl in functions.into_iter() { - let mut type_arguments = type_arguments.clone(); - // add generic params from impl trait into function type params - fn_decl.type_parameters.append(&mut type_arguments); - // ensure this fn decl's parameters and signature lines up with the - // one in the trait - - // replace SelfType with type of implementor - // i.e. fn add(self, other: u64) -> Self becomes fn - // add(self: u64, other: u64) -> u64 - fn_decl.parameters.iter_mut().for_each( - |FunctionParameter { ref mut r#type, .. }| { - if r#type == &TypeInfo::SelfType { - *r#type = type_implementing_for.clone(); - } - }, - ); - if fn_decl.return_type == TypeInfo::SelfType { - fn_decl.return_type = type_implementing_for.clone(); - } - - functions_buf.push(check!( - TypedFunctionDeclaration::type_check( - fn_decl, - namespace, - crate::type_engine::insert_type(TypeInfo::Unknown), - "", - implementing_for_type_id, - build_config, - dead_code_graph, - Mode::NonAbi, - dependency_graph, - json_abi - ), - continue, - warnings, - errors - )); - } - let trait_name = CallPath { - prefixes: vec![], - suffix: Ident { - primary_name: "r#Self", - span: block_span.clone(), - }, - }; - namespace.insert_trait_implementation( - trait_name.clone(), - look_up_type_id(implementing_for_type_id), - functions_buf.clone(), - ); - TypedDeclaration::ImplTrait { - trait_name, - span: block_span, - methods: functions_buf, - type_implementing_for, - } - } - Declaration::StructDeclaration(decl) => { - // look up any generic or struct types in the namespace - let fields = decl - .fields - .into_iter() - .map(|StructField { name, r#type, span }| TypedStructField { - name, - r#type: namespace.resolve_type_with_self(r#type, self_type), - span, - }) - .collect::>(); - let decl = TypedStructDeclaration { - name: decl.name.clone(), - type_parameters: decl.type_parameters.clone(), - fields, - visibility: decl.visibility, - }; + ); - // insert struct into namespace - namespace.insert( - decl.name.clone(), - TypedDeclaration::StructDeclaration(decl.clone()), - ); + println!("{:?}", methodz); - TypedDeclaration::StructDeclaration(decl) - } - Declaration::AbiDeclaration(AbiDeclaration { - name, + let decl = TypedDeclaration::AbiDeclaration(TypedAbiDeclaration { interface_surface, methods, + name: name.clone(), span, - }) => { - // type check the interface surface and methods - // We don't want the user to waste resources by contract calling - // themselves, and we don't want to do more work in the compiler, - // so we don't support the case of calling a contract's own interface - // from itself. This is by design. - let interface_surface = - type_check_interface_surface(interface_surface, namespace); - // type check these for errors but don't actually use them yet -- the real - // ones will be type checked with proper symbols when the ABI is implemented - let _methods = check!( - type_check_trait_methods( - methods.clone(), - namespace, - self_type, - build_config, - dead_code_graph, - dependency_graph, - json_abi - ), - vec![], - warnings, - errors - ); - - let decl = TypedDeclaration::AbiDeclaration(TypedAbiDeclaration { - interface_surface, - methods, - name: name.clone(), - span, - }); - namespace.insert(name, decl.clone()); - decl - } - }) - } - AstNodeContent::Expression(a) => { - let inner = check!( - TypedExpression::type_check( - a.clone(), - namespace, - None, - "", - self_type, - build_config, - dead_code_graph, - dependency_graph, - json_abi - ), - error_recovery_expr(a.span()), - warnings, - errors - ); - TypedAstNodeContent::Expression(inner) - } - AstNodeContent::ReturnStatement(ReturnStatement { expr }) => { - TypedAstNodeContent::ReturnStatement(TypedReturnStatement { - expr: check!( - TypedExpression::type_check( - expr.clone(), - namespace, - Some(return_type_annotation), - "Returned value must match up with the function return type \ - annotation.", - self_type, - build_config, - dead_code_graph, - dependency_graph, - json_abi - ), - error_recovery_expr(expr.span()), - warnings, - errors - ), - }) - } - AstNodeContent::ImplicitReturnExpression(expr) => { - let typed_expr = check!( + }); + namespace.insert(name, decl.clone()); + decl + } + }) + } + AstNodeContent::Expression(a) => { + let inner = check!( + TypedExpression::type_check( + a.clone(), + namespace, + None, + "", + self_type, + build_config, + dead_code_graph, + dependency_graph, + ), + error_recovery_expr(a.span()), + warnings, + errors + ); + TypedAstNodeContent::Expression(inner) + } + AstNodeContent::ReturnStatement(ReturnStatement { expr }) => { + TypedAstNodeContent::ReturnStatement(TypedReturnStatement { + expr: check!( TypedExpression::type_check( expr.clone(), namespace, Some(return_type_annotation), - format!( - "Implicit return must match up with block's type. {}", - help_text.into() - ), + "Returned value must match up with the function return type \ + annotation.", self_type, build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(expr.span()), warnings, errors - ); - TypedAstNodeContent::ImplicitReturnExpression(typed_expr) - } - AstNodeContent::WhileLoop(WhileLoop { condition, body }) => { - let typed_condition = check!( - TypedExpression::type_check( - condition, - namespace, - Some(crate::type_engine::insert_type(TypeInfo::Boolean)), - "A while loop's loop condition must be a boolean expression.", - self_type, - build_config, - dead_code_graph, - dependency_graph, - json_abi - ), - return err(warnings, errors), - warnings, - errors - ); - let (typed_body, _block_implicit_return) = check!( - TypedCodeBlock::type_check( - body.clone(), - namespace, - crate::type_engine::insert_type(TypeInfo::Unit), - "A while loop's loop body cannot implicitly return a value.Try \ - assigning it to a mutable variable declared outside of the loop \ - instead.", - self_type, - build_config, - dead_code_graph, - dependency_graph, - json_abi - ), - ( - TypedCodeBlock { - contents: vec![], - whole_block_span: body.whole_block_span.clone(), - }, - crate::type_engine::insert_type(TypeInfo::Unit) + ), + }) + } + AstNodeContent::ImplicitReturnExpression(expr) => { + let typed_expr = check!( + TypedExpression::type_check( + expr.clone(), + namespace, + Some(return_type_annotation), + format!( + "Implicit return must match up with block's type. {}", + help_text.into() ), - warnings, - errors - ); - TypedAstNodeContent::WhileLoop(TypedWhileLoop { - condition: typed_condition, - body: typed_body, - }) - } - }, + self_type, + build_config, + dead_code_graph, + dependency_graph, + ), + error_recovery_expr(expr.span()), + warnings, + errors + ); + TypedAstNodeContent::ImplicitReturnExpression(typed_expr) + } + AstNodeContent::WhileLoop(WhileLoop { condition, body }) => { + let typed_condition = check!( + TypedExpression::type_check( + condition, + namespace, + Some(crate::type_engine::insert_type(TypeInfo::Boolean)), + "A while loop's loop condition must be a boolean expression.", + self_type, + build_config, + dead_code_graph, + dependency_graph, + ), + return err(warnings, errors), + warnings, + errors + ); + let (typed_body, _block_implicit_return) = check!( + TypedCodeBlock::type_check( + body.clone(), + namespace, + crate::type_engine::insert_type(TypeInfo::Unit), + "A while loop's loop body cannot implicitly return a value.Try \ + assigning it to a mutable variable declared outside of the loop \ + instead.", + self_type, + build_config, + dead_code_graph, + dependency_graph, + ), + ( + TypedCodeBlock { + contents: vec![], + whole_block_span: body.whole_block_span.clone(), + }, + crate::type_engine::insert_type(TypeInfo::Unit) + ), + warnings, + errors + ); + TypedAstNodeContent::WhileLoop(TypedWhileLoop { + condition: typed_condition, + body: typed_body, + }) + } + }; + + let node = TypedAstNode { + content, span: node.span.clone(), }; @@ -700,7 +689,6 @@ fn reassignment<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, TypedDeclaration<'sc>> { let mut errors = vec![]; let mut warnings = vec![]; @@ -756,7 +744,6 @@ fn reassignment<'sc>( build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(span), warnings, @@ -793,7 +780,6 @@ fn reassignment<'sc>( build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(expr.span()), warnings, @@ -858,7 +844,6 @@ fn reassignment<'sc>( build_config, dead_code_graph, dependency_graph, - json_abi ), error_recovery_expr(span), warnings, @@ -929,7 +914,6 @@ fn type_check_trait_methods<'sc>( build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, Vec>> { let mut warnings = vec![]; let mut errors = vec![]; @@ -1047,7 +1031,6 @@ fn type_check_trait_methods<'sc>( build_config, dead_code_graph, dependency_graph, - json_abi ), continue, warnings, diff --git a/core_lang/src/semantic_analysis/syntax_tree.rs b/core_lang/src/semantic_analysis/syntax_tree.rs index 63b77f8e4d0..fb2b86bc6bd 100644 --- a/core_lang/src/semantic_analysis/syntax_tree.rs +++ b/core_lang/src/semantic_analysis/syntax_tree.rs @@ -76,7 +76,6 @@ impl<'sc> TypedParseTree<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, Self> { let mut new_namespace = initial_namespace.clone(); let mut warnings = Vec::new(); @@ -107,7 +106,6 @@ impl<'sc> TypedParseTree<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi ), return err(warnings, errors), warnings, @@ -163,7 +161,6 @@ impl<'sc> TypedParseTree<'sc> { build_config: &BuildConfig, dead_code_graph: &mut ControlFlowGraph<'sc>, dependency_graph: &mut HashMap>, - json_abi: &mut JsonABI, ) -> CompileResult<'sc, Vec>> { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -181,7 +178,6 @@ impl<'sc> TypedParseTree<'sc> { build_config, dead_code_graph, dependency_graph, - json_abi, ) }) .filter_map(|res| res.ok(&mut warnings, &mut errors)) diff --git a/forc/src/cli/commands/json_abi.rs b/forc/src/cli/commands/json_abi.rs index 4c883df83d3..c799020ba2b 100644 --- a/forc/src/cli/commands/json_abi.rs +++ b/forc/src/cli/commands/json_abi.rs @@ -1,7 +1,7 @@ use crate::ops::forc_abi_json; use structopt::{self, StructOpt}; -/// Compile the current or target project. +/// Output the JSON associated with the ABI. #[derive(Debug, StructOpt)] pub struct Command { /// Path to the project, if not specified, current working directory will be used. diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index 2fd57b199aa..052e1d75c84 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -47,7 +47,7 @@ pub fn build(command: JsonAbiCommand) -> Result, String> { let file_name = find_file_name(&manifest_dir, &main_path)?; let build_config = BuildConfig::root_from_file_name_and_manifest_path( - file_name.to_owned().to_path_buf(), + file_name.to_owned(), manifest_dir.clone(), ); @@ -92,8 +92,8 @@ pub fn build(command: JsonAbiCommand) -> Result, String> { json_abi.append(&mut compile_dependency_lib( &this_dir, - &dependency_name, - &dependency_details, + dependency_name, + dependency_details, &mut namespace, &mut dependency_graph, silent_mode, @@ -166,7 +166,7 @@ fn compile_dependency_lib<'source, 'manifest>( let file_name = find_file_name(&manifest_dir, &main_path)?; let build_config = BuildConfig::root_from_file_name_and_manifest_path( - file_name.to_owned().to_path_buf(), + file_name.to_owned(), manifest_dir.clone(), ); let mut dep_namespace = namespace.clone(); @@ -179,8 +179,8 @@ fn compile_dependency_lib<'source, 'manifest>( //return Err("Unimplemented: dependencies that have dependencies".into()); compile_dependency_lib( project_file_path, - &dep.0, - &dep.1, + dep.0, + dep.1, // give it a cloned namespace, which we then merge with this namespace &mut dep_namespace, dependency_graph, From 80c48c6ebaa8060d0393266ac205c0b11bfa0629 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Fri, 19 Nov 2021 12:19:49 -0600 Subject: [PATCH 07/25] More. --- core_lang/src/lib.rs | 33 ++++++++++++++++++- .../declaration/function_declaration.rs | 22 +++++++++++++ .../semantic_analysis/ast_node/declaration.rs | 10 ++++++ .../semantic_analysis/ast_node/impl_trait.rs | 2 -- .../src/semantic_analysis/ast_node/mod.rs | 1 - .../src/semantic_analysis/syntax_tree.rs | 4 +-- 6 files changed, 65 insertions(+), 7 deletions(-) diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index 12d6b867730..42acfc673f3 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -23,7 +23,7 @@ use crate::{asm_generation::compile_ast_to_asm, error::*}; pub use asm_generation::{AbstractInstructionSet, FinalizedAsm, HllAsmSet}; pub use build_config::BuildConfig; use control_flow_analysis::{ControlFlowGraph, Graph}; -use core_types::Function; +use core_types::{Function, JsonABI}; use pest::iterators::Pair; use pest::Parser; use std::collections::{HashMap, HashSet}; @@ -371,6 +371,12 @@ pub fn compile_to_asm<'sc>( return CompilationResult::Failure { errors, warnings }; } + let mut json_abi = vec![]; + json_abi.append(&mut parse_json_abi(&script_ast)); + json_abi.append(&mut parse_json_abi(&contract_ast)); + json_abi.append(&mut parse_json_abi(&predicate_ast)); + json_abi.append(&mut parse_json_abi_from_library_exports(&library_exports)); + // perform control flow analysis on each branch let (script_warnings, script_errors) = perform_control_flow_analysis(&script_ast, TreeType::Script, &mut dead_code_graph); @@ -555,6 +561,31 @@ fn perform_control_flow_analysis_on_library_exports<'sc>( (warnings, errors) } +fn parse_json_abi<'sc>(ast: &Option) -> JsonABI { + match ast { + Some(TypedParseTree::Contract { declarations, .. }) => declarations + .iter() + .flat_map(|x| x.parse_json_abi()) + .collect(), + Some(TypedParseTree::Predicate { declarations, .. }) => declarations + .iter() + .flat_map(|x| x.parse_json_abi()) + .collect(), + Some(TypedParseTree::Script { declarations, .. }) => declarations + .iter() + .flat_map(|x| x.parse_json_abi()) + .collect(), + _ => vec![], + } +} + +fn parse_json_abi_from_library_exports(ast: &LibraryExports) -> JsonABI { + ast.trees + .iter() + .flat_map(|x| parse_json_abi(&Some((*x).clone()))) + .collect() +} + // strategy: parse top level things // and if we encounter a function body or block, recursively call this function and build // sub-nodes diff --git a/core_lang/src/parse_tree/declaration/function_declaration.rs b/core_lang/src/parse_tree/declaration/function_declaration.rs index 3f842c7af64..b7db8cbe5f3 100644 --- a/core_lang/src/parse_tree/declaration/function_declaration.rs +++ b/core_lang/src/parse_tree/declaration/function_declaration.rs @@ -5,6 +5,7 @@ use crate::span::Span; use crate::style::is_snake_case; use crate::type_engine::TypeInfo; use crate::{CodeBlock, Ident, Rule}; +use core_types::{Function, Property}; use pest::iterators::Pair; #[derive(Debug, Clone)] @@ -187,6 +188,27 @@ impl<'sc> FunctionDeclaration<'sc> { errors, ) } + + pub fn parse_json_abi(&self) -> Function { + Function { + name: self.name.primary_name.to_string(), + type_field: "function".to_string(), + inputs: self + .parameters + .iter() + .map(|x| Property { + name: x.name.primary_name.to_string(), + type_field: x.r#type.friendly_type_str(), + components: None, + }) + .collect(), + outputs: vec![Property { + name: "".to_string(), + type_field: self.return_type.friendly_type_str().to_string(), + components: None, + }], + } + } } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index 49cbf9c40ee..5fa09bb9b2d 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -9,6 +9,7 @@ use crate::type_engine::*; use crate::ControlFlowGraph; use crate::{build_config::BuildConfig, error::*, Ident}; +use core_types::JsonABI; use sha2::{Digest, Sha256}; use std::collections::{HashMap, HashSet}; @@ -166,6 +167,15 @@ impl<'sc> TypedDeclaration<'sc> { } } } + + pub fn parse_json_abi(&self) -> JsonABI { + match self { + TypedDeclaration::AbiDeclaration(TypedAbiDeclaration { methods, .. }) => { + methods.iter().map(|x| x.parse_json_abi()).collect() + } + _ => vec![], + } + } } /// A `TypedAbiDeclaration` contains the type-checked version of the parse tree's [AbiDeclaration]. diff --git a/core_lang/src/semantic_analysis/ast_node/impl_trait.rs b/core_lang/src/semantic_analysis/ast_node/impl_trait.rs index 15be6f5c1b2..e0d00e04a7b 100644 --- a/core_lang/src/semantic_analysis/ast_node/impl_trait.rs +++ b/core_lang/src/semantic_analysis/ast_node/impl_trait.rs @@ -1,5 +1,3 @@ -use core_types::JsonABI; - use super::{declaration::TypedTraitFn, ERROR_RECOVERY_DECLARATION}; use crate::parse_tree::{FunctionDeclaration, ImplTrait, TypeParameter}; use crate::semantic_analysis::{Namespace, TypedDeclaration, TypedFunctionDeclaration}; diff --git a/core_lang/src/semantic_analysis/ast_node/mod.rs b/core_lang/src/semantic_analysis/ast_node/mod.rs index a77d6817f76..d80915f4edf 100644 --- a/core_lang/src/semantic_analysis/ast_node/mod.rs +++ b/core_lang/src/semantic_analysis/ast_node/mod.rs @@ -6,7 +6,6 @@ use crate::span::Span; use crate::{control_flow_analysis::ControlFlowGraph, parse_tree::*}; use crate::{AstNode, AstNodeContent, Ident, ReturnStatement}; -use core_types::{Function, JsonABI, Property}; use declaration::TypedTraitFn; pub(crate) use impl_trait::Mode; use std::sync::Arc; diff --git a/core_lang/src/semantic_analysis/syntax_tree.rs b/core_lang/src/semantic_analysis/syntax_tree.rs index fb2b86bc6bd..dbd51cb2136 100644 --- a/core_lang/src/semantic_analysis/syntax_tree.rs +++ b/core_lang/src/semantic_analysis/syntax_tree.rs @@ -7,8 +7,6 @@ use crate::span::Span; use crate::{error::*, type_engine::*}; use crate::{AstNode, AstNodeContent, ParseTree}; -use core_types::JsonABI; - use std::collections::{HashMap, HashSet}; #[derive(Clone, Copy, PartialEq, Eq)] @@ -19,7 +17,7 @@ pub(crate) enum TreeType { Library, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum TypedParseTree<'sc> { Script { main_function: TypedFunctionDeclaration<'sc>, From d14ce5721f4f31eb1b9e23bfc245b2439998df2b Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Fri, 19 Nov 2021 13:39:14 -0600 Subject: [PATCH 08/25] Print json to outfile. --- Cargo.lock | 1 + forc/Cargo.toml | 1 + forc/src/ops/forc_abi_json.rs | 11 +++++------ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5873cae78e6..7654d4e0544 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1222,6 +1222,7 @@ dependencies = [ "reqwest", "semver 1.0.4", "serde", + "serde_json", "source-span", "structopt 0.3.25", "tar", diff --git a/forc/Cargo.toml b/forc/Cargo.toml index 00ac70d96f7..badcd71ad1f 100644 --- a/forc/Cargo.toml +++ b/forc/Cargo.toml @@ -25,6 +25,7 @@ prettydiff = "0.4.0" reqwest = {version = "0.11.4", features = ["json"]} semver = "1.0.3" serde = {version = "1.0", features = ["derive"]} +serde_json = "*" source-span = "2.4" structopt = "0.3" tar = "0.4.35" diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index 052e1d75c84..f01132c536e 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -10,12 +10,11 @@ use crate::{ use core_types::Function; -use std::fs::File; -//use std::io::Write; - use anyhow::Result; use core_lang::{BuildConfig, CompilationResult, LibraryExports, Namespace}; +use serde_json::json; use std::collections::{HashMap, HashSet}; +use std::fs::File; use std::path::PathBuf; pub fn build(command: JsonAbiCommand) -> Result, String> { @@ -113,10 +112,10 @@ pub fn build(command: JsonAbiCommand) -> Result, String> { silent_mode, )?); if let Some(outfile) = json_outfile { - let _file = File::create(outfile).map_err(|e| e.to_string())?; - //file.write_all(json_abi).map_err(|e| e.to_string())?; + let file = File::create(outfile).map_err(|e| e.to_string())?; + serde_json::to_writer(&file, &json!(json_abi)).map_err(|e| e.to_string())?; } else { - println!("{:?}", json_abi); + println!("{:?}", json!(json_abi)); } Ok(json_abi) From 786d0088bd4f1908d99dcc5b7758dcfdd2c06fdf Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 22 Nov 2021 12:00:12 -0600 Subject: [PATCH 09/25] Actually output JSON. --- core_lang/src/lib.rs | 29 +++---------------- .../declaration/function_declaration.rs | 2 +- .../semantic_analysis/ast_node/declaration.rs | 23 ++++++++++++++- .../src/semantic_analysis/ast_node/mod.rs | 4 +-- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index 42acfc673f3..b8f48ef22a5 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -372,10 +372,7 @@ pub fn compile_to_asm<'sc>( } let mut json_abi = vec![]; - json_abi.append(&mut parse_json_abi(&script_ast)); json_abi.append(&mut parse_json_abi(&contract_ast)); - json_abi.append(&mut parse_json_abi(&predicate_ast)); - json_abi.append(&mut parse_json_abi_from_library_exports(&library_exports)); // perform control flow analysis on each branch let (script_warnings, script_errors) = @@ -444,8 +441,6 @@ pub fn compile_to_asm<'sc>( } })(); - let json_abi = vec![]; - if errors.is_empty() { // TODO move this check earlier and don't compile all of them if there is only one match (predicate_asm, contract_asm, script_asm, library_exports) { @@ -561,31 +556,15 @@ fn perform_control_flow_analysis_on_library_exports<'sc>( (warnings, errors) } -fn parse_json_abi<'sc>(ast: &Option) -> JsonABI { +fn parse_json_abi(ast: &Option) -> JsonABI { match ast { - Some(TypedParseTree::Contract { declarations, .. }) => declarations - .iter() - .flat_map(|x| x.parse_json_abi()) - .collect(), - Some(TypedParseTree::Predicate { declarations, .. }) => declarations - .iter() - .flat_map(|x| x.parse_json_abi()) - .collect(), - Some(TypedParseTree::Script { declarations, .. }) => declarations - .iter() - .flat_map(|x| x.parse_json_abi()) - .collect(), + Some(TypedParseTree::Contract { abi_entries, .. }) => { + abi_entries.iter().map(|x| x.parse_json_abi()).collect() + } _ => vec![], } } -fn parse_json_abi_from_library_exports(ast: &LibraryExports) -> JsonABI { - ast.trees - .iter() - .flat_map(|x| parse_json_abi(&Some((*x).clone()))) - .collect() -} - // strategy: parse top level things // and if we encounter a function body or block, recursively call this function and build // sub-nodes diff --git a/core_lang/src/parse_tree/declaration/function_declaration.rs b/core_lang/src/parse_tree/declaration/function_declaration.rs index 910359b572f..bd942a9d1b6 100644 --- a/core_lang/src/parse_tree/declaration/function_declaration.rs +++ b/core_lang/src/parse_tree/declaration/function_declaration.rs @@ -204,7 +204,7 @@ impl<'sc> FunctionDeclaration<'sc> { .collect(), outputs: vec![Property { name: "".to_string(), - type_field: self.return_type.friendly_type_str().to_string(), + type_field: self.return_type.friendly_type_str(), components: None, }], } diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index 5fa09bb9b2d..91dc133b2f4 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -9,7 +9,7 @@ use crate::type_engine::*; use crate::ControlFlowGraph; use crate::{build_config::BuildConfig, error::*, Ident}; -use core_types::JsonABI; +use core_types::{Function, JsonABI, Property}; use sha2::{Digest, Sha256}; use std::collections::{HashMap, HashSet}; @@ -421,6 +421,27 @@ impl<'sc> TypedFunctionDeclaration<'sc> { errors, ) } + + pub fn parse_json_abi(&self) -> Function { + Function { + name: self.name.primary_name.to_string(), + type_field: "function".to_string(), + inputs: self + .parameters + .iter() + .map(|x| Property { + name: x.name.primary_name.to_string(), + type_field: x.r#type.friendly_type_str(), + components: None, + }) + .collect(), + outputs: vec![Property { + name: "".to_string(), + type_field: self.return_type.friendly_type_str(), + components: None, + }], + } + } } #[test] diff --git a/core_lang/src/semantic_analysis/ast_node/mod.rs b/core_lang/src/semantic_analysis/ast_node/mod.rs index d80915f4edf..da92642528c 100644 --- a/core_lang/src/semantic_analysis/ast_node/mod.rs +++ b/core_lang/src/semantic_analysis/ast_node/mod.rs @@ -430,7 +430,7 @@ impl<'sc> TypedAstNode<'sc> { type_check_interface_surface(interface_surface, namespace); // type check these for errors but don't actually use them yet -- the real // ones will be type checked with proper symbols when the ABI is implemented - let methodz = check!( + let _methods = check!( type_check_trait_methods( methods.clone(), namespace, @@ -444,8 +444,6 @@ impl<'sc> TypedAstNode<'sc> { errors ); - println!("{:?}", methodz); - let decl = TypedDeclaration::AbiDeclaration(TypedAbiDeclaration { interface_surface, methods, From f9a554efd686dc4661e47ec245829d20de5134b9 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 22 Nov 2021 12:05:16 -0600 Subject: [PATCH 10/25] Delete unused function. --- core_lang/src/semantic_analysis/ast_node/declaration.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index 91dc133b2f4..979dc836ec8 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -167,15 +167,6 @@ impl<'sc> TypedDeclaration<'sc> { } } } - - pub fn parse_json_abi(&self) -> JsonABI { - match self { - TypedDeclaration::AbiDeclaration(TypedAbiDeclaration { methods, .. }) => { - methods.iter().map(|x| x.parse_json_abi()).collect() - } - _ => vec![], - } - } } /// A `TypedAbiDeclaration` contains the type-checked version of the parse tree's [AbiDeclaration]. From 75e545be1981930271a7407dfdf605e90c38db14 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 22 Nov 2021 12:25:43 -0600 Subject: [PATCH 11/25] JSON captures components field. --- .../semantic_analysis/ast_node/declaration.rs | 24 ++++++++++++++++--- core_lang/src/type_engine.rs | 19 +++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index 979dc836ec8..8830a5d1ff9 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -9,7 +9,7 @@ use crate::type_engine::*; use crate::ControlFlowGraph; use crate::{build_config::BuildConfig, error::*, Ident}; -use core_types::{Function, JsonABI, Property}; +use core_types::{Function, Property}; use sha2::{Digest, Sha256}; use std::collections::{HashMap, HashSet}; @@ -214,6 +214,14 @@ impl OwnedTypedStructField { span: span.clone(), } } + + pub fn parse_json_abi(&self) -> Property { + Property { + name: self.name.clone(), + type_field: self.r#type.friendly_type_str(), + components: self.r#type.parse_json_abi(), + } + } } impl TypedStructField<'_> { @@ -284,6 +292,16 @@ pub struct OwnedTypedEnumVariant { pub(crate) tag: usize, } +impl OwnedTypedEnumVariant { + pub fn parse_json_abi(&self) -> Property { + Property { + name: self.name.clone(), + type_field: self.r#type.friendly_type_str(), + components: self.r#type.parse_json_abi(), + } + } +} + #[derive(Clone, Debug)] pub struct TypedVariableDeclaration<'sc> { pub(crate) name: Ident<'sc>, @@ -423,13 +441,13 @@ impl<'sc> TypedFunctionDeclaration<'sc> { .map(|x| Property { name: x.name.primary_name.to_string(), type_field: x.r#type.friendly_type_str(), - components: None, + components: x.r#type.parse_json_abi(), }) .collect(), outputs: vec![Property { name: "".to_string(), type_field: self.return_type.friendly_type_str(), - components: None, + components: self.return_type.parse_json_abi(), }], } } diff --git a/core_lang/src/type_engine.rs b/core_lang/src/type_engine.rs index 473e0925fa9..78c74a79f6e 100644 --- a/core_lang/src/type_engine.rs +++ b/core_lang/src/type_engine.rs @@ -5,6 +5,7 @@ use std::iter::FromIterator; mod engine; mod integer_bits; mod type_info; +use core_types::Property; pub(crate) use engine::*; pub use integer_bits::*; pub use type_info::*; @@ -55,6 +56,24 @@ impl FriendlyTypeString for TypeId { } } +pub(crate) trait ToJsonAbi { + fn parse_json_abi(&self) -> Option>; +} + +impl ToJsonAbi for TypeId { + fn parse_json_abi(&self) -> Option> { + match look_up_type_id(*self) { + TypeInfo::Struct { fields, .. } => { + Some(fields.iter().map(|x| x.parse_json_abi()).collect()) + } + TypeInfo::Enum { variant_types, .. } => { + Some(variant_types.iter().map(|x| x.parse_json_abi()).collect()) + } + _ => None, + } + } +} + #[test] fn basic_numeric_unknown() { let mut engine = Engine::default(); From f86c33d3c52c2d57c9b7b5b33b8b6d8dfa7cfbb6 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Tue, 23 Nov 2021 14:01:43 -0600 Subject: [PATCH 12/25] Basic testing infra. --- .gitignore | 1 + Cargo.lock | 1 + forc/src/lib.rs | 4 +- forc/src/ops/forc_abi_json.rs | 13 +++-- test/Cargo.toml | 1 + test/src/e2e_vm_tests/harness.rs | 51 ++++++++++++++++++- test/src/e2e_vm_tests/mod.rs | 1 + .../aliased_imports/json_abi_oracle.json | 1 + .../asm_expr_basic/json_abi_oracle.json | 1 + .../asm_missing_return/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../asm_without_return/json_abi_oracle.json | 1 + .../assert_test/json_abi_oracle.json | 1 + .../auth_testing_abi/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../b256_bad_jumps/json_abi_oracle.json | 1 + .../b256_ops/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../basic_func_decl/json_abi_oracle.json | 1 + .../basic_storage/json_abi_oracle.json | 1 + .../basic_storage_abi/json_abi_oracle.json | 1 + .../bool_and_or/json_abi_oracle.json | 1 + .../call_basic_storage/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../caller_auth_test/json_abi_oracle.json | 1 + .../const_decl/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../contract_abi_impl/json_abi_oracle.json | 1 + .../contract_call/json_abi_oracle.json | 1 + .../dependencies/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../disallowed_gm/json_abi_oracle.json | 1 + .../doc_strings/json_abi_oracle.json | 1 + .../empty_impl/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../enum_in_fn_decl/json_abi_oracle.json | 1 + .../eq_4_test/json_abi_oracle.json | 1 + .../excess_fn_arguments/json_abi_oracle.json | 1 + .../fix_opcode_bug/json_abi_oracle.json | 1 + .../if_elseif_enum/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../increment_abi/json_abi_oracle.json | 1 + .../increment_contract/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../local_impl_for_ord/json_abi_oracle.json | 1 + .../main_returns_unit/json_abi_oracle.json | 1 + .../missing_fn_arguments/json_abi_oracle.json | 1 + .../neq_4_test/json_abi_oracle.json | 1 + .../op_precedence/json_abi_oracle.json | 1 + .../out_of_order_decl/json_abi_oracle.json | 1 + .../recursive_calls/json_abi_oracle.json | 1 + .../retd_b256/json_abi_oracle.json | 1 + .../retd_struct/json_abi_oracle.json | 1 + .../struct_field_access/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + .../top_level_vars/json_abi_oracle.json | 1 + .../unary_not_basic/json_abi_oracle.json | 1 + .../unary_not_basic_2/json_abi_oracle.json | 1 + .../json_abi_oracle.json | 1 + 59 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 test/src/e2e_vm_tests/test_programs/aliased_imports/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/asm_expr_basic/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/asm_missing_return/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/asm_should_not_have_return/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/asm_without_return/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/assert_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/auth_testing_abi/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/auth_testing_contract/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/b256_bad_jumps/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/b256_ops/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/b512_struct_alignment/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/basic_func_decl/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/basic_storage/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/basic_storage_abi/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/bool_and_or/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/call_basic_storage/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/call_increment_contract/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/caller_auth_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/const_decl/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/const_decl_in_library/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/contract_abi_impl/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/contract_call/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/dependencies/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/dependencies_parsing_error/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/disallowed_gm/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/doc_strings/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/empty_impl/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/empty_method_initializer/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/enum_in_fn_decl/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/eq_4_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/excess_fn_arguments/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/fix_opcode_bug/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/if_elseif_enum/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/import_method_from_other_file/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/increment_abi/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/increment_contract/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/infinite_dependencies/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/local_impl_for_ord/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/main_returns_unit/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/missing_fn_arguments/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/neq_4_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/op_precedence/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/out_of_order_decl/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/recursive_calls/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/retd_b256/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/retd_struct/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/struct_field_access/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/struct_field_reassignment/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/top_level_vars/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/unary_not_basic/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/unary_not_basic_2/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/unify_identical_unknowns/json_abi_oracle.json diff --git a/.gitignore b/.gitignore index eb941c1cec9..0d645a96019 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Generated by Cargo # will have compiled files and executables **/*/target/ +**/*/json_abi_output.json target # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries diff --git a/Cargo.lock b/Cargo.lock index 7654d4e0544..d44acb30f35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3379,6 +3379,7 @@ dependencies = [ "fuel-vm", "rand 0.8.4", "regex", + "serde_json", "tokio", ] diff --git a/forc/src/lib.rs b/forc/src/lib.rs index 9ff686e68e4..c0580787ad0 100644 --- a/forc/src/lib.rs +++ b/forc/src/lib.rs @@ -5,8 +5,8 @@ mod utils; #[cfg(feature = "test")] pub mod test { - pub use crate::cli::{BuildCommand, DeployCommand, RunCommand}; - pub use crate::ops::{forc_build, forc_deploy, forc_run}; + pub use crate::cli::{BuildCommand, DeployCommand, RunCommand, JsonAbiCommand}; + pub use crate::ops::{forc_build, forc_deploy, forc_run, forc_abi_json}; } #[cfg(feature = "util")] diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index f01132c536e..64dca8bf091 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -12,12 +12,12 @@ use core_types::Function; use anyhow::Result; use core_lang::{BuildConfig, CompilationResult, LibraryExports, Namespace}; -use serde_json::json; +use serde_json::{json, Value}; use std::collections::{HashMap, HashSet}; use std::fs::File; use std::path::PathBuf; -pub fn build(command: JsonAbiCommand) -> Result, String> { +pub fn build(command: JsonAbiCommand) -> Result { // find manifest directory, even if in subdirectory let this_dir = if let Some(ref path) = command.path { PathBuf::from(path) @@ -111,14 +111,17 @@ pub fn build(command: JsonAbiCommand) -> Result, String> { &mut dependency_graph, silent_mode, )?); + + let output_json = json!(json_abi); + if let Some(outfile) = json_outfile { let file = File::create(outfile).map_err(|e| e.to_string())?; - serde_json::to_writer(&file, &json!(json_abi)).map_err(|e| e.to_string())?; + serde_json::to_writer(&file, &output_json.clone()).map_err(|e| e.to_string())?; } else { - println!("{:?}", json!(json_abi)); + println!("{}", output_json); } - Ok(json_abi) + Ok(output_json) } /// Takes a dependency and returns a namespace of exported things from that dependency diff --git a/test/Cargo.toml b/test/Cargo.toml index 79297cd97cc..56c45fa1ff5 100644 --- a/test/Cargo.toml +++ b/test/Cargo.toml @@ -14,3 +14,4 @@ fuel-vm = { git = "ssh://git@github.com/FuelLabs/fuel-vm.git", features = ["rand rand = "0.8" regex = "1" tokio = "1.12" +serde_json = "*" diff --git a/test/src/e2e_vm_tests/harness.rs b/test/src/e2e_vm_tests/harness.rs index fe2bd7a3658..71a5f0e0f97 100644 --- a/test/src/e2e_vm_tests/harness.rs +++ b/test/src/e2e_vm_tests/harness.rs @@ -1,9 +1,14 @@ -use forc::test::{forc_build, forc_deploy, forc_run, BuildCommand, DeployCommand, RunCommand}; +use forc::test::{ + forc_abi_json, forc_build, forc_deploy, forc_run, BuildCommand, DeployCommand, JsonAbiCommand, + RunCommand, +}; use fuel_tx::{Input, Output, Transaction}; use fuel_vm::interpreter::Interpreter; use fuel_vm::prelude::*; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; +use serde_json::Value; +use std::fs; pub(crate) fn deploy_contract(file_name: &str) { // build the contract @@ -153,3 +158,47 @@ pub(crate) fn compile_to_bytes(file_name: &str) -> Result, String> { silent_mode: true, }) } + +pub(crate) fn test_json_abi(file_name: &str) -> Result<(), String> { + let _script = compile_to_json_abi(file_name)?; + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let oracle_path = format!( + "{}/src/e2e_vm_tests/test_programs/{}/{}", + manifest_dir, file_name, "json_abi_oracle.json" + ); + let output_path = format!( + "{}/src/e2e_vm_tests/test_programs/{}/{}", + manifest_dir, file_name, "json_abi_output.json" + ); + if fs::metadata(oracle_path.clone()).is_err() { + return Err("JSON ABI oracle file does not exist for this test.".to_string()); + } + if fs::metadata(output_path.clone()).is_err() { + return Err("JSON ABI output file does not exist for this test.".to_string()); + } + let oracle_contents = + fs::read_to_string(oracle_path).expect("Something went wrong reading the file."); + let output_contents = + fs::read_to_string(output_path).expect("Something went wrong reading the file."); + if oracle_contents != output_contents { + return Err("Mismatched ABI JSON output.".to_string()); + } + Ok(()) +} + +fn compile_to_json_abi(file_name: &str) -> Result { + println!(" ABI gen {}", file_name); + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + forc_abi_json::build(JsonAbiCommand { + path: Some(format!( + "{}/src/e2e_vm_tests/test_programs/{}", + manifest_dir, file_name + )), + json_outfile: Some(format!( + "{}/src/e2e_vm_tests/test_programs/{}/{}", + manifest_dir, file_name, "json_abi_output.json" + )), + offline_mode: false, + silent_mode: true, + }) +} diff --git a/test/src/e2e_vm_tests/mod.rs b/test/src/e2e_vm_tests/mod.rs index 13264862c72..a5cdf6be65f 100644 --- a/test/src/e2e_vm_tests/mod.rs +++ b/test/src/e2e_vm_tests/mod.rs @@ -62,6 +62,7 @@ pub fn run(filter_regex: Option) { project_names.into_iter().for_each(|(name, res)| { if filter(name) { assert_eq!(crate::e2e_vm_tests::harness::runs_in_vm(name), res); + assert_eq!(crate::e2e_vm_tests::harness::test_json_abi(name), Ok(())); } }); diff --git a/test/src/e2e_vm_tests/test_programs/aliased_imports/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/aliased_imports/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/aliased_imports/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/asm_expr_basic/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/asm_expr_basic/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/asm_expr_basic/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/asm_missing_return/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/asm_missing_return/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/asm_missing_return/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/asm_should_not_have_return/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/asm_should_not_have_return/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/asm_should_not_have_return/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/asm_without_return/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/asm_without_return/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/asm_without_return/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/assert_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/assert_test/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/assert_test/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/auth_testing_abi/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/auth_testing_abi/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/auth_testing_abi/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/auth_testing_contract/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/auth_testing_contract/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/auth_testing_contract/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/b256_bad_jumps/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/b256_bad_jumps/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/b256_bad_jumps/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/b256_ops/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/b256_ops/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/b256_ops/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/b512_struct_alignment/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/b512_struct_alignment/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/b512_struct_alignment/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/basic_func_decl/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/basic_func_decl/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/basic_func_decl/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/basic_storage/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/basic_storage/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/basic_storage/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/basic_storage_abi/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/basic_storage_abi/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/basic_storage_abi/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/bool_and_or/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/bool_and_or/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/bool_and_or/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/call_basic_storage/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/call_basic_storage/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/call_basic_storage/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/call_increment_contract/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/call_increment_contract/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/call_increment_contract/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/caller_auth_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/caller_auth_test/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/caller_auth_test/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/const_decl/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/const_decl/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/const_decl/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/const_decl_in_library/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/const_decl_in_library/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/const_decl_in_library/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/contract_abi_impl/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/contract_abi_impl/json_abi_oracle.json new file mode 100644 index 00000000000..8ffd25cafc2 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/contract_abi_impl/json_abi_oracle.json @@ -0,0 +1 @@ +[{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"coin","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":[{"components":null,"name":"field_1","type":"bool"},{"components":null,"name":"field_2","type":"u64"}],"name":"input","type":"struct InputStruct"}],"name":"foo","outputs":[{"components":[{"components":null,"name":"field_1","type":"bool"},{"components":null,"name":"field_2","type":"u64"}],"name":"","type":"struct InputStruct"}],"type":"function"},{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"coin","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":null,"name":"input","type":"bool"}],"name":"baz","outputs":[{"components":null,"name":"","type":"()"}],"type":"function"}] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/contract_call/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/contract_call/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/contract_call/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/dependencies/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/dependencies/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/dependencies/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/dependencies_parsing_error/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/dependencies_parsing_error/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/dependencies_parsing_error/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/disallowed_gm/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/disallowed_gm/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/disallowed_gm/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/doc_strings/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/doc_strings/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/doc_strings/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/empty_impl/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/empty_impl/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/empty_impl/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/empty_method_initializer/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/empty_method_initializer/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/empty_method_initializer/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/enum_in_fn_decl/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/enum_in_fn_decl/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/enum_in_fn_decl/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/eq_4_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/eq_4_test/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/eq_4_test/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/excess_fn_arguments/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/excess_fn_arguments/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/excess_fn_arguments/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/fix_opcode_bug/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/fix_opcode_bug/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/fix_opcode_bug/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/if_elseif_enum/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/if_elseif_enum/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/if_elseif_enum/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/import_method_from_other_file/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/import_method_from_other_file/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/import_method_from_other_file/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/increment_abi/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/increment_abi/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/increment_abi/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/increment_contract/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/increment_contract/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/increment_contract/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/infinite_dependencies/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/infinite_dependencies/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/infinite_dependencies/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/local_impl_for_ord/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/local_impl_for_ord/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/local_impl_for_ord/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/main_returns_unit/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/main_returns_unit/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/main_returns_unit/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/missing_fn_arguments/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/missing_fn_arguments/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/missing_fn_arguments/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/neq_4_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/neq_4_test/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/neq_4_test/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/op_precedence/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/op_precedence/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/op_precedence/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/out_of_order_decl/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/out_of_order_decl/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/out_of_order_decl/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/recursive_calls/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/recursive_calls/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/recursive_calls/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/retd_b256/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/retd_b256/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/retd_b256/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/retd_struct/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/retd_struct/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/retd_struct/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/struct_field_access/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/struct_field_access/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/struct_field_access/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/struct_field_reassignment/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/struct_field_reassignment/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/struct_field_reassignment/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/top_level_vars/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/top_level_vars/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/top_level_vars/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/unary_not_basic/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/unary_not_basic/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/unary_not_basic/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/unary_not_basic_2/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/unary_not_basic_2/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/unary_not_basic_2/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/unify_identical_unknowns/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/unify_identical_unknowns/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/unify_identical_unknowns/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file From 82f1002cb34e3f9928bf912df30a5af223462870 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Tue, 23 Nov 2021 15:56:20 -0600 Subject: [PATCH 13/25] Actual oracle values. --- .../test_programs/auth_testing_contract/json_abi_oracle.json | 2 +- .../test_programs/basic_storage/json_abi_oracle.json | 2 +- .../test_programs/increment_contract/json_abi_oracle.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/src/e2e_vm_tests/test_programs/auth_testing_contract/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/auth_testing_contract/json_abi_oracle.json index 0637a088a01..ff991774640 100644 --- a/test/src/e2e_vm_tests/test_programs/auth_testing_contract/json_abi_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/auth_testing_contract/json_abi_oracle.json @@ -1 +1 @@ -[] \ No newline at end of file +[{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"coins","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":null,"name":"input","type":"()"}],"name":"returns_gm_one","outputs":[{"components":null,"name":"","type":"bool"}],"type":"function"}] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/basic_storage/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/basic_storage/json_abi_oracle.json index 0637a088a01..7c74cc14963 100644 --- a/test/src/e2e_vm_tests/test_programs/basic_storage/json_abi_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/basic_storage/json_abi_oracle.json @@ -1 +1 @@ -[] \ No newline at end of file +[{"inputs":[{"components":null,"name":"gas_to_forward","type":"u64"},{"components":null,"name":"coins_to_forward","type":"u64"},{"components":null,"name":"color_of_coins","type":"b256"},{"components":[{"components":null,"name":"key","type":"b256"},{"components":null,"name":"value","type":"u64"}],"name":"storage","type":"struct StoreU64Request"}],"name":"store_u64","outputs":[{"components":null,"name":"","type":"()"}],"type":"function"},{"inputs":[{"components":null,"name":"gas_to_forward","type":"u64"},{"components":null,"name":"coins_to_forward","type":"u64"},{"components":null,"name":"color_of_coins","type":"b256"},{"components":null,"name":"storage_key","type":"b256"}],"name":"get_u64","outputs":[{"components":null,"name":"","type":"u64"}],"type":"function"}] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/increment_contract/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/increment_contract/json_abi_oracle.json index 0637a088a01..0d1d365536f 100644 --- a/test/src/e2e_vm_tests/test_programs/increment_contract/json_abi_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/increment_contract/json_abi_oracle.json @@ -1 +1 @@ -[] \ No newline at end of file +[{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"amt","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":null,"name":"initial_value","type":"u64"}],"name":"initialize","outputs":[{"components":null,"name":"","type":"u64"}],"type":"function"},{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"amt","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":null,"name":"increment_by","type":"u64"}],"name":"increment","outputs":[{"components":null,"name":"","type":"u64"}],"type":"function"}] \ No newline at end of file From 851a408d42c7bf1b994bc15479ede1a744bb5d71 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Tue, 23 Nov 2021 16:00:11 -0600 Subject: [PATCH 14/25] Format. --- forc/src/lib.rs | 4 ++-- forc/src/ops/forc_abi_json.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/forc/src/lib.rs b/forc/src/lib.rs index c0580787ad0..b8cabdf4d1d 100644 --- a/forc/src/lib.rs +++ b/forc/src/lib.rs @@ -5,8 +5,8 @@ mod utils; #[cfg(feature = "test")] pub mod test { - pub use crate::cli::{BuildCommand, DeployCommand, RunCommand, JsonAbiCommand}; - pub use crate::ops::{forc_build, forc_deploy, forc_run, forc_abi_json}; + pub use crate::cli::{BuildCommand, DeployCommand, JsonAbiCommand, RunCommand}; + pub use crate::ops::{forc_abi_json, forc_build, forc_deploy, forc_run}; } #[cfg(feature = "util")] diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index 64dca8bf091..a244661d7ab 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -111,7 +111,7 @@ pub fn build(command: JsonAbiCommand) -> Result { &mut dependency_graph, silent_mode, )?); - + let output_json = json!(json_abi); if let Some(outfile) = json_outfile { From 0c807465294356a6b4922587c2a64b3e6fae6dde Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Tue, 23 Nov 2021 16:33:25 -0600 Subject: [PATCH 15/25] Split compile_asm into compile_ast. --- core_lang/src/lib.rs | 267 ++++++++++-------- core_lang/src/semantic_analysis/mod.rs | 2 +- .../src/semantic_analysis/syntax_tree.rs | 2 +- forc/src/ops/forc_abi_json.rs | 44 +-- 4 files changed, 172 insertions(+), 143 deletions(-) diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index 185f29e0c7a..00d0f89d0ab 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -24,12 +24,11 @@ use crate::{asm_generation::compile_ast_to_asm, error::*}; pub use asm_generation::{AbstractInstructionSet, FinalizedAsm, HllAsmSet}; pub use build_config::BuildConfig; use control_flow_analysis::{ControlFlowGraph, Graph}; -use core_types::{Function, JsonABI}; use pest::iterators::Pair; use pest::Parser; use std::collections::{HashMap, HashSet}; -use semantic_analysis::{TreeType, TypedParseTree}; +pub use semantic_analysis::{TreeType, TypedParseTree}; pub mod types; pub(crate) mod utils; pub use crate::parse_tree::{Declaration, Expression, UseStatement, WhileLoop}; @@ -134,12 +133,10 @@ pub fn parse<'sc>( pub enum CompilationResult<'sc> { Success { asm: FinalizedAsm<'sc>, - json_abi: Vec, warnings: Vec>, }, Library { exports: LibraryExports<'sc>, - json_abi: Vec, warnings: Vec>, }, Failure { @@ -148,13 +145,12 @@ pub enum CompilationResult<'sc> { }, } -pub enum CompileASTsResult<'sc> { +pub enum CompileASTResult<'sc> { Success { contract_ast: Option>, script_ast: Option>, predicate_ast: Option>, library_exports: LibraryExports<'sc>, - json_abi: Vec, dead_code_graph: ControlFlowGraph<'sc>, warnings: Vec>, }, @@ -298,17 +294,17 @@ pub(crate) fn compile_inner_dependency<'sc>( ) } -pub fn compile_to_asm<'sc>( +pub fn compile_to_ast<'sc>( input: &'sc str, initial_namespace: &Namespace<'sc>, - build_config: BuildConfig, + build_config: &BuildConfig, dependency_graph: &mut HashMap>, -) -> CompilationResult<'sc> { +) -> CompileASTResult<'sc> { let mut warnings = Vec::new(); let mut errors = Vec::new(); let parse_tree = check!( - parse(input, Some(&build_config)), - return CompilationResult::Failure { errors, warnings }, + parse(input, Some(build_config)), + return CompileASTResult::Failure { errors, warnings }, warnings, errors ); @@ -369,113 +365,149 @@ pub fn compile_to_asm<'sc>( }; if !errors.is_empty() { - return CompilationResult::Failure { errors, warnings }; + return CompileASTResult::Failure { errors, warnings }; } - let mut json_abi = vec![]; - json_abi.append(&mut parse_json_abi(&contract_ast)); - - // perform control flow analysis on each branch - let (script_warnings, script_errors) = - perform_control_flow_analysis(&script_ast, TreeType::Script, &mut dead_code_graph); - let (contract_warnings, contract_errors) = - perform_control_flow_analysis(&contract_ast, TreeType::Contract, &mut dead_code_graph); - let (predicate_warnings, predicate_errors) = - perform_control_flow_analysis(&predicate_ast, TreeType::Predicate, &mut dead_code_graph); - let (library_warnings, library_errors) = - perform_control_flow_analysis_on_library_exports(&library_exports, &mut dead_code_graph); - - let mut l_warnings = [ - script_warnings, - contract_warnings, - predicate_warnings, - library_warnings, - ] - .concat(); - let mut l_errors = [ - script_errors, - contract_errors, - predicate_errors, - library_errors, - ] - .concat(); - - errors.append(&mut l_errors); - warnings.append(&mut l_warnings); - // for each syntax tree, generate assembly. - let predicate_asm = (|| { - if let Some(tree) = predicate_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None - } - })(); - - let contract_asm = (|| { - if let Some(tree) = contract_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None - } - })(); - - let script_asm = (|| { - if let Some(tree) = script_ast { - Some(check!( - compile_ast_to_asm(tree, &build_config), - return None, - warnings, - errors - )) - } else { - None + CompileASTResult::Success { + contract_ast, + predicate_ast, + script_ast, + library_exports, + dead_code_graph, + warnings, + } +} + +pub fn compile_to_asm<'sc>( + input: &'sc str, + initial_namespace: &Namespace<'sc>, + build_config: BuildConfig, + dependency_graph: &mut HashMap>, +) -> CompilationResult<'sc> { + match compile_to_ast(input, initial_namespace, &build_config, dependency_graph) { + CompileASTResult::Failure { warnings, errors } => { + CompilationResult::Failure { warnings, errors } } - })(); - - if errors.is_empty() { - // TODO move this check earlier and don't compile all of them if there is only one - match (predicate_asm, contract_asm, script_asm, library_exports) { - (Some(pred), None, None, o) if o.trees.is_empty() => CompilationResult::Success { - asm: pred, - json_abi, - warnings, - }, - (None, Some(contract), None, o) if o.trees.is_empty() => CompilationResult::Success { - asm: contract, - json_abi, - warnings, - }, - (None, None, Some(script), o) if o.trees.is_empty() => CompilationResult::Success { - asm: script, - json_abi, - warnings, - }, - (None, None, None, o) if !o.trees.is_empty() => CompilationResult::Library { - warnings, - json_abi, - exports: o, - }, - (None, None, None, o) if o.trees.is_empty() => { - todo!("do we want empty files to be valid programs?") + CompileASTResult::Success { + predicate_ast, + script_ast, + contract_ast, + library_exports, + mut dead_code_graph, + mut warnings, + } => { + let mut errors = vec![]; + //let mut json_abi = vec![]; + //json_abi.append(&mut parse_json_abi(&contract_ast)); + + // perform control flow analysis on each branch + let (script_warnings, script_errors) = + perform_control_flow_analysis(&script_ast, TreeType::Script, &mut dead_code_graph); + let (contract_warnings, contract_errors) = perform_control_flow_analysis( + &contract_ast, + TreeType::Contract, + &mut dead_code_graph, + ); + let (predicate_warnings, predicate_errors) = perform_control_flow_analysis( + &predicate_ast, + TreeType::Predicate, + &mut dead_code_graph, + ); + let (library_warnings, library_errors) = + perform_control_flow_analysis_on_library_exports( + &library_exports, + &mut dead_code_graph, + ); + + let mut l_warnings = [ + script_warnings, + contract_warnings, + predicate_warnings, + library_warnings, + ] + .concat(); + let mut l_errors = [ + script_errors, + contract_errors, + predicate_errors, + library_errors, + ] + .concat(); + + errors.append(&mut l_errors); + warnings.append(&mut l_warnings); + // for each syntax tree, generate assembly. + let predicate_asm = (|| { + if let Some(tree) = predicate_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None + } + })(); + + let contract_asm = (|| { + if let Some(tree) = contract_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None + } + })(); + + let script_asm = (|| { + if let Some(tree) = script_ast { + Some(check!( + compile_ast_to_asm(tree, &build_config), + return None, + warnings, + errors + )) + } else { + None + } + })(); + + if errors.is_empty() { + // TODO move this check earlier and don't compile all of them if there is only one + match (predicate_asm, contract_asm, script_asm, library_exports) { + (Some(pred), None, None, o) if o.trees.is_empty() => CompilationResult::Success { + asm: pred, + warnings, + }, + (None, Some(contract), None, o) if o.trees.is_empty() => CompilationResult::Success { + asm: contract, + warnings, + }, + (None, None, Some(script), o) if o.trees.is_empty() => CompilationResult::Success { + asm: script, + warnings, + }, + (None, None, None, o) if !o.trees.is_empty() => CompilationResult::Library { + warnings, + exports: o, + }, + (None, None, None, o) if o.trees.is_empty() => { + todo!("do we want empty files to be valid programs?") + } + // Default to compiling an empty library if there is no code or invalid state + _ => unimplemented!( + "Multiple contracts, libraries, scripts, or predicates in a single file are \ + unsupported." + ), + } + } else { + CompilationResult::Failure { errors, warnings } } - // Default to compiling an empty library if there is no code or invalid state - _ => unimplemented!( - "Multiple contracts, libraries, scripts, or predicates in a single file are \ - unsupported." - ), } - } else { - CompilationResult::Failure { errors, warnings } } } @@ -557,15 +589,6 @@ fn perform_control_flow_analysis_on_library_exports<'sc>( (warnings, errors) } -fn parse_json_abi(ast: &Option) -> JsonABI { - match ast { - Some(TypedParseTree::Contract { abi_entries, .. }) => { - abi_entries.iter().map(|x| x.parse_json_abi()).collect() - } - _ => vec![], - } -} - // strategy: parse top level things // and if we encounter a function body or block, recursively call this function and build // sub-nodes diff --git a/core_lang/src/semantic_analysis/mod.rs b/core_lang/src/semantic_analysis/mod.rs index ac36ce5b4ec..fb8292f6b86 100644 --- a/core_lang/src/semantic_analysis/mod.rs +++ b/core_lang/src/semantic_analysis/mod.rs @@ -5,6 +5,6 @@ mod syntax_tree; pub(crate) use ast_node::{TypedAstNode, TypedAstNodeContent, TypedExpression}; pub use ast_node::{TypedConstantDeclaration, TypedDeclaration, TypedFunctionDeclaration}; pub use namespace::Namespace; -pub(crate) use syntax_tree::{TreeType, TypedParseTree}; +pub use syntax_tree::{TreeType, TypedParseTree}; const ERROR_RECOVERY_DECLARATION: TypedDeclaration = TypedDeclaration::ErrorRecovery; diff --git a/core_lang/src/semantic_analysis/syntax_tree.rs b/core_lang/src/semantic_analysis/syntax_tree.rs index dbd51cb2136..54eeeebbc30 100644 --- a/core_lang/src/semantic_analysis/syntax_tree.rs +++ b/core_lang/src/semantic_analysis/syntax_tree.rs @@ -10,7 +10,7 @@ use crate::{AstNode, AstNodeContent, ParseTree}; use std::collections::{HashMap, HashSet}; #[derive(Clone, Copy, PartialEq, Eq)] -pub(crate) enum TreeType { +pub enum TreeType { Predicate, Script, Contract, diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index a244661d7ab..3fa8137a491 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -8,10 +8,10 @@ use crate::{ }, }; -use core_types::Function; +use core_types::{Function, JsonABI}; use anyhow::Result; -use core_lang::{BuildConfig, CompilationResult, LibraryExports, Namespace}; +use core_lang::{BuildConfig, CompileASTResult, LibraryExports, Namespace, TypedParseTree}; use serde_json::{json, Value}; use std::collections::{HashMap, HashSet}; use std::fs::File; @@ -216,21 +216,19 @@ fn compile_library<'source, 'manifest>( dependency_graph: &mut HashMap>, silent_mode: bool, ) -> Result<(LibraryExports<'source>, Vec), String> { - let res = core_lang::compile_to_asm(&source, namespace, build_config, dependency_graph); + let res = core_lang::compile_to_ast(&source, namespace, &build_config, dependency_graph); match res { - CompilationResult::Library { + CompileASTResult::Success { warnings, - json_abi, - exports, + contract_ast, + library_exports: exports, + .. } => { print_on_success_library(silent_mode, proj_name, warnings); + let json_abi = parse_json_abi(&contract_ast); Ok((exports, json_abi)) } - CompilationResult::Success { warnings, .. } => { - print_on_failure(silent_mode, warnings, vec![]); - Err(format!("Failed to compile {}", proj_name)) - } - CompilationResult::Failure { warnings, errors } => { + CompileASTResult::Failure { warnings, errors } => { print_on_failure(silent_mode, warnings, errors); Err(format!("Failed to compile {}", proj_name)) } @@ -245,21 +243,29 @@ fn compile<'source, 'manifest>( dependency_graph: &mut HashMap>, silent_mode: bool, ) -> Result, String> { - let res = core_lang::compile_to_asm(&source, namespace, build_config, dependency_graph); + let res = core_lang::compile_to_ast(&source, namespace, &build_config, dependency_graph); match res { - CompilationResult::Success { - warnings, json_abi, .. + CompileASTResult::Success { + warnings, + contract_ast, + .. } => { print_on_success_script(silent_mode, proj_name, warnings); + let json_abi = parse_json_abi(&contract_ast); Ok(json_abi) } - CompilationResult::Library { warnings, .. } => { - print_on_failure(silent_mode, warnings, vec![]); - Err(format!("Failed to compile {}", proj_name)) - } - CompilationResult::Failure { warnings, errors } => { + CompileASTResult::Failure { warnings, errors } => { print_on_failure(silent_mode, warnings, errors); Err(format!("Failed to compile {}", proj_name)) } } } + +fn parse_json_abi(ast: &Option) -> JsonABI { + match ast { + Some(TypedParseTree::Contract { abi_entries, .. }) => { + abi_entries.iter().map(|x| x.parse_json_abi()).collect() + } + _ => vec![], + } +} From bc861bc2edba0ae0d3e275e896873eadcd3d68a6 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 29 Nov 2021 18:53:24 -0600 Subject: [PATCH 16/25] Finish merge. --- Cargo.lock | 44 +- Cargo.toml | 3 +- core_lang/Cargo.toml | 4 - .../ast_node/expression/typed_expression.rs | 96 +-- .../src/semantic_analysis/ast_node/mod.rs | 610 ++++++------------ forc/Cargo.toml | 4 - forc/src/ops/forc_build.rs | 151 +---- forc/src/utils/helpers.rs | 87 ++- 8 files changed, 330 insertions(+), 669 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 584f5d575c5..0579158bfe9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -812,11 +812,8 @@ dependencies = [ "pest_derive", "petgraph", "sha2", -<<<<<<< HEAD - "source-span", -======= "smallvec", ->>>>>>> origin/master + "source-span", "structopt 0.3.25", "thiserror", "uuid-b64", @@ -1237,11 +1234,8 @@ dependencies = [ "reqwest", "semver 1.0.4", "serde", -<<<<<<< HEAD "serde_json", "source-span", -======= ->>>>>>> origin/master "structopt 0.3.25", "tar", "term-table", @@ -2171,6 +2165,12 @@ dependencies = [ "libc", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" + [[package]] name = "object" version = "0.27.1" @@ -2639,6 +2639,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_termios" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" +dependencies = [ + "redox_syscall 0.2.10", +] + [[package]] name = "redox_users" version = "0.3.5" @@ -3068,6 +3077,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "source-span" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3afeb8b7a1ae2e8721f2193cc2291c9e00dd68511907fd8b807e2c8d42caa3c" +dependencies = [ + "termion", +] + [[package]] name = "spin" version = "0.9.2" @@ -3351,6 +3369,18 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termion" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" +dependencies = [ + "libc", + "numtoa", + "redox_syscall 0.2.10", + "redox_termios", +] + [[package]] name = "test" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 0c7a76e9b2e..d5207af4e9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,7 @@ members = [ "docstrings", "forc", "formatter", - "parser" -, + "parser", "sway-server", "test"] diff --git a/core_lang/Cargo.toml b/core_lang/Cargo.toml index edd3b325109..6d10cf280c9 100644 --- a/core_lang/Cargo.toml +++ b/core_lang/Cargo.toml @@ -24,14 +24,10 @@ smallvec = "1.7" structopt = { version = "0.3", default-features = false, optional = true } thiserror = "1.0" uuid-b64 = "0.1" -<<<<<<< HEAD line-col = "0.2" source-span = "2.4" core-types = { path = "../core-types" } -lazy_static = "1.4" -======= ->>>>>>> origin/master [[bin]] name = "selector-debug" diff --git a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs index 50df8c855a8..c87832be187 100644 --- a/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/core_lang/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -379,77 +379,6 @@ impl<'sc> TypedExpression<'sc> { warnings, errors ); -<<<<<<< HEAD - let exp = match function_declaration { - TypedDeclaration::FunctionDeclaration(decl) => { - let TypedFunctionDeclaration { - parameters, - return_type, - body, - .. - } = decl.clone(); - match arguments.len().cmp(¶meters.len()) { - Ordering::Greater => { - let arguments_span = arguments.iter().fold( - arguments - .get(0) - .map(|x| x.span()) - .unwrap_or_else(|| name.span()), - |acc, arg| crate::utils::join_spans(acc, arg.span()), - ); - errors.push(CompileError::TooManyArgumentsForFunction { - span: arguments_span, - method_name: name.suffix.primary_name, - expected: parameters.len(), - received: arguments.len(), - }); - } - Ordering::Less => { - let arguments_span = arguments.iter().fold( - arguments - .get(0) - .map(|x| x.span()) - .unwrap_or_else(|| name.span()), - |acc, arg| crate::utils::join_spans(acc, arg.span()), - ); - errors.push(CompileError::TooFewArgumentsForFunction { - span: arguments_span, - method_name: name.suffix.primary_name, - expected: parameters.len(), - received: arguments.len(), - }); - } - Ordering::Equal => {} - } - // type check arguments in function application vs arguments in function - // declaration. Use parameter type annotations as annotations for the - // arguments - // - let typed_call_arguments = - arguments - .into_iter() - .zip(parameters.iter()) - .map(|(arg, param)| { - (param.name.clone(), TypedExpression::type_check( - arg.clone(), - namespace, - Some(param.r#type), - "The argument that has been provided to this function's type does \ - not match the declared type of the parameter in the function \ - declaration.", - self_type, - build_config, - dead_code_graph, - dependency_graph, - ) - .unwrap_or_else( - &mut warnings, - &mut errors, - || error_recovery_expr(arg.span()), - )) - }) - .collect(); -======= let TypedFunctionDeclaration { parameters, return_type, @@ -477,7 +406,6 @@ impl<'sc> TypedExpression<'sc> { }); return err(warnings, errors); }; ->>>>>>> origin/master match arguments.len().cmp(¶meters.len()) { Ordering::Greater => { @@ -586,7 +514,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(lhs.span()), warnings, @@ -602,7 +530,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(rhs.span()), warnings, @@ -705,7 +633,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), ( TypedCodeBlock { @@ -766,7 +694,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(condition.span()), warnings, @@ -781,7 +709,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(then.span()), warnings, @@ -797,7 +725,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(expr.span()), warnings, @@ -874,7 +802,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(initializer.span()), warnings, @@ -974,7 +902,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), continue, warnings, @@ -1038,7 +966,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), return err(warnings, errors), warnings, @@ -1149,7 +1077,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), return err(warnings, errors), warnings, @@ -1205,7 +1133,7 @@ impl<'sc> TypedExpression<'sc> { self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(err_span), warnings, @@ -1252,7 +1180,7 @@ impl<'sc> TypedExpression<'sc> { build_config, dead_code_graph, Mode::ImplAbiFn, - dependency_graph, + dependency_graph ), return err(warnings, errors), warnings, diff --git a/core_lang/src/semantic_analysis/ast_node/mod.rs b/core_lang/src/semantic_analysis/ast_node/mod.rs index 131ec4c1d68..2b428508481 100644 --- a/core_lang/src/semantic_analysis/ast_node/mod.rs +++ b/core_lang/src/semantic_analysis/ast_node/mod.rs @@ -153,215 +153,33 @@ impl<'sc> TypedAstNode<'sc> { ) }; - let content = match node.content.clone() { - AstNodeContent::UseStatement(a) => { - let mut res = match a.import_type { - ImportType::Star => namespace.star_import(a.call_path, a.is_absolute), - ImportType::Item(s) => { - namespace.item_import(a.call_path, &s, a.is_absolute, a.alias) - } - }; - warnings.append(&mut res.warnings); - errors.append(&mut res.errors); - TypedAstNodeContent::SideEffect - } - AstNodeContent::IncludeStatement(ref a) => { - // Import the file, parse it, put it in the namespace under the module name (alias or - // last part of the import by default) - let _ = check!( - import_new_file( - a, - namespace, - build_config, - dead_code_graph, - dependency_graph - ), - return err(warnings, errors), - warnings, - errors - ); - TypedAstNodeContent::SideEffect - } - AstNodeContent::Declaration(a) => { - TypedAstNodeContent::Declaration(match a { - Declaration::VariableDeclaration(VariableDeclaration { - name, - type_ascription, - body, - is_mutable, - }) => { - let result = type_check_ascribed_expr(type_ascription, body, "Variable"); - let body = check!( - result, - error_recovery_expr(name.span.clone()), - warnings, - errors - ); - let typed_var_decl = - TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { - name: name.clone(), - body, - is_mutable, - }); - namespace.insert(name, typed_var_decl.clone()); - typed_var_decl - } - Declaration::ConstantDeclaration(ConstantDeclaration { - name, - type_ascription, - value, - visibility, - }) => { - let result = type_check_ascribed_expr(type_ascription, value, "Constant"); - let value = check!( - result, - error_recovery_expr(name.span.clone()), - warnings, - errors - ); - let typed_const_decl = - TypedDeclaration::ConstantDeclaration(TypedConstantDeclaration { - name: name.clone(), - value, - visibility, - }); - namespace.insert(name, typed_const_decl.clone()); - typed_const_decl - } - Declaration::EnumDeclaration(e) => { - let span = e.span.clone(); - let primary_name = e.name.primary_name; - let decl = TypedDeclaration::EnumDeclaration( - e.to_typed_decl(namespace, self_type), - ); - - namespace.insert(Ident { primary_name, span }, decl.clone()); - decl - } - Declaration::FunctionDeclaration(fn_decl) => { - let decl = check!( - TypedFunctionDeclaration::type_check( - fn_decl.clone(), - namespace, - crate::type_engine::insert_type(TypeInfo::Unknown), - "", - self_type, - build_config, - dead_code_graph, - Mode::NonAbi, - dependency_graph, - ), - error_recovery_function_declaration(fn_decl), - warnings, - errors - ); - if errors.is_empty() { - // Add this function declaration to the namespace only if it - // fully typechecked without errors. - namespace.insert( - decl.name.clone(), - TypedDeclaration::FunctionDeclaration(decl.clone()), - ); + let node = TypedAstNode { + content: match node.content.clone() { + AstNodeContent::UseStatement(a) => { + let mut res = match a.import_type { + ImportType::Star => namespace.star_import(a.call_path, a.is_absolute), + ImportType::Item(s) => { + namespace.item_import(a.call_path, &s, a.is_absolute, a.alias) } - TypedDeclaration::FunctionDeclaration(decl) - } - Declaration::TraitDeclaration(TraitDeclaration { - name, - interface_surface, - methods, - type_parameters, - visibility, - }) => { - // type check the interface surface - let interface_surface = - type_check_interface_surface(interface_surface, namespace); - let mut trait_namespace = namespace.clone(); - // insert placeholder functions representing the interface surface - // to allow methods to use those functions - trait_namespace.insert_trait_implementation( - CallPath { - prefixes: vec![], - suffix: name.clone(), - }, - TypeInfo::SelfType, - interface_surface - .iter() - .map(|x| x.to_dummy_func(Mode::NonAbi)) - .collect(), - ); - // check the methods for errors but throw them away and use vanilla [FunctionDeclaration]s - let _methods = check!( - type_check_trait_methods( - methods.clone(), - &trait_namespace, - insert_type(TypeInfo::SelfType), - build_config, - dead_code_graph, - dependency_graph, - ), - vec![], - warnings, - errors - ); - let trait_decl = - TypedDeclaration::TraitDeclaration(TypedTraitDeclaration { - name: name.clone(), - interface_surface, - methods, - type_parameters, - visibility, - }); - namespace.insert(name, trait_decl.clone()); - trait_decl - } - Declaration::Reassignment(Reassignment { lhs, rhs, span }) => { - check!( - reassignment( - lhs, - rhs, - span, - namespace, - self_type, - build_config, - dead_code_graph, - dependency_graph, - ), - return err(warnings, errors), - warnings, - errors - ) - } - Declaration::ImplTrait(impl_trait) => check!( - implementation_of_trait( - impl_trait, + }; + warnings.append(&mut res.warnings); + errors.append(&mut res.errors); + TypedAstNodeContent::SideEffect + } + AstNodeContent::IncludeStatement(ref a) => { + // Import the file, parse it, put it in the namespace under the module name (alias or + // last part of the import by default) + let _ = check!( + import_new_file( + a, namespace, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), return err(warnings, errors), warnings, errors -<<<<<<< HEAD - ), - - Declaration::ImplSelf(ImplSelf { - type_arguments, - functions, - type_implementing_for, - block_span, - .. - }) => { - let implementing_for_type_id = - namespace.resolve_type_without_self(&type_implementing_for); - // check, if this is a custom type, if it is in scope or a generic. - let mut functions_buf: Vec = vec![]; - if !type_arguments.is_empty() { - errors.push(CompileError::Internal( - "Where clauses are not supported yet.", - type_arguments[0].clone().name_ident.span, - )); -======= ); TypedAstNodeContent::SideEffect } @@ -441,64 +259,33 @@ impl<'sc> TypedAstNode<'sc> { }); namespace.insert(name, typed_const_decl.clone()); typed_const_decl ->>>>>>> origin/master } - for mut fn_decl in functions.into_iter() { - let mut type_arguments = type_arguments.clone(); - // add generic params from impl trait into function type params - fn_decl.type_parameters.append(&mut type_arguments); - // ensure this fn decl's parameters and signature lines up with the - // one in the trait - - // replace SelfType with type of implementor - // i.e. fn add(self, other: u64) -> Self becomes fn - // add(self: u64, other: u64) -> u64 - fn_decl.parameters.iter_mut().for_each( - |FunctionParameter { ref mut r#type, .. }| { - if r#type == &TypeInfo::SelfType { - *r#type = type_implementing_for.clone(); - } - }, + Declaration::EnumDeclaration(e) => { + let span = e.span.clone(); + let primary_name = e.name.primary_name; + let decl = TypedDeclaration::EnumDeclaration( + e.to_typed_decl(namespace, self_type), ); - if fn_decl.return_type == TypeInfo::SelfType { - fn_decl.return_type = type_implementing_for.clone(); - } - functions_buf.push(check!( + namespace.insert(Ident { primary_name, span }, decl.clone()); + decl + } + Declaration::FunctionDeclaration(fn_decl) => { + let decl = check!( TypedFunctionDeclaration::type_check( - fn_decl, + fn_decl.clone(), namespace, crate::type_engine::insert_type(TypeInfo::Unknown), "", - implementing_for_type_id, + self_type, build_config, dead_code_graph, Mode::NonAbi, - dependency_graph, + dependency_graph ), - continue, + error_recovery_function_declaration(fn_decl), warnings, errors -<<<<<<< HEAD - )); - } - let trait_name = CallPath { - prefixes: vec![], - suffix: Ident { - primary_name: "r#Self", - span: block_span.clone(), - }, - }; - namespace.insert_trait_implementation( - trait_name.clone(), - look_up_type_id(implementing_for_type_id), - functions_buf.clone(), - ); - TypedDeclaration::ImplTrait { - trait_name, - span: block_span, - methods: functions_buf, -======= ); namespace.insert( decl.name.clone(), @@ -592,35 +379,77 @@ impl<'sc> TypedAstNode<'sc> { Declaration::ImplSelf(ImplSelf { type_arguments, functions, ->>>>>>> origin/master type_implementing_for, - } -<<<<<<< HEAD - } - Declaration::StructDeclaration(decl) => { - // look up any generic or struct types in the namespace - let fields = decl - .fields - .into_iter() - .map(|StructField { name, r#type, span }| TypedStructField { - name, - r#type: namespace.resolve_type_with_self(r#type, self_type), - span, - }) - .collect::>(); - let decl = TypedStructDeclaration { - name: decl.name.clone(), - type_parameters: decl.type_parameters.clone(), - fields, - visibility: decl.visibility, - }; + block_span, + .. + }) => { + let implementing_for_type_id = + namespace.resolve_type_without_self(&type_implementing_for); + // check, if this is a custom type, if it is in scope or a generic. + let mut functions_buf: Vec = vec![]; + if !type_arguments.is_empty() { + errors.push(CompileError::Internal( + "Where clauses are not supported yet.", + type_arguments[0].clone().name_ident.span, + )); + } + for mut fn_decl in functions.into_iter() { + let mut type_arguments = type_arguments.clone(); + // add generic params from impl trait into function type params + fn_decl.type_parameters.append(&mut type_arguments); + // ensure this fn decl's parameters and signature lines up with the + // one in the trait + + // replace SelfType with type of implementor + // i.e. fn add(self, other: u64) -> Self becomes fn + // add(self: u64, other: u64) -> u64 + fn_decl.parameters.iter_mut().for_each( + |FunctionParameter { ref mut r#type, .. }| { + if r#type == &TypeInfo::SelfType { + *r#type = type_implementing_for.clone(); + } + }, + ); + if fn_decl.return_type == TypeInfo::SelfType { + fn_decl.return_type = type_implementing_for.clone(); + } - // insert struct into namespace - namespace.insert( - decl.name.clone(), - TypedDeclaration::StructDeclaration(decl.clone()), - ); -======= + functions_buf.push(check!( + TypedFunctionDeclaration::type_check( + fn_decl, + namespace, + crate::type_engine::insert_type(TypeInfo::Unknown), + "", + implementing_for_type_id, + build_config, + dead_code_graph, + Mode::NonAbi, + dependency_graph + ), + continue, + warnings, + errors + )); + } + let trait_name = CallPath { + prefixes: vec![], + suffix: Ident { + primary_name: "r#Self", + span: block_span.clone(), + }, + }; + namespace.insert_trait_implementation( + trait_name.clone(), + look_up_type_id(implementing_for_type_id), + functions_buf.clone(), + ); + TypedDeclaration::ImplTrait { + trait_name, + span: block_span, + methods: functions_buf, + type_implementing_for, + } + } Declaration::StructDeclaration(decl) => { // look up any generic or struct types in the namespace // insert type parameters @@ -701,157 +530,122 @@ impl<'sc> TypedAstNode<'sc> { warnings, errors ); ->>>>>>> origin/master - TypedDeclaration::StructDeclaration(decl) - } - Declaration::AbiDeclaration(AbiDeclaration { - name, - interface_surface, - methods, - span, - }) => { - // type check the interface surface and methods - // We don't want the user to waste resources by contract calling - // themselves, and we don't want to do more work in the compiler, - // so we don't support the case of calling a contract's own interface - // from itself. This is by design. - let interface_surface = - type_check_interface_surface(interface_surface, namespace); - // type check these for errors but don't actually use them yet -- the real - // ones will be type checked with proper symbols when the ABI is implemented - let _methods = check!( - type_check_trait_methods( - methods.clone(), + let decl = TypedDeclaration::AbiDeclaration(TypedAbiDeclaration { + interface_surface, + methods, + name: name.clone(), + span, + }); + namespace.insert(name, decl.clone()); + decl + } + }) + } + AstNodeContent::Expression(a) => { + let inner = check!( + TypedExpression::type_check( + a.clone(), + namespace, + None, + "", + self_type, + build_config, + dead_code_graph, + dependency_graph + ), + error_recovery_expr(a.span()), + warnings, + errors + ); + TypedAstNodeContent::Expression(inner) + } + AstNodeContent::ReturnStatement(ReturnStatement { expr }) => { + TypedAstNodeContent::ReturnStatement(TypedReturnStatement { + expr: check!( + TypedExpression::type_check( + expr.clone(), namespace, + Some(return_type_annotation), + "Returned value must match up with the function return type \ + annotation.", self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), - vec![], + error_recovery_expr(expr.span()), warnings, errors - ); - - let decl = TypedDeclaration::AbiDeclaration(TypedAbiDeclaration { - interface_surface, - methods, - name: name.clone(), - span, - }); - namespace.insert(name, decl.clone()); - decl - } - }) - } - AstNodeContent::Expression(a) => { - let inner = check!( - TypedExpression::type_check( - a.clone(), - namespace, - None, - "", - self_type, - build_config, - dead_code_graph, - dependency_graph, - ), - error_recovery_expr(a.span()), - warnings, - errors - ); - TypedAstNodeContent::Expression(inner) - } - AstNodeContent::ReturnStatement(ReturnStatement { expr }) => { - TypedAstNodeContent::ReturnStatement(TypedReturnStatement { - expr: check!( + ), + }) + } + AstNodeContent::ImplicitReturnExpression(expr) => { + let typed_expr = check!( TypedExpression::type_check( expr.clone(), namespace, Some(return_type_annotation), - "Returned value must match up with the function return type \ - annotation.", + format!( + "Implicit return must match up with block's type. {}", + help_text.into() + ), self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(expr.span()), warnings, errors - ), - }) - } - AstNodeContent::ImplicitReturnExpression(expr) => { - let typed_expr = check!( - TypedExpression::type_check( - expr.clone(), - namespace, - Some(return_type_annotation), - format!( - "Implicit return must match up with block's type. {}", - help_text.into() + ); + TypedAstNodeContent::ImplicitReturnExpression(typed_expr) + } + AstNodeContent::WhileLoop(WhileLoop { condition, body }) => { + let typed_condition = check!( + TypedExpression::type_check( + condition, + namespace, + Some(crate::type_engine::insert_type(TypeInfo::Boolean)), + "A while loop's loop condition must be a boolean expression.", + self_type, + build_config, + dead_code_graph, + dependency_graph ), - self_type, - build_config, - dead_code_graph, - dependency_graph, - ), - error_recovery_expr(expr.span()), - warnings, - errors - ); - TypedAstNodeContent::ImplicitReturnExpression(typed_expr) - } - AstNodeContent::WhileLoop(WhileLoop { condition, body }) => { - let typed_condition = check!( - TypedExpression::type_check( - condition, - namespace, - Some(crate::type_engine::insert_type(TypeInfo::Boolean)), - "A while loop's loop condition must be a boolean expression.", - self_type, - build_config, - dead_code_graph, - dependency_graph, - ), - return err(warnings, errors), - warnings, - errors - ); - let (typed_body, _block_implicit_return) = check!( - TypedCodeBlock::type_check( - body.clone(), - namespace, - crate::type_engine::insert_type(TypeInfo::Unit), - "A while loop's loop body cannot implicitly return a value.Try \ - assigning it to a mutable variable declared outside of the loop \ - instead.", - self_type, - build_config, - dead_code_graph, - dependency_graph, - ), - ( - TypedCodeBlock { - contents: vec![], - whole_block_span: body.whole_block_span.clone(), - }, - crate::type_engine::insert_type(TypeInfo::Unit) - ), - warnings, - errors - ); - TypedAstNodeContent::WhileLoop(TypedWhileLoop { - condition: typed_condition, - body: typed_body, - }) - } - }; - - let node = TypedAstNode { - content, + return err(warnings, errors), + warnings, + errors + ); + let (typed_body, _block_implicit_return) = check!( + TypedCodeBlock::type_check( + body.clone(), + namespace, + crate::type_engine::insert_type(TypeInfo::Unit), + "A while loop's loop body cannot implicitly return a value.Try \ + assigning it to a mutable variable declared outside of the loop \ + instead.", + self_type, + build_config, + dead_code_graph, + dependency_graph + ), + ( + TypedCodeBlock { + contents: vec![], + whole_block_span: body.whole_block_span.clone(), + }, + crate::type_engine::insert_type(TypeInfo::Unit) + ), + warnings, + errors + ); + TypedAstNodeContent::WhileLoop(TypedWhileLoop { + condition: typed_condition, + body: typed_body, + }) + } + }, span: node.span.clone(), }; @@ -1031,7 +825,7 @@ fn reassignment<'sc>( self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(span), warnings, @@ -1067,7 +861,7 @@ fn reassignment<'sc>( self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(expr.span()), warnings, @@ -1131,7 +925,7 @@ fn reassignment<'sc>( self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), error_recovery_expr(span), warnings, @@ -1359,7 +1153,7 @@ fn type_check_trait_methods<'sc>( self_type, build_config, dead_code_graph, - dependency_graph, + dependency_graph ), continue, warnings, diff --git a/forc/Cargo.toml b/forc/Cargo.toml index 0c95f087c76..030d116ade2 100644 --- a/forc/Cargo.toml +++ b/forc/Cargo.toml @@ -24,13 +24,9 @@ pest = { git = "https://github.com/sezna/pest.git", rev = "8aa58791f759daf4caee2 prettydiff = "0.4.0" reqwest = { version = "0.11.4", features = ["json"] } semver = "1.0.3" -<<<<<<< HEAD serde = {version = "1.0", features = ["derive"]} serde_json = "*" source-span = "2.4" -======= -serde = { version = "1.0", features = ["derive"] } ->>>>>>> origin/master structopt = "0.3" tar = "0.4.35" term-table = "1.3" diff --git a/forc/src/ops/forc_build.rs b/forc/src/ops/forc_build.rs index 7086b6d930a..a2e37f95218 100644 --- a/forc/src/ops/forc_build.rs +++ b/forc/src/ops/forc_build.rs @@ -3,25 +3,14 @@ use crate::{ cli::BuildCommand, utils::dependency, utils::helpers::{ -<<<<<<< HEAD find_manifest_dir, get_main_file, print_on_failure, print_on_success_library, print_on_success_script, read_manifest, }, }; -======= - find_manifest_dir, get_main_file, println_green_err, println_red_err, println_yellow_err, - read_manifest, - }, -}; -use annotate_snippets::{ - display_list::{DisplayList, FormatOptions}, - snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, -}; use core_lang::FinalizedAsm; use std::fs::File; use std::io::Write; ->>>>>>> origin/master use core_lang::{ BuildConfig, BytecodeCompilationResult, CompilationResult, LibraryExports, Namespace, @@ -29,8 +18,6 @@ use core_lang::{ use anyhow::Result; use std::collections::{HashMap, HashSet}; -use std::fs::File; -use std::io::Write; use std::path::{Path, PathBuf}; pub fn build(command: BuildCommand) -> Result, String> { @@ -295,161 +282,33 @@ fn compile<'source>( return Ok(vec![]); } BytecodeCompilationResult::Failure { errors, warnings } => { -<<<<<<< HEAD print_on_failure(silent_mode, warnings, errors); return Err(format!("Failed to compile {}", proj_name)); -======= - let e_len = errors.len(); - - if !silent_mode { - warnings.iter().for_each(|warning| format_warning(warning)); - errors.iter().for_each(|error| format_err(error)); - } - - println_red_err(&format!( - " Aborting due to {} {}.", - e_len, - if e_len > 1 { "errors" } else { "error" } - )) - .unwrap(); - Err(format!("Failed to compile {}", proj_name)) } } } -fn format_warning(err: &core_lang::CompileWarning) { - let input = err.span.input(); - let path = err.path(); - - let (start_pos, mut end_pos) = err.span(); - let friendly_str = err.to_friendly_warning_string(); - if start_pos == end_pos { - // if start/pos are same we will not get that arrow pointing to code, so we add +1. - end_pos += 1; - } - let snippet = Snippet { - title: Some(Annotation { - label: None, - id: None, - annotation_type: AnnotationType::Warning, - }), - footer: vec![], - slices: vec![Slice { - source: input, - line_start: 0, - origin: Some(&path), - fold: true, - annotations: vec![SourceAnnotation { - label: &friendly_str, - annotation_type: AnnotationType::Warning, - range: (start_pos, end_pos), - }], - }], - opt: FormatOptions { - color: true, - ..Default::default() - }, - }; - eprintln!("{}", DisplayList::from(snippet)) -} - -fn format_err(err: &core_lang::CompileError) { - let input = err.internal_span().input(); - let path = err.path(); - - let (start_pos, mut end_pos) = err.span(); - if start_pos == end_pos { - // if start/pos are same we will not get that arrow pointing to code, so we add +1. - end_pos += 1; - } - let friendly_str = err.to_friendly_error_string(); - let snippet = Snippet { - title: Some(Annotation { - label: None, - id: None, - annotation_type: AnnotationType::Error, - }), - footer: vec![], - slices: vec![Slice { - source: input, - line_start: 0, - origin: Some(&path), - fold: true, - annotations: vec![SourceAnnotation { - label: &friendly_str, - annotation_type: AnnotationType::Error, - range: (start_pos, end_pos), - }], - }], - opt: FormatOptions { - color: true, - ..Default::default() - }, - }; - eprintln!("{}", DisplayList::from(snippet)) -} - fn compile_to_asm<'source>( source: &'source str, proj_name: &str, namespace: &Namespace<'source>, build_config: BuildConfig, dependency_graph: &mut HashMap>, + silent_mode: bool, ) -> Result, String> { let res = core_lang::compile_to_asm(source, namespace, build_config, dependency_graph); match res { CompilationResult::Success { asm, warnings } => { - warnings.iter().for_each(|warning| format_warning(warning)); - - if warnings.is_empty() { - let _ = println_green_err(&format!(" Compiled script {:?}.", proj_name)); - } else { - let _ = println_yellow_err(&format!( - " Compiled script {:?} with {} {}.", - proj_name, - warnings.len(), - if warnings.len() > 1 { - "warnings" - } else { - "warning" - } - )); - } + print_on_success_script(silent_mode, proj_name, warnings); Ok(asm) } CompilationResult::Library { warnings, .. } => { - warnings.iter().for_each(|warning| format_warning(warning)); - - if warnings.is_empty() { - let _ = println_green_err(&format!(" Compiled library {:?}.", proj_name)); - } else { - let _ = println_yellow_err(&format!( - " Compiled library {:?} with {} {}.", - proj_name, - warnings.len(), - if warnings.len() > 1 { - "warnings" - } else { - "warning" - } - )); - } + print_on_success_library(silent_mode, proj_name, warnings); Ok(FinalizedAsm::Library) } CompilationResult::Failure { errors, warnings } => { - let e_len = errors.len(); - - warnings.iter().for_each(format_warning); - errors.iter().for_each(format_err); - - println_red_err(&format!( - " Aborting due to {} {}.", - e_len, - if e_len > 1 { "errors" } else { "error" } - )) - .unwrap(); - Err(format!("Failed to compile {}", proj_name)) ->>>>>>> origin/master + print_on_failure(silent_mode, warnings, errors); + return Err(format!("Failed to compile {}", proj_name)); } } } diff --git a/forc/src/utils/helpers.rs b/forc/src/utils/helpers.rs index e6cb9e935d9..c7b279aea49 100644 --- a/forc/src/utils/helpers.rs +++ b/forc/src/utils/helpers.rs @@ -1,7 +1,10 @@ use super::constants::{SRC_DIR, SWAY_EXTENSION}; use super::manifest::Manifest; +use annotate_snippets::{ + display_list::{DisplayList, FormatOptions}, + snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, +}; use core_lang::{CompileError, CompileWarning}; -use source_span::fmt::{Color, Formatter}; use std::ffi::OsStr; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -234,17 +237,73 @@ fn println_with_color(txt: &str, color: TermColor, stream: StandardStream) -> io } fn format_err(err: &core_lang::CompileError) { - let mut fmt = Formatter::with_margin_color(Color::Blue); - let formatted = err.format(&mut fmt); - print_blue_err(" --> ").unwrap(); - print!("{}", err.path()); - println!("{}", formatted); -} - -fn format_warning(warning: &core_lang::CompileWarning) { - let mut fmt = Formatter::with_margin_color(Color::Blue); - let formatted = warning.format(&mut fmt); - print_blue_err(" --> ").unwrap(); - print!("{}", warning.path()); - println!("{}", formatted); + let input = err.internal_span().input(); + let path = err.path(); + + let (start_pos, mut end_pos) = err.span(); + if start_pos == end_pos { + // if start/pos are same we will not get that arrow pointing to code, so we add +1. + end_pos += 1; + } + let friendly_str = err.to_friendly_error_string(); + let snippet = Snippet { + title: Some(Annotation { + label: None, + id: None, + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![Slice { + source: input, + line_start: 0, + origin: Some(&path), + fold: true, + annotations: vec![SourceAnnotation { + label: &friendly_str, + annotation_type: AnnotationType::Error, + range: (start_pos, end_pos), + }], + }], + opt: FormatOptions { + color: true, + ..Default::default() + }, + }; + eprintln!("{}", DisplayList::from(snippet)) +} + +fn format_warning(err: &core_lang::CompileWarning) { + let input = err.span.input(); + let path = err.path(); + + let (start_pos, mut end_pos) = err.span(); + let friendly_str = err.to_friendly_warning_string(); + if start_pos == end_pos { + // if start/pos are same we will not get that arrow pointing to code, so we add +1. + end_pos += 1; + } + let snippet = Snippet { + title: Some(Annotation { + label: None, + id: None, + annotation_type: AnnotationType::Warning, + }), + footer: vec![], + slices: vec![Slice { + source: input, + line_start: 0, + origin: Some(&path), + fold: true, + annotations: vec![SourceAnnotation { + label: &friendly_str, + annotation_type: AnnotationType::Warning, + range: (start_pos, end_pos), + }], + }], + opt: FormatOptions { + color: true, + ..Default::default() + }, + }; + eprintln!("{}", DisplayList::from(snippet)) } From 7a9200cee4a1621ffed0a018fd9216e1bd3d54de Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 29 Nov 2021 18:59:54 -0600 Subject: [PATCH 17/25] nits --- core_lang/src/lib.rs | 14 +++++++------- forc/src/abi_spec/type_info.rs | 7 ------- forc/src/ops/forc_abi_json.rs | 10 +++++----- 3 files changed, 12 insertions(+), 19 deletions(-) delete mode 100644 forc/src/abi_spec/type_info.rs diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index 21b4fc8c1d1..d5632953c31 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -145,7 +145,7 @@ pub enum CompilationResult<'sc> { }, } -pub enum CompileASTResult<'sc> { +pub enum CompileAstResult<'sc> { Success { contract_ast: Option>, script_ast: Option>, @@ -299,12 +299,12 @@ pub fn compile_to_ast<'sc>( initial_namespace: &Namespace<'sc>, build_config: &BuildConfig, dependency_graph: &mut HashMap>, -) -> CompileASTResult<'sc> { +) -> CompileAstResult<'sc> { let mut warnings = Vec::new(); let mut errors = Vec::new(); let parse_tree = check!( parse(input, Some(build_config)), - return CompileASTResult::Failure { errors, warnings }, + return CompileAstResult::Failure { errors, warnings }, warnings, errors ); @@ -365,10 +365,10 @@ pub fn compile_to_ast<'sc>( }; if !errors.is_empty() { - return CompileASTResult::Failure { errors, warnings }; + return CompileAstResult::Failure { errors, warnings }; } - CompileASTResult::Success { + CompileAstResult::Success { contract_ast, predicate_ast, script_ast, @@ -385,10 +385,10 @@ pub fn compile_to_asm<'sc>( dependency_graph: &mut HashMap>, ) -> CompilationResult<'sc> { match compile_to_ast(input, initial_namespace, &build_config, dependency_graph) { - CompileASTResult::Failure { warnings, errors } => { + CompileAstResult::Failure { warnings, errors } => { CompilationResult::Failure { warnings, errors } } - CompileASTResult::Success { + CompileAstResult::Success { predicate_ast, script_ast, contract_ast, diff --git a/forc/src/abi_spec/type_info.rs b/forc/src/abi_spec/type_info.rs deleted file mode 100644 index 204aafdb4ac..00000000000 --- a/forc/src/abi_spec/type_info.rs +++ /dev/null @@ -1,7 +0,0 @@ -use core_lang::{CompileResult, TypeInfo}; - -use serde_json::Value; - -pub fn generate_abi_spec<'sc>(typ: TypeInfo<'sc>) -> CompileResult<'sc, Value> { - unimplemented!() -} \ No newline at end of file diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index 3fa8137a491..44e69f57f87 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -11,7 +11,7 @@ use crate::{ use core_types::{Function, JsonABI}; use anyhow::Result; -use core_lang::{BuildConfig, CompileASTResult, LibraryExports, Namespace, TypedParseTree}; +use core_lang::{BuildConfig, CompileAstResult, LibraryExports, Namespace, TypedParseTree}; use serde_json::{json, Value}; use std::collections::{HashMap, HashSet}; use std::fs::File; @@ -218,7 +218,7 @@ fn compile_library<'source, 'manifest>( ) -> Result<(LibraryExports<'source>, Vec), String> { let res = core_lang::compile_to_ast(&source, namespace, &build_config, dependency_graph); match res { - CompileASTResult::Success { + CompileAstResult::Success { warnings, contract_ast, library_exports: exports, @@ -228,7 +228,7 @@ fn compile_library<'source, 'manifest>( let json_abi = parse_json_abi(&contract_ast); Ok((exports, json_abi)) } - CompileASTResult::Failure { warnings, errors } => { + CompileAstResult::Failure { warnings, errors } => { print_on_failure(silent_mode, warnings, errors); Err(format!("Failed to compile {}", proj_name)) } @@ -245,7 +245,7 @@ fn compile<'source, 'manifest>( ) -> Result, String> { let res = core_lang::compile_to_ast(&source, namespace, &build_config, dependency_graph); match res { - CompileASTResult::Success { + CompileAstResult::Success { warnings, contract_ast, .. @@ -254,7 +254,7 @@ fn compile<'source, 'manifest>( let json_abi = parse_json_abi(&contract_ast); Ok(json_abi) } - CompileASTResult::Failure { warnings, errors } => { + CompileAstResult::Failure { warnings, errors } => { print_on_failure(silent_mode, warnings, errors); Err(format!("Failed to compile {}", proj_name)) } From 218bc2cf203a2182195fe72dd7dac42f11feaf0c Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 29 Nov 2021 19:20:04 -0600 Subject: [PATCH 18/25] Fix bad merge. --- core_lang/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index d5632953c31..ca307b7ae85 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -434,6 +434,8 @@ pub fn compile_to_asm<'sc>( errors.append(&mut l_errors); warnings.append(&mut l_warnings); + errors = dedup_unsorted(errors); + warnings = dedup_unsorted(warnings); // for each syntax tree, generate assembly. let predicate_asm = (|| { if let Some(tree) = predicate_ast { From 2c042f0ac525ef71b4a22488f9eabd63b25c6998 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Tue, 30 Nov 2021 13:38:47 -0600 Subject: [PATCH 19/25] Update oracles. --- .../test_programs/contract_abi_impl/json_abi_oracle.json | 2 +- .../test_programs/generic_enum/json_abi_oracle.json | 1 + .../test_programs/generic_functions/json_abi_oracle.json | 1 + .../test_programs/generic_struct/json_abi_oracle.json | 1 + .../test_programs/generic_structs/json_abi_oracle.json | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 test/src/e2e_vm_tests/test_programs/generic_enum/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/generic_functions/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/generic_struct/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/generic_structs/json_abi_oracle.json diff --git a/test/src/e2e_vm_tests/test_programs/contract_abi_impl/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/contract_abi_impl/json_abi_oracle.json index 8ffd25cafc2..11fe497ffb3 100644 --- a/test/src/e2e_vm_tests/test_programs/contract_abi_impl/json_abi_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/contract_abi_impl/json_abi_oracle.json @@ -1 +1 @@ -[{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"coin","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":[{"components":null,"name":"field_1","type":"bool"},{"components":null,"name":"field_2","type":"u64"}],"name":"input","type":"struct InputStruct"}],"name":"foo","outputs":[{"components":[{"components":null,"name":"field_1","type":"bool"},{"components":null,"name":"field_2","type":"u64"}],"name":"","type":"struct InputStruct"}],"type":"function"},{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"coin","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":null,"name":"input","type":"bool"}],"name":"baz","outputs":[{"components":null,"name":"","type":"()"}],"type":"function"}] \ No newline at end of file +[{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"coin","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":[{"components":null,"name":"field_1","type":"bool"},{"components":null,"name":"field_2","type":"u64"}],"name":"input","type":"struct InputStruct"}],"name":"foo","outputs":[{"components":[{"components":null,"name":"field_1","type":"bool"},{"components":null,"name":"field_2","type":"u64"}],"name":"","type":"struct InputStruct"}],"type":"function"},{"inputs":[{"components":null,"name":"gas","type":"u64"},{"components":null,"name":"coin","type":"u64"},{"components":null,"name":"color","type":"b256"},{"components":null,"name":"input","type":"bool"}],"name":"baz","outputs":[{"components":null,"name":"","type":"()"}],"type":"function"}] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/generic_enum/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/generic_enum/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/generic_enum/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/generic_functions/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/generic_functions/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/generic_functions/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/generic_struct/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/generic_struct/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/generic_struct/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/generic_structs/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/generic_structs/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/generic_structs/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file From c7f20bbc92071a36d95ff6292f4df1c165ff8bdf Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Tue, 30 Nov 2021 16:01:15 -0600 Subject: [PATCH 20/25] Missing oracle files. --- .../e2e_vm_tests/test_programs/address_test/json_abi_oracle.json | 1 + .../test_programs/array_bad_index/json_abi_oracle.json | 1 + .../e2e_vm_tests/test_programs/array_basics/json_abi_oracle.json | 1 + .../test_programs/array_dynamic_oob/json_abi_oracle.json | 1 + .../test_programs/array_generics/json_abi_oracle.json | 1 + .../e2e_vm_tests/test_programs/array_oob/json_abi_oracle.json | 1 + .../e2e_vm_tests/test_programs/b512_test/json_abi_oracle.json | 1 + .../test_programs/bad_generic_annotation/json_abi_oracle.json | 1 + .../bad_generic_var_annotation/json_abi_oracle.json | 1 + .../test_programs/missing_type_parameters/json_abi_oracle.json | 1 + 10 files changed, 10 insertions(+) create mode 100644 test/src/e2e_vm_tests/test_programs/address_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/array_bad_index/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/array_basics/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/array_dynamic_oob/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/array_generics/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/array_oob/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/b512_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/bad_generic_annotation/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/bad_generic_var_annotation/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/missing_type_parameters/json_abi_oracle.json diff --git a/test/src/e2e_vm_tests/test_programs/address_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/address_test/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/address_test/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/array_bad_index/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/array_bad_index/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/array_bad_index/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/array_basics/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/array_basics/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/array_basics/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/array_dynamic_oob/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/array_dynamic_oob/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/array_dynamic_oob/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/array_generics/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/array_generics/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/array_generics/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/array_oob/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/array_oob/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/array_oob/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/b512_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/b512_test/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/b512_test/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/bad_generic_annotation/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/bad_generic_annotation/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/bad_generic_annotation/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/bad_generic_var_annotation/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/bad_generic_var_annotation/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/bad_generic_var_annotation/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/missing_type_parameters/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/missing_type_parameters/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/missing_type_parameters/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file From 8d27323030e57daca84e213e67ebe026f58a4173 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Thu, 9 Dec 2021 18:00:21 -0600 Subject: [PATCH 21/25] fmt --- core_lang/src/lib.rs | 12 +++++++++--- forc/src/ops/forc_abi_json.rs | 8 +++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/core_lang/src/lib.rs b/core_lang/src/lib.rs index ea0e1c2e962..5c4c3d6b14b 100644 --- a/core_lang/src/lib.rs +++ b/core_lang/src/lib.rs @@ -328,7 +328,7 @@ pub fn compile_to_ast<'sc>( CompileAstResult::Success { parse_tree: typed_parse_tree, tree_type: parse_tree.tree_type, - warnings + warnings, } } @@ -339,8 +339,14 @@ pub fn compile_to_asm<'sc>( dependency_graph: &mut HashMap>, ) -> CompilationResult<'sc> { match compile_to_ast(input, initial_namespace, &build_config, dependency_graph) { - CompileAstResult::Failure { warnings, errors } => CompilationResult::Failure { warnings, errors }, - CompileAstResult::Success { parse_tree, tree_type, mut warnings } => { + CompileAstResult::Failure { warnings, errors } => { + CompilationResult::Failure { warnings, errors } + } + CompileAstResult::Success { + parse_tree, + tree_type, + mut warnings, + } => { let mut errors = vec![]; match tree_type { TreeType::Contract | TreeType::Script | TreeType::Predicate => { diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index d898cce41e0..4b419671a73 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -11,7 +11,9 @@ use crate::{ use core_types::{Function, JsonABI}; use anyhow::Result; -use core_lang::{BuildConfig, CompileAstResult, LibraryExports, Namespace, TypedParseTree, TreeType}; +use core_lang::{ + BuildConfig, CompileAstResult, LibraryExports, Namespace, TreeType, TypedParseTree, +}; use serde_json::{json, Value}; use std::collections::{HashMap, HashSet}; use std::fs::File; @@ -238,7 +240,7 @@ fn compile_library<'source, 'manifest>( ); exports.trees.push(parse_tree); Ok((exports, json_abi)) - }, + } _ => { print_on_failure(silent_mode, warnings, errors); Err(format!("Failed to compile {}", proj_name)) @@ -273,7 +275,7 @@ fn compile<'source, 'manifest>( print_on_success_script(silent_mode, proj_name, warnings); let json_abi = parse_json_abi(&Some(parse_tree)); Ok(json_abi) - }, + } _ => { print_on_failure(silent_mode, warnings, errors); Err(format!("Failed to compile {}", proj_name)) From 3aeafb2d2c14a47dbdb87768bf31534a716c730b Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Thu, 9 Dec 2021 18:04:08 -0600 Subject: [PATCH 22/25] rename function. --- .../src/semantic_analysis/ast_node/declaration.rs | 14 +++++++------- core_lang/src/type_engine.rs | 15 +++++++++------ forc/src/ops/forc_abi_json.rs | 8 ++++---- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/core_lang/src/semantic_analysis/ast_node/declaration.rs b/core_lang/src/semantic_analysis/ast_node/declaration.rs index f9b716b46fa..820a1a2da4c 100644 --- a/core_lang/src/semantic_analysis/ast_node/declaration.rs +++ b/core_lang/src/semantic_analysis/ast_node/declaration.rs @@ -281,11 +281,11 @@ impl OwnedTypedStructField { } } - pub fn parse_json_abi(&self) -> Property { + pub fn generate_json_abi(&self) -> Property { Property { name: self.name.clone(), type_field: self.r#type.friendly_type_str(), - components: self.r#type.parse_json_abi(), + components: self.r#type.generate_json_abi(), } } } @@ -376,11 +376,11 @@ pub struct OwnedTypedEnumVariant { } impl OwnedTypedEnumVariant { - pub fn parse_json_abi(&self) -> Property { + pub fn generate_json_abi(&self) -> Property { Property { name: self.name.clone(), type_field: self.r#type.friendly_type_str(), - components: self.r#type.parse_json_abi(), + components: self.r#type.generate_json_abi(), } } } @@ -600,7 +600,7 @@ impl<'sc> TypedFunctionDeclaration<'sc> { ) } - pub fn parse_json_abi(&self) -> Function { + pub fn generate_json_abi(&self) -> Function { Function { name: self.name.primary_name.to_string(), type_field: "function".to_string(), @@ -610,13 +610,13 @@ impl<'sc> TypedFunctionDeclaration<'sc> { .map(|x| Property { name: x.name.primary_name.to_string(), type_field: x.r#type.friendly_type_str(), - components: x.r#type.parse_json_abi(), + components: x.r#type.generate_json_abi(), }) .collect(), outputs: vec![Property { name: "".to_string(), type_field: self.return_type.friendly_type_str(), - components: self.return_type.parse_json_abi(), + components: self.return_type.generate_json_abi(), }], } } diff --git a/core_lang/src/type_engine.rs b/core_lang/src/type_engine.rs index 47c37535040..a90770b2add 100644 --- a/core_lang/src/type_engine.rs +++ b/core_lang/src/type_engine.rs @@ -24,18 +24,21 @@ impl FriendlyTypeString for TypeId { } pub(crate) trait ToJsonAbi { - fn parse_json_abi(&self) -> Option>; + fn generate_json_abi(&self) -> Option>; } impl ToJsonAbi for TypeId { - fn parse_json_abi(&self) -> Option> { + fn generate_json_abi(&self) -> Option> { match look_up_type_id(*self) { TypeInfo::Struct { fields, .. } => { - Some(fields.iter().map(|x| x.parse_json_abi()).collect()) - } - TypeInfo::Enum { variant_types, .. } => { - Some(variant_types.iter().map(|x| x.parse_json_abi()).collect()) + Some(fields.iter().map(|x| x.generate_json_abi()).collect()) } + TypeInfo::Enum { variant_types, .. } => Some( + variant_types + .iter() + .map(|x| x.generate_json_abi()) + .collect(), + ), _ => None, } } diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index 4b419671a73..3ac9a8366aa 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -229,7 +229,7 @@ fn compile_library<'source, 'manifest>( match tree_type { TreeType::Library { name } => { print_on_success_library(silent_mode, proj_name, warnings); - let json_abi = parse_json_abi(&Some(parse_tree.clone())); + let json_abi = generate_json_abi(&Some(parse_tree.clone())); let mut exports = LibraryExports { namespace: Default::default(), trees: vec![], @@ -273,7 +273,7 @@ fn compile<'source, 'manifest>( match tree_type { TreeType::Contract {} => { print_on_success_script(silent_mode, proj_name, warnings); - let json_abi = parse_json_abi(&Some(parse_tree)); + let json_abi = generate_json_abi(&Some(parse_tree)); Ok(json_abi) } _ => { @@ -289,10 +289,10 @@ fn compile<'source, 'manifest>( } } -fn parse_json_abi(ast: &Option) -> JsonABI { +fn generate_json_abi(ast: &Option) -> JsonABI { match ast { Some(TypedParseTree::Contract { abi_entries, .. }) => { - abi_entries.iter().map(|x| x.parse_json_abi()).collect() + abi_entries.iter().map(|x| x.generate_json_abi()).collect() } _ => vec![], } From 3dd12ecde29d38346b1898c3c03fb470e47c9326 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Fri, 10 Dec 2021 12:35:56 -0600 Subject: [PATCH 23/25] fix bug --- forc/src/ops/forc_abi_json.rs | 23 ++++++++++++++--------- forc/src/ops/forc_build.rs | 10 +++++----- forc/src/utils/helpers.rs | 29 +++++++++++++++++++++++------ test/src/e2e_vm_tests/harness.rs | 2 +- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index 3ac9a8366aa..6747e329c1e 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -4,7 +4,7 @@ use crate::{ utils::dependency, utils::helpers::{ find_file_name, find_main_path, find_manifest_dir, get_main_file, print_on_failure, - print_on_success_library, print_on_success_script, read_manifest, + print_on_success, read_manifest, }, }; @@ -218,7 +218,7 @@ fn compile_library<'source, 'manifest>( dependency_graph: &mut HashMap>, silent_mode: bool, ) -> Result<(LibraryExports<'source>, Vec), String> { - let res = core_lang::compile_to_ast(&source, namespace, &build_config, dependency_graph); + let res = core_lang::compile_to_ast(source, namespace, &build_config, dependency_graph); match res { CompileAstResult::Success { parse_tree, @@ -228,7 +228,12 @@ fn compile_library<'source, 'manifest>( let errors = vec![]; match tree_type { TreeType::Library { name } => { - print_on_success_library(silent_mode, proj_name, warnings); + print_on_success( + silent_mode, + proj_name, + warnings, + TreeType::Library { name: name.clone() }, + ); let json_abi = generate_json_abi(&Some(parse_tree.clone())); let mut exports = LibraryExports { namespace: Default::default(), @@ -271,15 +276,15 @@ fn compile<'source, 'manifest>( } => { let errors = vec![]; match tree_type { - TreeType::Contract {} => { - print_on_success_script(silent_mode, proj_name, warnings); - let json_abi = generate_json_abi(&Some(parse_tree)); - Ok(json_abi) - } - _ => { + TreeType::Library { .. } => { print_on_failure(silent_mode, warnings, errors); Err(format!("Failed to compile {}", proj_name)) } + typ => { + print_on_success(silent_mode, proj_name, warnings, typ); + let json_abi = generate_json_abi(&Some(parse_tree)); + Ok(json_abi) + } } } CompileAstResult::Failure { warnings, errors } => { diff --git a/forc/src/ops/forc_build.rs b/forc/src/ops/forc_build.rs index a16ff48657b..1948dce80b0 100644 --- a/forc/src/ops/forc_build.rs +++ b/forc/src/ops/forc_build.rs @@ -3,11 +3,11 @@ use crate::{ cli::BuildCommand, utils::dependency, utils::helpers::{ - find_manifest_dir, get_main_file, print_on_failure, print_on_success_library, - print_on_success_script, read_manifest, + find_manifest_dir, get_main_file, print_on_failure, print_on_success, + print_on_success_library, read_manifest, }, }; -use core_lang::FinalizedAsm; +use core_lang::{FinalizedAsm, TreeType}; use std::fs::File; use std::io::Write; @@ -279,7 +279,7 @@ fn compile<'n, 'source>( let res = core_lang::compile_to_bytecode(source, namespace, build_config, dependency_graph); match res { BytecodeCompilationResult::Success { bytes, warnings } => { - print_on_success_script(silent_mode, proj_name, warnings); + print_on_success(silent_mode, proj_name, warnings, TreeType::Script {}); return Ok(bytes); } BytecodeCompilationResult::Library { warnings } => { @@ -304,7 +304,7 @@ fn compile_to_asm<'sc>( let res = core_lang::compile_to_asm(source, namespace, build_config, dependency_graph); match res { CompilationResult::Success { asm, warnings } => { - print_on_success_script(silent_mode, proj_name, warnings); + print_on_success(silent_mode, proj_name, warnings, TreeType::Script {}); Ok(asm) } CompilationResult::Library { warnings, .. } => { diff --git a/forc/src/utils/helpers.rs b/forc/src/utils/helpers.rs index c7b279aea49..dbc74afa67f 100644 --- a/forc/src/utils/helpers.rs +++ b/forc/src/utils/helpers.rs @@ -4,7 +4,7 @@ use annotate_snippets::{ display_list::{DisplayList, FormatOptions}, snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}, }; -use core_lang::{CompileError, CompileWarning}; +use core_lang::{CompileError, CompileWarning, TreeType}; use std::ffi::OsStr; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -114,16 +114,29 @@ pub fn get_main_file( Ok(main_file) } -pub fn print_on_success_script(silent_mode: bool, proj_name: &str, warnings: Vec) { +pub fn print_on_success<'sc>( + silent_mode: bool, + proj_name: &str, + warnings: Vec, + tree_type: TreeType<'sc>, +) { + let type_str = match tree_type { + TreeType::Script {} => "script", + TreeType::Contract {} => "contract", + TreeType::Predicate {} => "predicate", + TreeType::Library { .. } => "library", + }; + if !silent_mode { warnings.iter().for_each(|warning| format_warning(warning)); } if warnings.is_empty() { - let _ = println_green_err(&format!(" Compiled script {:?}.", proj_name)); + let _ = println_green_err(&format!(" Compiled {} {:?}.", type_str, proj_name)); } else { let _ = println_yellow_err(&format!( - " Compiled script {:?} with {} {}.", + " Compiled {} {:?} with {} {}.", + type_str, proj_name, warnings.len(), if warnings.len() > 1 { @@ -135,13 +148,17 @@ pub fn print_on_success_script(silent_mode: bool, proj_name: &str, warnings: Vec } } -pub fn print_on_success_library(silent_mode: bool, proj_name: &str, warnings: Vec) { +pub fn print_on_success_library<'sc>( + silent_mode: bool, + proj_name: &str, + warnings: Vec, +) { if !silent_mode { warnings.iter().for_each(|warning| format_warning(warning)); } if warnings.is_empty() { - let _ = println_green_err(&format!(" Compiled script {:?}.", proj_name)); + let _ = println_green_err(&format!(" Compiled library {:?}.", proj_name)); } else { let _ = println_yellow_err(&format!( " Compiled library {:?} with {} {}.", diff --git a/test/src/e2e_vm_tests/harness.rs b/test/src/e2e_vm_tests/harness.rs index d223c739ac2..728c1b4b4ea 100644 --- a/test/src/e2e_vm_tests/harness.rs +++ b/test/src/e2e_vm_tests/harness.rs @@ -199,6 +199,6 @@ fn compile_to_json_abi(file_name: &str) -> Result { manifest_dir, file_name, "json_abi_output.json" )), offline_mode: false, - silent_mode: true, + silent_mode: false, }) } From d9ec3c3783d5b21967bf15fec3bc004f9bad9146 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 13 Dec 2021 14:26:07 -0600 Subject: [PATCH 24/25] Fix manifest_dir bug. --- forc/src/ops/forc_abi_json.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/forc/src/ops/forc_abi_json.rs b/forc/src/ops/forc_abi_json.rs index 6747e329c1e..d3c7fe0a6e3 100644 --- a/forc/src/ops/forc_abi_json.rs +++ b/forc/src/ops/forc_abi_json.rs @@ -17,7 +17,7 @@ use core_lang::{ use serde_json::{json, Value}; use std::collections::{HashMap, HashSet}; use std::fs::File; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; pub fn build(command: JsonAbiCommand) -> Result { // find manifest directory, even if in subdirectory @@ -129,7 +129,7 @@ pub fn build(command: JsonAbiCommand) -> Result { /// Takes a dependency and returns a namespace of exported things from that dependency /// trait implementations are included as well fn compile_dependency_lib<'source, 'manifest>( - project_file_path: &PathBuf, + project_file_path: &Path, dependency_name: &'manifest str, dependency_lib: &Dependency, namespace: &mut Namespace<'source>, @@ -156,14 +156,19 @@ fn compile_dependency_lib<'source, 'manifest>( }; // dependency paths are relative to the path of the project being compiled - let mut project_path = project_file_path.clone(); + let mut project_path = PathBuf::from(project_file_path); project_path.push(dep_path); // compile the dependencies of this dependency // this should detect circular dependencies let manifest_dir = match find_manifest_dir(&project_path) { Some(o) => o, - None => return Err("Manifest not found for dependency.".into()), + None => { + return Err(format!( + "Manifest not found for dependency {:?}.", + project_path + )) + } }; let manifest_of_dep = read_manifest(&manifest_dir)?; let main_path = find_main_path(&manifest_dir, &manifest_of_dep); @@ -182,7 +187,7 @@ fn compile_dependency_lib<'source, 'manifest>( // circular dependencies //return Err("Unimplemented: dependencies that have dependencies".into()); compile_dependency_lib( - project_file_path, + &manifest_dir, dep.0, dep.1, // give it a cloned namespace, which we then merge with this namespace From 213c0254641a8b07573e667ddb543aba50611d49 Mon Sep 17 00:00:00 2001 From: emilyaherbert Date: Mon, 13 Dec 2021 19:25:33 -0600 Subject: [PATCH 25/25] add missing oracle files --- .../e2e_vm_tests/test_programs/block_height/json_abi_oracle.json | 1 + .../test_programs/caller_context_test/json_abi_oracle.json | 1 + .../test_programs/context_testing_abi/json_abi_oracle.json | 1 + .../test_programs/context_testing_contract/json_abi_oracle.json | 1 + .../test_programs/contract_id_test/json_abi_oracle.json | 1 + .../test_programs/zero_field_types/json_abi_oracle.json | 1 + 6 files changed, 6 insertions(+) create mode 100644 test/src/e2e_vm_tests/test_programs/block_height/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/caller_context_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/context_testing_abi/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/context_testing_contract/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/contract_id_test/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/zero_field_types/json_abi_oracle.json diff --git a/test/src/e2e_vm_tests/test_programs/block_height/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/block_height/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/block_height/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/caller_context_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/caller_context_test/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/caller_context_test/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/context_testing_abi/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/context_testing_abi/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/context_testing_abi/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/context_testing_contract/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/context_testing_contract/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/context_testing_contract/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/contract_id_test/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/contract_id_test/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/contract_id_test/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/zero_field_types/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/zero_field_types/json_abi_oracle.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/zero_field_types/json_abi_oracle.json @@ -0,0 +1 @@ +[] \ No newline at end of file