mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
Do not return Option
from monomorphize_var
This commit is contained in:
parent
4b28136143
commit
9868c5cfac
3 changed files with 32 additions and 63 deletions
|
@ -114,40 +114,38 @@ impl<'a, 'c, 'd, 'i, 's, 't, P: Push<Problem>> Env<'a, 'c, 'd, 'i, 's, 't, P> {
|
|||
// Plain decimal number literals like `4.2` can still have an unbound var.
|
||||
MonoExpr::Number(Number::Dec(*val))
|
||||
}
|
||||
_ => match mono_from_var(*var) {
|
||||
Some(mono_id) => match mono_types.get(mono_id) {
|
||||
_ => {
|
||||
let mono_type = mono_from_var(*var);
|
||||
match mono_types.get(mono_type) {
|
||||
MonoType::Primitive(primitive) => to_frac(*primitive, *val, problems),
|
||||
other => {
|
||||
compiler_bug!(Problem::NumSpecializedToWrongType(Some(*other)))
|
||||
}
|
||||
},
|
||||
None => {
|
||||
compiler_bug!(Problem::NumSpecializedToWrongType(None))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Num(var, _, int_value, _) | Expr::Int(var, _, _, int_value, _) => {
|
||||
let mono_type = mono_from_var(*var);
|
||||
|
||||
// Number literals and int literals both specify integer numbers, so to_num() can work on both.
|
||||
match mono_from_var(*var) {
|
||||
Some(mono_id) => match mono_types.get(mono_id) {
|
||||
MonoType::Primitive(primitive) => to_num(*primitive, *int_value, problems),
|
||||
other => compiler_bug!(Problem::NumSpecializedToWrongType(Some(*other))),
|
||||
},
|
||||
None => compiler_bug!(Problem::NumSpecializedToWrongType(None)),
|
||||
match mono_types.get(mono_type) {
|
||||
MonoType::Primitive(primitive) => to_num(*primitive, *int_value, problems),
|
||||
other => compiler_bug!(Problem::NumSpecializedToWrongType(Some(*other))),
|
||||
}
|
||||
}
|
||||
Expr::SingleQuote(var, _, char, _) => match mono_from_var(*var) {
|
||||
Expr::SingleQuote(var, _, char, _) => {
|
||||
let mono_type = mono_from_var(*var);
|
||||
|
||||
// Single-quote characters monomorphize to an integer.
|
||||
// TODO if we store these using the same representation as other ints (e.g. Expr::Int,
|
||||
// TODO [mono2] if we store these using the same representation as other ints (e.g. Expr::Int,
|
||||
// or keeping a separate value but storing an IntValue instead of a char), then
|
||||
// even though we verify them differently, we can combine this branch with Num and Int.
|
||||
Some(mono_id) => match mono_types.get(mono_id) {
|
||||
match mono_types.get(mono_type) {
|
||||
MonoType::Primitive(primitive) => char_to_int(*primitive, *char, problems),
|
||||
other => compiler_bug!(Problem::CharSpecializedToWrongType(Some(*other))),
|
||||
},
|
||||
None => compiler_bug!(Problem::CharSpecializedToWrongType(None)),
|
||||
},
|
||||
}
|
||||
}
|
||||
Expr::Str(contents) => MonoExpr::Str(self.string_interns.get_id(
|
||||
self.arena,
|
||||
// TODO should be able to remove this alloc_str() once canonical Expr stores an arena-allocated string.
|
||||
|
|
|
@ -129,37 +129,21 @@ impl MonoTypes {
|
|||
|
||||
pub(crate) fn add_function(
|
||||
&mut self,
|
||||
ret: Option<MonoTypeId>,
|
||||
ret: MonoTypeId,
|
||||
args: impl IntoIterator<Item = MonoTypeId>,
|
||||
) -> MonoTypeId {
|
||||
let mono_type = match ret {
|
||||
Some(ret) => {
|
||||
let ret_then_args = {
|
||||
let start = self.ids.len();
|
||||
self.ids.push(ret);
|
||||
self.ids.extend(args);
|
||||
// Safety: we definitely have at least 2 elements in here, even if the iterator is empty.
|
||||
let length =
|
||||
unsafe { NonZeroU16::new_unchecked((self.ids.len() - start) as u16) };
|
||||
let ret_then_args = {
|
||||
let start = self.ids.len();
|
||||
self.ids.push(ret);
|
||||
self.ids.extend(args);
|
||||
// Safety: we definitely have at least 2 elements in here, even if the iterator is empty.
|
||||
let length = unsafe { NonZeroU16::new_unchecked((self.ids.len() - start) as u16) };
|
||||
|
||||
NonEmptySlice::new(start as u32, length)
|
||||
};
|
||||
|
||||
MonoType::Func { ret_then_args }
|
||||
}
|
||||
None => {
|
||||
let args = {
|
||||
let start = self.ids.len();
|
||||
self.ids.extend(args);
|
||||
let length = (self.ids.len() - start) as u16;
|
||||
|
||||
Slice::new(start as u32, length)
|
||||
};
|
||||
|
||||
MonoType::VoidFunc { args }
|
||||
}
|
||||
NonEmptySlice::new(start as u32, length)
|
||||
};
|
||||
|
||||
let mono_type = MonoType::Func { ret_then_args };
|
||||
|
||||
let index = self.entries.len();
|
||||
self.entries.push(mono_type);
|
||||
MonoTypeId::new(Index::new(index as u32))
|
||||
|
@ -275,16 +259,6 @@ pub enum MonoType {
|
|||
Func {
|
||||
ret_then_args: NonEmptySlice<MonoTypeId>,
|
||||
},
|
||||
|
||||
/// A function that does not have a return value (e.g. the return value was {}, which
|
||||
/// got eliminated), and which has 0 or more arguments.
|
||||
/// This has to be its own variant because the other function variant uses one slice to
|
||||
/// store the return value followed by the arguments. Without this separate variant,
|
||||
/// the other one couldn't distinguish between a function with a return value and 0 arguments,
|
||||
/// and a function with 1 argument but no return value.
|
||||
VoidFunc {
|
||||
args: Slice<MonoTypeId>,
|
||||
},
|
||||
// This last slot is tentatively reserved for Dict, because in the past we've discussed wanting to
|
||||
// implement Dict in Zig (for performance) instead of on top of List, like it is as of this writing.
|
||||
//
|
||||
|
|
|
@ -71,7 +71,7 @@ impl MonoTypeCache {
|
|||
problems: &mut impl Push<Problem>,
|
||||
debug_info: &mut Option<DebugInfo>,
|
||||
var: Variable,
|
||||
) -> Option<MonoTypeId> {
|
||||
) -> MonoTypeId {
|
||||
let mut env = Env {
|
||||
arena,
|
||||
cache: self,
|
||||
|
@ -135,7 +135,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
|
|||
mono_args.extend(
|
||||
arg_vars
|
||||
.into_iter()
|
||||
.flat_map(|var_index| self.lower_var(subs, subs[var_index])),
|
||||
.map(|var_index| self.lower_var(subs, subs[var_index])),
|
||||
);
|
||||
|
||||
// TODO [mono2] populate debuginfo as appropriate
|
||||
|
@ -143,7 +143,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
|
|||
self.mono_types.add_function(func, mono_args)
|
||||
}
|
||||
|
||||
fn lower_var(&mut self, subs: &Subs, var: Variable) -> Option<MonoTypeId> {
|
||||
fn lower_var(&mut self, subs: &Subs, var: Variable) -> MonoTypeId {
|
||||
let root_var = subs.get_root_key_without_compacting(var);
|
||||
|
||||
// TODO: we could replace this cache by having Subs store a Content::Monomorphic(MonoTypeId)
|
||||
|
@ -151,7 +151,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
|
|||
// for sure, and the lookups should be faster because they're O(1) but don't require hashing.
|
||||
// Kinda creates a cyclic dep though.
|
||||
if let Some(mono_id) = self.cache.inner.get(&root_var) {
|
||||
return Some(*mono_id);
|
||||
return *mono_id;
|
||||
}
|
||||
|
||||
// Convert the Content to a MonoType, often by passing an iterator. None of these iterators introduce allocations.
|
||||
|
@ -291,7 +291,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
|
|||
}
|
||||
_ => {
|
||||
// TODO [mono2] record in debuginfo the alias name for whatever we're lowering.
|
||||
self.lower_var(subs, real)?
|
||||
self.lower_var(subs, real)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,10 +313,7 @@ impl<'a, 'c, 'd, 'e, 'f, 'm, 'p, P: Push<Problem>> Env<'a, 'c, 'd, 'e, 'f, 'm, '
|
|||
};
|
||||
|
||||
// This var is now known to be monomorphic, so we don't repeat this work again later.
|
||||
// (We don't insert entries for Unit values.)
|
||||
self.cache.inner.insert(root_var, mono_id);
|
||||
|
||||
Some(mono_id)
|
||||
mono_id
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue