1use crate::{Lookup, LookupContext};
2use galvan_ast::{
3 DeclModifier, FnDecl, Ident, Ownership, ToplevelItem, TypeDecl, TypeElement, TypeIdent,
4};
5use std::collections::HashMap;
6
7#[derive(Debug, Default)]
8pub struct Scope<'a> {
9 pub parent: Option<&'a Scope<'a>>,
10 pub variables: HashMap<Ident, Variable>,
11
12 lookup: Option<LookupContext<'a>>,
13}
14
15impl Scope<'_> {
16 pub fn child(parent: &Self) -> Scope {
17 Scope {
18 parent: Some(parent),
19 variables: HashMap::new(),
20 lookup: None,
21 }
22 }
23
24 pub fn declare_variable(&mut self, variable: Variable) {
25 self.variables.insert(variable.ident.clone(), variable);
26 }
27
28 pub fn get_variable(&self, ident: &Ident) -> Option<&Variable> {
29 self.variables
30 .get(ident)
31 .or_else(|| self.parent.and_then(|parent| parent.get_variable(ident)))
32 }
33}
34
35impl<'a> Scope<'a> {
36 pub fn set_lookup(&mut self, lookup: LookupContext<'a>) {
37 self.lookup = Some(lookup);
38 }
39}
40
41impl Lookup for Scope<'_> {
42 fn resolve_type(&self, name: &TypeIdent) -> Option<&ToplevelItem<TypeDecl>> {
43 self.lookup
44 .as_ref()
45 .and_then(|lookup| lookup.resolve_type(name))
46 .or_else(|| self.parent.and_then(|parent| parent.resolve_type(name)))
47 }
48
49 fn resolve_function(
50 &self,
51 receiver: Option<&TypeIdent>,
52 name: &Ident,
53 labels: &[&str],
54 ) -> Option<&ToplevelItem<FnDecl>> {
55 self.lookup
56 .as_ref()
57 .and_then(|lookup| lookup.resolve_function(receiver, name, labels))
58 .or_else(|| {
59 self.parent
60 .and_then(|parent| parent.resolve_function(receiver, name, labels))
61 })
62 }
63}
64
65#[derive(Clone, Debug)]
66pub struct Variable {
67 pub ident: Ident,
68 pub modifier: DeclModifier,
69 pub ty: Option<TypeElement>,
71 pub ownership: Ownership,
72}
73
74impl Variable {
75 pub fn is_mut(&self) -> bool {
76 matches!(self.modifier, DeclModifier::Mut(_))
77 }
78}