mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Merge pull request #339 from rtfeldman/mono-module
code gen top-level module declarations
This commit is contained in:
commit
e3ec087657
25 changed files with 280 additions and 169 deletions
|
@ -16,7 +16,7 @@ use roc_gen::llvm::build::{
|
|||
use roc_gen::llvm::convert::basic_type_from_layout;
|
||||
use roc_load::file::{LoadedModule, LoadingProblem};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::expr::{Expr, Procs};
|
||||
use roc_mono::expr::{Env, Expr, PartialProc, Procs};
|
||||
use roc_mono::layout::Layout;
|
||||
use std::time::SystemTime;
|
||||
|
||||
|
@ -220,6 +220,8 @@ async fn build_file(
|
|||
Ok(binary_path)
|
||||
}
|
||||
|
||||
// TODO this should probably use more helper functions
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn gen(
|
||||
arena: &Bump,
|
||||
loaded: LoadedModule,
|
||||
|
@ -275,17 +277,22 @@ fn gen(
|
|||
}
|
||||
}
|
||||
|
||||
let mut decls_by_id = loaded.declarations_by_id;
|
||||
let home_decls = decls_by_id
|
||||
.remove(&loaded.module_id)
|
||||
.expect("Root module ID not found in loaded declarations_by_id");
|
||||
|
||||
// We use a loop label here so we can break all the way out of a nested
|
||||
// loop inside DeclareRec if we find the expr there.
|
||||
//
|
||||
// https://doc.rust-lang.org/1.30.0/book/first-edition/loops.html#loop-labels
|
||||
'find_expr: for decl in loaded.declarations {
|
||||
'find_expr: for decl in home_decls.iter() {
|
||||
use roc_can::def::Declaration::*;
|
||||
|
||||
match decl {
|
||||
Declare(def) => {
|
||||
if def.pattern_vars.contains_key(&main_symbol) {
|
||||
main_expr = Some(def.loc_expr);
|
||||
main_expr = Some(def.loc_expr.clone());
|
||||
|
||||
break 'find_expr;
|
||||
}
|
||||
|
@ -294,7 +301,7 @@ fn gen(
|
|||
DeclareRec(defs) => {
|
||||
for def in defs {
|
||||
if def.pattern_vars.contains_key(&main_symbol) {
|
||||
main_expr = Some(def.loc_expr);
|
||||
main_expr = Some(def.loc_expr.clone());
|
||||
|
||||
break 'find_expr;
|
||||
}
|
||||
|
@ -347,20 +354,74 @@ fn gen(
|
|||
ptr_bytes,
|
||||
};
|
||||
let mut procs = Procs::default();
|
||||
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
||||
|
||||
// Populate Procs and get the low-level Expr from the canonical Expr
|
||||
let mut mono_problems = std::vec::Vec::new();
|
||||
let main_body = Expr::new(
|
||||
&arena,
|
||||
&mut subs,
|
||||
&mut mono_problems,
|
||||
loc_expr.value,
|
||||
&mut procs,
|
||||
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
||||
let mut mono_env = Env {
|
||||
arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
&mut ident_ids,
|
||||
ptr_bytes,
|
||||
);
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size: ptr_bytes,
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
|
||||
// Add modules' decls to Procs
|
||||
for (_, mut decls) in decls_by_id
|
||||
.drain()
|
||||
.chain(std::iter::once((loaded.module_id, home_decls)))
|
||||
{
|
||||
for decl in decls.drain(..) {
|
||||
use roc_can::def::Declaration::*;
|
||||
use roc_can::expr::Expr::*;
|
||||
use roc_can::pattern::Pattern::*;
|
||||
|
||||
match decl {
|
||||
Declare(def) => match def.loc_pattern.value {
|
||||
Identifier(symbol) => {
|
||||
match def.loc_expr.value {
|
||||
Closure(annotation, _, _, loc_args, boxed_body) => {
|
||||
let (loc_body, ret_var) = *boxed_body;
|
||||
|
||||
procs.insert_closure(
|
||||
&mut mono_env,
|
||||
Some(symbol),
|
||||
annotation,
|
||||
loc_args,
|
||||
loc_body,
|
||||
ret_var,
|
||||
);
|
||||
}
|
||||
body => {
|
||||
let proc = PartialProc {
|
||||
annotation: def.expr_var,
|
||||
// This is a 0-arity thunk, so it has no arguments.
|
||||
patterns: bumpalo::collections::Vec::new_in(arena),
|
||||
body,
|
||||
};
|
||||
|
||||
procs.user_defined.insert(symbol, proc);
|
||||
procs.module_thunks.insert(symbol);
|
||||
}
|
||||
};
|
||||
}
|
||||
other => {
|
||||
todo!("TODO gracefully handle Declare({:?})", other);
|
||||
}
|
||||
},
|
||||
DeclareRec(_defs) => {
|
||||
todo!("TODO support DeclareRec");
|
||||
}
|
||||
InvalidCycle(_loc_idents, _regions) => {
|
||||
todo!("TODO handle InvalidCycle");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate Procs further and get the low-level Expr from the canonical Expr
|
||||
let main_body = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
|
|
@ -246,16 +246,17 @@ pub fn gen(src: &str, target: Triple, opt_level: OptLevel) -> Result<(String, St
|
|||
|
||||
// Populate Procs and get the low-level Expr from the canonical Expr
|
||||
let mut mono_problems = Vec::new();
|
||||
let main_body = roc_mono::expr::Expr::new(
|
||||
&arena,
|
||||
&mut subs,
|
||||
&mut mono_problems,
|
||||
loc_expr.value,
|
||||
&mut procs,
|
||||
let mut mono_env = roc_mono::expr::Env {
|
||||
arena: &arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
&mut ident_ids,
|
||||
ptr_bytes,
|
||||
);
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size: ptr_bytes,
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
let main_body = roc_mono::expr::Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in Env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
|
|
@ -35,8 +35,7 @@ pub fn standard_stdlib() -> StdLib {
|
|||
}
|
||||
}
|
||||
|
||||
/// Keep this up to date by hand!
|
||||
///
|
||||
/// Keep this up to date by hand! It's the number of builtin aliases that are imported by default.
|
||||
const NUM_BUILTIN_IMPORTS: usize = 7;
|
||||
|
||||
/// These can be shared between definitions, they will get instantiated when converted to Type
|
||||
|
|
|
@ -3,8 +3,8 @@ use crate::expr::Expr;
|
|||
use crate::expr::Recursive;
|
||||
use roc_collections::all::SendMap;
|
||||
use roc_module::ident::TagName;
|
||||
use roc_module::operator::CalledVia;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_parse::operator::CalledVia;
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_types::subs::{VarStore, Variable};
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ use crate::procedure::References;
|
|||
use crate::scope::Scope;
|
||||
use roc_collections::all::{ImSet, MutMap, MutSet, SendMap};
|
||||
use roc_module::ident::{Lowercase, TagName};
|
||||
use roc_module::operator::CalledVia;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_parse::ast;
|
||||
use roc_parse::operator::CalledVia;
|
||||
use roc_parse::pattern::PatternType::*;
|
||||
use roc_problem::can::{PrecedenceProblem, Problem, RuntimeError};
|
||||
use roc_region::all::{Located, Region};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_module::ident::ModuleName;
|
||||
use roc_module::operator::BinOp::Pizza;
|
||||
use roc_module::operator::{BinOp, CalledVia};
|
||||
use roc_parse::ast::Expr::{self, *};
|
||||
use roc_parse::ast::{AssignedField, Def, Pattern, WhenBranch};
|
||||
use roc_parse::operator::BinOp::Pizza;
|
||||
use roc_parse::operator::{BinOp, CalledVia};
|
||||
use roc_region::all::{Located, Region};
|
||||
|
||||
// BinOp precedence logic adapted from Gluon by Markus Westerlind, MIT licensed
|
||||
|
@ -201,7 +201,7 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
|
|||
})
|
||||
}
|
||||
UnaryOp(loc_arg, loc_op) | Nested(UnaryOp(loc_arg, loc_op)) => {
|
||||
use roc_parse::operator::UnaryOp::*;
|
||||
use roc_module::operator::UnaryOp::*;
|
||||
|
||||
let region = loc_op.region;
|
||||
let op = loc_op.value;
|
||||
|
@ -327,7 +327,7 @@ fn binop_to_function(binop: BinOp) -> (&'static str, &'static str) {
|
|||
}
|
||||
|
||||
fn desugar_bin_op<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'_>>) -> &'a Located<Expr<'a>> {
|
||||
use roc_parse::operator::Associativity::*;
|
||||
use roc_module::operator::Associativity::*;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
let mut infixes = Infixes::new(loc_expr);
|
||||
|
|
|
@ -4,9 +4,8 @@ use crate::spaces::{
|
|||
add_spaces, fmt_comments_only, fmt_condition_spaces, fmt_spaces, is_comment, newline, INDENT,
|
||||
};
|
||||
use bumpalo::collections::{String, Vec};
|
||||
use roc_module::operator::{self, BinOp};
|
||||
use roc_parse::ast::{AssignedField, Base, CommentOrNewline, Expr, Pattern, WhenBranch};
|
||||
use roc_parse::operator;
|
||||
use roc_parse::operator::BinOp;
|
||||
use roc_region::all::Located;
|
||||
|
||||
pub fn fmt_expr<'a>(
|
||||
|
|
|
@ -63,7 +63,17 @@ macro_rules! assert_llvm_evals_to {
|
|||
|
||||
// Populate Procs and get the low-level Expr from the canonical Expr
|
||||
let mut mono_problems = Vec::new();
|
||||
let main_body = Expr::new(&arena, &mut subs, &mut mono_problems, loc_expr.value, &mut procs, home, &mut ident_ids, ptr_bytes);
|
||||
let mut mono_env = roc_mono::expr::Env {
|
||||
arena: &arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size: ptr_bytes,
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
let main_body = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in Env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
@ -215,7 +225,17 @@ macro_rules! assert_opt_evals_to {
|
|||
|
||||
// Populate Procs and get the low-level Expr from the canonical Expr
|
||||
let mut mono_problems = Vec::new();
|
||||
let main_body = Expr::new(&arena, &mut subs, &mut mono_problems, loc_expr.value, &mut procs, home, &mut ident_ids, ptr_bytes);
|
||||
let mut mono_env = roc_mono::expr::Env {
|
||||
arena: &arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size: ptr_bytes,
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
let main_body = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in Env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
@ -361,7 +381,17 @@ macro_rules! emit_expr {
|
|||
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
||||
|
||||
// Populate Procs and get the low-level Expr from the canonical Expr
|
||||
let main_body = Expr::new(&arena, &mut subs, loc_expr.value, &mut procs, home, &mut ident_ids, $crate::helpers::eval::POINTER_SIZE);
|
||||
let mut mono_env = roc_mono::expr::Env {
|
||||
arena: &arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size: ptr_bytes,
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
let main_body = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in Env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
|
|
@ -282,7 +282,7 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
|
|||
})
|
||||
.collect();
|
||||
|
||||
//load builtin values
|
||||
// load builtin values
|
||||
let (_introduced_rigids, constraint) =
|
||||
constrain_imported_values(imports, constraint, &var_store);
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ pub struct LoadedModule {
|
|||
pub solved: Solved<Subs>,
|
||||
pub can_problems: Vec<roc_problem::can::Problem>,
|
||||
pub type_problems: Vec<solve::TypeError>,
|
||||
pub declarations: Vec<Declaration>,
|
||||
pub declarations_by_id: MutMap<ModuleId, Vec<Declaration>>,
|
||||
pub exposed_vars_by_symbol: Vec<(Symbol, Variable)>,
|
||||
pub src: Box<str>,
|
||||
}
|
||||
|
@ -417,10 +417,6 @@ pub async fn load<'a>(
|
|||
.into_inner()
|
||||
.expect("Unwrapping mutex for module_ids");
|
||||
|
||||
let declarations = declarations_by_id
|
||||
.remove(&module_id)
|
||||
.expect("declarations_by_id was missing root module_id entry");
|
||||
|
||||
let interns = Interns {
|
||||
module_ids,
|
||||
all_ident_ids: constrained_ident_ids,
|
||||
|
@ -432,7 +428,7 @@ pub async fn load<'a>(
|
|||
solved,
|
||||
can_problems,
|
||||
type_problems,
|
||||
declarations,
|
||||
declarations_by_id,
|
||||
exposed_vars_by_symbol,
|
||||
src,
|
||||
});
|
||||
|
|
|
@ -81,16 +81,18 @@ mod test_load {
|
|||
}
|
||||
}
|
||||
|
||||
fn expect_types(loaded_module: LoadedModule, expected_types: HashMap<&str, &str>) {
|
||||
fn expect_types(mut loaded_module: LoadedModule, expected_types: HashMap<&str, &str>) {
|
||||
let home = loaded_module.module_id;
|
||||
let mut subs = loaded_module.solved.into_inner();
|
||||
|
||||
assert_eq!(loaded_module.can_problems, Vec::new());
|
||||
assert_eq!(loaded_module.type_problems, Vec::new());
|
||||
|
||||
let num_decls = loaded_module.declarations.len();
|
||||
let mut num_decls = 0;
|
||||
|
||||
for decl in loaded_module.declarations_by_id.remove(&home).unwrap() {
|
||||
num_decls += 1;
|
||||
|
||||
for decl in loaded_module.declarations {
|
||||
match decl {
|
||||
Declare(def) => expect_def(
|
||||
&loaded_module.interns,
|
||||
|
@ -135,14 +137,17 @@ mod test_load {
|
|||
subs_by_module,
|
||||
)
|
||||
.await;
|
||||
let loaded_module = loaded.expect("Test module failed to load");
|
||||
|
||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
||||
|
||||
assert_eq!(loaded_module.can_problems, Vec::new());
|
||||
assert_eq!(loaded_module.type_problems, Vec::new());
|
||||
|
||||
let def_count: usize = loaded_module
|
||||
.declarations
|
||||
.iter()
|
||||
.declarations_by_id
|
||||
.remove(&loaded_module.module_id)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|decl| decl.def_count())
|
||||
.sum();
|
||||
|
||||
|
|
|
@ -76,16 +76,18 @@ mod test_uniq_load {
|
|||
}
|
||||
}
|
||||
|
||||
fn expect_types(loaded_module: LoadedModule, expected_types: HashMap<&str, &str>) {
|
||||
fn expect_types(mut loaded_module: LoadedModule, expected_types: HashMap<&str, &str>) {
|
||||
let home = loaded_module.module_id;
|
||||
let mut subs = loaded_module.solved.into_inner();
|
||||
|
||||
assert_eq!(loaded_module.can_problems, Vec::new());
|
||||
assert_eq!(loaded_module.type_problems, Vec::new());
|
||||
|
||||
let num_decls = loaded_module.declarations.len();
|
||||
let mut num_decls = 0;
|
||||
|
||||
for decl in loaded_module.declarations_by_id.remove(&home).unwrap() {
|
||||
num_decls += 1;
|
||||
|
||||
for decl in loaded_module.declarations {
|
||||
match decl {
|
||||
Declare(def) => expect_def(
|
||||
&loaded_module.interns,
|
||||
|
@ -130,14 +132,17 @@ mod test_uniq_load {
|
|||
subs_by_module,
|
||||
)
|
||||
.await;
|
||||
let loaded_module = loaded.expect("Test module failed to load");
|
||||
|
||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
||||
|
||||
assert_eq!(loaded_module.can_problems, Vec::new());
|
||||
assert_eq!(loaded_module.type_problems, Vec::new());
|
||||
|
||||
let def_count: usize = loaded_module
|
||||
.declarations
|
||||
.iter()
|
||||
.declarations_by_id
|
||||
.remove(&loaded_module.module_id)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|decl| decl.def_count())
|
||||
.sum();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#![allow(clippy::large_enum_variant)]
|
||||
|
||||
pub mod ident;
|
||||
pub mod operator;
|
||||
pub mod symbol;
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -27,7 +27,8 @@ pub struct Proc<'a> {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, Default)]
|
||||
pub struct Procs<'a> {
|
||||
user_defined: MutMap<Symbol, PartialProc<'a>>,
|
||||
pub user_defined: MutMap<Symbol, PartialProc<'a>>,
|
||||
pub module_thunks: MutSet<Symbol>,
|
||||
anonymous: MutMap<Symbol, Option<Proc<'a>>>,
|
||||
specializations: MutMap<ContentHash, (Symbol, Option<Proc<'a>>)>,
|
||||
builtin: MutSet<Symbol>,
|
||||
|
@ -42,6 +43,66 @@ impl<'a> Procs<'a> {
|
|||
self.anonymous.insert(symbol, proc);
|
||||
}
|
||||
|
||||
pub fn insert_closure(
|
||||
&mut self,
|
||||
env: &mut Env<'a, '_>,
|
||||
name: Option<Symbol>,
|
||||
annotation: Variable,
|
||||
loc_args: std::vec::Vec<(Variable, Located<roc_can::pattern::Pattern>)>,
|
||||
loc_body: Located<roc_can::expr::Expr>,
|
||||
ret_var: Variable,
|
||||
) -> Symbol {
|
||||
// turn record/tag patterns into a when expression, e.g.
|
||||
//
|
||||
// foo = \{ x } -> body
|
||||
//
|
||||
// becomes
|
||||
//
|
||||
// foo = \r -> when r is { x } -> body
|
||||
//
|
||||
// conversion of one-pattern when expressions will do the most optimal thing
|
||||
|
||||
let (arg_vars, arg_symbols, body) = patterns_to_when(env, loc_args, ret_var, loc_body);
|
||||
|
||||
match name {
|
||||
Some(symbol) => {
|
||||
// a named closure
|
||||
self.insert_user_defined(
|
||||
symbol,
|
||||
PartialProc {
|
||||
annotation,
|
||||
patterns: arg_symbols,
|
||||
body: body.value,
|
||||
},
|
||||
);
|
||||
|
||||
symbol
|
||||
}
|
||||
None => {
|
||||
// an anonymous closure. These will always be specialized already
|
||||
// by the surrounding context
|
||||
let symbol = env.fresh_symbol();
|
||||
|
||||
let opt_proc = specialize_proc_body(
|
||||
env,
|
||||
self,
|
||||
annotation,
|
||||
ret_var,
|
||||
symbol,
|
||||
&arg_vars,
|
||||
&arg_symbols,
|
||||
annotation,
|
||||
body.value,
|
||||
)
|
||||
.ok();
|
||||
|
||||
self.insert_anonymous(symbol, opt_proc);
|
||||
|
||||
symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_specialization(
|
||||
&mut self,
|
||||
hash: ContentHash,
|
||||
|
@ -96,8 +157,8 @@ pub struct Env<'a, 'i> {
|
|||
pub home: ModuleId,
|
||||
pub ident_ids: &'i mut IdentIds,
|
||||
pub pointer_size: u32,
|
||||
symbol_counter: usize,
|
||||
pub jump_counter: &'a mut u64,
|
||||
pub symbol_counter: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'i> Env<'a, 'i> {
|
||||
|
@ -203,27 +264,11 @@ pub enum MonoProblem {
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
impl<'a> Expr<'a> {
|
||||
pub fn new(
|
||||
arena: &'a Bump,
|
||||
subs: &'a mut Subs,
|
||||
problems: &mut std::vec::Vec<MonoProblem>,
|
||||
env: &mut Env<'a, '_>,
|
||||
can_expr: roc_can::expr::Expr,
|
||||
procs: &mut Procs<'a>,
|
||||
home: ModuleId,
|
||||
ident_ids: &mut IdentIds,
|
||||
pointer_size: u32,
|
||||
) -> Self {
|
||||
let mut env = Env {
|
||||
arena,
|
||||
subs,
|
||||
problems,
|
||||
home,
|
||||
ident_ids,
|
||||
pointer_size,
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
|
||||
from_can(&mut env, can_expr, procs, None)
|
||||
from_can(env, can_expr, procs, None)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,61 +471,24 @@ fn from_can<'a>(
|
|||
Int(_, num) => Expr::Int(num),
|
||||
Float(_, num) => Expr::Float(num),
|
||||
Str(string) | BlockStr(string) => Expr::Str(env.arena.alloc(string)),
|
||||
Var(symbol) => Expr::Load(symbol),
|
||||
Var(symbol) => {
|
||||
if procs.module_thunks.contains(&symbol) {
|
||||
let partial_proc = procs.get_user_defined(symbol).unwrap();
|
||||
let fn_var = partial_proc.annotation;
|
||||
let ret_var = partial_proc.annotation;
|
||||
|
||||
// This is a top-level declaration, which will code gen to a 0-arity thunk.
|
||||
call_by_name(env, procs, fn_var, ret_var, symbol, std::vec::Vec::new())
|
||||
} else {
|
||||
Expr::Load(symbol)
|
||||
}
|
||||
}
|
||||
LetRec(defs, ret_expr, _, _) => from_can_defs(env, defs, *ret_expr, procs),
|
||||
LetNonRec(def, ret_expr, _, _) => from_can_defs(env, vec![*def], *ret_expr, procs),
|
||||
|
||||
Closure(annotation, _, _, loc_args, boxed_body) => {
|
||||
let (loc_body, ret_var) = *boxed_body;
|
||||
|
||||
// turn record/tag patterns into a when expression, e.g.
|
||||
//
|
||||
// foo = \{ x } -> body
|
||||
//
|
||||
// becomes
|
||||
//
|
||||
// foo = \r -> when r is { x } -> body
|
||||
//
|
||||
// conversion of one-pattern when expressions will do the most optimal thing
|
||||
|
||||
let (arg_vars, arg_symbols, body) = patterns_to_when(env, loc_args, ret_var, loc_body);
|
||||
|
||||
let symbol = match name {
|
||||
Some(symbol) => {
|
||||
// a named closure
|
||||
procs.insert_user_defined(
|
||||
symbol,
|
||||
PartialProc {
|
||||
annotation,
|
||||
patterns: arg_symbols,
|
||||
body: body.value,
|
||||
},
|
||||
);
|
||||
symbol
|
||||
}
|
||||
None => {
|
||||
// an anonymous closure. These will always be specialized already
|
||||
// by the surrounding context
|
||||
let symbol = env.fresh_symbol();
|
||||
|
||||
let opt_proc = specialize_proc_body(
|
||||
env,
|
||||
procs,
|
||||
annotation,
|
||||
ret_var,
|
||||
symbol,
|
||||
&arg_vars,
|
||||
&arg_symbols,
|
||||
annotation,
|
||||
body.value,
|
||||
)
|
||||
.ok();
|
||||
|
||||
procs.insert_anonymous(symbol, opt_proc);
|
||||
|
||||
symbol
|
||||
}
|
||||
};
|
||||
let symbol = procs.insert_closure(env, name, annotation, loc_args, loc_body, ret_var);
|
||||
|
||||
Expr::FunctionPointer(symbol)
|
||||
}
|
||||
|
|
|
@ -53,16 +53,17 @@ mod test_mono {
|
|||
|
||||
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
|
||||
let mut mono_problems = Vec::new();
|
||||
let mono_expr = Expr::new(
|
||||
&arena,
|
||||
&mut subs,
|
||||
&mut mono_problems,
|
||||
loc_expr.value,
|
||||
&mut procs,
|
||||
let mut mono_env = roc_mono::expr::Env {
|
||||
arena: &arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
&mut ident_ids,
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size,
|
||||
);
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
let mono_expr = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns
|
||||
interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
|
|
@ -42,16 +42,17 @@ mod test_opt {
|
|||
|
||||
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
|
||||
let mut mono_problems = Vec::new();
|
||||
let mono_expr = Expr::new(
|
||||
&arena,
|
||||
&mut subs,
|
||||
&mut mono_problems,
|
||||
loc_expr.value,
|
||||
&mut procs,
|
||||
let mut mono_env = roc_mono::expr::Env {
|
||||
arena: &arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
&mut ident_ids,
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size,
|
||||
);
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
let mono_expr = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
let unexpected_calls = extract_named_calls(&mono_expr, &mut calls);
|
||||
let expected = CallProblems::default();
|
||||
|
@ -193,16 +194,17 @@ mod test_opt {
|
|||
|
||||
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
|
||||
let mut mono_problems = Vec::new();
|
||||
let mono_expr = Expr::new(
|
||||
&arena,
|
||||
&mut subs,
|
||||
&mut mono_problems,
|
||||
loc_expr.value,
|
||||
&mut procs,
|
||||
let mut mono_env = roc_mono::expr::Env {
|
||||
arena: &arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
&mut ident_ids,
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size,
|
||||
);
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
let mono_expr = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
assert_eq!(mono_expr, expected);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use crate::header::ModuleName;
|
||||
use crate::ident::Ident;
|
||||
use crate::operator::CalledVia;
|
||||
use crate::operator::{BinOp, UnaryOp};
|
||||
use bumpalo::collections::String;
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_module::operator::{BinOp, CalledVia, UnaryOp};
|
||||
use roc_region::all::{Loc, Region};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
|
@ -7,7 +7,6 @@ use crate::blankspace::{
|
|||
use crate::ident::{global_tag_or_ident, ident, lowercase_ident, Ident};
|
||||
use crate::keyword;
|
||||
use crate::number_literal::number_literal;
|
||||
use crate::operator::{BinOp, CalledVia, UnaryOp};
|
||||
use crate::parser::{
|
||||
self, allocated, char, fail, not, not_followed_by, optional, sep_by1, string, then, unexpected,
|
||||
unexpected_eof, Either, Fail, FailReason, ParseResult, Parser, State,
|
||||
|
@ -16,6 +15,7 @@ use crate::type_annotation;
|
|||
use bumpalo::collections::string::String;
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_module::operator::{BinOp, CalledVia, UnaryOp};
|
||||
use roc_region::all::{Located, Region};
|
||||
|
||||
pub fn expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>> {
|
||||
|
|
|
@ -21,7 +21,6 @@ pub mod ident;
|
|||
pub mod keyword;
|
||||
pub mod module;
|
||||
pub mod number_literal;
|
||||
pub mod operator;
|
||||
pub mod pattern;
|
||||
pub mod problems;
|
||||
pub mod string_literal;
|
||||
|
|
|
@ -18,6 +18,8 @@ mod test_parse {
|
|||
use crate::helpers::parse_with;
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::{self, Bump};
|
||||
use roc_module::operator::BinOp::*;
|
||||
use roc_module::operator::{CalledVia, UnaryOp};
|
||||
use roc_parse::ast::AssignedField::*;
|
||||
use roc_parse::ast::CommentOrNewline::*;
|
||||
use roc_parse::ast::Expr::{self, *};
|
||||
|
@ -27,9 +29,6 @@ mod test_parse {
|
|||
};
|
||||
use roc_parse::header::ModuleName;
|
||||
use roc_parse::module::{interface_header, module_defs};
|
||||
use roc_parse::operator::BinOp::*;
|
||||
use roc_parse::operator::CalledVia;
|
||||
use roc_parse::operator::UnaryOp;
|
||||
use roc_parse::parser::{Fail, FailReason, Parser, State};
|
||||
use roc_region::all::{Located, Region};
|
||||
use std::{f64, i64};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use inlinable_string::InlinableString;
|
||||
use roc_collections::all::MutSet;
|
||||
use roc_module::ident::{Ident, Lowercase, TagName};
|
||||
use roc_module::operator::BinOp;
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
use roc_parse::operator::BinOp;
|
||||
use roc_parse::pattern::PatternType;
|
||||
use roc_region::all::{Located, Region};
|
||||
|
||||
|
|
|
@ -299,7 +299,7 @@ impl<'a> RocDocAllocator<'a> {
|
|||
|
||||
pub fn binop(
|
||||
&'a self,
|
||||
content: roc_parse::operator::BinOp,
|
||||
content: roc_module::operator::BinOp,
|
||||
) -> DocBuilder<'a, Self, Annotation> {
|
||||
self.text(content.to_string()).annotate(Annotation::BinOp)
|
||||
}
|
||||
|
|
|
@ -90,16 +90,17 @@ mod test_reporting {
|
|||
let pointer_size = std::mem::size_of::<u64>() as u32;
|
||||
|
||||
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
|
||||
let _mono_expr = Expr::new(
|
||||
&arena,
|
||||
&mut subs,
|
||||
&mut mono_problems,
|
||||
loc_expr.value,
|
||||
&mut procs,
|
||||
let mut mono_env = roc_mono::expr::Env {
|
||||
arena: &arena,
|
||||
subs: &mut subs,
|
||||
problems: &mut mono_problems,
|
||||
home,
|
||||
&mut ident_ids,
|
||||
ident_ids: &mut ident_ids,
|
||||
pointer_size,
|
||||
);
|
||||
symbol_counter: 0,
|
||||
jump_counter: arena.alloc(0),
|
||||
};
|
||||
let _mono_expr = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
}
|
||||
|
||||
Ok((unify_problems, can_problems, mono_problems, home, interns))
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
app Hello provides [ main ] imports []
|
||||
|
||||
main = "Hello, World!"
|
||||
greeting =
|
||||
hi = "Hello, World!"
|
||||
|
||||
hi
|
||||
|
||||
main = greeting
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue