wip canonical builtins in modules

This commit is contained in:
Richard Feldman 2020-04-30 20:31:36 -04:00
parent dd3dc45b7a
commit a1750567ff
4 changed files with 63 additions and 26 deletions

View file

@ -307,12 +307,15 @@ fn gen(
let loc_expr = main_expr.unwrap_or_else(|| { let loc_expr = main_expr.unwrap_or_else(|| {
panic!("TODO gracefully handle the case where `main` was declared but not exposed") panic!("TODO gracefully handle the case where `main` was declared but not exposed")
}); });
let mut subs = loaded.solved.into_inner(); let mut subs = loaded.solved.into_inner();
let content = match main_var { let content = match main_var {
Some(var) => subs.get_without_compacting(var).content, Some(var) => subs.get_without_compacting(var).content,
None => todo!("TODO gracefully handle the case where `main` was declared but not exposed"), None => todo!("TODO gracefully handle the case where `main` was declared but not exposed"),
}; };
todo!("step 1. mono-module, step 2. actually have main here use the loaded builtin modules!");
// Generate the binary // Generate the binary
let context = Context::create(); let context = Context::create();

View file

@ -1,13 +1,27 @@
use crate::def::Def; use crate::def::{Declaration, Def};
use crate::expr::Expr; use crate::expr::{Expr, Recursive};
use crate::expr::Recursive; use roc_collections::all::{MutMap, MutSet, SendMap};
use roc_collections::all::SendMap;
use roc_module::ident::TagName; use roc_module::ident::TagName;
use roc_module::symbol::Symbol; use roc_module::symbol::{ModuleId, Symbol};
use roc_parse::operator::CalledVia; use roc_parse::operator::CalledVia;
use roc_region::all::{Located, Region}; use roc_region::all::{Located, Region};
use roc_types::subs::{VarStore, Variable}; use roc_types::subs::{VarStore, Variable};
fn exposed_symbols() -> MutMap<ModuleId, MutSet<Symbol>> {
let mut all = MutMap::default(); // TODO use with_capacity_and_hasher here
all.insert(ModuleId::LIST, {
let mut set = MutSet::default(); // TODO use with_capacity_and_hasher here
set.insert(Symbol::LIST_GET);
set.insert(Symbol::LIST_FIRST);
set
});
all
}
/// Some builtins cannot be constructed in code gen alone, and need to be defined /// Some builtins cannot be constructed in code gen alone, and need to be defined
/// as separate Roc defs. For example, List.get has this type: /// as separate Roc defs. For example, List.get has this type:
/// ///
@ -25,16 +39,24 @@ use roc_types::subs::{VarStore, Variable};
/// delegates to the compiler-internal List.getUnsafe function to do the actual /// delegates to the compiler-internal List.getUnsafe function to do the actual
/// lookup (if the bounds check passed). That internal function is hardcoded in code gen, /// lookup (if the bounds check passed). That internal function is hardcoded in code gen,
/// which works fine because it doesn't involve any open tag unions. /// which works fine because it doesn't involve any open tag unions.
pub fn builtin_defs(var_store: &VarStore) -> Vec<Def> { pub fn declarations_by_id() -> MutMap<ModuleId, Vec<Declaration>> {
vec![ let var_store = VarStore::default();
list_get(var_store), let mut decls = MutMap::default(); // TODO use with_capacity_and_hasher here
list_first(var_store),
int_div(var_store), decls.insert(
] ModuleId::LIST,
vec![
list_get(&var_store),
list_first(&var_store),
int_div(&var_store),
],
);
decls
} }
/// List.get : List elem, Int -> Result elem [ OutOfBounds ]* /// List.get : List elem, Int -> Result elem [ OutOfBounds ]*
fn list_get(var_store: &VarStore) -> Def { fn list_get(var_store: &VarStore) -> Declaration {
use crate::expr::Expr::*; use crate::expr::Expr::*;
defn( defn(
@ -105,7 +127,7 @@ fn list_get(var_store: &VarStore) -> Def {
} }
/// Int.div : Int, Int -> Result Int [ DivByZero ]* /// Int.div : Int, Int -> Result Int [ DivByZero ]*
fn int_div(var_store: &VarStore) -> Def { fn int_div(var_store: &VarStore) -> Declaration {
use crate::expr::Expr::*; use crate::expr::Expr::*;
use crate::pattern::Pattern::*; use crate::pattern::Pattern::*;
@ -174,17 +196,17 @@ fn int_div(var_store: &VarStore) -> Def {
Box::new((no_region(body), var_store.fresh())), Box::new((no_region(body), var_store.fresh())),
); );
Def { Declare(Def {
loc_pattern: no_region(Identifier(Symbol::INT_DIV)), loc_pattern: no_region(Identifier(Symbol::INT_DIV)),
loc_expr: no_region(expr), loc_expr: no_region(expr),
expr_var: var_store.fresh(), expr_var: var_store.fresh(),
pattern_vars: SendMap::default(), pattern_vars: SendMap::default(),
annotation: None, annotation: None,
} })
} }
/// List.first : List elem -> Result elem [ ListWasEmpty ]* /// List.first : List elem -> Result elem [ ListWasEmpty ]*
fn list_first(var_store: &VarStore) -> Def { fn list_first(var_store: &VarStore) -> Declaration {
use crate::expr::Expr::*; use crate::expr::Expr::*;
defn( defn(
@ -276,7 +298,7 @@ fn call(symbol: Symbol, args: Vec<Expr>, var_store: &VarStore) -> Expr {
} }
#[inline(always)] #[inline(always)]
fn defn(fn_name: Symbol, args: Vec<Symbol>, var_store: &VarStore, body: Expr) -> Def { fn defn(fn_name: Symbol, args: Vec<Symbol>, var_store: &VarStore, body: Expr) -> Declaration {
use crate::expr::Expr::*; use crate::expr::Expr::*;
use crate::pattern::Pattern::*; use crate::pattern::Pattern::*;
@ -293,11 +315,11 @@ fn defn(fn_name: Symbol, args: Vec<Symbol>, var_store: &VarStore, body: Expr) ->
Box::new((no_region(body), var_store.fresh())), Box::new((no_region(body), var_store.fresh())),
); );
Def { Declaration::Declare(Def {
loc_pattern: no_region(Identifier(fn_name)), loc_pattern: no_region(Identifier(fn_name)),
loc_expr: no_region(expr), loc_expr: no_region(expr),
expr_var: var_store.fresh(), expr_var: var_store.fresh(),
pattern_vars: SendMap::default(), pattern_vars: SendMap::default(),
annotation: None, annotation: None,
} })
} }

View file

@ -193,8 +193,7 @@ pub async fn load<'a>(
loading_started.insert(root_id); loading_started.insert(root_id);
// The declarations we'll ultimately be returning // The declarations we'll ultimately be returning
let mut declarations_by_id: MutMap<ModuleId, Vec<Declaration>> = MutMap::default(); let mut declarations_by_id: MutMap<ModuleId, Vec<Declaration>> = roc_can::builtins::declarations_by_id();
let mut exposed_symbols_by_module: MutMap<ModuleId, MutSet<Symbol>> = MutMap::default(); let mut exposed_symbols_by_module: MutMap<ModuleId, MutSet<Symbol>> = MutMap::default();
// Modules which are waiting for certain headers to be parsed // Modules which are waiting for certain headers to be parsed
@ -469,8 +468,11 @@ pub async fn load<'a>(
stdlib, stdlib,
); );
for _unused_module_id in unused_modules.iter() { for unused_module_id in unused_modules.iter() {
panic!("TODO gracefully report unused imports for {:?}, namely {:?}", home, unused_modules); // Never report builtin modules as unused
if !unused_module_id.is_builtin() {
todo!("TODO gracefully report unused imports for {:?}, namely {:?}", home, unused_modules);
}
} }
} }
} }
@ -581,7 +583,7 @@ fn send_header<'a>(
// If it isn't, report a problem! // If it isn't, report a problem!
let mut imported: Vec<(ModuleName, Vec<Ident>, Region)> = Vec::with_capacity(imports.len()); let mut imported: Vec<(ModuleName, Vec<Ident>, Region)> = Vec::with_capacity(imports.len());
let mut imported_modules: MutSet<ModuleId> = MutSet::default(); let mut imported_modules: MutSet<ModuleId> = ModuleId::default_imports();
let mut scope_size = 0; let mut scope_size = 0;
for loc_entry in imports { for loc_entry in imports {

View file

@ -1,8 +1,8 @@
use crate::ident::Ident; use crate::ident::Ident;
use inlinable_string::InlinableString; use inlinable_string::InlinableString;
use roc_collections::all::{default_hasher, ImMap, MutMap}; use roc_collections::all::{default_hasher, ImMap, MutMap, MutSet};
use roc_region::all::Region; use roc_region::all::Region;
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::{fmt, u32}; use std::{fmt, u32};
// TODO: benchmark this as { ident_id: u32, module_id: u32 } and see if perf stays the same // TODO: benchmark this as { ident_id: u32, module_id: u32 } and see if perf stays the same
@ -496,6 +496,16 @@ macro_rules! define_builtins {
self.0 < $total self.0 < $total
} }
pub fn default_imports() -> MutSet<ModuleId> {
let mut all = HashSet::with_capacity_and_hasher($total, default_hasher());
$(
all.insert(ModuleId($module_id));
)+
all
}
$( $(
pub const $module_const: ModuleId = ModuleId($module_id); pub const $module_const: ModuleId = ModuleId($module_id);
)+ )+