diff options
| -rw-r--r-- | src/semantic/analysis.rs | 89 | 
1 files changed, 48 insertions, 41 deletions
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<F: frame::Frame> { +    Function { +        level: LevelRef<F>, +        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<F>>;  type TypeEnvironment<'a> = environment::Environment<'a, String, Ty>;  pub type Result<T> = ::std::result::Result<T, WithLocation<TypeError>>; @@ -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<ast::Ty>) -> Result<Ty> {      match ty.value { @@ -81,7 +86,7 @@ fn trans_ty<'a>(  fn trans_decl<'a, F: frame::Frame>(      tr: &mut Translate<F>,      level: LevelRef<F>, -    venv: &mut VarEnvironment<'a>, +    venv: &mut VarEnvironment<'a, F>,      tenv: &mut TypeEnvironment<'a>,      decl: &WithLocation<ast::Declaration>) -> 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<F>,      level: LevelRef<F>, -    venv: &mut VarEnvironment<'a>, +    venv: &mut VarEnvironment<'a, F>,      tenv: &mut TypeEnvironment<'a>,      exp: &WithLocation<ast::Expression>)      -> 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 {  | 
