Skip to content

Commit

Permalink
Generate IR from AST
Browse files Browse the repository at this point in the history
  • Loading branch information
timsueberkrueb committed Jan 4, 2025
1 parent 7381b91 commit 87a02a8
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 1 deletion.
116 changes: 116 additions & 0 deletions lang/backend/src/ast2ir/decls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use crate::ir;
use crate::result::BackendError;

use super::traits::ToIR;

impl ToIR for ast::Module {
type Target = ir::Module;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::Module { uri, use_decls, decls, meta_vars: _ } = self;

Check warning on line 10 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L9-L10

Added lines #L9 - L10 were not covered by tests

let IRDecls { def_decls, codef_decls, let_decls } = to_ir_decls(decls)?;

Check warning on line 12 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L12

Added line #L12 was not covered by tests

Ok(ir::Module {
uri: uri.clone(),
use_decls: use_decls.clone(),
def_decls,
codef_decls,
let_decls,
})
}

Check warning on line 21 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L14-L21

Added lines #L14 - L21 were not covered by tests
}

struct IRDecls {
def_decls: Vec<ir::Def>,
codef_decls: Vec<ir::Codef>,
let_decls: Vec<ir::Let>,
}

fn to_ir_decls(decls: &[ast::Decl]) -> Result<IRDecls, BackendError> {
let mut def_decls = Vec::new();
let mut codef_decls = Vec::new();
let mut let_decls = Vec::new();

Check warning on line 33 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L30-L33

Added lines #L30 - L33 were not covered by tests

for decl in decls {
match decl {
ast::Decl::Def(def) => {
if let Some(def) = def.to_ir()? {
def_decls.push(def);
}

Check warning on line 40 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L35-L40

Added lines #L35 - L40 were not covered by tests
}
ast::Decl::Codef(codef) => codef_decls.push(codef.to_ir()?),
ast::Decl::Let(tl_let) => {
if let Some(tl_let) = tl_let.to_ir()? {
let_decls.push(tl_let);
}

Check warning on line 46 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L42-L46

Added lines #L42 - L46 were not covered by tests
}
ast::Decl::Data(_) => {}
ast::Decl::Codata(_) => {}

Check warning on line 49 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L48-L49

Added lines #L48 - L49 were not covered by tests
}
}

Ok(IRDecls { def_decls, codef_decls, let_decls })
}

Check warning on line 54 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L53-L54

Added lines #L53 - L54 were not covered by tests

impl ToIR for ast::Def {
type Target = Option<ir::Def>;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::Def { name, params, self_param, cases, .. } = self;

let params = params
.params
.iter()
.filter(|param| !param.erased)
.map(|param| param.name.to_string())
.collect();

Check warning on line 67 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L59-L67

Added lines #L59 - L67 were not covered by tests

let cases = cases.to_ir()?;

Check warning on line 69 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L69

Added line #L69 was not covered by tests

Ok(Some(ir::Def {
name: name.to_string(),
self_param: self_param.name.as_ref().map(|nm| nm.to_string()).unwrap_or_default(),
params,
cases,
}))
}

Check warning on line 77 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L71-L77

Added lines #L71 - L77 were not covered by tests
}

impl ToIR for ast::Codef {
type Target = ir::Codef;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::Codef { name, params, cases, .. } = self;

let params = params
.params
.iter()
.filter(|param| !param.erased)
.map(|param| param.name.to_string())
.collect();

Check warning on line 91 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L83-L91

Added lines #L83 - L91 were not covered by tests

let cases = cases.to_ir()?;

Check warning on line 93 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L93

Added line #L93 was not covered by tests

Ok(ir::Codef { name: name.to_string(), params, cases })
}

Check warning on line 96 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L95-L96

Added lines #L95 - L96 were not covered by tests
}

impl ToIR for ast::Let {
type Target = Option<ir::Let>;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::Let { name, params, body, .. } = self;

let params = params
.params
.iter()
.filter(|param| !param.erased)
.map(|param| param.name.to_string())
.collect();

Check warning on line 110 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L102-L110

Added lines #L102 - L110 were not covered by tests

let body = Box::new(body.to_ir()?);

Check warning on line 112 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L112

Added line #L112 was not covered by tests

Ok(Some(ir::Let { name: name.to_string(), params, body }))
}

Check warning on line 115 in lang/backend/src/ast2ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/decls.rs#L114-L115

Added lines #L114 - L115 were not covered by tests
}
160 changes: 160 additions & 0 deletions lang/backend/src/ast2ir/exprs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
use ast::LocalComatch;

use crate::ir;
use crate::result::BackendError;

use super::traits::ToIR;

