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

Implement Vec in the standard library; Bug Fixes #82

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a4022cd
begin work on vectors in the stdlib
Jun 9, 2021
cd2f7d3
progress in method exp debugging
Jun 9, 2021
4499936
sort out ambiguity in method parsing
Jun 9, 2021
20b45b1
switch all method invocations to this form with a base expression
Jun 9, 2021
832911d
WIP stdlib vector
Jun 11, 2021
79fb851
sketch out type trait constraints
Jun 11, 2021
7d0a724
trait constraints now work
Jun 11, 2021
d795a78
progress on that method debugging thing
Jun 16, 2021
a9f24fd
finish fixing methods bug; trait genericism works
Jun 16, 2021
89e5605
identify bug in struct field accesses
Jun 16, 2021
866e8ca
parser woes
Jun 16, 2021
0b683de
core-types: Initial implementation (#77)
vlopes11 Jun 17, 2021
7e009f2
Add Context to encapsulate debug ctx variants (#84)
vlopes11 Jun 17, 2021
466bdcb
Cli formatter (#81)
leviathanbeak Jun 17, 2021
9bb011b
parse call items
Jun 17, 2021
a4c3998
flesh out skeleton for subfield accesses
Jun 17, 2021
c37d842
continued refactoring of type checking on struct field accesses
Jun 17, 2021
414b5d1
improve error messages in method type checking
Jun 18, 2021
81c0685
implement struct field accesses on general expressions
Jun 18, 2021
59aa010
fix self type resolution in traits
Jun 19, 2021
c7b3182
further progress on vectors
Jun 19, 2021
815f89a
begin inner struct field reassignments
Jun 19, 2021
665381d
progress in struct field reassignments
Jun 19, 2021
59e60a4
basic struct field reassignment type checking
Jun 19, 2021
272f4e4
fix heap allocation bug; further in implemenation of struct field rea…
Jun 21, 2021
ba30d1e
Fix struct reassignment parsing; remove todos
Jun 21, 2021
ac92f8e
Remove license. (#87)
adlerjohn Jun 21, 2021
f0a7f8f
fix subfield lookup bug
Jun 21, 2021
be5332d
Multiline comments (#90)
leviathanbeak Jun 22, 2021
fec1b92
Formatter tests (#92)
leviathanbeak Jun 22, 2021
146ea70
fix struct field access bug
Jun 24, 2021
cdc6f88
tmp stdlib commit
Jun 24, 2021
0a63193
forgotten add
Jun 24, 2021
5891b81
Merge branch 'stdlib_vector' of github.com:fuellabs/sway into stdlib_…
Jun 24, 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
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,7 @@ fn connect_declaration<'sc>(
connect_impl_trait(&trait_name, graph, methods, entry_node);
vec![]
}
SideEffect | ErrorRecovery => {
unreachable!("These are error cases and should be removed in the type checking stage. ")
}
SideEffect | ErrorRecovery => leaves.to_vec(),
}
}

Expand Down
10 changes: 6 additions & 4 deletions core_lang/src/control_flow_analysis/dead_code_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,7 @@ fn connect_declaration<'sc>(
connect_impl_trait(&trait_name, graph, methods, entry_node, tree_type)?;
Ok(vec![])
}
SideEffect | ErrorRecovery => {
unreachable!("These are error cases and should be removed in the type checking stage. ")
}
SideEffect | ErrorRecovery => Ok(vec![]),
}
}

Expand Down Expand Up @@ -853,6 +851,10 @@ fn connect_enum_instantiation<'sc>(
vec![enum_instantiation_exit_idx]
}

