#![allow(missing_docs)]
use std::collections::BTreeMap;
use std::rc::Rc;
use harn_vm::VmValue;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SymbolKind {
Function,
Method,
Class,
Struct,
Enum,
Interface,
Protocol,
Type,
Variable,
Module,
Other,
}
impl SymbolKind {
pub fn as_str(self) -> &'static str {
match self {
SymbolKind::Function => "function",
SymbolKind::Method => "method",
SymbolKind::Class => "class",
SymbolKind::Struct => "struct",
SymbolKind::Enum => "enum",
SymbolKind::Interface => "interface",
SymbolKind::Protocol => "protocol",
SymbolKind::Type => "type",
SymbolKind::Variable => "variable",
SymbolKind::Module => "module",
SymbolKind::Other => "other",
}
}
pub fn is_container(self) -> bool {
matches!(
self,
SymbolKind::Class
| SymbolKind::Struct
| SymbolKind::Enum
| SymbolKind::Interface
| SymbolKind::Protocol
| SymbolKind::Module
)
}
}
#[derive(Debug, Clone)]
pub struct Symbol {
pub name: String,
pub kind: SymbolKind,
pub container: Option<String>,
pub signature: String,
pub start_row: u32,
pub start_col: u32,
pub end_row: u32,
pub end_col: u32,
}
impl Symbol {
pub fn to_vm_value(&self) -> VmValue {
let mut dict: BTreeMap<String, VmValue> = BTreeMap::new();
dict.insert("name".into(), VmValue::String(Rc::from(self.name.as_str())));
dict.insert("kind".into(), VmValue::String(Rc::from(self.kind.as_str())));
dict.insert(
"container".into(),
match &self.container {
Some(s) => VmValue::String(Rc::from(s.as_str())),
None => VmValue::Nil,
},
);
dict.insert(
"signature".into(),
VmValue::String(Rc::from(self.signature.as_str())),
);
dict.insert("start_row".into(), VmValue::Int(self.start_row as i64));
dict.insert("start_col".into(), VmValue::Int(self.start_col as i64));
dict.insert("end_row".into(), VmValue::Int(self.end_row as i64));
dict.insert("end_col".into(), VmValue::Int(self.end_col as i64));
VmValue::Dict(Rc::new(dict))
}
}
#[derive(Debug, Clone)]
pub struct OutlineItem {
pub name: String,
pub kind: SymbolKind,
pub signature: String,
pub start_row: u32,
pub end_row: u32,
pub children: Vec<OutlineItem>,
}
impl OutlineItem {
pub fn to_vm_value(&self) -> VmValue {
let mut dict: BTreeMap<String, VmValue> = BTreeMap::new();
dict.insert("name".into(), VmValue::String(Rc::from(self.name.as_str())));
dict.insert("kind".into(), VmValue::String(Rc::from(self.kind.as_str())));
dict.insert(
"signature".into(),
VmValue::String(Rc::from(self.signature.as_str())),
);
dict.insert("start_row".into(), VmValue::Int(self.start_row as i64));
dict.insert("end_row".into(), VmValue::Int(self.end_row as i64));
let kids: Vec<VmValue> = self.children.iter().map(OutlineItem::to_vm_value).collect();
dict.insert("children".into(), VmValue::List(Rc::new(kids)));
VmValue::Dict(Rc::new(dict))
}
}
#[derive(Debug, Clone)]
pub struct ParsedNode {
pub id: u32,
pub parent_id: Option<u32>,
pub kind: String,
pub is_named: bool,
pub start_byte: u32,
pub end_byte: u32,
pub start_row: u32,
pub start_col: u32,
pub end_row: u32,
pub end_col: u32,
}
impl ParsedNode {
pub fn to_vm_value(&self) -> VmValue {
let mut dict: BTreeMap<String, VmValue> = BTreeMap::new();
dict.insert("id".into(), VmValue::Int(self.id as i64));
dict.insert(
"parent_id".into(),
self.parent_id
.map_or(VmValue::Nil, |id| VmValue::Int(id as i64)),
);
dict.insert("kind".into(), VmValue::String(Rc::from(self.kind.as_str())));
dict.insert("is_named".into(), VmValue::Bool(self.is_named));
dict.insert("start_byte".into(), VmValue::Int(self.start_byte as i64));
dict.insert("end_byte".into(), VmValue::Int(self.end_byte as i64));
dict.insert("start_row".into(), VmValue::Int(self.start_row as i64));
dict.insert("start_col".into(), VmValue::Int(self.start_col as i64));
dict.insert("end_row".into(), VmValue::Int(self.end_row as i64));
dict.insert("end_col".into(), VmValue::Int(self.end_col as i64));
VmValue::Dict(Rc::new(dict))
}
}
#[derive(Debug, Clone)]
pub struct ParseError {
pub start_row: u32,
pub start_col: u32,
pub end_row: u32,
pub end_col: u32,
pub start_byte: u32,
pub end_byte: u32,
pub message: String,
pub snippet: String,
pub missing: bool,
}
impl ParseError {
pub fn to_vm_value(&self) -> VmValue {
let mut dict: BTreeMap<String, VmValue> = BTreeMap::new();
dict.insert("start_row".into(), VmValue::Int(self.start_row as i64));
dict.insert("start_col".into(), VmValue::Int(self.start_col as i64));
dict.insert("end_row".into(), VmValue::Int(self.end_row as i64));
dict.insert("end_col".into(), VmValue::Int(self.end_col as i64));
dict.insert("start_byte".into(), VmValue::Int(self.start_byte as i64));
dict.insert("end_byte".into(), VmValue::Int(self.end_byte as i64));
dict.insert(
"message".into(),
VmValue::String(Rc::from(self.message.as_str())),
);
dict.insert(
"snippet".into(),
VmValue::String(Rc::from(self.snippet.as_str())),
);
dict.insert("missing".into(), VmValue::Bool(self.missing));
VmValue::Dict(Rc::new(dict))
}
}
#[derive(Debug, Clone)]
pub struct UndefinedName {
pub name: String,
pub kind: &'static str,
pub row: u32,
pub column: u32,
}
impl UndefinedName {
pub fn to_vm_value(&self) -> VmValue {
let mut dict: BTreeMap<String, VmValue> = BTreeMap::new();
dict.insert("name".into(), VmValue::String(Rc::from(self.name.as_str())));
dict.insert("kind".into(), VmValue::String(Rc::from(self.kind)));
dict.insert("row".into(), VmValue::Int(self.row as i64));
dict.insert("column".into(), VmValue::Int(self.column as i64));
let message = format!("undefined name '{}'", self.name);
dict.insert(
"message".into(),
VmValue::String(Rc::from(message.as_str())),
);
VmValue::Dict(Rc::new(dict))
}
}