mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Merge remote-tracking branch 'origin/trunk' into single-quote-literal
This commit is contained in:
commit
f7c0e2ef19
634 changed files with 47014 additions and 21117 deletions
|
@ -1,4 +1,5 @@
|
|||
use crate::def::{canonicalize_defs, sort_can_defs, Declaration, Def};
|
||||
use crate::effect_module::HostedGeneratedFunctions;
|
||||
use crate::env::Env;
|
||||
use crate::expr::{ClosureData, Expr, Output};
|
||||
use crate::operator::desugar_def;
|
||||
|
@ -6,15 +7,16 @@ use crate::pattern::Pattern;
|
|||
use crate::scope::Scope;
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::all::{MutMap, MutSet, SendMap};
|
||||
use roc_module::ident::Ident;
|
||||
use roc_module::ident::Lowercase;
|
||||
use roc_module::ident::{Ident, TagName};
|
||||
use roc_module::symbol::{IdentIds, ModuleId, ModuleIds, Symbol};
|
||||
use roc_parse::ast;
|
||||
use roc_parse::header::HeaderFor;
|
||||
use roc_parse::pattern::PatternType;
|
||||
use roc_problem::can::{Problem, RuntimeError};
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_types::subs::{VarStore, Variable};
|
||||
use roc_types::types::Alias;
|
||||
use roc_types::types::{Alias, AliasKind, Type};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Module {
|
||||
|
@ -39,11 +41,36 @@ pub struct ModuleOutput {
|
|||
pub scope: Scope,
|
||||
}
|
||||
|
||||
fn validate_generate_with<'a>(
|
||||
generate_with: &'a [Loc<roc_parse::header::ExposedName<'a>>],
|
||||
) -> (HostedGeneratedFunctions, Vec<Loc<Ident>>) {
|
||||
let mut functions = HostedGeneratedFunctions::default();
|
||||
let mut unknown = Vec::new();
|
||||
|
||||
for generated in generate_with {
|
||||
match generated.value.as_str() {
|
||||
"after" => functions.after = true,
|
||||
"map" => functions.map = true,
|
||||
"always" => functions.always = true,
|
||||
"loop" => functions.loop_ = true,
|
||||
"forever" => functions.forever = true,
|
||||
other => {
|
||||
// we don't know how to generate this function
|
||||
let ident = Ident::from(other);
|
||||
unknown.push(Loc::at(generated.region, ident));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(functions, unknown)
|
||||
}
|
||||
|
||||
// TODO trim these down
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn canonicalize_module_defs<'a, F>(
|
||||
pub fn canonicalize_module_defs<'a>(
|
||||
arena: &Bump,
|
||||
loc_defs: &'a [Located<ast::Def<'a>>],
|
||||
loc_defs: &'a [Loc<ast::Def<'a>>],
|
||||
header_for: &roc_parse::header::HeaderFor,
|
||||
home: ModuleId,
|
||||
module_ids: &ModuleIds,
|
||||
exposed_ident_ids: IdentIds,
|
||||
|
@ -52,19 +79,76 @@ pub fn canonicalize_module_defs<'a, F>(
|
|||
exposed_imports: MutMap<Ident, (Symbol, Region)>,
|
||||
exposed_symbols: &MutSet<Symbol>,
|
||||
var_store: &mut VarStore,
|
||||
look_up_builtin: F,
|
||||
) -> Result<ModuleOutput, RuntimeError>
|
||||
where
|
||||
F: Fn(Symbol, &mut VarStore) -> Option<Def> + 'static + Send + Copy,
|
||||
{
|
||||
) -> Result<ModuleOutput, RuntimeError> {
|
||||
let mut can_exposed_imports = MutMap::default();
|
||||
let mut scope = Scope::new(home, var_store);
|
||||
let mut env = Env::new(home, dep_idents, module_ids, exposed_ident_ids);
|
||||
let num_deps = dep_idents.len();
|
||||
|
||||
for (name, alias) in aliases.into_iter() {
|
||||
scope.add_alias(name, alias.region, alias.type_variables, alias.typ);
|
||||
scope.add_alias(
|
||||
name,
|
||||
alias.region,
|
||||
alias.type_variables,
|
||||
alias.typ,
|
||||
alias.kind,
|
||||
);
|
||||
}
|
||||
|
||||
struct Hosted {
|
||||
effect_symbol: Symbol,
|
||||
generated_functions: HostedGeneratedFunctions,
|
||||
}
|
||||
|
||||
let hosted_info = if let HeaderFor::Hosted {
|
||||
generates,
|
||||
generates_with,
|
||||
} = header_for
|
||||
{
|
||||
let name: &str = generates.into();
|
||||
let (generated_functions, unknown_generated) = validate_generate_with(generates_with);
|
||||
|
||||
for unknown in unknown_generated {
|
||||
env.problem(Problem::UnknownGeneratesWith(unknown));
|
||||
}
|
||||
|
||||
let effect_symbol = scope
|
||||
.introduce(
|
||||
name.into(),
|
||||
&env.exposed_ident_ids,
|
||||
&mut env.ident_ids,
|
||||
Region::zero(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let effect_tag_name = TagName::Private(effect_symbol);
|
||||
|
||||
{
|
||||
let a_var = var_store.fresh();
|
||||
|
||||
let actual = crate::effect_module::build_effect_actual(
|
||||
effect_tag_name,
|
||||
Type::Variable(a_var),
|
||||
var_store,
|
||||
);
|
||||
|
||||
scope.add_alias(
|
||||
effect_symbol,
|
||||
Region::zero(),
|
||||
vec![Loc::at_zero(("a".into(), a_var))],
|
||||
actual,
|
||||
AliasKind::Structural,
|
||||
);
|
||||
}
|
||||
|
||||
Some(Hosted {
|
||||
effect_symbol,
|
||||
generated_functions,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Desugar operators (convert them to Apply calls, taking into account
|
||||
// operator precedence and associativity rules), before doing other canonicalization.
|
||||
//
|
||||
|
@ -76,13 +160,12 @@ where
|
|||
bumpalo::collections::Vec::with_capacity_in(loc_defs.len() + num_deps, arena);
|
||||
|
||||
for loc_def in loc_defs.iter() {
|
||||
desugared.push(&*arena.alloc(Located {
|
||||
desugared.push(&*arena.alloc(Loc {
|
||||
value: desugar_def(arena, &loc_def.value),
|
||||
region: loc_def.region,
|
||||
}));
|
||||
}
|
||||
|
||||
let mut env = Env::new(home, dep_idents, module_ids, exposed_ident_ids);
|
||||
let mut lookups = Vec::with_capacity(num_deps);
|
||||
let mut rigid_variables = MutMap::default();
|
||||
|
||||
|
@ -124,7 +207,11 @@ where
|
|||
// This is a type alias
|
||||
|
||||
// the symbol should already be added to the scope when this module is canonicalized
|
||||
debug_assert!(scope.contains_alias(symbol));
|
||||
debug_assert!(
|
||||
scope.contains_alias(symbol),
|
||||
"apparently, {:?} is not actually a type alias",
|
||||
symbol
|
||||
);
|
||||
|
||||
// but now we know this symbol by a different identifier, so we still need to add it to
|
||||
// the scope
|
||||
|
@ -139,7 +226,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
let (defs, scope, output, symbols_introduced) = canonicalize_defs(
|
||||
let (defs, mut scope, output, symbols_introduced) = canonicalize_defs(
|
||||
&mut env,
|
||||
Output::default(),
|
||||
var_store,
|
||||
|
@ -181,6 +268,17 @@ where
|
|||
references.insert(*symbol);
|
||||
}
|
||||
|
||||
// add any builtins used by other builtins
|
||||
let transitive_builtins: Vec<Symbol> = references
|
||||
.iter()
|
||||
.filter(|s| s.is_builtin())
|
||||
.map(|s| crate::builtins::builtin_dependencies(*s))
|
||||
.flatten()
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
references.extend(transitive_builtins);
|
||||
|
||||
// NOTE previously we inserted builtin defs into the list of defs here
|
||||
// this is now done later, in file.rs.
|
||||
|
||||
|
@ -193,7 +291,26 @@ where
|
|||
(Ok(mut declarations), output) => {
|
||||
use crate::def::Declaration::*;
|
||||
|
||||
for decl in declarations.iter() {
|
||||
if let Some(Hosted {
|
||||
effect_symbol,
|
||||
generated_functions,
|
||||
}) = hosted_info
|
||||
{
|
||||
let mut exposed_symbols = MutSet::default();
|
||||
|
||||
// NOTE this currently builds all functions, not just the ones that the user requested
|
||||
crate::effect_module::build_effect_builtins(
|
||||
&mut env,
|
||||
&mut scope,
|
||||
effect_symbol,
|
||||
var_store,
|
||||
&mut exposed_symbols,
|
||||
&mut declarations,
|
||||
generated_functions,
|
||||
);
|
||||
}
|
||||
|
||||
for decl in declarations.iter_mut() {
|
||||
match decl {
|
||||
Declare(def) => {
|
||||
for (symbol, _) in def.pattern_vars.iter() {
|
||||
|
@ -206,6 +323,59 @@ where
|
|||
exposed_but_not_defined.remove(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary hack: we don't know exactly what symbols are hosted symbols,
|
||||
// and which are meant to be normal definitions without a body. So for now
|
||||
// we just assume they are hosted functions (meant to be provided by the platform)
|
||||
if let Some(Hosted { effect_symbol, .. }) = hosted_info {
|
||||
macro_rules! make_hosted_def {
|
||||
() => {
|
||||
let symbol = def.pattern_vars.iter().next().unwrap().0;
|
||||
let ident_id = symbol.ident_id();
|
||||
let ident =
|
||||
env.ident_ids.get_name(ident_id).unwrap().to_string();
|
||||
let def_annotation = def.annotation.clone().unwrap();
|
||||
let annotation = crate::annotation::Annotation {
|
||||
typ: def_annotation.signature,
|
||||
introduced_variables: def_annotation.introduced_variables,
|
||||
references: Default::default(),
|
||||
aliases: Default::default(),
|
||||
};
|
||||
|
||||
let hosted_def = crate::effect_module::build_host_exposed_def(
|
||||
&mut env,
|
||||
&mut scope,
|
||||
*symbol,
|
||||
&ident,
|
||||
TagName::Private(effect_symbol),
|
||||
var_store,
|
||||
annotation,
|
||||
);
|
||||
|
||||
*def = hosted_def;
|
||||
};
|
||||
}
|
||||
|
||||
match &def.loc_expr.value {
|
||||
Expr::RuntimeError(RuntimeError::NoImplementationNamed {
|
||||
..
|
||||
}) => {
|
||||
make_hosted_def!();
|
||||
}
|
||||
Expr::Closure(closure_data)
|
||||
if matches!(
|
||||
closure_data.loc_body.value,
|
||||
Expr::RuntimeError(
|
||||
RuntimeError::NoImplementationNamed { .. }
|
||||
)
|
||||
) =>
|
||||
{
|
||||
make_hosted_def!();
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
DeclareRec(defs) => {
|
||||
for def in defs {
|
||||
|
@ -238,6 +408,18 @@ where
|
|||
|
||||
let mut aliases = MutMap::default();
|
||||
|
||||
if let Some(Hosted { effect_symbol, .. }) = hosted_info {
|
||||
// Remove this from exposed_symbols,
|
||||
// so that at the end of the process,
|
||||
// we can see if there were any
|
||||
// exposed symbols which did not have
|
||||
// corresponding defs.
|
||||
exposed_but_not_defined.remove(&effect_symbol);
|
||||
|
||||
let hosted_alias = scope.lookup_alias(effect_symbol).unwrap().clone();
|
||||
aliases.insert(effect_symbol, hosted_alias);
|
||||
}
|
||||
|
||||
for (symbol, alias) in output.aliases {
|
||||
// Remove this from exposed_symbols,
|
||||
// so that at the end of the process,
|
||||
|
@ -263,8 +445,8 @@ where
|
|||
|
||||
let runtime_error = RuntimeError::ExposedButNotDefined(symbol);
|
||||
let def = Def {
|
||||
loc_pattern: Located::new(0, 0, 0, 0, Pattern::Identifier(symbol)),
|
||||
loc_expr: Located::new(0, 0, 0, 0, Expr::RuntimeError(runtime_error)),
|
||||
loc_pattern: Loc::at(Region::zero(), Pattern::Identifier(symbol)),
|
||||
loc_expr: Loc::at(Region::zero(), Expr::RuntimeError(runtime_error)),
|
||||
expr_var: var_store.fresh(),
|
||||
pattern_vars,
|
||||
annotation: None,
|
||||
|
@ -303,7 +485,7 @@ where
|
|||
for symbol in references.iter() {
|
||||
if symbol.is_builtin() {
|
||||
// this can fail when the symbol is for builtin types, or has no implementation yet
|
||||
if let Some(def) = look_up_builtin(*symbol, var_store) {
|
||||
if let Some(def) = crate::builtins::builtin_defs_map(*symbol, var_store) {
|
||||
declarations.push(Declaration::Builtin(def));
|
||||
}
|
||||
}
|
||||
|
@ -361,6 +543,10 @@ fn fix_values_captured_in_closure_pattern(
|
|||
AppliedTag {
|
||||
arguments: loc_args,
|
||||
..
|
||||
}
|
||||
| UnwrappedOpaque {
|
||||
arguments: loc_args,
|
||||
..
|
||||
} => {
|
||||
for (_, loc_arg) in loc_args.iter_mut() {
|
||||
fix_values_captured_in_closure_pattern(&mut loc_arg.value, no_capture_symbols);
|
||||
|
@ -382,15 +568,16 @@ fn fix_values_captured_in_closure_pattern(
|
|||
}
|
||||
}
|
||||
Identifier(_)
|
||||
| NumLiteral(_, _, _)
|
||||
| IntLiteral(_, _, _)
|
||||
| FloatLiteral(_, _, _)
|
||||
| NumLiteral(..)
|
||||
| IntLiteral(..)
|
||||
| FloatLiteral(..)
|
||||
| StrLiteral(_)
|
||||
| SingleQuote(_)
|
||||
| Underscore
|
||||
| Shadowed(_, _)
|
||||
| Shadowed(..)
|
||||
| MalformedPattern(_, _)
|
||||
| UnsupportedPattern(_) => (),
|
||||
| UnsupportedPattern(_)
|
||||
| OpaqueNotInScope(..) => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,9 +626,9 @@ fn fix_values_captured_in_closure_expr(
|
|||
fix_values_captured_in_closure_expr(&mut loc_body.value, no_capture_symbols);
|
||||
}
|
||||
|
||||
Num(_, _, _)
|
||||
| Int(_, _, _, _)
|
||||
| Float(_, _, _, _)
|
||||
Num(..)
|
||||
| Int(..)
|
||||
| Float(..)
|
||||
| Str(_)
|
||||
| SingleQuote(_)
|
||||
| Var(_)
|
||||
|
@ -513,7 +700,7 @@ fn fix_values_captured_in_closure_expr(
|
|||
fix_values_captured_in_closure_expr(&mut loc_expr.value, no_capture_symbols);
|
||||
}
|
||||
|
||||
Tag { arguments, .. } | ZeroArgumentTag { arguments, .. } => {
|
||||
Tag { arguments, .. } | ZeroArgumentTag { arguments, .. } | OpaqueRef { arguments, .. } => {
|
||||
for (_, loc_arg) in arguments.iter_mut() {
|
||||
fix_values_captured_in_closure_expr(&mut loc_arg.value, no_capture_symbols);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue