mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-10 10:02:38 +03:00
wip
This commit is contained in:
parent
9e02537ebb
commit
0a9989e75f
@ -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) => {
|
||||||
|
@ -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!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
|
@ -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(),
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user