diff --git a/src/compile/binding.rs b/src/compile/binding.rs index 574eb1bd6..8b2db0fc7 100644 --- a/src/compile/binding.rs +++ b/src/compile/binding.rs @@ -314,31 +314,43 @@ impl Compiler { global_index: local.index, }); let no_code_words = binding.words.iter().all(|w| !w.value.is_code()); - let node = if let Some((def, _)) = &data_def { - self.in_method(def, |comp| comp.words(binding.words)) + let compile = |comp: &mut Compiler| -> UiuaResult { + // Compile the words + let node = comp.words(binding.words); + // Add an error binding if there was an error + let mut node = match node { + Ok(node) => node, + Err(e) => { + comp.asm.add_binding_at( + local, + BindingKind::Error, + Some(span.clone()), + meta.clone(), + ); + return Err(e); + } + }; + // Apply the signature comment + if let Some(comment_sig) = meta.comment.as_ref().and_then(|c| c.sig.as_ref()) { + comp.apply_node_comment( + &mut node, + comment_sig, + &format!("{name}'s"), + &binding.name.span, + ); + } + Ok(node) + }; + // We may need to compile the words in the context of a data definition method + let mut node = if let Some((def, _)) = &data_def { + self.in_method(def, compile)? } else { - self.words(binding.words) + compile(self)? }; let self_referenced = self.current_bindings.pop().unwrap().recurses > 0; - let mut node = match node { - Ok(node) => node, - Err(e) => { - self.asm - .add_binding_at(local, BindingKind::Error, Some(span.clone()), meta); - return Err(e); - } - }; let is_obverse = node .iter() .any(|n| matches!(n, Node::CustomInverse(cust, _) if cust.is_obverse)); - if let Some(comment_sig) = meta.comment.as_ref().and_then(|c| c.sig.as_ref()) { - self.apply_node_comment( - &mut node, - comment_sig, - &format!("{name}'s"), - &binding.name.span, - ); - } // Normalize external if external { diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 7a34a670c..e594df85e 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -796,8 +796,7 @@ code: if let Some(sig) = meta.comment.as_ref().and_then(|c| c.sig.as_ref()) { self.emit_diagnostic( format!( - "{}'s comment describes {}, but it is a constant", - name, + "{name}'s comment describes {}, but it is a constant", sig.sig_string(), ), DiagnosticKind::Warning, @@ -949,24 +948,10 @@ code: // Compile a line, checking an end-of-line signature comment fn line(&mut self, line: Vec>, must_be_callable: bool) -> UiuaResult { let comment_sig = line_sig(&line); - let is_empty = line.iter().all(|w| !w.value.is_code()); // Actually compile the line let mut node = self.words(line)?; // Validate line signature if let Some(comment_sig) = comment_sig { - if let Ok(sig) = node.sig() { - if !is_empty && !comment_sig.value.matches_sig(sig) { - self.emit_diagnostic( - format!( - "Line comment describes {}, \ - but its code has signature {sig}", - comment_sig.value.sig_string() - ), - DiagnosticKind::Warning, - comment_sig.span.clone(), - ); - } - } self.apply_node_comment(&mut node, &comment_sig.value, "Line", &comment_sig.span); } // Validate callability @@ -999,7 +984,10 @@ code: ) { let mut spandex: Option = None; // Validate comment signature - if let Ok(sig) = node.sig() { + if let Ok(mut sig) = node.sig() { + if let ScopeKind::Method(_) = self.scope.kind { + sig.args += 1; + } if !comment_sig.matches_sig(sig) { let span = *spandex.get_or_insert_with(|| self.add_span(span.clone())); self.emit_diagnostic( diff --git a/tests/data_defs.ua b/tests/data_defs.ua index eedfe0a92..82eab3cc2 100644 --- a/tests/data_defs.ua +++ b/tests/data_defs.ua @@ -7,8 +7,8 @@ |Foo {Bar Baz} |Qux [x y z] |Sed {M N} - |Wir - + |Wir + Format ← ⍣( $"_ and _" °Foo | $"⟨_ _ _⟩" °Qux @@ -57,7 +57,7 @@ S~PushB ┌─╴Foo |Bar [A] |Baz [A] - |Qux + |Qux └─╴ ⍤⤙≍ 1 /↥⌕"Non-boxed variant" ⍣Foo~Bar⋅∘ @a ⍤⤙≍ 1 /↥⌕"Non-boxed variant" ⍣Foo~Baz⋅∘ [1 2 3] @@ -71,7 +71,7 @@ S~PushB ┌─╴Foo ~{Bar Baz} ~AddBar ← +Bar - ~Sum ← AddBar Baz + ~Sum ← AddBar Baz # ? Foo ~WithBarSum ← Foo~Sum New 10 Baz ~WithBar ← Self °Bar ~IncrBar ← Self⍜Bar+₁