Skip to content

Initial Fuel HLL #2

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

Merged
merged 71 commits into from
May 8, 2021
Merged
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
159e747
initial parsing work
Jan 25, 2021
32d3ae5
parse trait declarations
Jan 27, 2021
42a8e80
import statements
Jan 27, 2021
c85792c
clean lexer tree; support method calls
Jan 27, 2021
9e71dda
basic ast skeleton beginnings
Jan 28, 2021
7a4edec
begin ast work
Jan 29, 2021
f767f96
checkpoint while i swap computers
Jan 29, 2021
40eb817
more ast parsing
Jan 29, 2021
8b7f12a
more ast parsing
Jan 29, 2021
e7bdaeb
ast: function appl, func decl, var exp
Jan 31, 2021
80ae5a9
ast: literals
Jan 31, 2021
73c4438
add compiler binary with nice error messages
Feb 1, 2021
d58e28b
ast: return statements, use statements
Feb 1, 2021
d40b2f2
fix error message
Feb 1, 2021
2e347c2
ast: traits
Feb 1, 2021
2a9edf9
more friendly parse error messages
Feb 1, 2021
d02fc85
old email
Feb 1, 2021
afdeef7
semicolons!
Feb 2, 2021
29ae513
byte literals; fix tests
Feb 3, 2021
5f8a909
parse binary and hex literals for byte and bytes32
Feb 4, 2021
9da8276
refactor expression parsing
Feb 4, 2021
8073cea
parse array exprs
Feb 4, 2021
6ddcb49
parse operator expressions
Feb 4, 2021
88e9fa5
type ascriptions
Feb 9, 2021
303f826
parser: polymorphism and trait bounds
Feb 9, 2021
f084b97
default to u64 instead of u32
Feb 10, 2021
720abfa
begin work on match statements
Feb 11, 2021
d23420c
parse structs
Feb 12, 2021
66b641c
refactor
Feb 13, 2021
3f2e581
a few program examples; parse match statements
Feb 13, 2021
f9234a6
lex struct expressions
Feb 16, 2021
4b2b948
parse to AST struct expressions
Feb 16, 2021
9e69615
compile warnings!
Feb 16, 2021
13e6a30
assert_or_warn macro
Feb 16, 2021
2af1365
generic struct parameters
Feb 17, 2021
98b46fa
parse contract/script/predicate
Feb 18, 2021
a11bf95
improve top level failure error message
Feb 18, 2021
937267e
s/ast/parse_tree
Feb 20, 2021
2f389a3
enums
Feb 20, 2021
0747988
begin semantic analysis
Feb 20, 2021
fc38750
begin work on type checking, inferencing, and semantics checking (#11)
sezna Feb 26, 2021
3b028e6
small error msg tweak
Feb 26, 2021
f7261d0
Refactor error and warning handling (#12)
sezna Mar 2, 2021
952ff98
type check predicates
Mar 3, 2021
029ea46
limit number of script main functions
Mar 3, 2021
217aa36
parse generic types for traits
Mar 4, 2021
3bed768
grammar for reassignments and while loops
Mar 4, 2021
ffa2450
variable reassignments; while loops
Mar 4, 2021
3eacf66
check generic type params in function declarations
Mar 4, 2021
6956d71
fix tests
Mar 5, 2021
d31ead1
grammar for inline asm
Mar 5, 2021
d74420a
Asm expressions (#13)
sezna Mar 28, 2021
ae30683
fix only last expr having type annotation; if branch enforcement of h…
Mar 30, 2021
a20104f
Control flow analysis + more (#28)
sezna Apr 16, 2021
12a0efa
add line_col method for errors and warnings
May 3, 2021
c7c73a9
Generate Assembly (#31)
sezna May 6, 2021
0a8a601
move license; clean warnings
May 6, 2021
e494d0c
Update forc/src/cli/build.rs
sezna May 6, 2021
09f3107
Update forc/src/cli/build.rs
sezna May 6, 2021
2d47def
code review feedback
May 6, 2021
f9a5a57
Merge branch 'parser_v1' of github.com:fuellabs/fuel-vm-hll into pars…
May 6, 2021
61c5b6e
Update forc/src/manifest.rs
sezna May 6, 2021
6b7b5b3
Update parser/src/control_flow_analysis/analyze_return_paths.rs
sezna May 6, 2021
824f0fd
more PR feedback
May 6, 2021
0e2793b
Merge branch 'parser_v1' of github.com:fuellabs/fuel-vm-hll into pars…
May 6, 2021
9328fcd
rename parser to core_lang
May 6, 2021
0127a8d
add minimum supported version
May 7, 2021
ee149cd
Update README.md
sezna May 7, 2021
a7416ce
check that struct size in words fits in a u32 gracefully
May 7, 2021
cfdfbcb
Merge branch 'parser_v1' of github.com:fuellabs/fuel-vm-hll into pars…
May 8, 2021
f1e8ff5
forgotten import
May 8, 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
3 changes: 2 additions & 1 deletion .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/
**/*/target/
target

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Expand Down
10 changes: 2 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
[package]
name = "hll"
version = "0.1.0"
authors = ["Alex <[email protected]>"]
edition = "2018"
[workspace]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
members = ["core_lang", "forc"]
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
# fuel-vm-hll
High Level Language (Name Subject to Change) for the FuelVM
# Fume

Fume is a language developed for the Fuel blockchain. It is heavily inspired by Rust and aims to bring modern language development and performance to the Ethereum ecosystem.

## Running the Compiler
To run the compiler from this directory:
```
cargo run --bin forc -- -p <path_to_project>

// e.g.

cargo run --bin forc -- build -p example_project/fuel_project
```


16 changes: 16 additions & 0 deletions core_lang/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "core_lang"
version = "0.1.0"
authors = ["Alex <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
pest = "2.0"
pest_derive = "2.0"
thiserror = "1.0"
either = "1.6"
Inflector = "0.11"
petgraph = "0.5"
uuid-b64 = "0.1"
8 changes: 8 additions & 0 deletions core_lang/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# fuel-vm-hll
High Level Language (Name Subject to Change) for the FuelVM.

# Running the Compiler
It is recommended to run this compiler from the `forc` executable, which can be found in this workspace.

# Minimum supported Rust version
As of now, this code was developed on and is guaranteed to run on Rust 1.50 stable.
1 change: 1 addition & 0 deletions core_lang/src/asm_generation/compiler_constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

15 changes: 15 additions & 0 deletions core_lang/src/asm_generation/declaration/fn_decl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::{
asm_generation::{AsmNamespace, RegisterSequencer},
asm_lang::Op,
error::*,
TypedFunctionDeclaration,
};

pub(crate) fn convert_fn_decl_to_asm<'sc>(
_decl: &TypedFunctionDeclaration<'sc>,
_namespace: &mut AsmNamespace,
_register_sequencer: &mut RegisterSequencer,
) -> CompileResult<'sc, Vec<Op<'sc>>> {
// for now, we inline all functions as a shortcut.
ok(vec![], vec![], vec![])
}
42 changes: 42 additions & 0 deletions core_lang/src/asm_generation/declaration/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use crate::{asm_lang::Op, error::*, TypedDeclaration};

use super::{AsmNamespace, RegisterSequencer};
mod fn_decl;
mod reassignment;
mod var_decl;
pub(crate) use fn_decl::convert_fn_decl_to_asm;
pub(crate) use reassignment::convert_reassignment_to_asm;
pub(crate) use var_decl::convert_variable_decl_to_asm;

pub(crate) fn convert_decl_to_asm<'sc>(
decl: &TypedDeclaration<'sc>,
namespace: &mut AsmNamespace<'sc>,
register_sequencer: &mut RegisterSequencer,
) -> CompileResult<'sc, Vec<Op<'sc>>> {
match decl {
// For an enum declaration, we don't generate any asm.
TypedDeclaration::EnumDeclaration(_) => ok(vec![], vec![], vec![]),
TypedDeclaration::FunctionDeclaration(typed_fn_decl) => {
convert_fn_decl_to_asm(typed_fn_decl, namespace, register_sequencer)
}
// a trait declaration also does not have any asm directly generated from it
TypedDeclaration::TraitDeclaration(_) => ok(vec![], vec![], vec![]),
// since all functions are inlined (for now -- shortcut), we also don't need to do anything for this.
TypedDeclaration::ImplTrait { .. } => ok(vec![], vec![], vec![]),
// once again the declaration of a type has no inherent asm, only instantiations
TypedDeclaration::StructDeclaration(_) => ok(vec![], vec![], vec![]),
TypedDeclaration::VariableDeclaration(var_decl) => {
convert_variable_decl_to_asm(var_decl, namespace, register_sequencer)
}
TypedDeclaration::Reassignment(reassignment) => {
convert_reassignment_to_asm(reassignment, namespace, register_sequencer)
}
_ => err(
vec![],
vec![CompileError::Unimplemented(
"ASM generation has not yet been implemented for this declaration variant.",
decl.span().clone(),
)],
),
}
}
52 changes: 52 additions & 0 deletions core_lang/src/asm_generation/declaration/reassignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use super::*;
use crate::{
asm_generation::{convert_expression_to_asm, AsmNamespace, RegisterSequencer},
semantics::ast_node::TypedReassignment,
};

pub(crate) fn convert_reassignment_to_asm<'sc>(
reassignment: &TypedReassignment<'sc>,
namespace: &mut AsmNamespace<'sc>,
register_sequencer: &mut RegisterSequencer,
) -> CompileResult<'sc, Vec<Op<'sc>>> {
// 0. evaluate the RHS of the reassignment
// 1. Find the register that the previous var was stored in
// 2. move the return register of the RHS into the register in the namespace

let mut buf = vec![];
let mut warnings = vec![];
let mut errors = vec![];
// step 0
let return_register = register_sequencer.next();
let mut rhs = type_check!(
convert_expression_to_asm(
&reassignment.rhs,
namespace,
&return_register,
register_sequencer
),
vec![],
warnings,
errors
);

buf.append(&mut rhs);

// step 1
let var_register = type_check!(
namespace.look_up_variable(&reassignment.lhs),
return err(warnings, errors),
warnings,
errors
);

// step 2
buf.push(Op::register_move_comment(
var_register.clone(),
return_register,
reassignment.lhs.span.clone(),
format!("variable {} reassignment", reassignment.lhs.primary_name),
));

ok(buf, warnings, errors)
}
20 changes: 20 additions & 0 deletions core_lang/src/asm_generation/declaration/var_decl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::{
asm_generation::{convert_expression_to_asm, AsmNamespace, RegisterSequencer},
asm_lang::Op,
error::*,
semantics::ast_node::TypedVariableDeclaration,
};

/// Provisions a register to put a variable in, and then adds the assembly used to initialize the
/// variable to the end of the buffer.
pub(crate) fn convert_variable_decl_to_asm<'sc>(
var_decl: &TypedVariableDeclaration<'sc>,
namespace: &mut AsmNamespace<'sc>,
register_sequencer: &mut RegisterSequencer,
) -> CompileResult<'sc, Vec<Op<'sc>>> {
let var_register = register_sequencer.next();
let initialization =
convert_expression_to_asm(&var_decl.body, namespace, &var_register, register_sequencer);
namespace.insert_variable(var_decl.name.clone(), var_register);
initialization
}
103 changes: 103 additions & 0 deletions core_lang/src/asm_generation/expression/enum_instantiation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use crate::asm_generation::{convert_expression_to_asm, AsmNamespace, RegisterSequencer};
use crate::asm_lang::{ConstantRegister, Op, Opcode, RegisterId};
use crate::error::*;
use crate::semantics::ast_node::TypedEnumDeclaration;
use crate::semantics::TypedExpression;
use crate::Literal;
use crate::{CompileResult, Ident};
use std::convert::TryFrom;

pub(crate) fn convert_enum_instantiation_to_asm<'sc>(
decl: &TypedEnumDeclaration<'sc>,
_variant_name: &Ident<'sc>,
tag: usize,
contents: &Option<Box<TypedExpression<'sc>>>,
return_register: &RegisterId,
namespace: &mut AsmNamespace<'sc>,
register_sequencer: &mut RegisterSequencer,
) -> CompileResult<'sc, Vec<Op<'sc>>> {
let mut warnings = vec![];
let mut errors = vec![];
// step 0: load the tag into a register
// step 1: load the data into a register
// step 2: write both registers sequentially to memory, extending the call frame
// step 3: write the location of the value to the return register
let mut asm_buf = vec![];
// step 0
let data_label = namespace.insert_data_value(&Literal::U64(tag as u64));
let tag_register = register_sequencer.next();
asm_buf.push(Op::unowned_load_data_comment(
tag_register.clone(),
data_label,
format!("{} enum instantiation", decl.name.primary_name),
));
let pointer_register = register_sequencer.next();
// copy stack pointer into pointer register
asm_buf.push(Op::unowned_register_move_comment(
pointer_register.clone(),
RegisterId::Constant(ConstantRegister::StackPointer),
"load $sp for enum pointer",
));
let size_of_enum = 1 /* tag */ + decl.as_type().stack_size_of();
let size_of_enum: u32 = match u32::try_from(size_of_enum) {
Ok(o) if o < 16777216 /* 2^24 */ => o,
_ => {
errors.push(CompileError::Unimplemented(
"Stack variables which exceed 2^24 (16777216) words in size are not supported yet.",
decl.clone().span,
));
return err(warnings, errors);
}
};

asm_buf.push(Op::unowned_stack_allocate_memory(size_of_enum));
// initialize all the memory to 0
asm_buf.push(Op::new(
Opcode::MemClearImmediate(pointer_register.clone(), size_of_enum),
decl.clone().span,
));
// write the tag
// step 2
asm_buf.push(Op::write_register_to_memory(
pointer_register.clone(),
tag_register.clone(),
0,
decl.clone().span,
));

// step 1 continued
// // if there are any enum contents, instantiate them
if let Some(instantiation) = contents {
let return_register = register_sequencer.next();
let mut asm = type_check!(
convert_expression_to_asm(
&*instantiation,
namespace,
&return_register.clone(),
register_sequencer
),
return err(warnings, errors),
warnings,
errors
);
asm_buf.append(&mut asm);
// write these enum contents to the address after the tag
// step 2
asm_buf.push(Op::write_register_to_memory_comment(
pointer_register.clone(),
return_register.clone(),
1, /* offset by 1 because the tag was already written */
instantiation.span.clone(),
format!("{} enum contents", decl.name.primary_name),
));
}

// step 3
asm_buf.push(Op::register_move(
return_register.clone(),
pointer_register,
decl.clone().span,
));

ok(asm_buf, warnings, errors)
}
Loading