use llmcc_core::context::CompileUnit;
use llmcc_core::ir::{HirId, HirNode};
use tree_sitter::Node;
use super::function::parse_type_expr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VariableKind {
Let,
Const,
Static,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VariableScope {
Global,
Local,
}
#[derive(Debug, Clone)]
pub struct VariableDescriptor {
pub hir_id: HirId,
pub name: String,
pub fqn: String,
pub kind: VariableKind,
pub is_mut: bool,
pub scope: VariableScope,
pub ty: Option<super::function::TypeExpr>,
}
impl VariableDescriptor {
pub(crate) fn from_let<'tcx>(
unit: CompileUnit<'tcx>,
node: &HirNode<'tcx>,
name: String,
fqn: String,
) -> Self {
let ts_node = node.inner_ts_node();
let ty = ts_node
.child_by_field_name("type")
.map(|n| parse_type_expr(unit, n));
let is_mut = has_mutable_specifier(ts_node);
VariableDescriptor {
hir_id: node.hir_id(),
name,
fqn,
kind: VariableKind::Let,
is_mut,
scope: VariableScope::Local,
ty,
}
}
pub(crate) fn from_const_item<'tcx>(
unit: CompileUnit<'tcx>,
node: &HirNode<'tcx>,
name: String,
fqn: String,
) -> Self {
let ts_node = node.inner_ts_node();
let ty = ts_node
.child_by_field_name("type")
.map(|n| parse_type_expr(unit, n));
VariableDescriptor {
hir_id: node.hir_id(),
name,
fqn,
kind: VariableKind::Const,
is_mut: false,
scope: VariableScope::Global,
ty,
}
}
pub(crate) fn from_static_item<'tcx>(
unit: CompileUnit<'tcx>,
node: &HirNode<'tcx>,
name: String,
fqn: String,
) -> Self {
let ts_node = node.inner_ts_node();
let ty = ts_node
.child_by_field_name("type")
.map(|n| parse_type_expr(unit, n));
let is_mut = has_mutable_specifier(ts_node);
VariableDescriptor {
hir_id: node.hir_id(),
name,
fqn,
kind: VariableKind::Static,
is_mut,
scope: VariableScope::Global,
ty,
}
}
}
fn has_mutable_specifier(ts_node: Node<'_>) -> bool {
if ts_node.child_by_field_name("mutable_specifier").is_some() {
return true;
}
let mut cursor = ts_node.walk();
if cursor.goto_first_child() {
loop {
if cursor.node().kind() == "mutable_specifier" {
return true;
}
if !cursor.goto_next_sibling() {
break;
}
}
}
false
}