Skip to content

Commit

Permalink
Implement type hints for let bindings.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vlamonster committed Nov 15, 2023
1 parent aec7fe0 commit 7430adc
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 76 deletions.
2 changes: 1 addition & 1 deletion compiler/src/passes/atomize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod tests;

use crate::passes::parse::types::Type;
use crate::passes::parse::{BinaryOp, Def};
use crate::passes::validate::{ExprValidated, TLit};
use crate::passes::validate::TLit;
use crate::utils::gen_sym::UniqueSym;
use std::collections::HashMap;

Expand Down
7 changes: 3 additions & 4 deletions compiler/src/passes/eliminate/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::interpreter::Val;
use crate::interpreter::IO;
use crate::passes::atomize::Atom;
use crate::passes::eliminate::{EExpr, ETail, PrgEliminated};
use crate::passes::parse::BinaryOp;
use crate::passes::validate::TLit;
use crate::utils::gen_sym::UniqueSym;
use crate::utils::push_map::PushMap;
Expand Down Expand Up @@ -101,9 +100,9 @@ impl<'p> PrgEliminated<'p> {

pub fn interpret_expr(
&self,
expr: &EExpr<'p>,
scope: &mut PushMap<UniqueSym<'p>, EVal<'p>>,
io: &mut impl IO,
_expr: &EExpr<'p>,
_scope: &mut PushMap<UniqueSym<'p>, EVal<'p>>,
_io: &mut impl IO,
) -> Vec<EVal<'p>> {
todo!()
// let val = match expr {
Expand Down
10 changes: 5 additions & 5 deletions compiler/src/passes/explicate/explicate.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::passes::atomize::{AExpr, Atom, PrgAtomized};
use crate::passes::explicate::{CExpr, CTail, PrgExplicated};
use crate::passes::parse::types::Type;
use crate::passes::parse::{BinaryOp, Def, TypeDef};
use crate::passes::parse::{Def, TypeDef};
use crate::passes::validate::TLit;
use crate::utils::gen_sym::{gen_sym, UniqueSym};
use std::collections::HashMap;
Expand Down Expand Up @@ -209,10 +209,10 @@ fn explicate_assign<'p>(
}

fn explicate_pred<'p>(
cnd: AExpr<'p>,
thn: CTail<'p>,
els: CTail<'p>,
env: &mut Env<'_, 'p>,
_cnd: AExpr<'p>,
_thn: CTail<'p>,
_els: CTail<'p>,
_env: &mut Env<'_, 'p>,
) -> CTail<'p> {
todo!()
// let mut create_block = |goto: CTail<'p>| {
Expand Down
9 changes: 3 additions & 6 deletions compiler/src/passes/explicate/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@ use crate::interpreter::Val;
use crate::interpreter::IO;
use crate::passes::atomize::Atom;
use crate::passes::explicate::{CExpr, CTail, PrgExplicated};
use crate::passes::parse::BinaryOp;
use crate::passes::validate::TLit;
use crate::utils::gen_sym::UniqueSym;
use crate::utils::push_map::PushMap;
use std::collections::HashMap;