impl ToIR for ast::Exp {
type Target = ir::Exp;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let out = match self {
ast::Exp::Variable(variable) => ir::Exp::Variable(variable.to_ir()?),
ast::Exp::TypCtor(_) => ir::Exp::ZST,
ast::Exp::Call(call) => match call.kind {
ast::CallKind::Constructor => ir::Exp::CtorCall(call.to_ir()?),
ast::CallKind::Codefinition => ir::Exp::CodefCall(call.to_ir()?),
ast::CallKind::LetBound => ir::Exp::LetCall(call.to_ir()?),

Check warning on line 18 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L11-L18

Added lines #L11 - L18 were not covered by tests
},
ast::Exp::DotCall(dot_call) => match dot_call.kind {
ast::DotCallKind::Destructor => ir::Exp::DtorCall(dot_call.to_ir()?),
ast::DotCallKind::Definition => ir::Exp::DefCall(dot_call.to_ir()?),

Check warning on line 22 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L20-L22

Added lines #L20 - L22 were not covered by tests
},
ast::Exp::Anno(anno) => anno.exp.to_ir()?,
ast::Exp::TypeUniv(_) => ir::Exp::ZST,
ast::Exp::LocalMatch(local_match) => ir::Exp::LocalMatch(local_match.to_ir()?),
ast::Exp::LocalComatch(local_comatch) => ir::Exp::LocalComatch(local_comatch.to_ir()?),
ast::Exp::Hole(hole) => hole.to_ir()?,

Check warning on line 28 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L24-L28

Added lines #L24 - L28 were not covered by tests
};

Ok(out)
}

Check warning on line 32 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L31-L32

Added lines #L31 - L32 were not covered by tests
}

impl ToIR for ast::Variable {
type Target = ir::Variable;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::Variable { name, .. } = self;

Ok(ir::Variable { name: name.to_string() })
}

Check warning on line 42 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L38-L42

Added lines #L38 - L42 were not covered by tests
}

impl ToIR for ast::Call {
type Target = ir::Call;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::Call { name, args, .. } = self;

Check warning on line 49 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L48-L49

Added lines #L48 - L49 were not covered by tests

let args = args
.args
.iter()
.filter(|arg| !arg.erased())
.map(|arg| arg.exp())
.map(|arg| arg.to_ir())
.collect::<Result<_, _>>()?;

Check warning on line 57 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L51-L57

Added lines #L51 - L57 were not covered by tests

Ok(ir::Call { name: name.to_string(), module_uri: name.uri.clone(), args })
}

Check warning on line 60 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L59-L60

Added lines #L59 - L60 were not covered by tests
}

impl ToIR for ast::DotCall {
type Target = ir::DotCall;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::DotCall { exp, name, args, .. } = self;

Check warning on line 67 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L66-L67

Added lines #L66 - L67 were not covered by tests

let args = args
.args
.iter()
.filter(|arg| !arg.erased())
.map(|arg| arg.exp())
.map(|arg| arg.to_ir())
.collect::<Result<_, _>>()?;

Check warning on line 75 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L69-L75

Added lines #L69 - L75 were not covered by tests

let exp = Box::new(exp.to_ir()?);

Check warning on line 77 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L77

Added line #L77 was not covered by tests

Ok(ir::DotCall { exp, module_uri: name.uri.clone(), name: name.to_string(), args })
}

Check warning on line 80 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L79-L80

Added lines #L79 - L80 were not covered by tests
}

impl ToIR for ast::LocalMatch {
type Target = ir::LocalMatch;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::LocalMatch { on_exp, cases, .. } = self;

Check warning on line 87 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L86-L87

Added lines #L86 - L87 were not covered by tests

let on_exp = Box::new(on_exp.to_ir()?);
let cases = cases.to_ir()?;

Check warning on line 90 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L89-L90

Added lines #L89 - L90 were not covered by tests

Ok(ir::LocalMatch { on_exp, cases })
}

Check warning on line 93 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L92-L93

Added lines #L92 - L93 were not covered by tests
}

impl ToIR for ast::LocalComatch {
type Target = ir::LocalComatch;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let LocalComatch { cases, .. } = self;

Check warning on line 100 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L99-L100

Added lines #L99 - L100 were not covered by tests

let cases = cases.to_ir()?;

Check warning on line 102 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L102

Added line #L102 was not covered by tests

Ok(ir::LocalComatch { cases })
}

Check warning on line 105 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L104-L105

Added lines #L104 - L105 were not covered by tests
}

impl ToIR for ast::Hole {
type Target = ir::Exp;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::Hole { kind, solution, .. } = self;

Check warning on line 112 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L111-L112

Added lines #L111 - L112 were not covered by tests

let res =
match kind {
ast::MetaVarKind::MustSolve | ast::MetaVarKind::Inserted => match solution {
Some(solution) => solution.to_ir()?,
None => return Err(BackendError::Impossible(
"Encountered hole without solution that must be solved during typechecking"
.to_owned(),
)),

Check warning on line 121 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L114-L121

Added lines #L114 - L121 were not covered by tests
},
ast::MetaVarKind::CanSolve => {
ir::Exp::Panic(ir::Panic { message: "not yet implemented".to_owned() })

Check warning on line 124 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L124

Added line #L124 was not covered by tests
}
};

Ok(res)
}

