Skip to content

Commit 2015655

Browse files
committed
RegisterMap can now handle scopes.
1 parent 0c2a537 commit 2015655

File tree

5 files changed

+99
-25
lines changed

5 files changed

+99
-25
lines changed

luacompiler/build.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use lrlex::LexerBuilder;
55
use lrpar::CTParserBuilder;
66

77
fn main() -> Result<(), Box<std::error::Error>> {
8-
let lex_rule_ids_map = CTParserBuilder::<u8>::new().process_file_in_src("lua5_3/lua5_3.y")?;
8+
let lex_rule_ids_map =
9+
CTParserBuilder::<u8>::new_with_storaget().process_file_in_src("lua5_3/lua5_3.y")?;
910
LexerBuilder::new()
1011
.rule_ids_map(lex_rule_ids_map)
1112
.process_file_in_src("lua5_3/lua5_3.l")?;

luacompiler/src/lib/errors.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
use lrpar::{Node, ParseError};
1+
use lrpar::{LexParseError, Node, ParseError};
22
use std::io;
33

44
type ParseErr = (Option<Node<u8>>, Vec<ParseError<u8>>);
55

66
#[derive(Debug)]
77
pub enum CliError {
88
Io(io::Error),
9-
LexError(lrpar::LexParseError<u8>),
9+
LexError(Vec<LexParseError<u8>>),
1010
ParseError(ParseErr),
1111
}
1212

13-
impl From<lrpar::LexParseError<u8>> for CliError {
14-
fn from(err: lrpar::LexParseError<u8>) -> CliError {
13+
impl From<Vec<LexParseError<u8>>> for CliError {
14+
fn from(err: Vec<LexParseError<u8>>) -> CliError {
1515
CliError::LexError(err)
1616
}
1717
}

luacompiler/src/lib/irgen/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ impl<'a> LuaToIR<'a> {
7777
fn compile_variable(&self, node: &Node<u8>) -> &'a str {
7878
let name = LuaToIR::find_term(node, lua5_3_l::T_NAME);
7979
match name {
80-
Some(Term { lexeme }) => self.pt.get_string(lexeme.start(), lexeme.end()),
80+
Some(Term { lexeme }) => self
81+
.pt
82+
.get_string(lexeme.start(), lexeme.end().unwrap_or(lexeme.start())),
8183
_ => {
8284
panic!("Must have assignments of form: var = expr!");
8385
}
@@ -105,7 +107,9 @@ impl<'a> LuaToIR<'a> {
105107
}
106108
}
107109
Term { lexeme } => {
108-
let value = self.pt.get_string(lexeme.start(), lexeme.end());
110+
let value = self
111+
.pt
112+
.get_string(lexeme.start(), lexeme.end().unwrap_or(lexeme.start()));
109113
match lexeme.tok_id() {
110114
lua5_3_l::T_NUMERAL => {
111115
let reg = self.reg_map.get_new_reg();

luacompiler/src/lib/irgen/register_map.rs

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,32 +31,58 @@ impl Lifetime {
3131
}
3232

3333
/// Represents a structure that is used to map Lua variables to registers, and to keep
34-
/// track of their lifetimes. Each Lua file has its own register map.
34+
/// track of their lifetimes. Each Lua module has its own register map.
3535
pub struct RegisterMap<'a> {
3636
lifetimes: Vec<Lifetime>,
37-
reg_map: HashMap<&'a str, usize>,
37+
reg_maps: Vec<HashMap<&'a str, usize>>,
3838
}
3939

4040
impl<'a> RegisterMap<'a> {
4141
pub fn new() -> RegisterMap<'a> {
4242
RegisterMap {
4343
lifetimes: vec![],
44-
reg_map: HashMap::new(),
44+
// the first map holds the variables of the module
45+
reg_maps: vec![HashMap::new()],
4546
}
4647
}
4748

48-
/// Creates and returns a new register, whose lifetime begins from self.current_instr.
49+
/// Pushes a new map of registers. All new registers will be allocated in the newly
50+
/// created map.
51+
pub fn push_scope(&mut self) {
52+
self.reg_maps.push(HashMap::new());
53+
}
54+
55+
/// Pops the last map of registers.
56+
pub fn pop_scope(&mut self) {
57+
self.reg_maps.pop();
58+
}
59+
60+
/// Creates and returns a new register.
4961
pub fn get_new_reg(&mut self) -> usize {
5062
let lifetime = Lifetime::new(self.lifetimes.len());
5163
self.lifetimes.push(lifetime);
5264
self.lifetimes.len() - 1
5365
}
5466

55-
/// Get the register of <name>, or create it if it doesn't exist.
67+
/// Creates a mapping between <name> and a newly created register.
68+
pub fn create_reg(&mut self, name: &'a str) -> usize {
69+
let reg = self.get_new_reg();
70+
self.set_reg(name, reg);
71+
reg
72+
}
73+
74+
/// Get the register of <name>.
5675
pub fn get_reg(&mut self, name: &'a str) -> usize {
5776
let lifetimes = &mut self.lifetimes;
58-
*self
59-
.reg_map
77+
for map in self.reg_maps[1..].iter().rev() {
78+
if let Some(&reg) = map.get(name) {
79+
return reg;
80+
}
81+
}
82+
// In lua, if a variable is queried, but isn't in scope, a Nil is returned instead
83+
// If none of the maps have a definition for <name> that means we have to define
84+
// it ourselves in the map of the module (the first map in <reg_maps>).
85+
*self.reg_maps[0]
6086
.entry(name)
6187
.and_modify(|reg| {
6288
let len = lifetimes.len();
@@ -71,7 +97,7 @@ impl<'a> RegisterMap<'a> {
7197

7298
/// Set the register of <name> to <reg>.
7399
pub fn set_reg(&mut self, name: &'a str, reg: usize) {
74-
self.reg_map.insert(name, reg);
100+
self.reg_maps.last_mut().unwrap().insert(name, reg);
75101
}
76102

77103
/// Get the total number of registers that were needed.
@@ -98,17 +124,34 @@ mod tests {
98124
}
99125

100126
#[test]
101-
fn get_reg_correctly_maps_strings_to_registers() {
127+
fn correctly_maps_strings_to_registers() {
102128
let mut rm = RegisterMap::new();
103129
// create a new register
104130
assert_eq!(rm.get_new_reg(), 0);
105131
// create a mapping
132+
assert_eq!(rm.create_reg("foo"), 1);
133+
assert_eq!(*rm.reg_maps[0].get("foo").unwrap(), 1);
106134
assert_eq!(rm.get_reg("foo"), 1);
107-
assert_eq!(*rm.reg_map.get("foo").unwrap(), 1);
135+
assert_eq!(*rm.reg_maps[0].get("foo").unwrap(), 1);
136+
assert_eq!(rm.get_reg("bar"), 2);
137+
assert_eq!(*rm.reg_maps[0].get("bar").unwrap(), 2);
138+
// create a new scope in which we define another foo
139+
rm.push_scope();
140+
assert_eq!(rm.create_reg("foo"), 3);
141+
assert_eq!(*rm.reg_maps[1].get("foo").unwrap(), 3);
142+
assert_eq!(rm.get_reg("foo"), 3);
143+
assert_eq!(*rm.reg_maps[1].get("foo").unwrap(), 3);
144+
assert_eq!(rm.get_reg("bar"), 2);
145+
assert_eq!(*rm.reg_maps[0].get("bar").unwrap(), 2);
146+
assert!(rm.reg_maps[1].get("bar").is_none());
147+
rm.pop_scope();
148+
// pop the scope and query foo and bar again to check if they have the same values
108149
assert_eq!(rm.get_reg("foo"), 1);
109-
assert_eq!(*rm.reg_map.get("foo").unwrap(), 1);
150+
assert_eq!(*rm.reg_maps[0].get("foo").unwrap(), 1);
151+
assert_eq!(rm.get_reg("bar"), 2);
152+
assert_eq!(*rm.reg_maps[0].get("bar").unwrap(), 2);
110153
// test total number of registers created
111-
assert_eq!(rm.reg_count(), 2);
154+
assert_eq!(rm.reg_count(), 4);
112155
}
113156

114157
#[test]
@@ -117,12 +160,30 @@ mod tests {
117160
let reg1 = rm.get_new_reg();
118161
assert_eq!(rm.lifetimes[reg1].0, 0);
119162
assert_eq!(rm.lifetimes[reg1].1, 1);
120-
let reg2 = rm.get_reg("reg");
163+
let reg2 = rm.create_reg("reg");
121164
assert_eq!(rm.lifetimes[reg2].0, 1);
122165
assert_eq!(rm.lifetimes[reg2].1, 2);
123166
rm.get_reg("reg");
124167
assert_eq!(rm.lifetimes[reg2].0, 1);
125168
assert_eq!(rm.lifetimes[reg2].1, 3);
126-
assert_eq!(rm.reg_count(), 2);
169+
rm.push_scope();
170+
let reg3 = rm.create_reg("reg3");
171+
rm.pop_scope();
172+
assert_eq!(rm.lifetimes[reg3].0, 2);
173+
assert_eq!(rm.lifetimes[reg3].1, 3);
174+
assert_eq!(rm.reg_count(), 3);
175+
}
176+
177+
#[test]
178+
fn registers_are_retrieved_in_the_correct_order() {
179+
let mut rm = RegisterMap::new();
180+
for i in 0..3 {
181+
rm.push_scope();
182+
rm.create_reg("foo");
183+
}
184+
for i in 0..3 {
185+
assert_eq!(rm.get_reg("foo"), 2 - i);
186+
rm.pop_scope();
187+
}
127188
}
128189
}

luacompiler/src/lib/mod.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,12 @@ impl LuaParseTree {
4747
{
4848
let lexerdef = lua5_3_l::lexerdef();
4949
let mut lexer = lexerdef.lexer(&mut pt.contents);
50-
let tree = lua5_3_y::parse(&mut lexer)?;
51-
pt.tree = tree;
50+
let (tree, errs) = lua5_3_y::parse(&mut lexer);
51+
if let Some(tree) = tree {
52+
pt.tree = tree;
53+
} else {
54+
return Err(CliError::from(errs));
55+
}
5256
}
5357
Ok(pt)
5458
}
@@ -65,8 +69,12 @@ impl LuaParseTree {
6569
{
6670
let lexerdef = lua5_3_l::lexerdef();
6771
let mut lexer = lexerdef.lexer(&mut pt.contents);
68-
let tree = lua5_3_y::parse(&mut lexer)?;
69-
pt.tree = tree;
72+
let (tree, errs) = lua5_3_y::parse(&mut lexer);
73+
if let Some(tree) = tree {
74+
pt.tree = tree;
75+
} else {
76+
return Err(CliError::from(errs));
77+
}
7078
}
7179
Ok(pt)
7280
}

0 commit comments

Comments
 (0)