From 84babea244bb8ef85c6b84fd63eeeedc85781c03 Mon Sep 17 00:00:00 2001
From: David Li 
Date: Tue, 28 Nov 2017 19:46:49 -0500
Subject: Define how to represent functions in environment
---
 src/semantic/analysis.rs | 89 ++++++++++++++++++++++++++----------------------
 1 file changed, 48 insertions(+), 41 deletions(-)
(limited to 'src')
diff --git a/src/semantic/analysis.rs b/src/semantic/analysis.rs
index b7462a0..8335719 100644
--- a/src/semantic/analysis.rs
+++ b/src/semantic/analysis.rs
@@ -26,12 +26,17 @@ pub enum TypeError {
     UnboundName,
 }
 
-enum VarValue {
-    Function,
+enum VarValue {
+    Function {
+        level: LevelRef,
+        label: Expression,
+        body: Expression,
+        ty: Ty,
+    },
     Variable(Expression, Ty),
 }
 
-type VarEnvironment<'a> = environment::Environment<'a, String, VarValue>;
+type VarEnvironment<'a, F> = environment::Environment<'a, String, VarValue>;
 type TypeEnvironment<'a> = environment::Environment<'a, String, Ty>;
 pub type Result = ::std::result::Result>;
 
@@ -53,8 +58,8 @@ macro_rules! err {
     }
 }
 
-fn trans_ty<'a>(
-    venv: &mut VarEnvironment<'a>,
+fn trans_ty<'a, F: frame::Frame>(
+    venv: &mut VarEnvironment<'a, F>,
     tenv: &mut TypeEnvironment<'a>,
     ty: &WithLocation) -> Result {
     match ty.value {
@@ -81,7 +86,7 @@ fn trans_ty<'a>(
 fn trans_decl<'a, F: frame::Frame>(
     tr: &mut Translate,
     level: LevelRef,
-    venv: &mut VarEnvironment<'a>,
+    venv: &mut VarEnvironment<'a, F>,
     tenv: &mut TypeEnvironment<'a>,
     decl: &WithLocation) -> Result<(translate::Expression, Ty)> {
     match decl.declaration {
@@ -139,7 +144,7 @@ fn trans_decl<'a, F: frame::Frame>(
 fn trans_exp<'a, F: frame::Frame>(
     tr: &mut Translate,
     level: LevelRef,
-    venv: &mut VarEnvironment<'a>,
+    venv: &mut VarEnvironment<'a, F>,
     tenv: &mut TypeEnvironment<'a>,
     exp: &WithLocation)
     -> Result<(translate::Expression, Ty)> {
@@ -172,39 +177,41 @@ fn trans_exp<'a, F: frame::Frame>(
                 .ok_or(WithLocation::new(TypeError::UnboundName,
                                          exp.start, exp.end))?;
             match value {
-                &VarValue::Function => {
-                    // (ref fun_exp, ref fun_ty);
-                    // match fun_ty {
-                    //     &Ty::Function(ref expected_args, ref result) => {
-                    //         if expected_args.len() != arg_types.len() {
-                    //             return err!(exp, TypeError::LengthMismatch {
-                    //                 expected: expected_args.len(),
-                    //                 actual: arg_types.len(),
-                    //             });
-                    //         }
-                    //         for (i, (&(_, ref provided_ty), expected_ty)) in
-                    //             arg_types.iter().zip(expected_args).enumerate() {
-                    //                 if provided_ty != expected_ty {
-                    //                     return err!(args[i], TypeError::Mismatch {
-                    //                         expected: expected_ty.clone(),
-                    //                         actual: provided_ty.clone(),
-                    //                     })
-                    //                 }
-                    //             }
-                    //         err!(exp, TypeError::Unimplemented)
-                    //         // Ok((**result).clone())
-                    //     },
-                    //     otherwise => {
-                    //         err!(exp, TypeError::Mismatch {
-                    //             // TODO: better way to handle this
-                    //             expected: Ty::Function(
-                    //                 arg_types.into_iter().map(|v| v.1).collect(),
-                    //                 Box::new(Ty::Nil)),
-                    //             actual: otherwise.clone(),
-                    //         })
-                    //     }
-                    // }
-                    err!(exp, TypeError::Unimplemented)
+                &VarValue::Function {
+                    level: ref level,
+                    label: ref label,
+                    body: ref fun_exp,
+                    ty: ref fun_ty,
+                } => {
+                    match fun_ty {
+                        &Ty::Function(ref expected_args, ref result) => {
+                            if expected_args.len() != arg_types.len() {
+                                return err!(exp, TypeError::LengthMismatch {
+                                    expected: expected_args.len(),
+                                    actual: arg_types.len(),
+                                });
+                            }
+                            for (i, (&(_, ref provided_ty), expected_ty)) in
+                                arg_types.iter().zip(expected_args).enumerate() {
+                                    if provided_ty != expected_ty {
+                                        return err!(args[i], TypeError::Mismatch {
+                                            expected: expected_ty.clone(),
+                                            actual: provided_ty.clone(),
+                                        })
+                                    }
+                                }
+                            Ok((label.clone(), (**result).clone()))
+                        },
+                        otherwise => {
+                            err!(exp, TypeError::Mismatch {
+                                // TODO: better way to handle this
+                                expected: Ty::Function(
+                                    arg_types.into_iter().map(|v| v.1).collect(),
+                                    Box::new(Ty::Nil)),
+                                actual: otherwise.clone(),
+                            })
+                        }
+                    }
                 }
                 &VarValue::Variable(..) => {
                     err!(exp, TypeError::Unimplemented)
@@ -280,7 +287,7 @@ fn trans_exp<'a, F: frame::Frame>(
                 // TODO: clone might be expensive, Rc?
                 Ok((exp.clone(), ty.clone()))
             }
-            else if let Some(&VarValue::Function) = result {
+            else if let Some(&VarValue::Function { .. }) = result {
                 err!(exp, TypeError::Unimplemented)
             }
             else {
-- 
cgit v1.2.3