celestial_hub_compass/ast/
context.rs1use std::collections::HashMap;
4
5use crate::ast::{Argument, VarType};
6
7use super::{Function, Statement, Variable};
8
9#[derive(Debug)]
11pub struct Context {
12 pub scope_level: usize,
14 pub variables: HashMap<usize, Vec<Variable>>,
16
17 pub functions: HashMap<String, Function>,
19
20 pub optimization_level: u8,
21}
22
23impl Context {
24 pub fn new(optimization_level: u8) -> Self {
25 Self {
26 scope_level: 0,
27 optimization_level,
28 variables: HashMap::new(),
29 functions: HashMap::new(),
30 }
31 }
32
33 pub fn push_scope(&mut self) {
34 self.scope_level += 1;
35 }
36
37 pub fn pop_scope(&mut self) {
38 self.scope_level -= 1;
39 }
40
41 pub fn add_variable(&mut self, statement: Statement) {
42 let variable = statement.into();
43
44 if let Some(variables) = self.variables.get_mut(&self.scope_level) {
45 variables.push(variable);
46 } else {
47 self.variables.insert(self.scope_level, vec![variable]);
48 }
49 }
50
51 pub fn get_variable(&self, name: String) -> Option<&Variable> {
52 for scope in (0..=self.scope_level).rev() {
53 if let Some(variables) = self.variables.get(&scope) {
54 for variable in variables {
55 if variable.name == name {
56 return Some(variable);
57 }
58 }
59 }
60 }
61
62 None
63 }
64
65 pub fn add_function(&mut self, function: &Function) -> Result<(), String> {
66 if self.functions.contains_key(&function.name) {
67 return Err(format!("Function `{}` already defined", function.name));
68 }
69
70 self
71 .functions
72 .insert(function.name.clone(), function.clone());
73
74 Ok(())
75 }
76
77 pub fn get_function(&self, name: &str) -> Option<Function> {
78 self
79 .builtins()
80 .iter()
81 .find(|f| f.name == name)
82 .cloned()
83 .or_else(|| self.functions.get(name).cloned())
84 }
85
86 fn builtins(&self) -> Vec<Function> {
87 vec![
88 Function {
89 name: "write_string".to_string(),
90 body: vec![],
91 args: vec![Argument {
92 name: "message".to_string(),
93 var_type: VarType::Str,
94 }],
95 return_type: VarType::Void,
96 location: 0..0,
97 is_builtin: true,
98 },
99 Function {
100 name: "write_int".to_string(),
101 body: vec![],
102 args: vec![Argument {
103 name: "number".to_string(),
104 var_type: VarType::I32,
105 }],
106 return_type: VarType::Void,
107 location: 0..0,
108 is_builtin: true,
109 },
110 Function {
111 name: "read_int".to_string(),
112 body: vec![],
113 args: vec![],
114 return_type: VarType::I32,
115 location: 0..0,
116 is_builtin: true,
117 },
118 Function {
119 name: "read_string".to_string(),
120 body: vec![],
121 args: vec![Argument {
122 name: "size".to_string(),
123 var_type: VarType::U32,
124 }],
125 return_type: VarType::Str,
126 location: 0..0,
127 is_builtin: true,
128 },
129 ]
130 }
131}
132
133impl Default for Context {
134 fn default() -> Self {
135 Self::new(0)
136 }
137}
138
139impl From<Statement> for Variable {
140 fn from(statement: Statement) -> Self {
141 match statement {
142 Statement::VariableDeclaration(var) => var,
143 _ => panic!("Cannot convert statement to variable"),
144 }
145 }
146}