Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate a JSON abi from a .sw file #343

Merged
merged 32 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e34f93b
first commit
Oct 29, 2021
c24ea42
Pass around a JsonABI object.
Oct 29, 2021
3faff5a
Creating the JSON abi output.
Oct 29, 2021
a81acc8
Complete abi json functionality.
Nov 15, 2021
4b6f055
Merge with master.
Nov 16, 2021
2fab502
Merge remote-tracking branch 'origin/master' into emilyaherbert-322-2…
Nov 16, 2021
4c651da
format
Nov 16, 2021
878bf93
Undo the mistakes of past. i.e. type inference means that the JsonABI…
Nov 17, 2021
80c48c6
More.
Nov 19, 2021
d14ce57
Print json to outfile.
Nov 19, 2021
7fcfbe0
Merge remote-tracking branch 'origin/master' into emilyaherbert-322-2…
Nov 19, 2021
786d008
Actually output JSON.
Nov 22, 2021
f9a554e
Delete unused function.
Nov 22, 2021
75e545b
JSON captures components field.
Nov 22, 2021
09db90f
Merge remote-tracking branch 'origin/master' into emilyaherbert-322-2…
Nov 23, 2021
f86c33d
Basic testing infra.
Nov 23, 2021
82f1002
Actual oracle values.
Nov 23, 2021
851a408
Format.
Nov 23, 2021
0c80746
Split compile_asm into compile_ast.
Nov 23, 2021
038b7d8
Working on merge with master.
Nov 30, 2021
bc861bc
Finish merge.
Nov 30, 2021
7a9200c
nits
Nov 30, 2021
218bc2c
Fix bad merge.
Nov 30, 2021
2c042f0
Update oracles.
Nov 30, 2021
c7f20bb
Missing oracle files.
Nov 30, 2021
0ee5b08
Merge with master.
Dec 10, 2021
8d27323
fmt
Dec 10, 2021
3aeafb2
rename function.
Dec 10, 2021
3dd12ec
fix bug
Dec 10, 2021
d9ec3c3
Fix manifest_dir bug.
Dec 13, 2021
5ecfdc8
Merge with master.
Dec 13, 2021
213c025
add missing oracle files
Dec 14, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -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
Expand Down
43 changes: 43 additions & 0 deletions Cargo.lock

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

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ members = [
"docstrings",
"forc",
"formatter",
"parser"
,
"parser",
"sway-server",
"test"]

Expand Down
4 changes: 4 additions & 0 deletions core_lang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ smallvec = "1.7"
structopt = { version = "0.3", default-features = false, optional = true }
thiserror = "1.0"
uuid-b64 = "0.1"
line-col = "0.2"
source-span = "2.4"
core-types = { path = "../core-types" }
emilyaherbert marked this conversation as resolved.
Show resolved Hide resolved


[[bin]]
name = "selector-debug"
Expand Down
61 changes: 61 additions & 0 deletions core_lang/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ use crate::span::Span;
use crate::style::{to_screaming_snake_case, to_snake_case, to_upper_camel_case};
use crate::type_engine::*;
use crate::type_engine::{IntegerBits, TypeInfo};
use line_col::LineColLookup;
use source_span::{
fmt::{Formatter, Style},
Position,
};
use std::fmt;
use thiserror::Error;

Expand Down Expand Up @@ -184,6 +189,34 @@ impl<'sc> CompileWarning<'sc> {
self.span.end_pos().line_col().into(),
)
}

pub fn format(&self, fmt: &mut Formatter) -> source_span::fmt::Formatted {
let input = self.span.input();
let chars = input.chars().map(|x| -> Result<_, ()> { Ok(x) });

let metrics = source_span::DEFAULT_METRICS;
let buffer = source_span::SourceBuffer::new(chars, Position::default(), metrics);

for c in buffer.iter() {
let _ = c.unwrap(); // report eventual errors.
}

let (start_pos, end_pos) = self.span();
let lookup = LineColLookup::new(input);
let (start_line, start_col) = lookup.get(start_pos);
let (end_line, end_col) = lookup.get(end_pos - 1);

let err_start = Position::new(start_line - 1, start_col - 1);
let err_end = Position::new(end_line - 1, end_col - 1);
let err_span = source_span::Span::new(err_start, err_end, err_end.next_column());
fmt.add(
err_span,
Some(self.to_friendly_warning_string()),
Style::Warning,
);

fmt.render(buffer.iter(), buffer.span(), &metrics).unwrap()
}
}

#[derive(Debug, Clone, PartialEq, Hash)]
Expand Down Expand Up @@ -977,4 +1010,32 @@ impl<'sc> CompileError<'sc> {
self.internal_span().end_pos().line_col().into(),
)
}

