From 1d5ec57d4ee0695a2a3e2542939b091f51c00036 Mon Sep 17 00:00:00 2001
From: David Li 
Date: Tue, 28 Nov 2017 19:42:11 -0500
Subject: Reference-count levels
---
 src/semantic/analysis.rs  | 26 ++++++++++++++------------
 src/semantic/translate.rs | 23 ++++++++++++++---------
 2 files changed, 28 insertions(+), 21 deletions(-)
(limited to 'src/semantic')
diff --git a/src/semantic/analysis.rs b/src/semantic/analysis.rs
index c7acfc9..b7462a0 100644
--- a/src/semantic/analysis.rs
+++ b/src/semantic/analysis.rs
@@ -3,11 +3,13 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+use std::rc::Rc;
+
 use ::ast::{self, WithLocation};
 use super::environment;
 use super::frame;
 use super::ir;
-use super::translate::{self, Expression, Level, Translate};
+use super::translate::{self, Expression, LevelRef, Translate};
 use super::types::{self, Ty};
 
 #[derive(Debug)]
@@ -33,9 +35,9 @@ type VarEnvironment<'a> = environment::Environment<'a, String, VarValue>;
 type TypeEnvironment<'a> = environment::Environment<'a, String, Ty>;
 pub type Result = ::std::result::Result>;
 
-pub fn translate<'a, F: frame::Frame>(
+pub fn translate(
     translate: &mut Translate,
-    level: &mut Level<'a, F>,
+    level: LevelRef,
     program: &ast::Program)
     -> Result<(translate::Expression, Ty)> {
     let mut venv = VarEnvironment::new(None);
@@ -76,9 +78,9 @@ fn trans_ty<'a>(
     }
 }
 
-fn trans_decl<'a, 'b, F: frame::Frame>(
+fn trans_decl<'a, F: frame::Frame>(
     tr: &mut Translate,
-    level: &mut Level<'b, F>,
+    level: LevelRef,
     venv: &mut VarEnvironment<'a>,
     tenv: &mut TypeEnvironment<'a>,
     decl: &WithLocation) -> Result<(translate::Expression, Ty)> {
@@ -119,7 +121,7 @@ fn trans_decl<'a, 'b, F: frame::Frame>(
         }
         ast::DeclarationBody::Var { ref ty, ref value } => {
             let (var_exp, actual_ty) =
-                trans_exp(tr, level, venv, tenv, &value)?;
+                trans_exp(tr, level.clone(), venv, tenv, &value)?;
             if let &Some(ref ty) = ty {
                 let decl_ty = trans_ty(venv, tenv, &ty)?;
                 if decl_ty != actual_ty {
@@ -129,14 +131,14 @@ fn trans_decl<'a, 'b, F: frame::Frame>(
                     });
                 }
             }
-            Ok((tr.alloc_local(level, frame::Escape::Yes), actual_ty))
+            Ok((tr.alloc_local(&mut level.borrow_mut(), frame::Escape::Yes), actual_ty))
         }
     }
 }
 
-fn trans_exp<'a, 'b, F: frame::Frame>(
+fn trans_exp<'a, F: frame::Frame>(
     tr: &mut Translate,
-    level: &mut Level<'b, F>,
+    level: LevelRef,
     venv: &mut VarEnvironment<'a>,
     tenv: &mut TypeEnvironment<'a>,
     exp: &WithLocation)
@@ -148,7 +150,7 @@ fn trans_exp<'a, 'b, F: frame::Frame>(
             let mut new_venv = VarEnvironment::new(Some(venv));
             let mut new_tenv = TypeEnvironment::new(Some(tenv));
             for decl in decls.iter() {
-                let (decl_exp, decl_ty) = trans_decl(tr, level, &mut new_venv, &mut new_tenv, decl)?;
+                let (decl_exp, decl_ty) = trans_decl(tr, level.clone(), &mut new_venv, &mut new_tenv, decl)?;
                 match decl.declaration {
                     ast::DeclarationBody::Fun { .. } | ast::DeclarationBody::Var { .. } => {
                         new_venv.add_binding(decl.name.clone(), VarValue::Variable(decl_exp, decl_ty));
@@ -163,7 +165,7 @@ fn trans_exp<'a, 'b, F: frame::Frame>(
         &Call(ref name, ref args) => {
             let mut arg_types = vec![];
             for arg in args {
-                arg_types.push(trans_exp(tr, level, venv, tenv, arg)?);
+                arg_types.push(trans_exp(tr, level.clone(), venv, tenv, arg)?);
             }
 
             let value = venv.lookup(name)
@@ -234,7 +236,7 @@ fn trans_exp<'a, 'b, F: frame::Frame>(
         },
         &BinOp(ref op, ref left, ref right) => {
             use ast::BinOp::*;
-            let (left_exp, left_ty) = trans_exp(tr, level, venv, tenv, left)?;
+            let (left_exp, left_ty) = trans_exp(tr, level.clone(), venv, tenv, left)?;
             let (right_exp, right_ty) = trans_exp(tr, level, venv, tenv, right)?;
             match op {
                 &Add => {
diff --git a/src/semantic/translate.rs b/src/semantic/translate.rs
index f802c3f..08e600f 100644
--- a/src/semantic/translate.rs
+++ b/src/semantic/translate.rs
@@ -1,3 +1,6 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+
 use super::frame;
 use super::ir;
 use super::temp;
@@ -14,16 +17,18 @@ pub struct Translate {
     _frametype: ::std::marker::PhantomData,
 }
 
-pub enum Level<'a, F>
-    where F: 'a + frame::Frame {
+pub enum Level
+    where F: frame::Frame {
     Top,
     Level {
-        parent: &'a Level<'a, F>,
+        parent: LevelRef,
         frame: F,
         unique_id: usize,
     },
 }
 
+pub type LevelRef = Rc>>;
+
 impl Translate {
     pub fn new() -> Translate {
         Translate {
@@ -33,17 +38,17 @@ impl Translate {
         }
     }
 
-    pub fn make_level<'a>(
+    pub fn make_level(
         &mut self,
-        parent: &'a Level,
-        formals: Vec) -> Level<'a, F> {
+        parent: LevelRef,
+        formals: Vec) -> LevelRef {
         let id = self.level_counter;
         self.level_counter += 1;
-        Level::Level {
+        Rc::new(RefCell::new(Level::Level {
             parent: parent,
             frame: F::new(self.temp.next_label(), formals),
             unique_id: id,
-        }
+        }))
     }
 
     pub fn make_num(&mut self, num: u64) -> Expression {
@@ -61,7 +66,7 @@ impl Translate {
     }
 
     pub fn alloc_local<'a>(&mut self,
-                           level: &mut Level<'a, F>,
+                           level: &mut Level,
                            escapes: frame::Escape) -> Expression {
         match level {
             &mut Level::Top => {
-- 
cgit v1.2.3