Check warning on line 129 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L128-L129

Added lines #L128 - L129 were not covered by tests
}

impl ToIR for ast::Case {
type Target = ir::Case;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
let ast::Case { pattern, body, .. } = self;
let ast::Pattern { is_copattern, params, name } = pattern;

let params = params
.params
.iter()
.filter(|param| !param.erased)
.map(|param| param.name.to_string())
.collect::<Vec<_>>();

let pattern = ir::Pattern {
is_copattern: *is_copattern,
name: name.to_string(),
module_uri: name.uri.clone(),
params,
};

Check warning on line 151 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L135-L151

Added lines #L135 - L151 were not covered by tests

let body = match body {
Some(body) => Some(Box::new(body.to_ir()?)),
None => None,

Check warning on line 155 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L153-L155

Added lines #L153 - L155 were not covered by tests
};

Ok(ir::Case { pattern, body })
}

Check warning on line 159 in lang/backend/src/ast2ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/exprs.rs#L158-L159

Added lines #L158 - L159 were not covered by tests
}
3 changes: 3 additions & 0 deletions lang/backend/src/ast2ir/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod decls;
pub mod exprs;
pub mod traits;
26 changes: 26 additions & 0 deletions lang/backend/src/ast2ir/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::result::BackendError;

pub trait ToIR {
type Target;

fn to_ir(&self) -> Result<Self::Target, BackendError>;
}

impl<T: ToIR> ToIR for Vec<T> {
type Target = Vec<T::Target>;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
self.iter().map(|x| x.to_ir()).collect()
}

Check warning on line 14 in lang/backend/src/ast2ir/traits.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/traits.rs#L12-L14

Added lines #L12 - L14 were not covered by tests
}

impl<T: ToIR> ToIR for Option<T> {
type Target = Option<T::Target>;

fn to_ir(&self) -> Result<Self::Target, BackendError> {
match self {
Some(x) => Ok(Some(x.to_ir()?)),
None => Ok(None),

Check warning on line 23 in lang/backend/src/ast2ir/traits.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/traits.rs#L20-L23

Added lines #L20 - L23 were not covered by tests
}
}

Check warning on line 25 in lang/backend/src/ast2ir/traits.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ast2ir/traits.rs#L25

Added line #L25 was not covered by tests
}
8 changes: 7 additions & 1 deletion lang/backend/src/ir/decls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,16 @@ impl Print for Module {
//
//

if use_decls.is_nil() {
let doc = if use_decls.is_nil() {

Check warning on line 50 in lang/backend/src/ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ir/decls.rs#L50

Added line #L50 was not covered by tests
decls
} else {
use_decls.append(alloc.line()).append(alloc.line()).append(decls)
};

if doc.is_nil() {
doc

Check warning on line 57 in lang/backend/src/ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ir/decls.rs#L56-L57

Added lines #L56 - L57 were not covered by tests
} else {
doc.append(alloc.hardline())

Check warning on line 59 in lang/backend/src/ir/decls.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ir/decls.rs#L59

Added line #L59 was not covered by tests
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions lang/backend/src/ir/exprs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ impl Print for Pattern {
}

pub fn print_params<'a>(params: &'a [String], alloc: &'a Alloc<'a>) -> Builder<'a> {
if params.is_empty() {
return alloc.nil();
}

Check warning on line 228 in lang/backend/src/ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ir/exprs.rs#L225-L228

Added lines #L225 - L228 were not covered by tests
let mut doc = alloc.nil();
let mut first = true;

Expand Down Expand Up @@ -260,6 +264,10 @@ pub fn print_cases<'a>(cases: &'a [Case], cfg: &PrintCfg, alloc: &'a Alloc<'a>)
}

fn print_args<'a>(args: &'a [Exp], cfg: &PrintCfg, alloc: &'a Alloc<'a>) -> Builder<'a> {
if args.is_empty() {
return alloc.nil();
}

Check warning on line 270 in lang/backend/src/ir/exprs.rs

View check run for this annotation

Codecov / codecov/patch

lang/backend/src/ir/exprs.rs#L267-L270

Added lines #L267 - L270 were not covered by tests
let mut doc = alloc.nil();
let mut first = true;

Expand Down
1 change: 1 addition & 0 deletions lang/backend/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod ast2ir;
pub mod ir;
pub mod result;

0 comments on commit 87a02a8

Please sign in to comment.