Skip to content

Commit

Permalink
Allow inclusion of multiple source files as dependencies for a single…
Browse files Browse the repository at this point in the history
… contract/script/etc. (FuelLabs#62)

* begin register allocator

* begin reg alloc

* mutable virtual registers; basic allocation algorithm skeleton

* mutable registers in allocation

* pull in fuel-asm official ops

* switching laptops

* begin work on virtual registers and ops

* daily checkpoint

* add AllocatedOp abstraction

* template for parsing ops

* allocation algorithm progress

* change op parsing logic

* WIP parsing inline asm to new ops

* more op parsing

* finish parsing virtual ops from asm

* start registers method

* register allocation method

* convert virtual registers to allocated ones

* switch back to organizational labels for jumps

* realized ops

* fully allocate registers and resolve labels

* print allocated registers

* fill in todo!() errors in asm parsing

* resolve all todosudo apt-get install vlc in core_lang

* switch to ssh for fuel-asm

* resolve warnings

* fix git url

* rustfmt

* small self-code-review

* resolve module

* map the virtual opcodes to fuel_asm ops

* code review feedback

* factor finalized asm out into its own file

* realize data section and instructions to bits

* data section offset label

* initial bytecode generation

* add forc --asm command

* print out the loading of the data section op

* resolve warnings

* fix register allocater bug

* cleanup

* fix bad error message

* code review feedback

* fix doctest

* fix typo

* reference fuel_core for register constants

* add stdlib stuff

* allow use of interface surface functions in the methods section of trait declarations

* comment

* basic math stdlib

* begin work on include statements

* checkpoint while i get breakfast

* parse include statements

* tiny expect fixes

* introduce BuildConfig

* build_config module

* do plumbing for new files

* render warnings and errors on the right text

* use interior library name for module name; support aliasing

* sketch out include compilation and dead code analysis

* perform dead code analysis on imported files

* TDD: broken test cases

* nested dep example

* remove todo

* importing absolutely from the root of the project

* tests of multi-level dependencies

* fix namespace catastrophic short-circuiting when hitting import errors

* use constants for message contents; update error message wording

Co-authored-by: Alexander Hansen <[email protected]>
  • Loading branch information
sezna and Alexander Hansen authored Jun 9, 2021
1 parent 799a159 commit f253593
Show file tree
Hide file tree
Showing 32 changed files with 760 additions and 133 deletions.
35 changes: 23 additions & 12 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion core_lang/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ rust = "1.50"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
pest = "2.0"
#pest = "2.0"
pest_derive = "2.0"
pest = { git = "https://github.com/sezna/pest.git" , rev = "8aa58791f759daf4caee26e8560e862df5a6afb7" }
thiserror = "1.0"
either = "1.6"
Inflector = "0.11"
Expand Down
10 changes: 5 additions & 5 deletions core_lang/src/asm_generation/expression/enum_instantiation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use crate::asm_lang::{
},
Op,
};
use crate::error::*;
use crate::semantic_analysis::ast_node::TypedEnumDeclaration;
use crate::semantic_analysis::TypedExpression;
use crate::Literal;
use crate::{CompileResult, Ident};
use crate::{
error::*,
semantic_analysis::{ast_node::TypedEnumDeclaration, TypedExpression},
CompileResult, Ident, Literal,
};

pub(crate) fn convert_enum_instantiation_to_asm<'sc>(
decl: &TypedEnumDeclaration<'sc>,
Expand Down
17 changes: 17 additions & 0 deletions core_lang/src/build_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use std::path::PathBuf;

/// Configuration for the overall build and compilation process.
#[derive(Clone)]
pub struct BuildConfig {
pub(crate) dir_of_code: PathBuf,
}

