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