/// Given a `TypedAstNode` that we know is not reached in the graph, construct a warning
/// representing its unreached status. For example, we want to say "this function is never called"
/// if the node is a function declaration, but "this trait is never used" if it is a trait
/// declaration.
fn construct_dead_code_warning_from_node<'sc>(node: &TypedAstNode<'sc>) -> CompileWarning<'sc> {
match node {
// if this is a function, struct, or trait declaration that is never called, then it is dead
Expand Down Expand Up @@ -886,7 +888,7 @@ fn construct_dead_code_warning_from_node<'sc>(node: &TypedAstNode<'sc>) -> Compi
warning_content: Warning::DeadTrait,
},
TypedAstNode {
content: TypedAstNodeContent::Declaration(TypedDeclaration::EnumDeclaration(..)),
content: TypedAstNodeContent::Declaration(..),
span,
} => CompileWarning {
span: span.clone(),
Expand Down
18 changes: 12 additions & 6 deletions core_lang/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ pub enum CompileError<'sc> {
ModuleNotFound { span: Span<'sc>, name: String },
#[error("\"{name}\" is a {actually}, not a struct. Fields can only be accessed on structs.")]
NotAStruct {
name: &'sc str,
name: String,
span: Span<'sc>,
actually: String,
},
Expand All @@ -526,7 +526,7 @@ pub enum CompileError<'sc> {
span: Span<'sc>,
},
#[error("Could not find symbol \"{name}\" in this scope.")]
SymbolNotFound { span: Span<'sc>, name: &'sc str },
SymbolNotFound { span: Span<'sc>, name: String },
#[error(
"Because this if expression's value is used, an \"else\" branch is required and it must \
return type \"{r#type}\""
Expand Down Expand Up @@ -586,10 +586,7 @@ pub enum CompileError<'sc> {
},
#[error("Unknown opcode: \"{op_name}\".")]
UnrecognizedOp { op_name: &'sc str, span: Span<'sc> },
#[error(
"Unable to infer concrete type for partial type \"{ty}\". Type must be known at this \
point. Try providing an annotation or using a concrete type."
)]
#[error("Unknown type \"{ty}\".")]
TypeMustBeKnown { ty: String, span: Span<'sc> },
#[error("The value \"{val}\" is too large to fit in this 6-bit immediate spot.")]
Immediate06TooLarge { val: u64, span: Span<'sc> },
Expand Down Expand Up @@ -641,6 +638,12 @@ pub enum CompileError<'sc> {
},
#[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> },
#[error("An enum instantiaton cannot contain more than one value. This should be a single value of type {ty}.")]
MoreThanOneEnumInstantiator { span: Span<'sc>, ty: String },
#[error("This enum variant represents the unit type, so it should not be instantiated with any value.")]
UnnecessaryEnumInstantiator { span: Span<'sc> },
#[error("Trait \"{name}\" does not exist in this scope.")]
TraitNotFound { name: &'sc str, span: Span<'sc> },
}

impl<'sc> std::convert::From<TypeError<'sc>> for CompileError<'sc> {
Expand Down Expand Up @@ -797,6 +800,9 @@ impl<'sc> CompileError<'sc> {
FileNotFound { span, .. } => span,
FileCouldNotBeRead { span, .. } => span,
ImportMustBeLibrary { span, .. } => span,
MoreThanOneEnumInstantiator { span, .. } => span,
UnnecessaryEnumInstantiator { span, .. } => span,
TraitNotFound { span, .. } => span,
}
}

Expand Down
18 changes: 11 additions & 7 deletions core_lang/src/hll.pest
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,22 @@ 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}
expr_inner = _{literal_value|if_exp|asm_expression|code_block|func_app|struct_expression|method_exp|struct_field_access|delineated_path|var_exp|array_exp|parenthesized_expression|match_expression|unit}
parenthesized_expression = {"(" ~ expr ~ ")"}
// // op exps built in to expr to prevent left recursion
expr = {expr_inner ~ (op ~ expr_inner)*}
func_app = {fn_name ~ fn_args}
fn_args = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
fn_name = {var_exp}
var_exp = {unary_op? ~ var_name_ident}
method_exp = {subfield_exp ~ "(" ~ (expr ~ ("," ~ expr)*)? ~ ")"}
subfield_exp = {(call_item ~ ".")+ ~ call_item}
call_item = {ident}
delineated_path = {path_component ~ ("(" ~ expr ~ ")")?}
struct_field_access = {subfield_path}
method_exp = {subfield_exp | fully_qualified_method}
subfield_exp = {subfield_path ~ fn_args}
// TODO subfield path should allow parenthesized expressions _or_ just idents
subfield_path = {(call_item ~ ".")+ ~ call_item}
fully_qualified_method = {(path_ident ~ path_separator)* ~ "~" ~ type_name ~ path_separator ~ call_item ~ fn_args}
call_item = {ident | "(" ~ expr ~ ")" }
delineated_path = {path_component ~ fn_args?}
path_component = {path_ident ~ (path_separator ~ path_ident)+}
path_ident = {ident}

