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