Replace ProcDeclaration::is_verb with a ProcDeclKind enum

This commit is contained in:
Tad Hardesty 2019-02-21 22:56:30 -08:00
parent bacae4ff99
commit 8e2748313e
6 changed files with 56 additions and 18 deletions

View file

@ -248,7 +248,7 @@ fn main() -> Result<(), Box<std::error::Error>> {
type_path: format_type_path(&p.var_type.type_path),
}).collect(),
decl: match proc.declaration {
Some(ref decl) => if decl.is_verb { "verb" } else { "proc" },
Some(ref decl) => decl.kind.name(),
None => "",
},
file: context.file_path(proc_value.location.file),

View file

@ -493,6 +493,47 @@ impl From<IndexOrField> for Follow {
}
}
/// The proc declaration kind, either `proc` or `verb`.
///
/// DM requires referinging proc paths to include whether the target is
/// declared as a proc or verb, even though the two modes are functionally
/// identical in many other respects.
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
pub enum ProcDeclKind {
Proc,
Verb,
}
impl ProcDeclKind {
/// Attempt to convert a string to a declaration kind.
pub fn from_name(name: &str) -> Option<ProcDeclKind> {
match name {
"proc" => Some(ProcDeclKind::Proc),
"verb" => Some(ProcDeclKind::Verb),
_ => None,
}
}
/// Return whether `self` is `ProcDeclKind::Verb`.
pub fn is_verb(self) -> bool {
self == ProcDeclKind::Verb
}
/// Return the string representation of this declaration kind.
pub fn name(self) -> &'static str {
match self {
ProcDeclKind::Proc => "proc",
ProcDeclKind::Verb => "verb",
}
}
}
impl fmt::Display for ProcDeclKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(self.name())
}
}
/// A parameter declaration in the header of a proc.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Parameter {

View file

@ -9,7 +9,7 @@ use petgraph::visit::EdgeRef;
use petgraph::Direction;
use linked_hash_map::LinkedHashMap;
use super::ast::{Expression, VarType, VarSuffix, PathOp, Parameter, Statement};
use super::ast::{Expression, VarType, VarSuffix, PathOp, Parameter, Statement, ProcDeclKind};
use super::constants::{Constant, Pop};
use super::docs::DocCollection;
use super::{DMError, Location, Context};
@ -45,7 +45,7 @@ pub struct TypeVar {
#[derive(Debug, Clone)]
pub struct ProcDeclaration {
pub location: Location,
pub is_verb: bool,
pub kind: ProcDeclKind,
}
#[derive(Debug, Clone)]
@ -759,25 +759,22 @@ impl ObjectTree {
location: Location,
parent: NodeIndex,
name: &str,
mut declaration: Option<bool>,
mut declaration: Option<ProcDeclKind>,
parameters: Vec<Parameter>,
code: Code,
) -> Result<(usize, &mut ProcValue), DMError> {
let node = self.graph.node_weight_mut(parent).unwrap();
let proc = node.procs.entry(name.to_owned()).or_insert_with(Default::default);
if let Some(is_verb) = declaration {
if let Some(kind) = declaration {
if let Some(ref decl) = proc.declaration {
DMError::new(location, format!("duplicate definition of {}/{}",
if is_verb { "verb" } else { "proc" },
name,
))
DMError::new(location, format!("duplicate definition of {}/{}", kind, name))
.add_note(decl.location, "previous definition")
.register(context);
declaration = None; // suppress the later check
} else {
proc.declaration = Some(ProcDeclaration {
location,
is_verb,
kind,
});
}
}
@ -855,9 +852,9 @@ impl ObjectTree {
code: Code,
) -> Result<(usize, &mut ProcValue), DMError> {
let (parent, mut proc_name) = self.get_from_path(location, &mut path, len)?;
let mut is_verb = None;
if is_proc_decl(proc_name) {
is_verb = Some(proc_name == "verb");
let mut declaration = None;
if let Some(kind) = ProcDeclKind::from_name(proc_name) {
declaration = Some(kind);
proc_name = match path.next() {
Some(name) => name,
None => return Err(DMError::new(location, "proc must have a name")),
@ -872,7 +869,7 @@ impl ObjectTree {
));
}
self.register_proc(context, location, parent, proc_name, is_verb, parameters, code)
self.register_proc(context, location, parent, proc_name, declaration, parameters, code)
}
}

View file

@ -304,7 +304,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
Some(decl) => decl,
None => continue,
};
if proc_decl.is_verb != (decl == "verb") {
if proc_decl.kind.is_verb() != (decl == "verb") {
continue;
}
if contains(name, query) {

View file

@ -597,7 +597,7 @@ handle_method_call! {
for (proc_name, pv) in ty.procs.iter() {
if let Some(decl) = pv.declaration.as_ref() {
if query.matches_proc(&proc_name, decl.is_verb) {
if query.matches_proc(&proc_name, decl.kind) {
results.push(SymbolInformation {
name: proc_name.clone(),
kind: if idx.index() == 0 {
@ -730,7 +730,7 @@ handle_method_call! {
infos.push_front(message);
if let Some(ref decl) = proc.declaration {
let mut declaration = String::new();
declaration.push_str(if decl.is_verb { "verb" } else { "proc" });
declaration.push_str(decl.kind.name());
declaration.push_str("/**");
declaration.push_str(last);
declaration.push_str("**");

View file

@ -71,7 +71,7 @@ impl Query {
}
}
pub fn matches_proc(&self, name: &str, _is_verb: bool) -> bool {
pub fn matches_proc(&self, name: &str, _kind: ::dm::ast::ProcDeclKind) -> bool {
match *self {
Query::Anything(ref q) |
Query::Proc(ref q) => starts_with(name, q),