Expand Down Expand Up @@ -104,7 +108,7 @@ enum_fields = {enum_field_name ~ ":" ~ type_name ~ ("," ~ enum_field_name
enum_name = {ident}
enum_field_name = {ident}

impl_self = {impl_keyword ~ type_name ~ type_params? ~ trait_bounds? ~ ("{" ~ fn_decl* ~ "}")}
impl_self = {impl_keyword ~ type_params? ~ type_name ~ trait_bounds? ~ ("{" ~ fn_decl* ~ "}")}

// // fn declaration
fn_decl_params = {"(" ~ (fn_decl_param ~ ("," ~ fn_decl_param)*)? ~ ")"}
Expand All @@ -116,7 +120,7 @@ fn_decl_name = {ident}
type_name = {(str_type|ident ~ type_params?)|unit}
str_type = { "str" ~ "[" ~ basic_integer ~ "]" }
trait_bounds = {"where" ~ (generic_type_param ~ ":" ~ trait_name) ~ ("," ~ generic_type_param ~ ":" ~ trait_name)*}
generic_type_param = @{ident}
generic_type_param = {ident}

// statements
// // statements are basically non-expressions that don't alter the namespace like declarations do
Expand Down
2 changes: 1 addition & 1 deletion core_lang/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct Ident<'sc> {
}

// custom implementation of Hash so that namespacing isn't reliant on the span itself, which will
// always be different.
// often be different.
impl Hash for Ident<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.primary_name.hash(state);
Expand Down
69 changes: 41 additions & 28 deletions core_lang/src/parse_tree/declaration/type_parameter.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::error::*;
use crate::{error::*, types::TypeInfo, Ident};
use crate::{CompileError, Rule};
use pest::iterators::Pair;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct TypeParameter<'sc> {
pub(crate) name: &'sc str,
trait_constraint: Vec<TraitConstraint<'sc>>,
pub(crate) name: TypeInfo<'sc>,
pub(crate) name_ident: Ident<'sc>,
pub(crate) trait_constraints: Vec<TraitConstraint<'sc>>,
}

impl<'sc> TypeParameter<'sc> {
Expand All @@ -13,14 +14,19 @@ impl<'sc> TypeParameter<'sc> {
where_clause_pair: Option<Pair<'sc, Rule>>,
) -> CompileResult<'sc, Vec<TypeParameter<'sc>>> {
let mut errors = Vec::new();
let mut warnings = vec![];
let mut params: Vec<TypeParameter> = match type_params_pair {
Some(type_params_pair) => type_params_pair
.into_inner()
.map(|pair| TypeParameter {
name: pair.as_str(),
trait_constraint: Vec::new(),
})
.collect(),
Some(type_params_pair) => {
let mut buf = vec![];
for pair in type_params_pair.into_inner() {
buf.push(TypeParameter {
name_ident: eval!(Ident::parse_from_pair, warnings, errors, pair, continue),
name: eval!(TypeInfo::parse_from_pair, warnings, errors, pair, continue),
trait_constraints: Vec::new(),
});
}
buf
}
None => {
// no type params specified, ensure where clause is empty
if let Some(where_clause_pair) = where_clause_pair {
Expand All @@ -44,32 +50,39 @@ impl<'sc> TypeParameter<'sc> {
assert_eq!(trait_constraint.as_rule(), Rule::trait_name);
// assign trait constraints to above parsed type params
// find associated type name
let param_to_edit = match params
.iter_mut()
.find(|TypeParameter { name, .. }| *name == type_param.as_str())
{
Some(o) => o,
None => {
errors.push(CompileError::ConstrainedNonExistentType {
type_name: type_param.as_str(),
trait_name: trait_constraint.as_str(),
span: trait_constraint.as_span(),
});
continue;
}
};
param_to_edit.trait_constraint.push(TraitConstraint {
name: trait_constraint.as_str(),
let param_to_edit =
match params.iter_mut().find(|TypeParameter { name_ident, .. }| {
name_ident.primary_name == type_param.as_str()
}) {
Some(o) => o,
None => {
errors.push(CompileError::ConstrainedNonExistentType {
type_name: type_param.as_str(),
trait_name: trait_constraint.as_str(),
span: trait_constraint.as_span(),
});
continue;
}
};

param_to_edit.trait_constraints.push(TraitConstraint {
name: eval!(
Ident::parse_from_pair,
warnings,
errors,
trait_constraint,
continue
),
});
}
}
None => (),
}
ok(params, Vec::new(), errors)
ok(params, warnings, errors)
}
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) struct TraitConstraint<'sc> {
name: &'sc str,
pub(crate) name: Ident<'sc>,
}
Loading