This commit is contained in:
Richard Feldman 2020-06-06 23:41:12 -04:00
parent 9e02537ebb
commit 0a9989e75f
7 changed files with 61 additions and 30 deletions

View File

@ -21,6 +21,7 @@ use inkwell::targets::{
use std::path::{Path, PathBuf};
use target_lexicon::{Architecture, OperatingSystem, Triple, Vendor};
// TODO how should imported modules factor into this? What if those use builtins too?
// TODO this should probably use more helper functions
// TODO make this polymorphic in the llvm functions so it can be reused for another backend.
#[allow(clippy::cognitive_complexity)]
@ -110,7 +111,9 @@ pub fn build(
}
}
}
InvalidCycle(_, _) => {}
InvalidCycle(_, _) | Builtin(_) => {
// These can never contain main.
}
}
}
@ -181,7 +184,7 @@ pub fn build(
use roc_can::pattern::Pattern::*;
match decl {
Declare(def) => match def.loc_pattern.value {
Declare(def) | Builtin(def) => match def.loc_pattern.value {
Identifier(symbol) => {
match def.loc_expr.value {
Closure(annotation, _, _, loc_args, boxed_body) => {

View File

@ -91,6 +91,7 @@ pub enum Declaration {
Vec<Located<Ident>>,
Vec<(Region /* pattern */, Region /* expr */)>,
),
Builtin(Def),
}
impl Declaration {
@ -100,6 +101,7 @@ impl Declaration {
Declare(_) => 1,
DeclareRec(defs) => defs.len(),
InvalidCycle(_, _) => 0,
Builtin(_) => 0,
}
}
}
@ -1249,6 +1251,10 @@ fn decl_to_let(
Declaration::InvalidCycle(symbols, regions) => {
Expr::RuntimeError(RuntimeError::CircularDef(symbols, regions))
}
Declaration::Builtin(_) => {
// Builtins should only be added to top-level decls, not to let-exprs!
unreachable!()
}
}
}

View File

@ -151,6 +151,7 @@ pub fn canonicalize_module_defs<'a>(
(Ok(declarations), output) => {
use crate::def::Declaration::*;
// Record the variables for all exposed symbols.
let mut exposed_vars_by_symbol = Vec::with_capacity(exposed_symbols.len());
for decl in declarations.iter() {
@ -193,6 +194,14 @@ pub fn canonicalize_module_defs<'a>(
InvalidCycle(identifiers, _) => {
panic!("TODO gracefully handle potentially attempting to expose invalid cyclic defs {:?}" , identifiers);
}
Builtin(def) => {
// Builtins cannot be exposed in module declarations.
// This should never happen!
debug_assert!(def
.pattern_vars
.iter()
.all(|(symbol, _)| !exposed_symbols.contains(symbol)));
}
}
}

View File

@ -880,7 +880,7 @@ pub fn constrain_decls(
for decl in decls.iter().rev() {
// NOTE: rigids are empty because they are not shared between top-level definitions
match decl {
Declaration::Declare(def) => {
Declaration::Declare(def) | Declaration::Builtin(def) => {
constraint = exists_with_aliases(
aliases.clone(),
Vec::new(),

View File

@ -70,7 +70,7 @@ pub fn constrain_decls(
for decl in decls.iter().rev() {
// NOTE: rigids are empty because they are not shared between top-level definitions
match decl {
Declaration::Declare(def) => {
Declaration::Declare(def) | Declaration::Builtin(def) => {
sharing::annotate_usage(&def.loc_expr.value, &mut var_usage);
}
Declaration::DeclareRec(defs) => {
@ -87,7 +87,7 @@ pub fn constrain_decls(
for decl in decls.iter().rev() {
// NOTE: rigids are empty because they are not shared between top-level definitions
match decl {
Declaration::Declare(def) => {
Declaration::Declare(def) | Declaration::Builtin(def) => {
constraint = exists_with_aliases(
aliases.clone(),
Vec::new(),

View File

@ -19,7 +19,15 @@ mod gen_module {
use inkwell::passes::PassManager;
use inkwell::types::BasicType;
use inkwell::OptimizationLevel;
use roc_can::{canonicalize_module_defs, operator};
use roc_can::{
builtins::builtin_defs,
def::Declaration,
expected::Expected,
expr::{canonicalize_expr, Env},
module::canonicalize_module_defs,
operator,
scope::Scope,
};
use roc_collections::all::{ImMap, MutMap, MutSet};
use roc_gen::llvm::build::{build_proc, build_proc_header};
use roc_gen::llvm::convert::basic_type_from_layout;
@ -30,7 +38,8 @@ mod gen_module {
use roc_parse::blankspace::space0_before;
use roc_parse::parser::{self, loc, Parser};
use roc_region::all::{Located, Region};
use roc_types::subs::{Content, Subs, VarStore, Variable};
use roc_types::subs::{Subs, VarStore};
use roc_types::types::Type;
static TEST_MODULE_NAME: &str = "Test";
@ -72,7 +81,10 @@ mod gen_module {
region: Region::zero(),
value: main_pattern,
};
let loc_def = ast::Def::Body(&loc_main_pattern, &loc_expr);
let loc_def = Located {
region: Region::zero(),
value: ast::Def::Body(&loc_main_pattern, &loc_expr),
};
let loc_defs = bumpalo::vec![in arena; loc_def];
let module_ids = ModuleIds::default();
let home: ModuleId = module_ids.get_or_insert(&TEST_MODULE_NAME.into());
@ -85,11 +97,11 @@ mod gen_module {
exposed_ident_ids.add(main_fn_name.into());
// Canonicalize the module.
let module_output = canonicalize_module_defs(
let mut module_output = canonicalize_module_defs(
arena,
loc_defs,
home,
module_ids,
&module_ids,
exposed_ident_ids,
dep_idents,
exposed_imports,
@ -98,9 +110,26 @@ mod gen_module {
)
.expect("Error canonicalizing test module");
// TODO add the builtins as separate (unexposed) Declarations to the module
// Add the builtins as Declarations to the module.
let module_output = {
let builtins = builtin_defs(&var_store);
let decls = &mut module_output.declarations;
let references = module_output.references;
// TODO type-check the module
decls.reserve(builtins.len());
for (symbol, builtin_def) in builtins.into_iter() {
// Only add decls for builtins that were actually referenced.
if references.contains(&symbol) {
decls.push(Declaration::Builtin(builtin_def));
}
}
// Release the borrows on declarations and references
module_output
};
// TODO type-check the module, making sure to use builtin types from std.rs/unique.rs
// TODO monomorphize the module
// TODO code gen the module
@ -119,24 +148,6 @@ mod gen_module {
&loc_expr.value,
);
let mut with_builtins = loc_expr.value;
// Add builtin defs (e.g. List.get) directly to the canonical Expr,
// since we aren't using modules here.
let builtin_defs = roc_can::builtins::builtin_defs(&var_store);
for def in builtin_defs {
with_builtins = Expr::LetNonRec(
Box::new(def),
Box::new(Located {
region: Region::zero(),
value: with_builtins,
}),
var_store.fresh(),
SendMap::default(),
);
}
let loc_expr = Located {
region: loc_expr.region,
value: with_builtins,

View File

@ -67,6 +67,8 @@ impl<'a> Procs<'a> {
self.add_pending_specialization(name, layout.clone(), pending);
debug_assert!(!self.partial_procs.contains_key(&name), "Procs was told to insert a value for key {:?}, but there was already an entry for that key! Procs should never attempt to insert duplicates.", name);
// a named closure
self.partial_procs.insert(
name,