mirror of
https://github.com/HigherOrderCO/Kind1.git
synced 2024-09-11 08:45:32 +03:00
feat: simple inline
This commit is contained in:
parent
0b16e63eed
commit
4357ec0078
@ -149,7 +149,6 @@ pub fn compile_in_session<T>(
|
|||||||
Log::Checked(start.elapsed())
|
Log::Checked(start.elapsed())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
eprintln!();
|
|
||||||
res
|
res
|
||||||
} else {
|
} else {
|
||||||
render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed()));
|
render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed()));
|
||||||
|
@ -9,4 +9,5 @@ edition = "2021"
|
|||||||
kind-span = { path = "../kind-span" }
|
kind-span = { path = "../kind-span" }
|
||||||
kind-tree = { path = "../kind-tree" }
|
kind-tree = { path = "../kind-tree" }
|
||||||
kind-report = { path = "../kind-report" }
|
kind-report = { path = "../kind-report" }
|
||||||
fxhash = "0.2.1"
|
fxhash = "0.2.1"
|
||||||
|
im = "*"
|
@ -1,22 +1,275 @@
|
|||||||
use fxhash::FxHashMap;
|
use fxhash::FxHashMap;
|
||||||
use kind_tree::{
|
|
||||||
concrete::{expr::Expr, visitor::Visitor},
|
use kind_span::Range;
|
||||||
symbol::Symbol,
|
|
||||||
};
|
use kind_tree::concrete::expr::{Binding, Case, CaseBinding, Destruct, Expr, ExprKind, SttmKind};
|
||||||
|
use kind_tree::concrete::pat::{Pat, PatIdent, PatKind};
|
||||||
|
use kind_tree::concrete::visitor::Visitor;
|
||||||
|
use kind_tree::symbol::{Ident, QualifiedIdent, Symbol};
|
||||||
|
use kind_tree::visit_vec;
|
||||||
|
|
||||||
pub struct Subst<'a> {
|
pub struct Subst<'a> {
|
||||||
|
pub context_vars: Vec<(Range, String)>,
|
||||||
pub names: &'a FxHashMap<String, String>,
|
pub names: &'a FxHashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Visitor for Subst<'a> {
|
impl<'a> Visitor for Subst<'a> {
|
||||||
fn visit_ident(&mut self, ident: &mut kind_tree::symbol::Ident) {
|
fn visit_attr(&mut self, _: &mut kind_tree::concrete::Attribute) {}
|
||||||
if let Some(res) = self.names.get(ident.to_str()) {
|
|
||||||
ident.data = Symbol::new(res.clone());
|
fn visit_ident(&mut self, ident: &mut Ident) {
|
||||||
|
let name = ident.to_str();
|
||||||
|
if self.context_vars.iter().all(|x| x.1 != name) {
|
||||||
|
if let Some(res) = self.names.get(name) {
|
||||||
|
ident.data = Symbol::new(res.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_pat_ident(&mut self, ident: &mut PatIdent) {
|
||||||
|
self.visit_ident(&mut ident.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_destruct(&mut self, destruct: &mut Destruct) {
|
||||||
|
match destruct {
|
||||||
|
Destruct::Destruct(range, ty, bindings, _) => {
|
||||||
|
self.visit_qualified_ident(
|
||||||
|
&mut QualifiedIdent::add_segment(ty, "open").to_generated(),
|
||||||
|
);
|
||||||
|
self.visit_range(range);
|
||||||
|
self.visit_qualified_ident(ty);
|
||||||
|
for bind in bindings {
|
||||||
|
self.visit_case_binding(bind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Destruct::Ident(ident) => self.context_vars.push((ident.range, ident.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_sttm(&mut self, sttm: &mut kind_tree::concrete::expr::Sttm) {
|
||||||
|
match &mut sttm.data {
|
||||||
|
SttmKind::Ask(ident, val, next) => {
|
||||||
|
self.visit_expr(val);
|
||||||
|
let vars = self.context_vars.clone();
|
||||||
|
self.visit_destruct(ident);
|
||||||
|
self.visit_sttm(next);
|
||||||
|
self.context_vars = vars;
|
||||||
|
}
|
||||||
|
SttmKind::Let(ident, val, next) => {
|
||||||
|
self.visit_expr(val);
|
||||||
|
let vars = self.context_vars.clone();
|
||||||
|
self.visit_destruct(ident);
|
||||||
|
self.visit_sttm(next);
|
||||||
|
self.context_vars = vars;
|
||||||
|
}
|
||||||
|
SttmKind::Expr(expr, next) => {
|
||||||
|
self.visit_expr(expr);
|
||||||
|
self.visit_sttm(next);
|
||||||
|
}
|
||||||
|
SttmKind::Return(expr) => {
|
||||||
|
self.visit_expr(expr);
|
||||||
|
}
|
||||||
|
SttmKind::RetExpr(expr) => {
|
||||||
|
self.visit_expr(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_pat(&mut self, pat: &mut Pat) {
|
||||||
|
match &mut pat.data {
|
||||||
|
PatKind::Var(ident) => self.visit_pat_ident(ident),
|
||||||
|
PatKind::Str(_) => (),
|
||||||
|
PatKind::Num(_) => (),
|
||||||
|
PatKind::Hole => (),
|
||||||
|
PatKind::List(ls) => {
|
||||||
|
for pat in ls {
|
||||||
|
self.visit_pat(pat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PatKind::Pair(fst, snd) => {
|
||||||
|
self.visit_pat(fst);
|
||||||
|
self.visit_pat(snd);
|
||||||
|
}
|
||||||
|
PatKind::App(t, ls) => {
|
||||||
|
self.visit_qualified_ident(t);
|
||||||
|
for pat in ls {
|
||||||
|
self.visit_pat(pat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_case_binding(&mut self, case_binding: &mut CaseBinding) {
|
||||||
|
match case_binding {
|
||||||
|
CaseBinding::Field(ident) | CaseBinding::Renamed(_, ident) => {
|
||||||
|
self.context_vars.push((ident.range, ident.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_case(&mut self, case: &mut Case) {
|
||||||
|
let vars = self.context_vars.clone();
|
||||||
|
for binding in &mut case.bindings {
|
||||||
|
self.visit_case_binding(binding);
|
||||||
|
}
|
||||||
|
self.visit_expr(&mut case.value);
|
||||||
|
self.context_vars = vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_match(&mut self, matcher: &mut kind_tree::concrete::expr::Match) {
|
||||||
|
self.visit_expr(&mut matcher.scrutinizer);
|
||||||
|
for case in &mut matcher.cases {
|
||||||
|
self.visit_case(case);
|
||||||
|
}
|
||||||
|
match &mut matcher.motive {
|
||||||
|
Some(x) => self.visit_expr(x),
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_binding(&mut self, binding: &mut Binding) {
|
||||||
|
match binding {
|
||||||
|
Binding::Positional(e) => self.visit_expr(e),
|
||||||
|
Binding::Named(_, _, e) => self.visit_expr(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, expr: &mut Expr) {
|
||||||
|
match &mut expr.data {
|
||||||
|
ExprKind::Var { name } => self.visit_ident(name),
|
||||||
|
ExprKind::Constr { name, args } => {
|
||||||
|
self.visit_qualified_ident(name);
|
||||||
|
visit_vec!(args.iter_mut(), arg => self.visit_binding(arg));
|
||||||
|
}
|
||||||
|
ExprKind::All {
|
||||||
|
param: None,
|
||||||
|
typ,
|
||||||
|
body,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
self.visit_expr(typ);
|
||||||
|
self.visit_expr(body);
|
||||||
|
}
|
||||||
|
ExprKind::All {
|
||||||
|
param: Some(ident),
|
||||||
|
typ,
|
||||||
|
body,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
self.visit_expr(typ);
|
||||||
|
self.context_vars.push((ident.range, ident.to_string()));
|
||||||
|
self.visit_expr(body);
|
||||||
|
self.context_vars.pop();
|
||||||
|
}
|
||||||
|
ExprKind::Lambda {
|
||||||
|
param, typ, body, ..
|
||||||
|
} => {
|
||||||
|
match typ {
|
||||||
|
Some(x) => self.visit_expr(x),
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
self.context_vars.push((param.range, param.to_string()));
|
||||||
|
self.visit_expr(body);
|
||||||
|
self.context_vars.pop();
|
||||||
|
}
|
||||||
|
ExprKind::App { fun, args } => {
|
||||||
|
self.visit_expr(fun);
|
||||||
|
visit_vec!(args.iter_mut(), arg => self.visit_expr(&mut arg.data));
|
||||||
|
}
|
||||||
|
ExprKind::Ann { val, typ } => {
|
||||||
|
self.visit_expr(val);
|
||||||
|
self.visit_expr(typ);
|
||||||
|
}
|
||||||
|
ExprKind::Lit { lit } => self.visit_literal(lit),
|
||||||
|
ExprKind::Binary { op: _, fst, snd } => {
|
||||||
|
self.visit_expr(fst);
|
||||||
|
self.visit_expr(snd);
|
||||||
|
}
|
||||||
|
ExprKind::Let { name, val, next } => {
|
||||||
|
self.visit_expr(val);
|
||||||
|
let vars = self.context_vars.clone();
|
||||||
|
self.visit_destruct(name);
|
||||||
|
self.visit_expr(next);
|
||||||
|
self.context_vars = vars;
|
||||||
|
}
|
||||||
|
ExprKind::Sigma {
|
||||||
|
param: None,
|
||||||
|
fst,
|
||||||
|
snd,
|
||||||
|
} => {
|
||||||
|
self.visit_qualified_ident(&mut QualifiedIdent::new_static(
|
||||||
|
"Sigma", None, expr.range,
|
||||||
|
));
|
||||||
|
self.visit_expr(fst);
|
||||||
|
self.visit_expr(snd);
|
||||||
|
}
|
||||||
|
ExprKind::Sigma {
|
||||||
|
param: Some(ident),
|
||||||
|
fst,
|
||||||
|
snd,
|
||||||
|
} => {
|
||||||
|
self.visit_qualified_ident(&mut QualifiedIdent::new_static(
|
||||||
|
"Sigma", None, expr.range,
|
||||||
|
));
|
||||||
|
self.visit_expr(fst);
|
||||||
|
self.context_vars.push((ident.range, ident.to_string()));
|
||||||
|
self.visit_expr(snd);
|
||||||
|
self.context_vars.pop();
|
||||||
|
}
|
||||||
|
ExprKind::Match(matcher) => {
|
||||||
|
self.visit_qualified_ident(&mut matcher.typ.add_segment("match"));
|
||||||
|
self.visit_match(matcher)
|
||||||
|
}
|
||||||
|
ExprKind::Subst(subst) => {
|
||||||
|
self.visit_ident(&mut subst.name);
|
||||||
|
|
||||||
|
if let Some(pos) = self
|
||||||
|
.context_vars
|
||||||
|
.iter()
|
||||||
|
.position(|x| x.1 == subst.name.to_string())
|
||||||
|
{
|
||||||
|
subst.indx = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.visit_expr(&mut subst.expr)
|
||||||
|
}
|
||||||
|
ExprKind::Hole => {}
|
||||||
|
ExprKind::Do { typ, sttm } => {
|
||||||
|
self.visit_qualified_ident(&mut typ.add_segment("pure").to_generated());
|
||||||
|
self.visit_qualified_ident(&mut typ.add_segment("bind").to_generated());
|
||||||
|
self.visit_sttm(sttm)
|
||||||
|
}
|
||||||
|
ExprKind::If { cond, then_, else_ } => {
|
||||||
|
self.visit_qualified_ident(&mut QualifiedIdent::new_sugared(
|
||||||
|
"Bool", "if", expr.range,
|
||||||
|
));
|
||||||
|
self.visit_expr(cond);
|
||||||
|
self.visit_expr(then_);
|
||||||
|
self.visit_expr(else_);
|
||||||
|
}
|
||||||
|
ExprKind::Pair { fst, snd } => {
|
||||||
|
self.visit_qualified_ident(&mut QualifiedIdent::new_sugared(
|
||||||
|
"Pair", "new", expr.range,
|
||||||
|
));
|
||||||
|
self.visit_expr(fst);
|
||||||
|
self.visit_expr(snd);
|
||||||
|
}
|
||||||
|
ExprKind::List { args } => {
|
||||||
|
self.visit_qualified_ident(&mut QualifiedIdent::new_sugared(
|
||||||
|
"List", "nil", expr.range,
|
||||||
|
));
|
||||||
|
self.visit_qualified_ident(&mut QualifiedIdent::new_sugared(
|
||||||
|
"List", "cons", expr.range,
|
||||||
|
));
|
||||||
|
visit_vec!(args.iter_mut(), arg => self.visit_expr(arg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn substitute_in_expr(expr: &mut Expr, names: &FxHashMap<String, String>) {
|
pub fn substitute_in_expr(expr: &mut Expr, names: &FxHashMap<String, String>) {
|
||||||
let mut session = Subst { names };
|
let mut session = Subst {
|
||||||
|
context_vars: Default::default(),
|
||||||
|
names,
|
||||||
|
};
|
||||||
session.visit_expr(expr)
|
session.visit_expr(expr)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use checker::eval;
|
use checker::eval;
|
||||||
use errors::DriverError;
|
use errors::DriverError;
|
||||||
use kind_pass::{desugar, erasure, expand};
|
use kind_pass::{desugar, erasure, expand, inline::inline_book};
|
||||||
use kind_report::report::FileCache;
|
use kind_report::report::FileCache;
|
||||||
use kind_span::SyntaxCtxIndex;
|
use kind_span::SyntaxCtxIndex;
|
||||||
|
|
||||||
@ -33,7 +33,10 @@ pub fn type_check_book(session: &mut Session, path: &PathBuf) -> Option<untyped:
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
todo!()
|
let mut book = erasure::erase_book(&desugared_book, session.diagnostic_sender.clone())?;
|
||||||
|
inline_book(&mut book);
|
||||||
|
|
||||||
|
Some(book)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_book(session: &mut Session, path: &PathBuf) -> Option<concrete::Book> {
|
pub fn to_book(session: &mut Session, path: &PathBuf) -> Option<concrete::Book> {
|
||||||
@ -56,7 +59,10 @@ pub fn erase_book(
|
|||||||
) -> Option<untyped::Book> {
|
) -> Option<untyped::Book> {
|
||||||
let concrete_book = to_book(session, path)?;
|
let concrete_book = to_book(session, path)?;
|
||||||
let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?;
|
let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?;
|
||||||
erasure::erase_book(&desugared_book, session.diagnostic_sender.clone())
|
let mut book = erasure::erase_book(&desugared_book, session.diagnostic_sender.clone())?;
|
||||||
|
inline_book(&mut book);
|
||||||
|
Some(book)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn desugar_book(session: &mut Session, path: &PathBuf) -> Option<desugared::Book> {
|
pub fn desugar_book(session: &mut Session, path: &PathBuf) -> Option<desugared::Book> {
|
||||||
@ -82,7 +88,10 @@ pub fn compile_book_to_kdl(
|
|||||||
) -> Option<kind_target_kdl::File> {
|
) -> Option<kind_target_kdl::File> {
|
||||||
let concrete_book = to_book(session, path)?;
|
let concrete_book = to_book(session, path)?;
|
||||||
let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?;
|
let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?;
|
||||||
let book = erasure::erase_book(&desugared_book, session.diagnostic_sender.clone())?;
|
let mut book = erasure::erase_book(&desugared_book, session.diagnostic_sender.clone())?;
|
||||||
|
|
||||||
|
inline_book(&mut book);
|
||||||
|
|
||||||
kind_target_kdl::compile_book(book, session.diagnostic_sender.clone(), namespace)
|
kind_target_kdl::compile_book(book, session.diagnostic_sender.clone(), namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
96
crates/kind-pass/src/inline/mod.rs
Normal file
96
crates/kind-pass/src/inline/mod.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
use fxhash::FxHashMap;
|
||||||
|
use kind_tree::untyped;
|
||||||
|
|
||||||
|
use crate::unbound::subst::subst_on_expr;
|
||||||
|
|
||||||
|
struct Inlinable {
|
||||||
|
names: Vec<String>,
|
||||||
|
body: Box<untyped::Expr>,
|
||||||
|
}
|
||||||
|
struct InlineState {
|
||||||
|
funs: FxHashMap<String, Inlinable>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inlinable(entry: &untyped::Entry) -> Option<Inlinable> {
|
||||||
|
if entry.rules.len() == 1 {
|
||||||
|
let mut names = Vec::new();
|
||||||
|
for pat in &entry.rules[0].pats {
|
||||||
|
match &pat.data {
|
||||||
|
untyped::ExprKind::Var { name } => {
|
||||||
|
names.push(name.to_string())
|
||||||
|
},
|
||||||
|
_ => return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Check if is recursive
|
||||||
|
Some(Inlinable { names, body: entry.rules[0].body.clone() })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inline_book(book: &mut untyped::Book) {
|
||||||
|
let mut funs = FxHashMap::default();
|
||||||
|
|
||||||
|
let mut to_remove = Vec::new();
|
||||||
|
|
||||||
|
for entr in book.entrs.values() {
|
||||||
|
if entr.attrs.inlined {
|
||||||
|
if let Some(inlinable) = inlinable(&entr) {
|
||||||
|
funs.insert(entr.name.to_string(), inlinable);
|
||||||
|
to_remove.push(entr.name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for name in &to_remove {
|
||||||
|
book.entrs.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut state = InlineState { funs };
|
||||||
|
|
||||||
|
for entr in &mut book.entrs {
|
||||||
|
state.inline_entry(entr.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlineState {
|
||||||
|
fn inline_entry(&mut self, entry: &mut untyped::Entry) {
|
||||||
|
for rule in &mut entry.rules {
|
||||||
|
self.inline_expr(&mut rule.body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inline_expr(&mut self, expr: &mut Box<untyped::Expr>) {
|
||||||
|
use untyped::ExprKind::*;
|
||||||
|
match &mut expr.data {
|
||||||
|
Lambda { body, .. } => self.inline_expr(body),
|
||||||
|
App { fun, args } => {
|
||||||
|
self.inline_expr(fun);
|
||||||
|
for arg in args {
|
||||||
|
self.inline_expr(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fun { name, args } | Ctr { name, args } => {
|
||||||
|
if let Some(inlinable) = self.funs.get(name.to_str()) {
|
||||||
|
let subst = FxHashMap::from_iter(inlinable.names.iter().cloned().zip(args.clone()));
|
||||||
|
*expr = inlinable.body.clone();
|
||||||
|
subst_on_expr(expr, subst);
|
||||||
|
}else {
|
||||||
|
for arg in args {
|
||||||
|
self.inline_expr(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Let { val, next, .. } => {
|
||||||
|
self.inline_expr(val);
|
||||||
|
self.inline_expr(next);
|
||||||
|
}
|
||||||
|
Binary { left, right, .. } => {
|
||||||
|
self.inline_expr(left);
|
||||||
|
self.inline_expr(right);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,3 +9,4 @@ pub mod erasure;
|
|||||||
mod errors;
|
mod errors;
|
||||||
pub mod expand;
|
pub mod expand;
|
||||||
pub mod unbound;
|
pub mod unbound;
|
||||||
|
pub mod inline;
|
||||||
|
@ -21,6 +21,8 @@ use kind_tree::{visit_opt, visit_vec};
|
|||||||
|
|
||||||
use crate::errors::PassError;
|
use crate::errors::PassError;
|
||||||
|
|
||||||
|
pub mod subst;
|
||||||
|
|
||||||
pub struct UnboundCollector {
|
pub struct UnboundCollector {
|
||||||
pub errors: Sender<Box<dyn Diagnostic>>,
|
pub errors: Sender<Box<dyn Diagnostic>>,
|
||||||
|
|
||||||
|
101
crates/kind-pass/src/unbound/subst.rs
Normal file
101
crates/kind-pass/src/unbound/subst.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use fxhash::FxHashMap;
|
||||||
|
use kind_tree::untyped::*;
|
||||||
|
|
||||||
|
pub struct Subst {
|
||||||
|
vars: FxHashMap<String, Box<Expr>>,
|
||||||
|
ctx: im::HashSet<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subst_on_expr(expr: &mut Box<Expr>, vars: FxHashMap<String, Box<Expr>>) {
|
||||||
|
let mut state = Subst {
|
||||||
|
vars,
|
||||||
|
ctx: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
state.subst_expr(expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Subst {
|
||||||
|
pub fn subst_entry(&mut self, entry: &mut Entry) {
|
||||||
|
let backup = self.ctx.clone();
|
||||||
|
|
||||||
|
self.ctx = backup;
|
||||||
|
|
||||||
|
for rule in &mut entry.rules {
|
||||||
|
self.subst_rule(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subst_rule(&mut self, rule: &mut Rule) {
|
||||||
|
let backup = self.ctx.clone();
|
||||||
|
|
||||||
|
for pat in &mut rule.pats {
|
||||||
|
self.subst_expr(pat)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.subst_expr(&mut rule.body);
|
||||||
|
|
||||||
|
self.ctx = backup;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subst_pat(&mut self, expr: &mut Box<Expr>) {
|
||||||
|
use ExprKind::*;
|
||||||
|
|
||||||
|
match &mut expr.data {
|
||||||
|
Var { name } => {
|
||||||
|
self.ctx.insert(name.to_string());
|
||||||
|
}
|
||||||
|
Fun { name: _, args } | Ctr { name: _, args } => {
|
||||||
|
for arg in args {
|
||||||
|
self.subst_pat(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subst_expr(&mut self, expr: &mut Box<Expr>) {
|
||||||
|
use ExprKind::*;
|
||||||
|
|
||||||
|
match &mut expr.data {
|
||||||
|
Var { name } => {
|
||||||
|
if self.ctx.contains(name.to_str()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Some(res) = self.vars.get(name.to_str()) {
|
||||||
|
*expr = res.clone().clone();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Lambda { param, body, .. } => {
|
||||||
|
let backup = self.ctx.clone();
|
||||||
|
self.ctx.insert(param.to_string());
|
||||||
|
self.subst_expr(body);
|
||||||
|
self.ctx = backup;
|
||||||
|
}
|
||||||
|
App { fun, args } => {
|
||||||
|
self.subst_expr(fun);
|
||||||
|
for arg in args {
|
||||||
|
self.subst_expr(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fun { name: _, args } | Ctr { name: _, args } => {
|
||||||
|
for arg in args {
|
||||||
|
self.subst_expr(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Let { name, val, next } => {
|
||||||
|
let backup = self.ctx.clone();
|
||||||
|
self.ctx.insert(name.to_string());
|
||||||
|
self.subst_expr(val);
|
||||||
|
self.subst_expr(next);
|
||||||
|
self.ctx = backup;
|
||||||
|
}
|
||||||
|
Binary { left, right, .. } => {
|
||||||
|
self.subst_expr(left);
|
||||||
|
self.subst_expr(right);
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,12 +17,9 @@ pub fn compile_book(
|
|||||||
sender: Sender<Box<dyn Diagnostic>>,
|
sender: Sender<Box<dyn Diagnostic>>,
|
||||||
namespace: &str,
|
namespace: &str,
|
||||||
) -> Option<compile::File> {
|
) -> Option<compile::File> {
|
||||||
// TODO: Inlining
|
|
||||||
// TODO: Remove kdl_states (maybe check if they're ever called?)
|
// TODO: Remove kdl_states (maybe check if they're ever called?)
|
||||||
// TODO: Don't erase kdl_state functions
|
|
||||||
// TODO: Convert to some sort of Kindelia.Contract
|
// TODO: Convert to some sort of Kindelia.Contract
|
||||||
let flattened = flatten(book);
|
let flattened = flatten(book);
|
||||||
|
|
||||||
|
|
||||||
let file = compile::compile_book(&flattened, sender, namespace)?;
|
let file = compile::compile_book(&flattened, sender, namespace)?;
|
||||||
let file = linearize::linearize_file(file);
|
let file = linearize::linearize_file(file);
|
||||||
|
Loading…
Reference in New Issue
Block a user