Skip to content

Commit ca53cf8

Browse files
committed
fix(parser): enable and fix previously ignored parser tests
- Remove #[ignore] from statement parser tests (if/while/for/def) - Remove #[ignore] from ADT type parser test - Fix whitespace handling: use multispace0 after keywords since keyword() helper already consumes trailing whitespace - Add constructor_name() helper to parse ADT constructors that are also keywords (Just, Nothing, Ok, Err) - Use parse_basic_types in ADT constructors to avoid recursion.
2 parents 8cfc7a7 + fa151a4 commit ca53cf8

File tree

15 files changed

+645
-305
lines changed

15 files changed

+645
-305
lines changed

src/environment/environment.rs

Lines changed: 90 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
use crate::ir::ast::Function;
2-
use crate::ir::ast::Name;
3-
use crate::ir::ast::ValueConstructor;
1+
use crate::ir::ast::{FuncSignature, Function, Name, ValueConstructor};
42
use indexmap::IndexMap;
5-
use std::collections::HashMap;
6-
use std::collections::LinkedList;
3+
use std::collections::{HashMap, LinkedList};
4+
use std::fmt::Debug;
75

86
#[derive(Clone)]
97
pub struct Scope<A> {
108
pub variables: HashMap<Name, (bool, A)>,
11-
pub functions: HashMap<Name, Function>,
9+
pub functions: HashMap<FuncSignature, Function>,
1210
pub adts: HashMap<Name, Vec<ValueConstructor>>,
1311
pub tests: IndexMap<Name, Function>,
1412
}
@@ -19,28 +17,25 @@ impl<A: Clone> Scope<A> {
1917
variables: HashMap::new(),
2018
functions: HashMap::new(),
2119
adts: HashMap::new(),
22-
tests: IndexMap::new(), //TODO: Apresentar Mudança no Environment
20+
tests: IndexMap::new(),
2321
}
2422
}
2523