pub fn format(&self, fmt: &mut Formatter) -> source_span::fmt::Formatted {
let input = self.internal_span().input();
let chars = input.chars().map(Result::<_, String>::Ok);

let metrics = source_span::DEFAULT_METRICS;
let buffer = source_span::SourceBuffer::new(chars, Position::default(), metrics);

for c in buffer.iter() {
let _ = c.unwrap(); // report eventual errors.
}

let (start_pos, end_pos) = self.span();
let lookup = LineColLookup::new(input);
let (start_line, start_col) = lookup.get(start_pos);
let (end_line, end_col) = lookup.get(if end_pos == 0 { 0 } else { end_pos - 1 });

let err_start = Position::new(start_line - 1, start_col - 1);
let err_end = Position::new(end_line - 1, end_col - 1);
let err_span = source_span::Span::new(err_start, err_end, err_end.next_column());
fmt.add(
err_span,
Some(self.to_friendly_error_string()),
Style::Error,
);

fmt.render(buffer.iter(), buffer.span(), &metrics).unwrap()
}
}
90 changes: 64 additions & 26 deletions core_lang/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use pest::Parser;
use std::collections::{HashMap, HashSet};

pub use semantic_analysis::TreeType;
use semantic_analysis::TypedParseTree;
pub use semantic_analysis::TypedParseTree;
pub mod types;
pub(crate) mod utils;
pub use crate::parse_tree::{Declaration, Expression, UseStatement, WhileLoop};
Expand Down Expand Up @@ -177,6 +177,18 @@ pub enum CompilationResult<'sc> {
},
}

pub enum CompileAstResult<'sc> {
Success {
parse_tree: TypedParseTree<'sc>,
tree_type: TreeType<'sc>,
warnings: Vec<CompileWarning<'sc>>,
},
Failure {
warnings: Vec<CompileWarning<'sc>>,
errors: Vec<CompileError<'sc>>,
},
}

/// Represents the result of compiling Sway code via `compile_to_bytecode`.
/// Contains the compiled bytecode in byte form, or, resulting errors, and any warnings generated.
pub enum BytecodeCompilationResult<'sc> {
Expand Down Expand Up @@ -297,19 +309,17 @@ pub(crate) fn compile_inner_dependency<'sc>(
)
}

/// Given input Sway source code, compile to a [CompilationResult] which contains the asm in opcode
/// form (not raw bytes/bytecode).
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<String, HashSet<String>>,
) -> 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
);
Expand All @@ -328,7 +338,7 @@ pub fn compile_to_asm<'sc>(
&mut dead_code_graph,
dependency_graph,
),
return CompilationResult::Failure { errors, warnings },
return CompileAstResult::Failure { errors, warnings },
warnings,
errors
);
Expand All @@ -345,26 +355,54 @@ pub fn compile_to_asm<'sc>(
warnings = dedup_unsorted(warnings);

if !errors.is_empty() {
return CompilationResult::Failure { errors, warnings };
return CompileAstResult::Failure { errors, warnings };
}
match parse_tree.tree_type {
TreeType::Contract | TreeType::Script | TreeType::Predicate => {
let asm = check!(
compile_ast_to_asm(typed_parse_tree, &build_config),
return CompilationResult::Failure { errors, warnings },
warnings,
errors
);
if !errors.is_empty() {
return CompilationResult::Failure { errors, warnings };

CompileAstResult::Success {
parse_tree: typed_parse_tree,
tree_type: parse_tree.tree_type,
warnings,
}
}

/// Given input Sway source code, compile to a [CompilationResult] which contains the asm in opcode
/// form (not raw bytes/bytecode).
pub fn compile_to_asm<'sc>(
input: &'sc str,
initial_namespace: &Namespace<'sc>,
build_config: BuildConfig,
dependency_graph: &mut HashMap<String, HashSet<String>>,
) -> 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,
} => {
let mut errors = vec![];
match tree_type {
TreeType::Contract | TreeType::Script | TreeType::Predicate => {
let asm = check!(
compile_ast_to_asm(parse_tree, &build_config),
return CompilationResult::Failure { errors, warnings },
warnings,
errors
);
if !errors.is_empty() {
return CompilationResult::Failure { errors, warnings };
}
CompilationResult::Success { asm, warnings }
}
TreeType::Library { name } => CompilationResult::Library {
warnings,
name,
namespace: parse_tree.into_namespace(),
},
}
CompilationResult::Success { asm, warnings }
}
TreeType::Library { name } => CompilationResult::Library {
warnings,
name,
namespace: typed_parse_tree.into_namespace(),
},
}
}

Expand Down
22 changes: 22 additions & 0 deletions core_lang/src/parse_tree/declaration/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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(),
components: None,
}],
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
2 changes: 1 addition & 1 deletion core_lang/src/semantic_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ pub(crate) use ast_node::{TypedAstNode, TypedAstNodeContent, TypedExpression};
pub use ast_node::{TypedConstantDeclaration, TypedDeclaration, TypedFunctionDeclaration};
pub use namespace::Namespace;
pub use syntax_tree::TreeType;
pub(crate) use syntax_tree::TypedParseTree;
pub use syntax_tree::TypedParseTree;

const ERROR_RECOVERY_DECLARATION: TypedDeclaration = TypedDeclaration::ErrorRecovery;
Loading