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 std::path::{Path, PathBuf};
use target_lexicon::{Architecture, OperatingSystem, Triple, Vendor}; 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 this should probably use more helper functions
// TODO make this polymorphic in the llvm functions so it can be reused for another backend. // TODO make this polymorphic in the llvm functions so it can be reused for another backend.
#[allow(clippy::cognitive_complexity)] #[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::*; use roc_can::pattern::Pattern::*;
match decl { match decl {
Declare(def) => match def.loc_pattern.value { Declare(def) | Builtin(def) => match def.loc_pattern.value {
Identifier(symbol) => { Identifier(symbol) => {
match def.loc_expr.value { match def.loc_expr.value {
Closure(annotation, _, _, loc_args, boxed_body) => { Closure(annotation, _, _, loc_args, boxed_body) => {

View File

@ -91,6 +91,7 @@ pub enum Declaration {
Vec<Located<Ident>>, Vec<Located<Ident>>,
Vec<(Region /* pattern */, Region /* expr */)>, Vec<(Region /* pattern */, Region /* expr */)>,
), ),
Builtin(Def),
} }
impl Declaration { impl Declaration {
@ -100,6 +101,7 @@ impl Declaration {
Declare(_) => 1, Declare(_) => 1,
DeclareRec(defs) => defs.len(), DeclareRec(defs) => defs.len(),
InvalidCycle(_, _) => 0, InvalidCycle(_, _) => 0,
Builtin(_) => 0,
} }
} }
} }
@ -1249,6 +1251,10 @@ fn decl_to_let(
Declaration::InvalidCycle(symbols, regions) => { Declaration::InvalidCycle(symbols, regions) => {
Expr::RuntimeError(RuntimeError::CircularDef(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) => { (Ok(declarations), output) => {
use crate::def::Declaration::*; use crate::def::Declaration::*;
// Record the variables for all exposed symbols.
let mut exposed_vars_by_symbol = Vec::with_capacity(exposed_symbols.len()); let mut exposed_vars_by_symbol = Vec::with_capacity(exposed_symbols.len());
for decl in declarations.iter() { for decl in declarations.iter() {
@ -193,6 +194,14 @@ pub fn canonicalize_module_defs<'a>(
InvalidCycle(identifiers, _) => { InvalidCycle(identifiers, _) => {
panic!("TODO gracefully handle potentially attempting to expose invalid cyclic defs {:?}" , 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() { for decl in decls.iter().rev() {
// NOTE: rigids are empty because they are not shared between top-level definitions // NOTE: rigids are empty because they are not shared between top-level definitions
match decl { match decl {
Declaration::Declare(def) => { Declaration::Declare(def) | Declaration::Builtin(def) => {
constraint = exists_with_aliases( constraint = exists_with_aliases(
aliases.clone(), aliases.clone(),
Vec::new(), Vec::new(),

View File

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

View File

@ -19,7 +19,15 @@ mod gen_module {
use inkwell::passes::PassManager; use inkwell::passes::PassManager;
use inkwell::types::BasicType; use inkwell::types::BasicType;
use inkwell::OptimizationLevel; 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_collections::all::{ImMap, MutMap, MutSet};
use roc_gen::llvm::build::{build_proc, build_proc_header}; use roc_gen::llvm::build::{build_proc, build_proc_header};
use roc_gen::llvm::convert::basic_type_from_layout; 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::blankspace::space0_before;
use roc_parse::parser::{self, loc, Parser}; use roc_parse::parser::{self, loc, Parser};
use roc_region::all::{Located, Region}; 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"; static TEST_MODULE_NAME: &str = "Test";
@ -72,7 +81,10 @@ mod gen_module {
region: Region::zero(), region: Region::zero(),
value: main_pattern, 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 loc_defs = bumpalo::vec![in arena; loc_def];
let module_ids = ModuleIds::default(); let module_ids = ModuleIds::default();
let home: ModuleId = module_ids.get_or_insert(&TEST_MODULE_NAME.into()); 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()); exposed_ident_ids.add(main_fn_name.into());
// Canonicalize the module. // Canonicalize the module.
let module_output = canonicalize_module_defs( let mut module_output = canonicalize_module_defs(
arena, arena,
loc_defs, loc_defs,
home, home,
module_ids, &module_ids,
exposed_ident_ids, exposed_ident_ids,
dep_idents, dep_idents,
exposed_imports, exposed_imports,
@ -98,9 +110,26 @@ mod gen_module {
) )
.expect("Error canonicalizing test 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 monomorphize the module
// TODO code gen the module // TODO code gen the module
@ -119,24 +148,6 @@ mod gen_module {
&loc_expr.value, &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 { let loc_expr = Located {
region: loc_expr.region, region: loc_expr.region,
value: with_builtins, value: with_builtins,

View File

@ -67,6 +67,8 @@ impl<'a> Procs<'a> {
self.add_pending_specialization(name, layout.clone(), pending); 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 // a named closure
self.partial_procs.insert( self.partial_procs.insert(
name, name,