From 9630b53836c0717a7ac0ab86dda3a4efb5bf9fb9 Mon Sep 17 00:00:00 2001
From: David Li 
Date: Tue, 28 Nov 2017 20:16:25 -0500
Subject: Translate function calls
---
 src/semantic/analysis.rs  | 37 +++++++++++++++++++++++++------------
 src/semantic/frame.rs     |  7 +++++--
 src/semantic/translate.rs | 28 ++++++++++++++++++++++++++--
 3 files changed, 56 insertions(+), 16 deletions(-)
(limited to 'src/semantic')
diff --git a/src/semantic/analysis.rs b/src/semantic/analysis.rs
index 8335719..0c8dfa3 100644
--- a/src/semantic/analysis.rs
+++ b/src/semantic/analysis.rs
@@ -9,7 +9,7 @@ use ::ast::{self, WithLocation};
 use super::environment;
 use super::frame;
 use super::ir;
-use super::translate::{self, Expression, LevelRef, Translate};
+use super::translate::{self, Expression, Level, LevelRef, Translate};
 use super::types::{self, Ty};
 
 #[derive(Debug)]
@@ -88,9 +88,10 @@ fn trans_decl<'a, F: frame::Frame>(
     level: LevelRef,
     venv: &mut VarEnvironment<'a, F>,
     tenv: &mut TypeEnvironment<'a>,
-    decl: &WithLocation) -> Result<(translate::Expression, Ty)> {
+    decl: &WithLocation) -> Result> {
     match decl.declaration {
         ast::DeclarationBody::Fun { ref ty, ref params, ref body } => {
+            let new_level = tr.make_level(level, params.iter().map(|_| frame::Escape::Yes));
             let declared_ty = if let &Some(ref ty) = ty {
                 Some(ast::WithLocation::new(trans_ty(venv, tenv, &ty)?, ty.start, ty.end))
             } else { None };
@@ -101,12 +102,13 @@ fn trans_decl<'a, F: frame::Frame>(
             for param in params.iter() {
                 let arg_ty = trans_ty(&mut new_venv, &mut new_tenv, ¶m.ty)?;
                 arg_types.push(arg_ty.clone());
-                // TODO:
-                // new_venv.add_binding(param.name.value.clone(), arg_ty);
+                // TODO: don't assume args are in registers
+                new_venv.add_binding(param.name.value.clone(),
+                                     VarValue::Variable(unimplemented!(), arg_ty));
             }
 
             let (body_exp, body_ty) =
-                trans_exp(tr, level, &mut new_venv, &mut new_tenv, &*body)?;
+                trans_exp(tr, new_level.clone(), &mut new_venv, &mut new_tenv, &*body)?;
 
             if let Some(decl_ty) = declared_ty {
                 if &decl_ty.value != &body_ty {
@@ -117,8 +119,13 @@ fn trans_decl<'a, F: frame::Frame>(
                 }
             }
 
-            return err!(decl, TypeError::Unimplemented);
-            // Ok(Ty::Function(arg_types, Box::new(body_ty)))
+            let label = new_level.borrow().to_exp();
+            Ok(VarValue::Function {
+                level: new_level,
+                label: label,
+                body: body_exp,
+                ty: Ty::Function(arg_types, Box::new(body_ty)),
+            })
         }
         ast::DeclarationBody::Ty { ref ty } => {
             return err!(decl, TypeError::Unimplemented);
@@ -136,7 +143,9 @@ fn trans_decl<'a, F: frame::Frame>(
                     });
                 }
             }
-            Ok((tr.alloc_local(&mut level.borrow_mut(), frame::Escape::Yes), actual_ty))
+            Ok(VarValue::Variable(
+                tr.alloc_local(&mut level.borrow_mut(), frame::Escape::Yes),
+                actual_ty))
         }
     }
 }
@@ -155,13 +164,14 @@ fn trans_exp<'a, 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.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));
+                        let binding = trans_decl(tr, level.clone(), &mut new_venv, &mut new_tenv, decl)?;
+                        new_venv.add_binding(decl.name.clone(), binding);
                     }
                     ast::DeclarationBody::Ty { .. } => {
-                        new_tenv.add_binding(decl.name.clone(), decl_ty);
+                        unimplemented!();
+                        // new_tenv.add_binding(decl.name.clone(), decl_ty);
                     }
                 }
             }
@@ -200,7 +210,10 @@ fn trans_exp<'a, F: frame::Frame>(
                                         })
                                     }
                                 }
-                            Ok((label.clone(), (**result).clone()))
+                            Ok((
+                                tr.call(label.clone(), arg_types.into_iter().map(|(a, b)| a)),
+                                (**result).clone()
+                            ))
                         },
                         otherwise => {
                             err!(exp, TypeError::Mismatch {
diff --git a/src/semantic/frame.rs b/src/semantic/frame.rs
index 95d18a1..5b7bfaa 100644
--- a/src/semantic/frame.rs
+++ b/src/semantic/frame.rs
@@ -14,11 +14,14 @@ pub enum Escape {
 }
 
 pub trait Frame {
-    fn new(name: temp::TempLabel, formals: Vec) -> Self;
+    fn new>(name: temp::TempLabel, formals: I) -> Self;
     fn name(&self) -> temp::TempLabel;
     fn formals(&self) -> &[Location];
     fn alloc_local(&mut self, temp: &mut temp::Temp, escapes: Escape) -> Location;
     fn location_to_exp(&mut self, location: Location) -> ir::Expression;
+    fn to_exp(&self) -> ir::Expression {
+        ir::Expression::Name(self.name())
+    }
 }
 
 pub struct Amd64Frame {
@@ -27,7 +30,7 @@ pub struct Amd64Frame {
 }
 
 impl Frame for Amd64Frame {
-    fn new(name: temp::TempLabel, formals: Vec) -> Self {
+    fn new>(name: temp::TempLabel, formals: I) -> Self {
         Amd64Frame {
             offset: 0,
             name: name,
diff --git a/src/semantic/translate.rs b/src/semantic/translate.rs
index 08e600f..4d51e60 100644
--- a/src/semantic/translate.rs
+++ b/src/semantic/translate.rs
@@ -38,10 +38,10 @@ impl Translate {
         }
     }
 
-    pub fn make_level(
+    pub fn make_level>(
         &mut self,
         parent: LevelRef,
-        formals: Vec) -> LevelRef {
+        formals: I) -> LevelRef {
         let id = self.level_counter;
         self.level_counter += 1;
         Rc::new(RefCell::new(Level::Level {
@@ -78,4 +78,28 @@ impl Translate {
             }
         }
     }
+
+    pub fn call>(&mut self, target: Expression, parameters: I) -> Expression {
+        Expression::Exp(ir::Expression::Call(
+            Box::new(match target {
+                Expression::Exp(e) => e,
+                Expression::Void(_) => panic!("Can't call Void expression"),
+            }), parameters.into_iter().map(|p| match p {
+                Expression::Exp(e) => e,
+                Expression::Void(_) => panic!("Can't evaluate Void expression"),
+            }).collect()))
+    }
+}
+
+impl Level {
+    pub fn to_exp(&self) -> Expression {
+        match self {
+            &Level::Top => {
+                panic!("Function defined in top level frame")
+            }
+            &Level::Level { ref frame, .. } => {
+                Expression::Exp(frame.to_exp())
+            }
+        }
+    }
 }
-- 
cgit v1.2.3