Skip to content

Commit

Permalink
Parse mut
Browse files Browse the repository at this point in the history
  • Loading branch information
sbillig committed Aug 31, 2022
1 parent a5e8321 commit 449e31a
Show file tree
Hide file tree
Showing 26 changed files with 429 additions and 154 deletions.
32 changes: 13 additions & 19 deletions crates/analyzer/src/db/queries/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub fn function_signature(
.iter()
.enumerate()
.filter_map(|(index, arg)| match &arg.kind {
ast::FunctionArg::Self_ => {
ast::FunctionArg::Self_ { .. }=> {
if matches!(fn_parent, Item::Module(_)) {
scope.error(
"`self` can only be used in contract, struct, trait or impl functions",
Expand All @@ -104,12 +104,12 @@ pub fn function_signature(
}
None
}
ast::FunctionArg::Regular(reg) => {
let typ = resolve_function_param_type(db, function, &mut scope, &reg.typ).and_then(|typ| match typ {
ast::FunctionArg::Regular { mut_: _, label, name, typ: typedesc } => {
let typ = resolve_function_param_type(db, function, &mut scope, &typedesc).and_then(|typ| match typ {
typ if typ.has_fixed_size(db) => Ok(typ),
_ => Err(TypeError::new(scope.error(
"function parameter types must have fixed size",
reg.typ.span,
typedesc.span,
&format!("`{}` type can't be used as a function parameter", typ.display(db)),
))),
});
Expand All @@ -122,12 +122,6 @@ pub fn function_signature(
arg.span,
"instances of `Context` must be named `ctx`",
);
} else if !function.parent(db).is_contract() {
scope.error(
"`ctx` cannot be passed into pure functions",
arg.span,
"`ctx` can only be passed into contract functions",
);
} else if self_decl.is_some() && index != 1 {
scope.error(
"invalid parameter order",
Expand All @@ -144,7 +138,7 @@ pub fn function_signature(
}
}

if let Some(label) = &reg.label {
if let Some(label) = &label {
if_chain! {
if label.kind != "_";
if let Some(dup_idx) = labels.get(&label.kind);
Expand All @@ -163,29 +157,29 @@ pub fn function_signature(
}
}

if let Ok(Some(named_item)) = scope.resolve_name(&reg.name.kind, reg.name.span) {
if let Ok(Some(named_item)) = scope.resolve_name(&name.kind, name.span) {
scope.name_conflict_error(
"function parameter",
&reg.name.kind,
&name.kind,
&named_item,
named_item.name_span(db),
reg.name.span,
name.span,
);
None
} else if let Some(dup_idx) = names.get(&reg.name.kind) {
} else if let Some(dup_idx) = names.get(&name.kind) {
let dup_arg: &Node<ast::FunctionArg> = &def.kind.args[*dup_idx];
scope.duplicate_name_error(
&format!("duplicate parameter names in function `{}`", function.name(db)),
&reg.name.kind,
&name.kind,
dup_arg.span,
arg.span,
);
None
} else {
names.insert(&reg.name.kind, index);
names.insert(&name.kind, index);
Some(types::FunctionParam::new(
reg.label.as_ref().map(|s| s.kind.as_str()),
&reg.name.kind,
label.as_ref().map(|s| s.kind.as_str()),
&name.kind,
typ,
))
}
Expand Down
10 changes: 4 additions & 6 deletions crates/analyzer/src/namespace/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,7 @@ impl FunctionSigId {
db.lookup_intern_function_sig(*self)
}

// XXX #[deprecated]
pub fn takes_self(&self, db: &dyn AnalyzerDb) -> bool {
self.signature(db).self_decl.is_some()
}
Expand All @@ -1123,12 +1124,9 @@ impl FunctionSigId {
}
pub fn self_span(&self, db: &dyn AnalyzerDb) -> Option<Span> {
if self.takes_self(db) {
self.data(db)
.ast
.kind
.args
.iter()
.find_map(|arg| matches!(arg.kind, ast::FunctionArg::Self_).then(|| arg.span))
self.data(db).ast.kind.args.iter().find_map(|arg| {
matches!(arg.kind, ast::FunctionArg::Self_ { .. }).then(|| arg.span)
})
} else {
None
}
Expand Down
8 changes: 7 additions & 1 deletion crates/analyzer/src/traversal/declarations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ use fe_parser::node::Node;

/// Gather context information for var declarations and check for type errors.
pub fn var_decl(scope: &mut BlockScope, stmt: &Node<fe::FuncStmt>) -> Result<(), FatalError> {
if let fe::FuncStmt::VarDecl { target, typ, value } = &stmt.kind {
if let fe::FuncStmt::VarDecl {
target,
typ,
value,
mut_: _,
} = &stmt.kind
{
let declared_type = types::type_desc(scope, typ)?;
if let Type::Map(_) = declared_type.typ(scope.db()) {
return Err(FatalError::new(scope.error(
Expand Down
1 change: 0 additions & 1 deletion crates/analyzer/tests/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ test_ingot! { bad_visibility }
test_file! { ctx_not_first }
test_file! { ctx_not_after_self }
test_file! { ctx_init }
test_file! { ctx_pure }
test_file! { ctx_undeclared }
test_file! { ctx_missing_internal_call }
test_file! { ctx_missing_create }
Expand Down
12 changes: 0 additions & 12 deletions crates/analyzer/tests/snapshots/errors__ctx_pure.snap

This file was deleted.

7 changes: 4 additions & 3 deletions crates/mir/src/lower/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1257,14 +1257,15 @@ impl Scope {
}

fn self_arg_source(db: &dyn MirDb, func: analyzer_items::FunctionId) -> SourceInfo {
// XXX use self_span
func.data(db.upcast())
.ast
.kind
.sig
.kind
.args
.iter()
.find(|arg| matches!(arg.kind, ast::FunctionArg::Self_))
.find(|arg| matches!(arg.kind, ast::FunctionArg::Self_ { .. }))
.unwrap()
.into()
}
Expand All @@ -1278,14 +1279,14 @@ fn arg_source(db: &dyn MirDb, func: analyzer_items::FunctionId, arg_name: &str)
.args
.iter()
.find_map(|arg| match &arg.kind {
ast::FunctionArg::Regular(ast::RegularFunctionArg { name, .. }) => {
ast::FunctionArg::Regular { name, .. } => {
if name.kind == arg_name {
Some(name.into())
} else {
None
}
}
ast::FunctionArg::Self_ => None,
ast::FunctionArg::Self_ { .. } => None,
})
.unwrap()
}
Expand Down
82 changes: 56 additions & 26 deletions crates/parser/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,18 +218,18 @@ pub struct EventField {
pub typ: Node<TypeDesc>,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
pub struct RegularFunctionArg {
pub label: Option<Node<SmolStr>>,
pub name: Node<SmolStr>,
pub typ: Node<TypeDesc>,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
#[allow(clippy::large_enum_variant)]
pub enum FunctionArg {
Regular(RegularFunctionArg),
Self_,
Regular {
mut_: Option<Span>,
label: Option<Node<SmolStr>>,
name: Node<SmolStr>,
typ: Node<TypeDesc>,
},
Self_ {
mut_: Option<Span>,
},
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
Expand All @@ -238,6 +238,7 @@ pub enum FuncStmt {
value: Option<Node<Expr>>,
},
VarDecl {
mut_: Option<Span>,
target: Node<VarDeclTarget>,
typ: Node<TypeDesc>,
value: Option<Node<Expr>>,
Expand Down Expand Up @@ -435,15 +436,15 @@ impl Node<Function> {
impl Node<FunctionArg> {
pub fn name(&self) -> &str {
match &self.kind {
FunctionArg::Regular(arg) => &arg.name.kind,
FunctionArg::Self_ => "self",
FunctionArg::Regular { name, .. } => &name.kind,
FunctionArg::Self_ { .. } => "self",
}
}

pub fn name_span(&self) -> Span {
match &self.kind {
FunctionArg::Regular(arg) => arg.name.span,
FunctionArg::Self_ => self.span,
FunctionArg::Regular { name, .. } => name.span,
FunctionArg::Self_ { .. } => self.span,
}
}
}
Expand Down Expand Up @@ -792,20 +793,39 @@ impl fmt::Display for EventField {
}
}

impl fmt::Display for RegularFunctionArg {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(label) = &self.label {
write!(f, "{} ", label.kind)?;
}
write!(f, "{}: {}", self.name.kind, self.typ.kind)
}
}
// impl fmt::Display for RegularFunctionArg {
// fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
// if let Some(label) = &self.label {
// write!(f, "{} ", label.kind)?;
// }
// write!(f, "{}: {}", self.name.kind, self.typ.kind)
// }
// }

impl fmt::Display for FunctionArg {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
FunctionArg::Regular(arg) => write!(f, "{}", arg),
FunctionArg::Self_ => write!(f, "self"),
FunctionArg::Regular {
mut_,
label,
name,
typ,
} => {
if mut_.is_some() {
write!(f, "mut ")?
}
if let Some(label) = label {
write!(f, "{} ", label.kind)?
}

write!(f, "{}: {}", name.kind, typ.kind)
}
FunctionArg::Self_ { mut_ } => {
if mut_.is_some() {
write!(f, "mut ")?;
}
write!(f, "self")
}
}
}
}
Expand All @@ -820,11 +840,21 @@ impl fmt::Display for FuncStmt {
write!(f, "return")
}
}
FuncStmt::VarDecl { target, typ, value } => {
FuncStmt::VarDecl {
mut_,
target,
typ,
value,
} => {
let mut_ = if mut_.is_some() { "mut " } else { "" };
if let Some(value) = value {
write!(f, "let {}: {} = {}", target.kind, typ.kind, value.kind)
write!(
f,
"let {}{}: {} = {}",
mut_, target.kind, typ.kind, value.kind
)
} else {
write!(f, "let {}: {}", target.kind, typ.kind)
write!(f, "let {}{}: {}", mut_, target.kind, typ.kind)
}
}
FuncStmt::ConstantDecl { name, typ, value } => {
Expand Down
Loading

0 comments on commit 449e31a

Please sign in to comment.