impl<'p> PrgExplicated<'p> {
pub fn interpret(&self, io: &mut impl IO) -> Val<'p, UniqueSym<'p>> {
Expand Down Expand Up @@ -38,9 +35,9 @@ impl<'p> PrgExplicated<'p> {

pub fn interpret_expr(
&self,
expr: &CExpr<'p>,
scope: &mut PushMap<UniqueSym<'p>, Val<'p, UniqueSym<'p>>>,
io: &mut impl IO,
_expr: &CExpr<'p>,
_scope: &mut PushMap<UniqueSym<'p>, Val<'p, UniqueSym<'p>>>,
_io: &mut impl IO,
) -> Val<'p, UniqueSym<'p>> {
todo!()
// match expr {
Expand Down
10 changes: 7 additions & 3 deletions compiler/src/passes/parse/display.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::passes::parse::{BinaryOp, Def, Expr, TypeDef};
use crate::passes::parse::{Def, Expr, TypeDef};
use indenter::indented;
use itertools::Itertools;
use std::fmt::Write;
Expand Down Expand Up @@ -62,13 +62,17 @@ impl<IdentVars: Display, IdentFields: Display, Lit: Display, M> Display
Expr::Let {
sym,
mutable,
typ,
bnd,
bdy,
} => {
writeln!(
f,
"let {}{sym} = {bnd};",
if *mutable { "mut " } else { "" }
"let {}{sym}{} = {bnd};",
if *mutable { "mut " } else { "" },
typ.as_ref()
.map(|typ| format!(": {typ}"))
.unwrap_or("".to_string())
)?;
write!(f, "{bdy}")
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/passes/parse/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,10 @@ Type: Type<Meta<Span, &'input str>> = {
Expr = ExprStmt;

ExprStmt: Expr<Meta<Span, &'input str>, Meta<Span, &'input str>, Lit<'input>, Span> = {
"let" <mutable:"mut"?> <sym:Ident> "=" <bnd:Spanned<ExprLogicalOr<Struct>>> ";" <bdy:Spanned<ExprStmt?>> => Expr::Let {
"let" <mutable:"mut"?> <sym:Ident> <typ:(":" <Type>)?> "=" <bnd:Spanned<ExprLogicalOr<Struct>>> ";" <bdy:Spanned<ExprStmt?>> => Expr::Let {
sym,
mutable: mutable.is_some(),
typ,
bnd: Box::new(bnd),
bdy: Box::new(bdy.fmap(|bdy| bdy.unwrap_or(Expr::Lit { val: Lit::Unit }))),
},
Expand Down
1 change: 1 addition & 0 deletions compiler/src/passes/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ pub enum Expr<IdentVars, IdentFields, Lit, M> {
sym: IdentVars,
/// Indicates whether the variable is mutable (true) or immutable (false).
mutable: bool,
typ: Option<Type<IdentVars>>,
/// The expression to which the variable is bound.
bnd: Box<Meta<M, Expr<IdentVars, IdentFields, Lit, M>>>,
/// The expression that is evaluated using the new variable binding.
Expand Down
1 change: 0 additions & 1 deletion compiler/src/passes/parse/types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use derive_more::Display;
use functor_derive::Functor;
use itertools::Itertools;
use std::fmt::Display;

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/passes/reveal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod tests;

use crate::passes::parse::types::Type;
use crate::passes::parse::{BinaryOp, Def};
use crate::passes::validate::{ExprValidated, TLit};
use crate::passes::validate::TLit;
use crate::utils::gen_sym::UniqueSym;
use std::collections::HashMap;

Expand Down
6 changes: 3 additions & 3 deletions compiler/src/passes/select/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ fn select_tail<'p>(tail: ETail<'p>, instrs: &mut Vec<Instr<'p, VarArg<'p>>>, std
}

fn select_assign<'p>(
dsts: &[UniqueSym<'p>],
expr: EExpr<'p>,
std: &Std<'p>,
_dsts: &[UniqueSym<'p>],
_expr: EExpr<'p>,
_std: &Std<'p>,
) -> Vec<Instr<'p, VarArg<'p>>> {
todo!()
// let dst = var!(dsts[0]);
Expand Down
2 changes: 0 additions & 2 deletions compiler/src/passes/validate/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use crate::passes::parse::types::Type;
use crate::passes::validate::generate_constraints::PartialType;
use miette::Diagnostic;
use thiserror::Error;

Expand Down
84 changes: 58 additions & 26 deletions compiler/src/passes/validate/generate_constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,20 @@ fn constrain_expr<'p>(
},
}
}
ExprUniquified::BinaryOp { op, exprs: [lhs, rhs] } => {
ExprUniquified::BinaryOp {
op,
exprs: [lhs, rhs],
} => {
// input: None = Any but equal, Some = expect this
// output: None = Same as input, Some = this
let (input, output) = match op {
BinaryOp::Add | BinaryOp::Sub | BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => (Some(PartialType::Int), None),
BinaryOp::Add | BinaryOp::Sub | BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => {
(Some(PartialType::Int), None)
}
BinaryOp::LAnd | BinaryOp::LOr | BinaryOp::Xor => (Some(PartialType::Bool), None),
BinaryOp::GT | BinaryOp::GE | BinaryOp::LE | BinaryOp::LT => (Some(PartialType::Int), Some(PartialType::Bool)),
BinaryOp::GT | BinaryOp::GE | BinaryOp::LE | BinaryOp::LT => {
(Some(PartialType::Int), Some(PartialType::Bool))
}
BinaryOp::EQ | BinaryOp::NE => (None, Some(PartialType::Bool)),
};

Expand All @@ -203,35 +210,40 @@ fn constrain_expr<'p>(
// Check inputs satisfy constraints
if let Some(input) = input {
let mut check = |expr: &Meta<CMeta, ExprConstrained<'p>>| {
env.uf.expect_partial_type(expr.meta.index, input.clone(), |got, expect| TypeError::OperandExpect {
expect,
got,
op: op.to_string(),
span_op: span,
span_arg: expr.meta.span,
})
env.uf
.expect_partial_type(expr.meta.index, input.clone(), |got, expect| {
TypeError::OperandExpect {
expect,
got,
op: op.to_string(),
span_op: span,
span_arg: expr.meta.span,
}
})
};

check(&e1)?;
check(&e2)?;
}

// Check inputs equal
let input_index = env.uf.expect_equal(e1.meta.index, e2.meta.index, |lhs, rhs| TypeError::OperandEqual {
lhs,
rhs,
op: op.to_string(),
span_op: span,
span_lhs: e1.meta.span,
span_rhs: e2.meta.span,
})?;
let input_index = env
.uf
.expect_equal(e1.meta.index, e2.meta.index, |lhs, rhs| {
TypeError::OperandEqual {
lhs,
rhs,
op: op.to_string(),
span_op: span,
span_lhs: e1.meta.span,
span_rhs: e2.meta.span,
}
})?;

// Generate output index
let output_index = match output {
None => input_index,
Some(e) => {
env.uf.add(e)
}
Some(e) => env.uf.add(e),
};

Meta {
Expand All @@ -245,23 +257,43 @@ fn constrain_expr<'p>(
},
}
}
ExprUniquified::Let { sym, mutable, bnd, bdy } => {
ExprUniquified::Let {
sym,
mutable,
typ,
bnd,
bdy,
} => {
let bnd = constrain_expr(*bnd, env)?;
env.scope.insert(sym.inner, EnvEntry::Type { mutable, typ: bnd.meta.index });

if let Some(typ) = &typ {
env.uf
.expect_type(bnd.meta.index, typ.clone(), |_, _| todo!())?;
}

env.scope.insert(
sym.inner,
EnvEntry::Type {
mutable,
typ: bnd.meta.index,
},
);
let bdy = constrain_expr(*bdy, env)?;

Meta {
meta: CMeta {
span, index: bdy.meta.index
span,
index: bdy.meta.index,
},
inner: ExprConstrained::Let {
sym,
mutable,
typ,
bnd: Box::new(bnd),
bdy: Box::new(bdy),
}
},
}
},
}
ExprUniquified::If { .. } => todo!(),
ExprUniquified::Apply { .. } => todo!(),
ExprUniquified::Loop { .. } => todo!(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/passes/validate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub mod uniquify;
pub mod validate;

use crate::passes::parse::types::Type;
use crate::passes::parse::{BinaryOp, Def, Expr, Lit, Meta, Span};
use crate::passes::parse::{Def, Expr, Lit, Meta, Span};
use crate::passes::validate::generate_constraints::PartialType;
use crate::utils::gen_sym::UniqueSym;
use crate::utils::union_find::{UnionFind, UnionIndex};
Expand Down
49 changes: 28 additions & 21 deletions compiler/src/passes/validate/resolve_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,23 +112,23 @@ fn resolve_expr<'p>(
let expr = match expr.inner {
Expr::Lit { val } => {
let val = match val {
Lit::Int { val } => {
match &typ {
None => return Err(dbg!(TypeError::IntegerAmbiguous {
Lit::Int { val } => match &typ {
None => {
return Err(dbg!(TypeError::IntegerAmbiguous {
span: expr.meta.span
})),
Some(typ) => match typ {
Type::I64 => TLit::I64 {
val: val.parse().map_err(|_| TypeError::IntegerOutOfBounds {
span: expr.meta.span,
typ: "I64",
})?,
},
Type::U64 => todo!(),
_ => unreachable!(),
},
}))
}
}
Some(typ) => match typ {
Type::I64 => TLit::I64 {
val: val.parse().map_err(|_| TypeError::IntegerOutOfBounds {
span: expr.meta.span,
typ: "I64",
})?,
},
Type::U64 => todo!(),
_ => unreachable!(),
},
},
Lit::Bool { val } => TLit::Bool { val },
Lit::Unit => TLit::Unit,
};
Expand All @@ -142,16 +142,23 @@ fn resolve_expr<'p>(
op,
expr: Box::new(resolve_expr(*expr_inner, uf)?),
},
Expr::BinaryOp { op, exprs: [e1, e2] } => Expr::BinaryOp {
Expr::BinaryOp {
op,
exprs: [
resolve_expr(*e1, uf)?,
resolve_expr(*e2, uf)?
].map(Box::new)
exprs: [e1, e2],
} => Expr::BinaryOp {
op,
exprs: [resolve_expr(*e1, uf)?, resolve_expr(*e2, uf)?].map(Box::new),
},
Expr::Let { sym, mutable, bnd, bdy } => Expr::Let {
Expr::Let {
sym,
mutable,
typ,
bnd,
bdy,
} => Expr::Let {
sym: sym.inner,
mutable,
typ: typ.map(resolve_type),
bnd: Box::new(resolve_expr(*bnd, uf)?),
bdy: Box::new(resolve_expr(*bdy, uf)?),
},
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/passes/validate/uniquify.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::passes::parse::types::Type;
use crate::passes::parse::{
Def, DefParsed, Expr, ExprParsed, Lit, Meta, Param, PrgParsed, Span, TypeDef,
Def, DefParsed, Expr, ExprParsed, Meta, Param, PrgParsed, Span, TypeDef,
};
use crate::passes::validate::error::TypeError;
use crate::passes::validate::error::TypeError::{NoMain, UndeclaredVar};
Expand Down Expand Up @@ -129,6 +129,7 @@ fn uniquify_expr<'p>(
let inner = match expr.inner {
Expr::Let {
sym,
typ,
bnd,
bdy,
mutable,
Expand All @@ -142,6 +143,7 @@ fn uniquify_expr<'p>(
Expr::Let {
sym: unique_sym,
mutable,
typ: typ.map(|typ| uniquify_type(typ, scope)).transpose()?,
bnd: Box::new(unique_bnd),
bdy: Box::new(unique_bdy),
}
Expand Down
5 changes: 5 additions & 0 deletions programs/good/simple/let_hint.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//* ret: true
fn main() -> Bool {
let x : I64 = 42;
x == 42
}

0 comments on commit 7430adc

Please sign in to comment.