26-
fn map_variable(&mut self, var: Name, mutable: bool, value: A) -> () {
24+
fn map_variable(&mut self, var: Name, mutable: bool, value: A) {
2725
self.variables.insert(var, (mutable, value));
28-
return ();
2926
}
3027

31-
fn map_function(&mut self, function: Function) -> () {
32-
self.functions.insert(function.name.clone(), function);
33-
return ();
28+
fn map_function(&mut self, function: Function) {
29+
let func_signature = FuncSignature::from_func(&function);
30+
self.functions.insert(func_signature, function);
3431
}
3532

36-
fn map_test(&mut self, test: Function) -> () {
33+
fn map_test(&mut self, test: Function) {
3734
self.tests.insert(test.name.clone(), test);
38-
return ();
3935
}
4036

41-
fn map_adt(&mut self, name: Name, adt: Vec<ValueConstructor>) -> () {
37+
fn map_adt(&mut self, name: Name, adt: Vec<ValueConstructor>) {
4238
self.adts.insert(name.clone(), adt);
43-
return ();
4439
}
4540

4641
fn lookup_var(&self, var: &Name) -> Option<(bool, A)> {
@@ -52,8 +47,7 @@ impl<A: Clone> Scope<A> {
5247
fn update_var(&mut self, var: &Name, value: A) -> bool {
5348
if let Some((mutable, slot)) = self.variables.get_mut(var) {
5449
*slot = value;
55-
// preserve existing mutability flag
56-
let _ = mutable; // silence unused warning if optimised out
50+
let _ = mutable;
5751
true
5852
} else {
5953
false
@@ -64,8 +58,18 @@ impl<A: Clone> Scope<A> {
6458
self.variables.remove(var).is_some()
6559
}
6660

67-
fn lookup_function(&self, name: &Name) -> Option<&Function> {
68-
self.functions.get(name)
61+
fn lookup_function(&self, func_signature: &FuncSignature) -> Option<&Function> {
62+
self.functions.get(func_signature)
63+
}
64+
65+
fn lookup_function_by_name(&self, name: &Name) -> Option<&Function> {
66+
self.functions.iter().find_map(|(signature, function)| {
67+
if &signature.name == name {
68+
Some(function)
69+
} else {
70+
None
71+
}
72+
})
6973
}
7074

7175
fn lookup_test(&self, name: &Name) -> Option<&Function> {
@@ -78,41 +82,59 @@ impl<A: Clone> Scope<A> {
7882
}
7983

8084
#[derive(Clone)]
81-
pub struct Environment<A> {
85+
pub struct Environment<A: Clone + Debug> {
86+
pub current_func: FuncSignature,
8287
pub globals: Scope<A>,
8388
pub stack: LinkedList<Scope<A>>,
8489
}
8590

86-
impl<A: Clone> Environment<A> {
91+
impl<A: Clone + Debug> Environment<A> {
8792
pub fn new() -> Environment<A> {
8893
Environment {
94+
current_func: FuncSignature::new(),
8995
globals: Scope::new(),
9096
stack: LinkedList::new(),
9197
}
9298
}
9399

94-
pub fn map_variable(&mut self, var: Name, mutable: bool, value: A) -> () {
100+
pub fn get_current_func(&self) -> FuncSignature {
101+
self.current_func.clone()
102+
}
103+
104+
pub fn get_current_scope(&self) -> &Scope<A> {
105+
self.stack.front().unwrap_or(&self.globals)
106+
}
107+
108+
pub fn set_current_func(&mut self, func_signature: &FuncSignature) {
109+
self.current_func = func_signature.clone();
110+
}
111+
112+
pub fn set_global_functions(&mut self, global_functions: HashMap<FuncSignature, Function>) {
113+
self.globals.functions = global_functions;
114+
}
115+
116+
pub fn map_variable(&mut self, var: Name, mutable: bool, value: A) {
95117
match self.stack.front_mut() {
96118
None => self.globals.map_variable(var, mutable, value),
97119
Some(top) => top.map_variable(var, mutable, value),
98120
}
99121
}
100122

101-
pub fn map_function(&mut self, function: Function) -> () {
123+
pub fn map_function(&mut self, function: Function) {
102124
match self.stack.front_mut() {
103125
None => self.globals.map_function(function),
104126
Some(top) => top.map_function(function),
105127
}
106128
}
107129

108-
pub fn map_test(&mut self, test: Function) -> () {
130+
pub fn map_test(&mut self, test: Function) {
109131
match self.stack.front_mut() {
110132
None => self.globals.map_test(test),
111133
Some(top) => top.map_test(test),
112134
}
113135
}
114136

115-
pub fn map_adt(&mut self, name: Name, cons: Vec<ValueConstructor>) -> () {
137+
pub fn map_adt(&mut self, name: Name, cons: Vec<ValueConstructor>) {
116138
match self.stack.front_mut() {
117139
None => self.globals.map_adt(name, cons),
118140
Some(top) => top.map_adt(name, cons),
@@ -131,13 +153,11 @@ impl<A: Clone> Environment<A> {
131153
/// Update an existing variable in the nearest scope where it's defined.
132154
/// Returns true if the variable existed and was updated; false otherwise.
133155
pub fn update_existing_variable(&mut self, var: &Name, value: A) -> bool {
134-
// Search local scopes first (top-most first)
135156
for scope in self.stack.iter_mut() {
136157
if scope.update_var(var, value.clone()) {
137158
return true;
138159
}
139160
}
140-
// Fallback to globals
141161
self.globals.update_var(var, value)
142162
}
143163

@@ -152,13 +172,31 @@ impl<A: Clone> Environment<A> {
152172
self.globals.remove_var(var)
153173
}
154174

155-
pub fn lookup_function(&self, name: &Name) -> Option<&Function> {
175+
pub fn lookup_function(&self, func_signature: &FuncSignature) -> Option<&Function> {
156176
for scope in self.stack.iter() {
157-
if let Some(func) = scope.lookup_function(name) {
177+
if let Some(func) = scope.lookup_function(func_signature) {
158178
return Some(func);
159179
}
160180
}
161-
self.globals.lookup_function(name)
181+
self.globals.lookup_function(func_signature)
182+
}
183+
184+
pub fn lookup_var_or_func(&self, name: &Name) -> Option<FuncOrVar<A>> {
185+
for scope in self.stack.iter() {
186+
if let Some(value) = scope.lookup_var(name) {
187+
return Some(FuncOrVar::Var(value));
188+
}
189+
if let Some(func) = scope.lookup_function_by_name(name) {
190+
return Some(FuncOrVar::Func(func.clone()));
191+
}
192+
}
193+
if let Some(value) = self.globals.lookup_var(name) {
194+
return Some(FuncOrVar::Var(value));
195+
}
196+
if let Some(func) = self.globals.lookup_function_by_name(name) {
197+
return Some(FuncOrVar::Func(func.clone()));
198+
}
199+
None
162200
}
163201

164202
pub fn lookup_test(&self, name: &Name) -> Option<&Function> {
@@ -196,18 +234,17 @@ impl<A: Clone> Environment<A> {
196234
!self.stack.is_empty()
197235
}
198236

199-
pub fn push(&mut self) -> () {
237+
pub fn push(&mut self) {
200238
self.stack.push_front(Scope::new());
201239
}
202240

203-
pub fn pop(&mut self) -> () {
241+
pub fn pop(&mut self) {
204242
self.stack.pop_front();
205243
}
206244

207245
pub fn get_all_variables(&self) -> Vec<(Name, (bool, A))> {
208246
let mut vars = Vec::new();
209247

210-
// First get variables from local scopes (in reverse order to respect shadowing)
211248
for scope in self.stack.iter() {
212249
for (name, value) in &scope.variables {
213250
if !vars.iter().any(|(n, _)| n == name) {
@@ -216,15 +253,32 @@ impl<A: Clone> Environment<A> {
216253
}
217254
}
218255

219-
// Then get variables from global scope (if not already found)
220256
for (name, value) in &self.globals.variables {
221257
if !vars.iter().any(|(n, _)| n == name) {
222258
vars.push((name.clone(), value.clone()));
223259
}
224260
}
225-
226261
vars
227262
}
263+
264+
/// The type checker ensures that each function is defined only once.
265+
pub fn get_all_functions(&self) -> HashMap<FuncSignature, Function> {
266+
let mut all_functions = HashMap::new();
267+
for (func_signature, func) in &self.globals.functions {
268+
all_functions.insert(func_signature.clone(), func.clone());
269+
}
270+
for scope in self.stack.iter().rev() {
271+
for (func_signature, func) in &scope.functions {
272+
all_functions.insert(func_signature.clone(), func.clone());
273+
}
274+
}
275+
all_functions
276+
}
277+
}
278+
279+
pub enum FuncOrVar<A: Clone + Debug> {
280+
Func(Function),
281+
Var((bool, A)),
228282
}
229283

230284
pub struct TestResult {
@@ -242,75 +296,3 @@ impl TestResult {
242296
}
243297
}
244298
}
245-
246-
#[cfg(test)]
247-
mod tests {
248-
use super::*;
249-
use crate::ir::ast::Type;
250-
251-
#[test]
252-
fn test_variable_scoping() {
253-
let mut env: Environment<i32> = Environment::new();
254-
255-
// Test global scope
256-
env.map_variable("x".to_string(), true, 32);
257-
assert_eq!(Some((true, 32)), env.lookup(&"x".to_string()));
258-
259-
// Test nested scopes
260-
env.push(); // scope 1
261-
env.map_variable("y".to_string(), true, 23);
262-
env.map_variable("x".to_string(), true, 55); // shadows global x
263-
264-
env.push(); // scope 2
265-
env.map_variable("z".to_string(), true, 44);
266-
267-
// Variables from all scopes should be accessible
268-
assert_eq!(Some((true, 55)), env.lookup(&"x".to_string())); // from scope 1
269-
assert_eq!(Some((true, 23)), env.lookup(&"y".to_string())); // from scope 1
270-
assert_eq!(Some((true, 44)), env.lookup(&"z".to_string())); // from scope 2
271-
272-
// Pop scope 2
273-
env.pop();
274-
assert_eq!(Some((true, 55)), env.lookup(&"x".to_string())); // still in scope 1
275-
assert_eq!(Some((true, 23)), env.lookup(&"y".to_string())); // still in scope 1
276-
assert_eq!(None, env.lookup(&"z".to_string())); // z is gone
277-
278-
// Pop scope 1
279-
env.pop();
280-
assert_eq!(Some((true, 32)), env.lookup(&"x".to_string())); // back to global x
281-
assert_eq!(None, env.lookup(&"y".to_string())); // y is gone
282-
}
283-
284-
#[test]
285-
fn test_function_scoping() {
286-
let mut env: Environment<i32> = Environment::new();
287-
288-
let global_func = Function {
289-
name: "global".to_string(),
290-
kind: Type::TVoid,
291-
params: Vec::new(),
292-
body: None,
293-
};
294-
295-
let local_func = Function {
296-
name: "local".to_string(),
297-
kind: Type::TVoid,
298-
params: Vec::new(),
299-
body: None,
300-
};
301-
302-
// Test function scoping
303-
env.map_function(global_func.clone());
304-
assert!(env.lookup_function(&"global".to_string()).is_some());
305-
306-
env.push();
307-
env.map_function(local_func.clone());
308-
309-
assert!(env.lookup_function(&"global".to_string()).is_some()); // can see global
310-
assert!(env.lookup_function(&"local".to_string()).is_some()); // can see local
311-
312-
env.pop();
313-
assert!(env.lookup_function(&"global".to_string()).is_some()); // global still visible
314-
assert!(env.lookup_function(&"local".to_string()).is_none()); // local gone
315-
}
316-
}

0 commit comments

Comments
 (0)