impl BuildConfig {
// note this is intentionally not the trait Default
// since we need at least a manifest path to work with
pub fn root_from_manifest_path(canonicalized_manifest_path: PathBuf) -> Self {
let mut path = canonicalized_manifest_path.clone();
path.push("src");
Self { dir_of_code: path }
}
}
2 changes: 2 additions & 0 deletions core_lang/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub const DEFAULT_FILE_EXTENSION: &str = "sw";
pub const LANGUAGE_NAME: &str = "Sway";
27 changes: 17 additions & 10 deletions core_lang/src/control_flow_analysis/dead_code_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,19 @@ impl<'sc> ControlFlowGraph<'sc> {
})
.collect()
}
/// Constructs a graph that is designed to identify unused declarations and sections of code.
pub(crate) fn construct_dead_code_graph(

pub(crate) fn append_to_dead_code_graph(
ast: &TypedParseTree<'sc>,
tree_type: TreeType,
) -> Result<Self, CompileError<'sc>> {
let mut graph = ControlFlowGraph {
graph: Graph::new(),
entry_points: vec![],
namespace: Default::default(),
};
graph: &mut ControlFlowGraph<'sc>,
// the `Result` return is just to handle `Unimplemented` errors
) -> Result<(), CompileError<'sc>> {
// do a depth first traversal and cover individual inner ast nodes
let mut leaves = vec![];
let exit_node = Some(graph.add_node(("Program exit".to_string()).into()));
for ast_entrypoint in ast.all_nodes().iter() {
let (l_leaves, _new_exit_node) =
connect_node(ast_entrypoint, &mut graph, &leaves, exit_node, tree_type)?;
connect_node(ast_entrypoint, graph, &leaves, exit_node, tree_type)?;

leaves = l_leaves;
}
Expand Down Expand Up @@ -168,6 +165,16 @@ impl<'sc> ControlFlowGraph<'sc> {
)),
..
}) => true,
ControlFlowGraphNode::ProgramNode(TypedAstNode {
content:
TypedAstNodeContent::Declaration(TypedDeclaration::StructDeclaration(
TypedStructDeclaration {
visibility: Visibility::Public,
..
},
)),
..
}) => true,
ControlFlowGraphNode::ProgramNode(TypedAstNode {
content:
TypedAstNodeContent::Declaration(TypedDeclaration::ImplTrait { .. }),
Expand All @@ -177,7 +184,7 @@ impl<'sc> ControlFlowGraph<'sc> {
})
.collect(),
};
Ok(graph)
Ok(())
}
}
fn connect_node<'sc>(
Expand Down
17 changes: 17 additions & 0 deletions core_lang/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,20 @@ pub enum CompileError<'sc> {
UnknownType { span: Span<'sc> },
#[error("Bytecode can only support programs with up to 2^12 words worth of opcodes. Try refactoring into contract calls? This is a temporary error and will be implemented in the future.")]
TooManyInstructions { span: Span<'sc> },
#[error(
"No valid {} file (.{}) was found at {file_path}",
crate::constants::LANGUAGE_NAME,
crate::constants::DEFAULT_FILE_EXTENSION
)]
FileNotFound { span: Span<'sc>, file_path: String },
#[error("The file {file_path} could not be read: {stringified_error}")]
FileCouldNotBeRead {
span: Span<'sc>,
file_path: String,
stringified_error: String,
},
#[error("This imported file must be a library. It must start with \"library <name>\", where \"name\" is the name of the library this file contains.")]
ImportMustBeLibrary { span: Span<'sc> },
}

impl<'sc> std::convert::From<TypeError<'sc>> for CompileError<'sc> {
Expand Down Expand Up @@ -780,6 +794,9 @@ impl<'sc> CompileError<'sc> {
UnknownType { span, .. } => span,
InvalidStrType { span, .. } => span,
TooManyInstructions { span, .. } => span,
FileNotFound { span, .. } => span,
FileCouldNotBeRead { span, .. } => span,
ImportMustBeLibrary { span, .. } => span,
}
}

Expand Down
23 changes: 15 additions & 8 deletions core_lang/src/hll.pest
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,21 @@ block_comment_open = {"/*"}
block_comment_close = {"*/"}
fn_returns = {"->"}
path_separator = {"::"}
include_keyword = { "dep" }

// top level
program = {SOI ~ (library|contract|script|predicate)? ~ EOI}

library = {"library" ~ library_name ~ ";" ~ (control_flow|declaration|use_statement)* }
library = {"library" ~ library_name ~ ";" ~ (control_flow|declaration|use_statement|include_statement)* }
library_name = {ident}
contract = {"contract" ~ ";" ~ (control_flow|declaration|use_statement)*}
script = {"script" ~ ";" ~ (control_flow|declaration|use_statement)*}
predicate = {"predicate" ~ ";" ~ (control_flow|declaration|use_statement)*}

contract = {"contract" ~ ";" ~ (control_flow|declaration|use_statement|include_statement)*}
script = {"script" ~ ";" ~ (control_flow|declaration|use_statement|include_statement)*}
predicate = {"predicate" ~ ";" ~ (control_flow|declaration|use_statement|include_statement)*}

// including other files
file_path = { ident ~ ("/" ~ ident)* }
include_statement = { include_keyword ~ file_path ~ alias? ~ ";"}
alias = { "as" ~ ident }
// expressions
expr_inner = _{literal_value|if_exp|parenthesized_expression|asm_expression|code_block|func_app|struct_expression|delineated_path|method_exp|subfield_exp|var_exp|array_exp|match_expression|unit}
parenthesized_expression = {"(" ~ expr ~ ")"}
Expand Down Expand Up @@ -131,9 +136,11 @@ impl_trait = {impl_keyword ~ trait_name ~ type_params? ~ "for" ~ type_name ~

// imports

use_statement = {use_keyword ~ import_path ~ ";"}
import_path = {ident ~ (path_separator ~ (ident|star))*}
star = {"*"}
use_statement = {relative_use_statement | absolute_use_statement}
relative_use_statement = {use_keyword ~ import_path ~ ";"}
absolute_use_statement = {use_keyword ~ path_separator ~ import_path ~ ";"}
import_path = {ident ~ (path_separator ~ (ident|star))*}
star = {"*"}

// loops
while_loop = {while_keyword ~ expr ~ code_block}
Expand Down
Loading

0 comments on commit f253593

Please sign in to comment.