mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
merge main
This commit is contained in:
commit
e463ccf4a6
59 changed files with 1192 additions and 706 deletions
|
@ -121,16 +121,18 @@ impl<'a> Env<'a> {
|
|||
|
||||
Ok(symbol)
|
||||
}
|
||||
None => Err(RuntimeError::LookupNotInScope(
|
||||
Loc {
|
||||
None => Err(RuntimeError::LookupNotInScope {
|
||||
loc_name: Loc {
|
||||
value: Ident::from(ident),
|
||||
region,
|
||||
},
|
||||
self.ident_ids
|
||||
suggestion_options: self
|
||||
.ident_ids
|
||||
.ident_strs()
|
||||
.map(|(_, string)| string.into())
|
||||
.collect(),
|
||||
)),
|
||||
underscored_suggestion_region: None,
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
match self.dep_idents.get(&module_id) {
|
||||
|
|
|
@ -203,13 +203,14 @@ impl Scope {
|
|||
pub fn lookup(&mut self, ident: &Ident, region: Region) -> Result<Symbol, RuntimeError> {
|
||||
match self.idents.get(ident) {
|
||||
Some((symbol, _)) => Ok(*symbol),
|
||||
None => Err(RuntimeError::LookupNotInScope(
|
||||
Loc {
|
||||
None => Err(RuntimeError::LookupNotInScope {
|
||||
loc_name: Loc {
|
||||
region,
|
||||
value: ident.clone().into(),
|
||||
},
|
||||
self.idents.keys().map(|v| v.as_ref().into()).collect(),
|
||||
)),
|
||||
suggestion_options: self.idents.keys().map(|v| v.as_ref().into()).collect(),
|
||||
underscored_suggestion_region: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -403,7 +403,7 @@ fn build_entry_point<'a>(
|
|||
|
||||
let block = builder.add_block();
|
||||
|
||||
let struct_layout = interner.insert_no_semantic(LayoutRepr::struct_(layouts));
|
||||
let struct_layout = interner.insert_direct_no_semantic(LayoutRepr::struct_(layouts));
|
||||
let type_id = layout_spec(env, &mut builder, interner, struct_layout)?;
|
||||
|
||||
let argument = builder.add_unknown_with(block, &[], type_id)?;
|
||||
|
@ -461,7 +461,7 @@ fn proc_spec<'a>(
|
|||
|
||||
let root = BlockExpr(block, value_id);
|
||||
let args_struct_layout =
|
||||
interner.insert_no_semantic(LayoutRepr::struct_(argument_layouts.into_bump_slice()));
|
||||
interner.insert_direct_no_semantic(LayoutRepr::struct_(argument_layouts.into_bump_slice()));
|
||||
let arg_type_id = layout_spec(&mut env, &mut builder, interner, args_struct_layout)?;
|
||||
let ret_type_id = layout_spec(&mut env, &mut builder, interner, proc.ret_layout)?;
|
||||
|
||||
|
@ -851,8 +851,9 @@ fn call_spec<'a>(
|
|||
|
||||
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
|
||||
|
||||
let state_layout = interner
|
||||
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*return_layout)));
|
||||
let state_layout = interner.insert_direct_no_semantic(LayoutRepr::Builtin(
|
||||
Builtin::List(*return_layout),
|
||||
));
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
|
||||
let init_state = new_list(builder, block, output_element_type)?;
|
||||
|
@ -880,7 +881,7 @@ fn call_spec<'a>(
|
|||
let arg0_layout = argument_layouts[0];
|
||||
|
||||
let state_layout = interner
|
||||
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(arg0_layout)));
|
||||
.insert_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(arg0_layout)));
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
let init_state = list;
|
||||
|
||||
|
@ -907,8 +908,9 @@ fn call_spec<'a>(
|
|||
|
||||
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
|
||||
|
||||
let state_layout = interner
|
||||
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*return_layout)));
|
||||
let state_layout = interner.insert_direct_no_semantic(LayoutRepr::Builtin(
|
||||
Builtin::List(*return_layout),
|
||||
));
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
|
||||
let init_state = new_list(builder, block, output_element_type)?;
|
||||
|
@ -941,8 +943,9 @@ fn call_spec<'a>(
|
|||
|
||||
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
|
||||
|
||||
let state_layout = interner
|
||||
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*return_layout)));
|
||||
let state_layout = interner.insert_direct_no_semantic(LayoutRepr::Builtin(
|
||||
Builtin::List(*return_layout),
|
||||
));
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
|
||||
let init_state = new_list(builder, block, output_element_type)?;
|
||||
|
@ -981,8 +984,9 @@ fn call_spec<'a>(
|
|||
|
||||
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
|
||||
|
||||
let state_layout = interner
|
||||
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*return_layout)));
|
||||
let state_layout = interner.insert_direct_no_semantic(LayoutRepr::Builtin(
|
||||
Builtin::List(*return_layout),
|
||||
));
|
||||
let state_type = layout_spec(env, builder, interner, state_layout)?;
|
||||
|
||||
let init_state = new_list(builder, block, output_element_type)?;
|
||||
|
@ -1111,12 +1115,12 @@ fn lowlevel_spec<'a>(
|
|||
let new_list = with_new_heap_cell(builder, block, bag)?;
|
||||
|
||||
// depending on the types, the list or value will come first in the struct
|
||||
let fields = match interner.get(layout).repr {
|
||||
let fields = match interner.get_repr(layout) {
|
||||
LayoutRepr::Struct(field_layouts) => field_layouts,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
match (interner.get(fields[0]).repr, interner.get(fields[1]).repr) {
|
||||
match (interner.get_repr(fields[0]), interner.get_repr(fields[1])) {
|
||||
(LayoutRepr::Builtin(Builtin::List(_)), LayoutRepr::Builtin(Builtin::List(_))) => {
|
||||
// field name is the tie breaker, list is first in
|
||||
// { list : List a, value : a }
|
||||
|
@ -1144,7 +1148,7 @@ fn lowlevel_spec<'a>(
|
|||
ListWithCapacity => {
|
||||
// essentially an empty list, capacity is not relevant for morphic
|
||||
|
||||
match interner.get(layout).repr {
|
||||
match interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
|
||||
let type_id = layout_spec(env, builder, interner, element_layout)?;
|
||||
new_list(builder, block, type_id)
|
||||
|
@ -1440,7 +1444,7 @@ fn expr_spec<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
EmptyArray => match interner.get(layout).repr {
|
||||
EmptyArray => match interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
|
||||
let type_id = layout_spec(env, builder, interner, element_layout)?;
|
||||
new_list(builder, block, type_id)
|
||||
|
@ -1457,7 +1461,7 @@ fn expr_spec<'a>(
|
|||
} => {
|
||||
let tag_value_id = env.symbols[symbol];
|
||||
|
||||
let union_layout = match interner.get(layout).repr {
|
||||
let union_layout = match interner.get_repr(layout) {
|
||||
LayoutRepr::Union(ul) => ul,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -1539,7 +1543,7 @@ fn layout_spec_help<'a>(
|
|||
) -> Result<TypeId> {
|
||||
use LayoutRepr::*;
|
||||
|
||||
match interner.get(layout).repr {
|
||||
match interner.get_repr(layout) {
|
||||
Builtin(builtin) => builtin_spec(env, builder, interner, &builtin),
|
||||
Struct(field_layouts) => build_recursive_tuple_type(env, builder, interner, field_layouts),
|
||||
LambdaSet(lambda_set) => {
|
||||
|
@ -1578,7 +1582,7 @@ fn layout_spec_help<'a>(
|
|||
builder.add_tuple_type(&[cell_type, inner_type])
|
||||
}
|
||||
// TODO(recursive-layouts): update once we have recursive pointer loops
|
||||
RecursivePointer(union_layout) => match interner.get(union_layout).repr {
|
||||
RecursivePointer(union_layout) => match interner.get_repr(union_layout) {
|
||||
LayoutRepr::Union(union_layout) => {
|
||||
assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
|
||||
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
|
||||
|
|
|
@ -34,7 +34,9 @@ pub const DEFAULT_ROC_FILENAME: &str = "main.roc";
|
|||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct CodeGenTiming {
|
||||
pub code_gen: Duration,
|
||||
pub generate_final_ir: Duration,
|
||||
pub code_gen_object: Duration,
|
||||
pub total: Duration,
|
||||
}
|
||||
|
||||
pub fn report_problems_monomorphized(loaded: &mut MonomorphizedModule) -> Problems {
|
||||
|
@ -144,7 +146,7 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
use inkwell::module::Linkage;
|
||||
use inkwell::targets::{FileType, RelocMode};
|
||||
|
||||
let code_gen_start = Instant::now();
|
||||
let all_code_gen_start = Instant::now();
|
||||
|
||||
// Generate the binary
|
||||
let target_info = roc_target::TargetInfo::from(target);
|
||||
|
@ -238,6 +240,10 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
&loaded.glue_layouts,
|
||||
);
|
||||
|
||||
// We are now finished building the LLVM IR.
|
||||
let generate_final_ir = all_code_gen_start.elapsed();
|
||||
let code_gen_object_start = Instant::now();
|
||||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// we don't use the debug info, and it causes weird errors.
|
||||
|
@ -439,11 +445,16 @@ fn gen_from_mono_module_llvm<'a>(
|
|||
}
|
||||
};
|
||||
|
||||
let code_gen = code_gen_start.elapsed();
|
||||
let code_gen_object = code_gen_object_start.elapsed();
|
||||
let total = all_code_gen_start.elapsed();
|
||||
|
||||
(
|
||||
CodeObject::MemoryBuffer(memory_buffer),
|
||||
CodeGenTiming { code_gen },
|
||||
CodeGenTiming {
|
||||
generate_final_ir,
|
||||
code_gen_object,
|
||||
total,
|
||||
},
|
||||
ExpectMetadata {
|
||||
interns: env.interns,
|
||||
layout_interner: loaded.layout_interner,
|
||||
|
@ -503,7 +514,7 @@ fn gen_from_mono_module_dev_wasm32<'a>(
|
|||
preprocessed_host_path: &Path,
|
||||
wasm_dev_stack_bytes: Option<u32>,
|
||||
) -> GenFromMono<'a> {
|
||||
let code_gen_start = Instant::now();
|
||||
let all_code_gen_start = Instant::now();
|
||||
let MonomorphizedModule {
|
||||
module_id,
|
||||
procedures,
|
||||
|
@ -550,11 +561,18 @@ fn gen_from_mono_module_dev_wasm32<'a>(
|
|||
procedures,
|
||||
);
|
||||
|
||||
let code_gen = code_gen_start.elapsed();
|
||||
let generate_final_ir = all_code_gen_start.elapsed();
|
||||
let code_gen_object_start = Instant::now();
|
||||
let code_gen_object = code_gen_object_start.elapsed();
|
||||
let total = all_code_gen_start.elapsed();
|
||||
|
||||
(
|
||||
CodeObject::Vector(final_binary_bytes),
|
||||
CodeGenTiming { code_gen },
|
||||
CodeGenTiming {
|
||||
generate_final_ir,
|
||||
code_gen_object,
|
||||
total,
|
||||
},
|
||||
ExpectMetadata {
|
||||
interns,
|
||||
layout_interner,
|
||||
|
@ -569,7 +587,7 @@ fn gen_from_mono_module_dev_assembly<'a>(
|
|||
target: &target_lexicon::Triple,
|
||||
backend_mode: AssemblyBackendMode,
|
||||
) -> GenFromMono<'a> {
|
||||
let code_gen_start = Instant::now();
|
||||
let all_code_gen_start = Instant::now();
|
||||
|
||||
let lazy_literals = true;
|
||||
|
||||
|
@ -593,15 +611,23 @@ fn gen_from_mono_module_dev_assembly<'a>(
|
|||
let module_object =
|
||||
roc_gen_dev::build_module(&env, &mut interns, &mut layout_interner, target, procedures);
|
||||
|
||||
let code_gen = code_gen_start.elapsed();
|
||||
let generate_final_ir = all_code_gen_start.elapsed();
|
||||
let code_gen_object_start = Instant::now();
|
||||
|
||||
let module_out = module_object
|
||||
.write()
|
||||
.expect("failed to build output object");
|
||||
|
||||
let code_gen_object = code_gen_object_start.elapsed();
|
||||
let total = all_code_gen_start.elapsed();
|
||||
|
||||
(
|
||||
CodeObject::Vector(module_out),
|
||||
CodeGenTiming { code_gen },
|
||||
CodeGenTiming {
|
||||
generate_final_ir,
|
||||
code_gen_object,
|
||||
total,
|
||||
},
|
||||
ExpectMetadata {
|
||||
interns,
|
||||
layout_interner,
|
||||
|
@ -919,9 +945,12 @@ fn build_loaded_file<'a>(
|
|||
|
||||
report_timing(
|
||||
buf,
|
||||
"Generate Assembly from Mono IR",
|
||||
code_gen_timing.code_gen,
|
||||
"Generate final IR from Mono IR",
|
||||
code_gen_timing.generate_final_ir,
|
||||
);
|
||||
report_timing(buf, "Generate object", code_gen_timing.code_gen_object);
|
||||
buf.push('\n');
|
||||
report_timing(buf, "Total", code_gen_timing.total);
|
||||
|
||||
let compilation_end = compilation_start.elapsed();
|
||||
let size = roc_app_bytes.len();
|
||||
|
|
|
@ -124,18 +124,19 @@ impl<'a> Env<'a> {
|
|||
Ok(symbol)
|
||||
}
|
||||
None => {
|
||||
let error = RuntimeError::LookupNotInScope(
|
||||
Loc {
|
||||
let error = RuntimeError::LookupNotInScope {
|
||||
loc_name: Loc {
|
||||
value: Ident::from(ident),
|
||||
region,
|
||||
},
|
||||
scope
|
||||
suggestion_options: scope
|
||||
.locals
|
||||
.ident_ids
|
||||
.ident_strs()
|
||||
.map(|(_, string)| string.into())
|
||||
.collect(),
|
||||
);
|
||||
underscored_suggestion_region: None,
|
||||
};
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1019,9 +1019,18 @@ pub fn canonicalize_expr<'a>(
|
|||
}
|
||||
ast::Expr::Underscore(name) => {
|
||||
// we parse underscores, but they are not valid expression syntax
|
||||
|
||||
let problem = roc_problem::can::RuntimeError::MalformedIdentifier(
|
||||
(*name).into(),
|
||||
roc_parse::ident::BadIdent::Underscore(region.start()),
|
||||
if name.is_empty() {
|
||||
roc_parse::ident::BadIdent::UnderscoreAlone(region.start())
|
||||
} else {
|
||||
roc_parse::ident::BadIdent::UnderscoreAtStart {
|
||||
position: region.start(),
|
||||
// Check if there's an ignored identifier with this name in scope (for better error messages)
|
||||
declaration_region: scope.lookup_ignored_local(name),
|
||||
}
|
||||
},
|
||||
region,
|
||||
);
|
||||
|
||||
|
|
|
@ -379,6 +379,12 @@ pub fn canonicalize_pattern<'a>(
|
|||
Err(pattern) => pattern,
|
||||
}
|
||||
}
|
||||
Underscore(name) => {
|
||||
// An underscored identifier can't be used, but we'll still add it to the scope
|
||||
// for better error messages if someone tries to use it.
|
||||
scope.introduce_ignored_local(name, region);
|
||||
Pattern::Underscore
|
||||
}
|
||||
Tag(name) => {
|
||||
// Canonicalize the tag's name.
|
||||
Pattern::AppliedTag {
|
||||
|
@ -479,8 +485,6 @@ pub fn canonicalize_pattern<'a>(
|
|||
ptype => unsupported_pattern(env, ptype, region),
|
||||
},
|
||||
|
||||
Underscore(_) => Pattern::Underscore,
|
||||
|
||||
&NumLiteral(str) => match pattern_type {
|
||||
WhenBranch => match finish_parsing_num(str) {
|
||||
Err(_error) => {
|
||||
|
|
|
@ -41,6 +41,10 @@ pub struct Scope {
|
|||
|
||||
/// Identifiers that are in scope, and defined in the current module
|
||||
pub locals: ScopedIdentIds,
|
||||
|
||||
/// Ignored variables (variables that start with an underscore).
|
||||
/// We won't intern them because they're only used during canonicalization for error reporting.
|
||||
ignored_locals: VecMap<String, Region>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
|
@ -65,6 +69,7 @@ impl Scope {
|
|||
abilities_store: starting_abilities_store,
|
||||
shadows: VecMap::default(),
|
||||
imports: default_imports,
|
||||
ignored_locals: VecMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,13 +94,17 @@ impl Scope {
|
|||
match self.scope_contains_ident(ident) {
|
||||
InScope(symbol, _) => Ok(symbol),
|
||||
NotInScope(_) | NotPresent => {
|
||||
let error = RuntimeError::LookupNotInScope(
|
||||
Loc {
|
||||
// identifier not found
|
||||
|
||||
let error = RuntimeError::LookupNotInScope {
|
||||
loc_name: Loc {
|
||||
region,
|
||||
value: Ident::from(ident),
|
||||
},
|
||||
self.idents_in_scope().map(|v| v.as_ref().into()).collect(),
|
||||
);
|
||||
suggestion_options: self.idents_in_scope().map(|v| v.as_ref().into()).collect(),
|
||||
// Check if the user just forgot to remove an underscore from an ignored identifier
|
||||
underscored_suggestion_region: self.lookup_ignored_local(ident),
|
||||
};
|
||||
|
||||
Err(error)
|
||||
}
|
||||
|
@ -418,11 +427,13 @@ impl Scope {
|
|||
// - exposed_ident_count: unchanged
|
||||
// - home: unchanged
|
||||
let aliases_count = self.aliases.len();
|
||||
let ignored_locals_count = self.ignored_locals.len();
|
||||
let locals_snapshot = self.locals.in_scope.len();
|
||||
|
||||
let result = f(self);
|
||||
|
||||
self.aliases.truncate(aliases_count);
|
||||
self.ignored_locals.truncate(ignored_locals_count);
|
||||
|
||||
// anything added in the inner scope is no longer in scope now
|
||||
for i in locals_snapshot..self.locals.in_scope.len() {
|
||||
|
@ -444,6 +455,19 @@ impl Scope {
|
|||
pub fn gen_unique_symbol(&mut self) -> Symbol {
|
||||
Symbol::new(self.home, self.locals.gen_unique())
|
||||
}
|
||||
|
||||
/// Introduce a new ignored variable (variable starting with an underscore).
|
||||
/// The underscore itself should not be included in `ident`.
|
||||
pub fn introduce_ignored_local(&mut self, ident: &str, region: Region) {
|
||||
self.ignored_locals.insert(ident.to_owned(), region);
|
||||
}
|
||||
|
||||
/// Lookup an ignored variable (variable starting with an underscore).
|
||||
/// The underscore itself should not be included in `ident`.
|
||||
/// Returns the source code region of the ignored variable if it's found.
|
||||
pub fn lookup_ignored_local(&self, ident: &str) -> Option<Region> {
|
||||
self.ignored_locals.get(&ident.to_owned()).copied()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_alias(
|
||||
|
|
|
@ -332,7 +332,7 @@ mod test_can {
|
|||
matches!(
|
||||
problem,
|
||||
Problem::SignatureDefMismatch { .. }
|
||||
| Problem::RuntimeError(RuntimeError::LookupNotInScope(_, _))
|
||||
| Problem::RuntimeError(RuntimeError::LookupNotInScope { .. })
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ mod test_can {
|
|||
matches!(
|
||||
problem,
|
||||
Problem::SignatureDefMismatch { .. }
|
||||
| Problem::RuntimeError(RuntimeError::LookupNotInScope(_, _))
|
||||
| Problem::RuntimeError(RuntimeError::LookupNotInScope { .. })
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -761,7 +761,15 @@ fn remove_spaces_bad_ident(ident: BadIdent) -> BadIdent {
|
|||
match ident {
|
||||
BadIdent::Start(_) => BadIdent::Start(Position::zero()),
|
||||
BadIdent::Space(e, _) => BadIdent::Space(e, Position::zero()),
|
||||
BadIdent::Underscore(_) => BadIdent::Underscore(Position::zero()),
|
||||
BadIdent::UnderscoreAlone(_) => BadIdent::UnderscoreAlone(Position::zero()),
|
||||
BadIdent::UnderscoreInMiddle(_) => BadIdent::UnderscoreInMiddle(Position::zero()),
|
||||
BadIdent::UnderscoreAtStart {
|
||||
position: _,
|
||||
declaration_region,
|
||||
} => BadIdent::UnderscoreAtStart {
|
||||
position: Position::zero(),
|
||||
declaration_region,
|
||||
},
|
||||
BadIdent::QualifiedTag(_) => BadIdent::QualifiedTag(Position::zero()),
|
||||
BadIdent::WeirdAccessor(_) => BadIdent::WeirdAccessor(Position::zero()),
|
||||
BadIdent::WeirdDotAccess(_) => BadIdent::WeirdDotAccess(Position::zero()),
|
||||
|
|
|
@ -888,7 +888,7 @@ impl<
|
|||
|
||||
fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>) {
|
||||
// move return value to dst.
|
||||
let ret_repr = self.interner().get(*ret_layout).repr;
|
||||
let ret_repr = self.interner().get_repr(*ret_layout);
|
||||
match ret_repr {
|
||||
single_register_integers!() => {
|
||||
let width = RegisterWidth::try_from_layout(ret_repr).unwrap();
|
||||
|
@ -1070,7 +1070,7 @@ impl<
|
|||
}
|
||||
|
||||
fn build_num_abs(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>) {
|
||||
match self.interner().get(*layout).repr {
|
||||
match self.interner().get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
|
||||
|
@ -1086,7 +1086,7 @@ impl<
|
|||
}
|
||||
|
||||
fn build_num_add(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
||||
match self.layout_interner.get(*layout).repr {
|
||||
match self.layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(quadword_and_smaller!())) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
|
@ -1120,7 +1120,7 @@ impl<
|
|||
src2: Symbol,
|
||||
layout: InLayout<'a>,
|
||||
) {
|
||||
match self.layout_interner.get(layout).repr {
|
||||
match self.layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width @ quadword_and_smaller!())) => {
|
||||
let intrinsic = bitcode::NUM_ADD_SATURATED_INT[width].to_string();
|
||||
self.build_fn_call(&dst, intrinsic, &[src1, src2], &[layout, layout], &layout);
|
||||
|
@ -1161,7 +1161,7 @@ impl<
|
|||
|
||||
let base_offset = self.storage_manager.claim_stack_area(dst, struct_size);
|
||||
|
||||
match self.layout_interner.get(*num_layout).repr {
|
||||
match self.layout_interner.get_repr(*num_layout) {
|
||||
LayoutRepr::Builtin(Int(
|
||||
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
|
||||
)) => {
|
||||
|
@ -1208,7 +1208,7 @@ impl<
|
|||
num_layout: &InLayout<'a>,
|
||||
return_layout: &InLayout<'a>,
|
||||
) {
|
||||
let function_name = match self.interner().get(*num_layout).repr {
|
||||
let function_name = match self.interner().get_repr(*num_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => &bitcode::NUM_SUB_CHECKED_INT[width],
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => &bitcode::NUM_SUB_CHECKED_FLOAT[width],
|
||||
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_SUB_WITH_OVERFLOW,
|
||||
|
@ -1227,7 +1227,7 @@ impl<
|
|||
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
||||
use Builtin::Int;
|
||||
|
||||
match self.layout_interner.get(*layout).repr {
|
||||
match self.layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Int(
|
||||
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
|
||||
)) => {
|
||||
|
@ -1291,7 +1291,7 @@ impl<
|
|||
}
|
||||
|
||||
fn build_num_div(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
||||
match self.layout_interner.get(*layout).repr {
|
||||
match self.layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(
|
||||
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
|
||||
)) => {
|
||||
|
@ -1347,7 +1347,7 @@ impl<
|
|||
}
|
||||
|
||||
fn build_num_rem(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
|
||||
match self.layout_interner.get(*layout).repr {
|
||||
match self.layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(
|
||||
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
|
||||
)) => {
|
||||
|
@ -1391,7 +1391,7 @@ impl<
|
|||
}
|
||||
|
||||
fn build_num_neg(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>) {
|
||||
match self.layout_interner.get(*layout).repr {
|
||||
match self.layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
|
||||
|
@ -1414,7 +1414,7 @@ impl<
|
|||
src2: &Symbol,
|
||||
layout: &InLayout<'a>,
|
||||
) {
|
||||
match self.layout_interner.get(*layout).repr {
|
||||
match self.layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(quadword_and_smaller!())) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
|
@ -1430,7 +1430,7 @@ impl<
|
|||
}
|
||||
|
||||
fn build_eq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>) {
|
||||
let repr = self.interner().get(*arg_layout).repr;
|
||||
let repr = self.interner().get_repr(*arg_layout);
|
||||
match repr {
|
||||
single_register_int_builtins!() | LayoutRepr::BOOL => {
|
||||
let width = match repr {
|
||||
|
@ -1546,7 +1546,7 @@ impl<
|
|||
}
|
||||
|
||||
fn build_neq(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, arg_layout: &InLayout<'a>) {
|
||||
match self.interner().get(*arg_layout).repr {
|
||||
match self.interner().get_repr(*arg_layout) {
|
||||
single_register_int_builtins!() | LayoutRepr::BOOL => {
|
||||
let width = match *arg_layout {
|
||||
Layout::BOOL | Layout::I8 | Layout::U8 => RegisterWidth::W8,
|
||||
|
@ -1588,7 +1588,7 @@ impl<
|
|||
}
|
||||
|
||||
fn build_not(&mut self, dst: &Symbol, src: &Symbol, arg_layout: &InLayout<'a>) {
|
||||
match self.interner().get(*arg_layout).repr {
|
||||
match self.interner().get_repr(*arg_layout) {
|
||||
LayoutRepr::BOOL => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
|
||||
|
@ -1613,8 +1613,8 @@ impl<
|
|||
) {
|
||||
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
|
||||
match (
|
||||
self.layout_interner.get(*arg_layout).repr,
|
||||
self.layout_interner.get(*ret_layout).repr,
|
||||
self.layout_interner.get_repr(*arg_layout),
|
||||
self.layout_interner.get_repr(*ret_layout),
|
||||
) {
|
||||
(
|
||||
LayoutRepr::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::I64)),
|
||||
|
@ -1850,8 +1850,9 @@ impl<
|
|||
let new_element_layout = higher_order.passed_function.return_layout;
|
||||
|
||||
let input_list_layout = LayoutRepr::Builtin(Builtin::List(old_element_layout));
|
||||
let input_list_in_layout =
|
||||
self.layout_interner.insert_no_semantic(input_list_layout);
|
||||
let input_list_in_layout = self
|
||||
.layout_interner
|
||||
.insert_direct_no_semantic(input_list_layout);
|
||||
|
||||
let caller = self.debug_symbol("caller");
|
||||
let data = self.debug_symbol("data");
|
||||
|
@ -2256,7 +2257,7 @@ impl<
|
|||
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
|
||||
|
||||
let ret_fields =
|
||||
if let LayoutRepr::Struct(field_layouts) = self.layout_interner.get(*ret_layout).repr {
|
||||
if let LayoutRepr::Struct(field_layouts) = self.layout_interner.get_repr(*ret_layout) {
|
||||
field_layouts
|
||||
} else {
|
||||
internal_error!(
|
||||
|
@ -2478,7 +2479,7 @@ impl<
|
|||
element_in_layout: &InLayout<'a>,
|
||||
elements: &[ListLiteralElement<'a>],
|
||||
) {
|
||||
let element_layout = self.layout_interner.get(*element_in_layout);
|
||||
let element_layout = self.layout_interner.get_repr(*element_in_layout);
|
||||
let element_width = self.layout_interner.stack_size(*element_in_layout) as u64;
|
||||
|
||||
// load the total size of the data we want to store (excludes refcount)
|
||||
|
@ -2677,7 +2678,7 @@ impl<
|
|||
_ => {
|
||||
let union_in_layout = self
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Union(*union_layout));
|
||||
.insert_direct_no_semantic(LayoutRepr::Union(*union_layout));
|
||||
todo!(
|
||||
"loading from union type: {:?}",
|
||||
self.layout_interner.dbg(union_in_layout)
|
||||
|
@ -2700,7 +2701,7 @@ impl<
|
|||
let element_width = self.layout_interner.stack_size(element_layout) as u64;
|
||||
let element_offset = 0;
|
||||
|
||||
let layout = self.layout_interner.get(element_layout);
|
||||
let layout = self.layout_interner.get_repr(element_layout);
|
||||
|
||||
Self::ptr_write(
|
||||
&mut self.buf,
|
||||
|
@ -2958,7 +2959,7 @@ impl<
|
|||
let temp_sym = Symbol::DEV_TMP5;
|
||||
let layout = self
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Struct(other_fields));
|
||||
.insert_direct_no_semantic(LayoutRepr::Struct(other_fields));
|
||||
|
||||
self.load_literal_symbols(fields);
|
||||
self.storage_manager.create_struct(
|
||||
|
@ -2995,7 +2996,7 @@ impl<
|
|||
let temp_sym = Symbol::DEV_TMP5;
|
||||
let layout = self
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Struct(other_fields));
|
||||
.insert_direct_no_semantic(LayoutRepr::Struct(other_fields));
|
||||
|
||||
self.load_literal_symbols(fields);
|
||||
self.storage_manager.create_struct(
|
||||
|
@ -3042,13 +3043,13 @@ impl<
|
|||
}
|
||||
|
||||
fn load_literal(&mut self, sym: &Symbol, layout: &InLayout<'a>, lit: &Literal<'a>) {
|
||||
let layout = self.layout_interner.get(*layout);
|
||||
let layout = self.layout_interner.get_repr(*layout);
|
||||
|
||||
if let LayoutRepr::LambdaSet(lambda_set) = layout.repr {
|
||||
if let LayoutRepr::LambdaSet(lambda_set) = layout {
|
||||
return self.load_literal(sym, &lambda_set.runtime_representation(), lit);
|
||||
}
|
||||
|
||||
match (lit, layout.repr) {
|
||||
match (lit, layout) {
|
||||
(
|
||||
Literal::Int(x),
|
||||
LayoutRepr::Builtin(Builtin::Int(
|
||||
|
@ -3176,7 +3177,7 @@ impl<
|
|||
}
|
||||
|
||||
fn return_symbol(&mut self, sym: &Symbol, layout: &InLayout<'a>) {
|
||||
let repr = self.layout_interner.get(*layout).repr;
|
||||
let repr = self.layout_interner.get_repr(*layout);
|
||||
if self.storage_manager.is_stored_primitive(sym) {
|
||||
// Just load it to the correct type of reg as a stand alone value.
|
||||
match repr {
|
||||
|
@ -3547,7 +3548,7 @@ impl<
|
|||
src2: &Symbol,
|
||||
arg_layout: &InLayout<'a>,
|
||||
) {
|
||||
match self.interner().get(*arg_layout).repr {
|
||||
match self.interner().get_repr(*arg_layout) {
|
||||
single_register_integers!() => {
|
||||
let buf = &mut self.buf;
|
||||
|
||||
|
@ -3749,7 +3750,7 @@ impl<
|
|||
element_in_layout: InLayout<'a>,
|
||||
dst: Symbol,
|
||||
) {
|
||||
match layout_interner.get(element_in_layout).repr {
|
||||
match layout_interner.get_repr(element_in_layout) {
|
||||
LayoutRepr::Builtin(builtin) => match builtin {
|
||||
Builtin::Int(int_width) => match int_width {
|
||||
IntWidth::I128 | IntWidth::U128 => {
|
||||
|
@ -3865,10 +3866,10 @@ impl<
|
|||
ptr_reg: GeneralReg,
|
||||
element_offset: i32,
|
||||
element_width: u64,
|
||||
element_layout: Layout<'a>,
|
||||
element_layout: LayoutRepr<'a>,
|
||||
value: Symbol,
|
||||
) {
|
||||
match element_layout.repr {
|
||||
match element_layout {
|
||||
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
|
||||
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
|
||||
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg);
|
||||
|
@ -3894,7 +3895,7 @@ impl<
|
|||
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg);
|
||||
}
|
||||
LayoutRepr::LambdaSet(lambda_set) => {
|
||||
let layout = layout_interner.get(lambda_set.runtime_representation());
|
||||
let repr = layout_interner.get_repr(lambda_set.runtime_representation());
|
||||
|
||||
Self::ptr_write(
|
||||
buf,
|
||||
|
@ -3903,7 +3904,7 @@ impl<
|
|||
ptr_reg,
|
||||
element_offset,
|
||||
element_width,
|
||||
layout,
|
||||
repr,
|
||||
value,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -665,7 +665,7 @@ impl<
|
|||
|
||||
let mut in_layout = *layout;
|
||||
let layout = loop {
|
||||
match layout_interner.get(in_layout).repr {
|
||||
match layout_interner.get_repr(in_layout) {
|
||||
LayoutRepr::LambdaSet(inner) => in_layout = inner.runtime_representation(),
|
||||
other => break other,
|
||||
}
|
||||
|
@ -728,7 +728,7 @@ impl<
|
|||
sym: &Symbol,
|
||||
layout: &InLayout<'a>,
|
||||
) {
|
||||
match layout_interner.get(*layout).repr {
|
||||
match layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(builtin) => match builtin {
|
||||
Builtin::Int(int_width) => match int_width {
|
||||
IntWidth::I128 | IntWidth::U128 => {
|
||||
|
@ -1104,7 +1104,7 @@ impl<
|
|||
symbol: Symbol,
|
||||
layout: InLayout<'a>,
|
||||
) {
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
single_register_layouts!() | pointer_layouts!() => {
|
||||
let base_offset = self.claim_stack_size(8);
|
||||
self.symbol_storage_map.insert(
|
||||
|
@ -1169,7 +1169,7 @@ impl<
|
|||
layout: InLayout<'a>,
|
||||
base_offset: i32,
|
||||
) {
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
single_register_integers!() | pointer_layouts!() => {
|
||||
let reg = self.load_to_general_reg(buf, &symbol);
|
||||
ASM::mov_base32_reg64(buf, base_offset, reg);
|
||||
|
@ -1491,7 +1491,7 @@ impl<
|
|||
}
|
||||
|
||||
fn is_primitive(layout_interner: &mut STLayoutInterner<'_>, layout: InLayout<'_>) -> bool {
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
single_register_layouts!() => true,
|
||||
pointer_layouts!() => true,
|
||||
LayoutRepr::LambdaSet(lambda_set) => {
|
||||
|
|
|
@ -346,7 +346,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
sym: &Symbol,
|
||||
layout: &InLayout<'a>,
|
||||
) {
|
||||
match layout_interner.get(*layout).repr {
|
||||
match layout_interner.get_repr(*layout) {
|
||||
single_register_layouts!() => {
|
||||
internal_error!("single register layouts are not complex symbols");
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
sym: &Symbol,
|
||||
layout: &InLayout<'a>,
|
||||
) {
|
||||
match layout_interner.get(*layout).repr {
|
||||
match layout_interner.get_repr(*layout) {
|
||||
single_register_layouts!() => {
|
||||
internal_error!("single register layouts are not complex symbols");
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ impl X64_64SystemVStoreArgs {
|
|||
sym: Symbol,
|
||||
in_layout: InLayout<'a>,
|
||||
) {
|
||||
match layout_interner.get(in_layout).repr {
|
||||
match layout_interner.get_repr(in_layout) {
|
||||
single_register_integers!() => self.store_arg_general(buf, storage_manager, sym),
|
||||
pointer_layouts!() => self.store_arg_general(buf, storage_manager, sym),
|
||||
single_register_floats!() => self.store_arg_float(buf, storage_manager, sym),
|
||||
|
@ -654,7 +654,7 @@ impl X64_64SystemVLoadArgs {
|
|||
in_layout: InLayout<'a>,
|
||||
) {
|
||||
let stack_size = layout_interner.stack_size(in_layout);
|
||||
match layout_interner.get(in_layout).repr {
|
||||
match layout_interner.get_repr(in_layout) {
|
||||
single_register_integers!() => self.load_arg_general(storage_manager, sym),
|
||||
pointer_layouts!() => self.load_arg_general(storage_manager, sym),
|
||||
single_register_floats!() => self.load_arg_float(storage_manager, sym),
|
||||
|
@ -885,7 +885,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
}
|
||||
|
||||
for (layout, sym) in args.iter() {
|
||||
match layout_interner.get(*layout).repr {
|
||||
match layout_interner.get_repr(*layout) {
|
||||
single_register_integers!() => {
|
||||
match Self::GENERAL_PARAM_REGS.get(general_registers_used) {
|
||||
Some(reg) => {
|
||||
|
@ -946,7 +946,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
let mut float_registers_used = 0;
|
||||
|
||||
for (sym, layout) in args.iter().zip(arg_layouts.iter()) {
|
||||
match layout_interner.get(*layout).repr {
|
||||
match layout_interner.get_repr(*layout) {
|
||||
single_register_integers!() => {
|
||||
match Self::GENERAL_PARAM_REGS.get(general_registers_used) {
|
||||
Some(reg) => {
|
||||
|
|
|
@ -360,7 +360,7 @@ trait Backend<'a> {
|
|||
}
|
||||
|
||||
fn list_argument(&mut self, list_layout: InLayout<'a>) -> ListArgument<'a> {
|
||||
let element_layout = match self.interner().get(list_layout).repr {
|
||||
let element_layout = match self.interner().get_repr(list_layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(e)) => e,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -384,7 +384,7 @@ trait Backend<'a> {
|
|||
fn increment_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol {
|
||||
let box_layout = self
|
||||
.interner_mut()
|
||||
.insert_no_semantic(LayoutRepr::Boxed(layout));
|
||||
.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
|
||||
|
||||
let element_increment = self.debug_symbol("element_increment");
|
||||
let element_increment_symbol = self.build_indirect_inc(layout);
|
||||
|
@ -404,7 +404,7 @@ trait Backend<'a> {
|
|||
fn decrement_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol {
|
||||
let box_layout = self
|
||||
.interner_mut()
|
||||
.insert_no_semantic(LayoutRepr::Boxed(layout));
|
||||
.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
|
||||
|
||||
let element_decrement = self.debug_symbol("element_decrement");
|
||||
let element_decrement_symbol = self.build_indirect_dec(layout);
|
||||
|
@ -801,7 +801,7 @@ trait Backend<'a> {
|
|||
self.tag(sym, arguments, tag_layout, *tag_id, None);
|
||||
}
|
||||
Expr::ExprBox { symbol: value } => {
|
||||
let element_layout = match self.interner().get(*layout).repr {
|
||||
let element_layout = match self.interner().get_repr(*layout) {
|
||||
LayoutRepr::Boxed(boxed) => boxed,
|
||||
_ => unreachable!("{:?}", self.interner().dbg(*layout)),
|
||||
};
|
||||
|
@ -1030,7 +1030,7 @@ trait Backend<'a> {
|
|||
);
|
||||
self.build_num_sub_wrap(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
LowLevel::NumSubSaturated => match self.interner().get(*ret_layout).repr {
|
||||
LowLevel::NumSubSaturated => match self.interner().get_repr(*ret_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::NUM_SUB_SATURATED_INT[int_width].to_string(),
|
||||
|
@ -1053,7 +1053,7 @@ trait Backend<'a> {
|
|||
},
|
||||
LowLevel::NumBitwiseAnd => {
|
||||
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
|
||||
self.interner().get(*ret_layout).repr
|
||||
self.interner().get_repr(*ret_layout)
|
||||
{
|
||||
self.build_int_bitwise_and(sym, &args[0], &args[1], int_width)
|
||||
} else {
|
||||
|
@ -1062,7 +1062,7 @@ trait Backend<'a> {
|
|||
}
|
||||
LowLevel::NumBitwiseOr => {
|
||||
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
|
||||
self.interner().get(*ret_layout).repr
|
||||
self.interner().get_repr(*ret_layout)
|
||||
{
|
||||
self.build_int_bitwise_or(sym, &args[0], &args[1], int_width)
|
||||
} else {
|
||||
|
@ -1071,7 +1071,7 @@ trait Backend<'a> {
|
|||
}
|
||||
LowLevel::NumBitwiseXor => {
|
||||
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
|
||||
self.interner().get(*ret_layout).repr
|
||||
self.interner().get_repr(*ret_layout)
|
||||
{
|
||||
self.build_int_bitwise_xor(sym, &args[0], &args[1], int_width)
|
||||
} else {
|
||||
|
@ -1079,14 +1079,14 @@ trait Backend<'a> {
|
|||
}
|
||||
}
|
||||
LowLevel::And => {
|
||||
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get(*ret_layout).repr {
|
||||
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get_repr(*ret_layout) {
|
||||
self.build_int_bitwise_and(sym, &args[0], &args[1], IntWidth::U8)
|
||||
} else {
|
||||
internal_error!("bitwise and on a non-integer")
|
||||
}
|
||||
}
|
||||
LowLevel::Or => {
|
||||
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get(*ret_layout).repr {
|
||||
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get_repr(*ret_layout) {
|
||||
self.build_int_bitwise_or(sym, &args[0], &args[1], IntWidth::U8)
|
||||
} else {
|
||||
internal_error!("bitwise or on a non-integer")
|
||||
|
@ -1094,7 +1094,7 @@ trait Backend<'a> {
|
|||
}
|
||||
LowLevel::NumShiftLeftBy => {
|
||||
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
|
||||
self.interner().get(*ret_layout).repr
|
||||
self.interner().get_repr(*ret_layout)
|
||||
{
|
||||
self.build_int_shift_left(sym, &args[0], &args[1], int_width)
|
||||
} else {
|
||||
|
@ -1103,7 +1103,7 @@ trait Backend<'a> {
|
|||
}
|
||||
LowLevel::NumShiftRightBy => {
|
||||
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
|
||||
self.interner().get(*ret_layout).repr
|
||||
self.interner().get_repr(*ret_layout)
|
||||
{
|
||||
self.build_int_shift_right(sym, &args[0], &args[1], int_width)
|
||||
} else {
|
||||
|
@ -1112,7 +1112,7 @@ trait Backend<'a> {
|
|||
}
|
||||
LowLevel::NumShiftRightZfBy => {
|
||||
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
|
||||
self.interner().get(*ret_layout).repr
|
||||
self.interner().get_repr(*ret_layout)
|
||||
{
|
||||
self.build_int_shift_right_zero_fill(sym, &args[0], &args[1], int_width)
|
||||
} else {
|
||||
|
@ -1523,13 +1523,13 @@ trait Backend<'a> {
|
|||
ret_layout,
|
||||
),
|
||||
LowLevel::StrToNum => {
|
||||
let number_layout = match self.interner().get(*ret_layout).repr {
|
||||
let number_layout = match self.interner().get_repr(*ret_layout) {
|
||||
LayoutRepr::Struct(field_layouts) => field_layouts[0], // TODO: why is it sometimes a struct?
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// match on the return layout to figure out which zig builtin we need
|
||||
let intrinsic = match self.interner().get(number_layout).repr {
|
||||
let intrinsic = match self.interner().get_repr(number_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
|
||||
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
|
||||
&bitcode::STR_TO_FLOAT[float_width]
|
||||
|
@ -1549,7 +1549,7 @@ trait Backend<'a> {
|
|||
self.build_ptr_cast(sym, &args[0])
|
||||
}
|
||||
LowLevel::PtrWrite => {
|
||||
let element_layout = match self.interner().get(*ret_layout).repr {
|
||||
let element_layout = match self.interner().get_repr(*ret_layout) {
|
||||
LayoutRepr::Boxed(boxed) => boxed,
|
||||
_ => unreachable!("cannot write to {:?}", self.interner().dbg(*ret_layout)),
|
||||
};
|
||||
|
@ -1600,7 +1600,7 @@ trait Backend<'a> {
|
|||
),
|
||||
LowLevel::NumToStr => {
|
||||
let arg_layout = arg_layouts[0];
|
||||
let intrinsic = match self.interner().get(arg_layout).repr {
|
||||
let intrinsic = match self.interner().get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => &bitcode::STR_FROM_INT[width],
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => &bitcode::STR_FROM_FLOAT[width],
|
||||
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_TO_STR,
|
||||
|
@ -1614,12 +1614,12 @@ trait Backend<'a> {
|
|||
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout);
|
||||
}
|
||||
LowLevel::NumIntCast => {
|
||||
let source_width = match self.interner().get(arg_layouts[0]).repr {
|
||||
let source_width = match self.interner().get_repr(arg_layouts[0]) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let target_width = match self.interner().get(*ret_layout).repr {
|
||||
let target_width = match self.interner().get_repr(*ret_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
|
|
@ -464,7 +464,7 @@ fn build_exposed_generic_proc<'a, B: Backend<'a>>(backend: &mut B, proc: &Proc<'
|
|||
|
||||
let box_layout = backend
|
||||
.interner_mut()
|
||||
.insert_no_semantic(roc_mono::layout::LayoutRepr::Boxed(proc.ret_layout));
|
||||
.insert_direct_no_semantic(roc_mono::layout::LayoutRepr::Boxed(proc.ret_layout));
|
||||
|
||||
let mut args = bumpalo::collections::Vec::new_in(arena);
|
||||
args.extend(proc.args);
|
||||
|
|
|
@ -610,7 +610,7 @@ pub fn build_compare_wrapper<'a, 'ctx>(
|
|||
|
||||
let closure_data_repr = closure_data_layout.runtime_representation();
|
||||
|
||||
let arguments_cast = match layout_interner.get(closure_data_repr).repr {
|
||||
let arguments_cast = match layout_interner.get_repr(closure_data_repr) {
|
||||
LayoutRepr::Struct(&[]) => {
|
||||
// nothing to add
|
||||
&default
|
||||
|
|
|
@ -783,7 +783,7 @@ pub fn build_exp_literal<'a, 'ctx>(
|
|||
use roc_mono::ir::Literal::*;
|
||||
|
||||
match literal {
|
||||
Int(bytes) => match layout_interner.get(layout).repr {
|
||||
Int(bytes) => match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Bool) => env
|
||||
.context
|
||||
.bool_type()
|
||||
|
@ -797,7 +797,7 @@ pub fn build_exp_literal<'a, 'ctx>(
|
|||
|
||||
U128(bytes) => const_u128(env, u128::from_ne_bytes(*bytes)).into(),
|
||||
|
||||
Float(float) => match layout_interner.get(layout).repr {
|
||||
Float(float) => match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
|
||||
float_with_precision(env, *float, float_width)
|
||||
}
|
||||
|
@ -1178,7 +1178,7 @@ pub fn build_exp_expr<'a, 'ctx>(
|
|||
let tag_ptr = tag_ptr.into_pointer_value();
|
||||
|
||||
// reset is only generated for union values
|
||||
let union_layout = match layout_interner.get(layout).repr {
|
||||
let union_layout = match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Union(ul) => ul,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -1323,7 +1323,7 @@ pub fn build_exp_expr<'a, 'ctx>(
|
|||
} => {
|
||||
let (value, layout) = load_symbol_and_layout(scope, structure);
|
||||
|
||||
let layout = if let LayoutRepr::LambdaSet(lambda_set) = layout_interner.get(layout).repr
|
||||
let layout = if let LayoutRepr::LambdaSet(lambda_set) = layout_interner.get_repr(layout)
|
||||
{
|
||||
lambda_set.runtime_representation()
|
||||
} else {
|
||||
|
@ -1331,7 +1331,7 @@ pub fn build_exp_expr<'a, 'ctx>(
|
|||
};
|
||||
|
||||
// extract field from a record
|
||||
match (value, layout_interner.get(layout).repr) {
|
||||
match (value, layout_interner.get_repr(layout)) {
|
||||
(StructValue(argument), LayoutRepr::Struct(field_layouts)) => {
|
||||
debug_assert!(!field_layouts.is_empty());
|
||||
|
||||
|
@ -1385,8 +1385,8 @@ pub fn build_exp_expr<'a, 'ctx>(
|
|||
|
||||
let field_layouts = tag_layouts[*tag_id as usize];
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let struct_layout = layout_interner
|
||||
.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let struct_type = basic_type_from_layout(env, layout_interner, struct_layout);
|
||||
|
||||
let opaque_data_ptr = env
|
||||
|
@ -1442,8 +1442,8 @@ pub fn build_exp_expr<'a, 'ctx>(
|
|||
)
|
||||
}
|
||||
UnionLayout::NonNullableUnwrapped(field_layouts) => {
|
||||
let struct_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let struct_layout = layout_interner
|
||||
.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
|
||||
let struct_type = basic_type_from_layout(env, layout_interner, struct_layout);
|
||||
let target_loaded_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
@ -1493,8 +1493,8 @@ pub fn build_exp_expr<'a, 'ctx>(
|
|||
debug_assert_ne!(*tag_id != 0, *nullable_id);
|
||||
|
||||
let field_layouts = other_fields;
|
||||
let struct_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let struct_layout = layout_interner
|
||||
.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
|
||||
let struct_type = basic_type_from_layout(env, layout_interner, struct_layout);
|
||||
let target_loaded_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
@ -1625,7 +1625,7 @@ fn build_tag_field_value<'a, 'ctx>(
|
|||
value: BasicValueEnum<'ctx>,
|
||||
tag_field_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
if let LayoutRepr::RecursivePointer(_) = layout_interner.get(tag_field_layout).repr {
|
||||
if let LayoutRepr::RecursivePointer(_) = layout_interner.get_repr(tag_field_layout) {
|
||||
debug_assert!(value.is_pointer_value());
|
||||
|
||||
// we store recursive pointers as `i64*`
|
||||
|
@ -1696,7 +1696,10 @@ fn build_struct<'a, 'ctx>(
|
|||
// Zero-sized fields have no runtime representation.
|
||||
// The layout of the struct expects them to be dropped!
|
||||
let (field_expr, field_layout) = load_symbol_and_layout(scope, symbol);
|
||||
if !layout_interner.get(field_layout).is_dropped_because_empty() {
|
||||
if !layout_interner
|
||||
.get_repr(field_layout)
|
||||
.is_dropped_because_empty()
|
||||
{
|
||||
let field_type = basic_type_from_layout(env, layout_interner, field_layout);
|
||||
field_types.push(field_type);
|
||||
|
||||
|
@ -1780,8 +1783,8 @@ fn build_tag<'a, 'ctx>(
|
|||
use std::cmp::Ordering::*;
|
||||
match tag_id.cmp(&(*nullable_id as _)) {
|
||||
Equal => {
|
||||
let layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Union(*union_layout));
|
||||
let layout = layout_interner
|
||||
.insert_direct_no_semantic(LayoutRepr::Union(*union_layout));
|
||||
|
||||
return basic_type_from_layout(env, layout_interner, layout)
|
||||
.into_pointer_type()
|
||||
|
@ -2133,7 +2136,8 @@ fn lookup_at_index_ptr2<'a, 'ctx>(
|
|||
) -> BasicValueEnum<'ctx> {
|
||||
let builder = env.builder;
|
||||
|
||||
let struct_layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let struct_layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let struct_type =
|
||||
basic_type_from_layout(env, layout_interner, struct_layout).into_struct_type();
|
||||
|
||||
|
@ -2545,7 +2549,7 @@ pub fn build_exp_stmt<'a, 'ctx>(
|
|||
|
||||
for (symbol, expr, layout) in queue {
|
||||
debug_assert!(!matches!(
|
||||
layout_interner.get(*layout).repr,
|
||||
layout_interner.get_repr(*layout),
|
||||
LayoutRepr::RecursivePointer(_)
|
||||
));
|
||||
|
||||
|
@ -2845,12 +2849,12 @@ pub fn build_exp_stmt<'a, 'ctx>(
|
|||
DecRef(symbol) => {
|
||||
let (value, layout) = load_symbol_and_layout(scope, symbol);
|
||||
|
||||
let lay = layout_interner.get(layout);
|
||||
match lay.repr {
|
||||
let lay = layout_interner.get_repr(layout);
|
||||
match lay {
|
||||
LayoutRepr::Builtin(Builtin::Str) => todo!(),
|
||||
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
|
||||
debug_assert!(value.is_struct_value());
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let element_layout = layout_interner.get_repr(element_layout);
|
||||
let alignment =
|
||||
element_layout.alignment_bytes(layout_interner, env.target_info);
|
||||
|
||||
|
@ -2859,7 +2863,7 @@ pub fn build_exp_stmt<'a, 'ctx>(
|
|||
|
||||
_ if lay.is_refcounted() => {
|
||||
if value.is_pointer_value() {
|
||||
let value_ptr = match lay.repr {
|
||||
let value_ptr = match lay {
|
||||
LayoutRepr::Union(union_layout)
|
||||
if union_layout
|
||||
.stores_tag_id_in_pointer(env.target_info) =>
|
||||
|
@ -3437,7 +3441,7 @@ fn build_switch_ir<'a, 'ctx>(
|
|||
let cont_block = context.append_basic_block(parent, "cont");
|
||||
|
||||
// Build the condition
|
||||
let cond = match layout_interner.get(cond_layout).repr {
|
||||
let cond = match layout_interner.get_repr(cond_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
|
||||
// float matches are done on the bit pattern
|
||||
cond_layout = Layout::float_width(float_width);
|
||||
|
@ -3463,7 +3467,7 @@ fn build_switch_ir<'a, 'ctx>(
|
|||
// Build the cases
|
||||
let mut incoming = Vec::with_capacity_in(branches.len(), arena);
|
||||
|
||||
if let LayoutRepr::Builtin(Builtin::Bool) = layout_interner.get(cond_layout).repr {
|
||||
if let LayoutRepr::Builtin(Builtin::Bool) = layout_interner.get_repr(cond_layout) {
|
||||
match (branches, default_branch) {
|
||||
([(0, _, false_branch)], true_branch) | ([(1, _, true_branch)], false_branch) => {
|
||||
let then_block = context.append_basic_block(parent, "then_block");
|
||||
|
@ -3764,7 +3768,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let wrapped_layout = layout_interner.insert_no_semantic(roc_call_result_layout(
|
||||
let wrapped_layout = layout_interner.insert_direct_no_semantic(roc_call_result_layout(
|
||||
env.arena,
|
||||
return_layout,
|
||||
env.target_info,
|
||||
|
@ -3871,7 +3875,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
|
|||
// the C and Fast calling conventions agree
|
||||
arguments_for_call.push(*arg);
|
||||
} else {
|
||||
match layout_interner.get(*layout).repr {
|
||||
match layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(_)) => {
|
||||
let list_type = arg_type
|
||||
.into_pointer_type()
|
||||
|
@ -3905,7 +3909,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
|
|||
|
||||
builder.position_at_end(last_block);
|
||||
|
||||
let wrapper_result = layout_interner.insert_no_semantic(LayoutRepr::struct_(
|
||||
let wrapper_result = layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(
|
||||
env.arena.alloc([Layout::U64, return_layout]),
|
||||
));
|
||||
|
||||
|
@ -4010,7 +4014,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
|
|||
};
|
||||
|
||||
for (i, layout) in arguments.iter().enumerate() {
|
||||
if let LayoutRepr::Builtin(Builtin::Str) = layout_interner.get(*layout).repr {
|
||||
if let LayoutRepr::Builtin(Builtin::Str) = layout_interner.get_repr(*layout) {
|
||||
// Indicate to LLVM that this argument is semantically passed by-value
|
||||
// even though technically (because of its size) it is passed by-reference
|
||||
let byval_attribute_id = Attribute::get_named_enum_kind_id("byval");
|
||||
|
@ -4110,7 +4114,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
|
|||
env.target_info.architecture,
|
||||
roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64
|
||||
) {
|
||||
let c_abi_type = match layout_interner.get(*layout).repr {
|
||||
let c_abi_type = match layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Builtin(Builtin::Str | Builtin::List(_)) => {
|
||||
c_abi_roc_str_type
|
||||
}
|
||||
|
@ -5679,7 +5683,7 @@ fn to_cc_type<'a, 'ctx>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
match layout_interner.runtime_representation(layout).repr {
|
||||
match layout_interner.runtime_representation(layout) {
|
||||
LayoutRepr::Builtin(builtin) => to_cc_type_builtin(env, &builtin),
|
||||
_ => {
|
||||
// TODO this is almost certainly incorrect for bigger structs
|
||||
|
@ -5726,7 +5730,7 @@ impl RocReturn {
|
|||
target_info: TargetInfo,
|
||||
layout: InLayout,
|
||||
) -> bool {
|
||||
match interner.get(layout).repr {
|
||||
match interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(builtin) => {
|
||||
use Builtin::*;
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ fn build_eq<'a, 'ctx>(
|
|||
rhs_layout
|
||||
);
|
||||
|
||||
match layout_interner.get(*lhs_layout).repr {
|
||||
match layout_interner.get_repr(*lhs_layout) {
|
||||
LayoutRepr::Builtin(builtin) => build_eq_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -215,7 +215,7 @@ fn build_eq<'a, 'ctx>(
|
|||
"i64_to_opaque",
|
||||
);
|
||||
|
||||
let union_layout = match layout_interner.get(rec_layout).repr {
|
||||
let union_layout = match layout_interner.get_repr(rec_layout) {
|
||||
LayoutRepr::Union(union_layout) => {
|
||||
debug_assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
|
||||
union_layout
|
||||
|
@ -342,7 +342,7 @@ fn build_neq<'a, 'ctx>(
|
|||
);
|
||||
}
|
||||
|
||||
match layout_interner.get(lhs_layout).repr {
|
||||
match layout_interner.get_repr(lhs_layout) {
|
||||
LayoutRepr::Builtin(builtin) => build_neq_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -425,7 +425,7 @@ fn build_list_eq<'a, 'ctx>(
|
|||
|
||||
let symbol = Symbol::LIST_EQ;
|
||||
let element_layout =
|
||||
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get(element_layout).repr {
|
||||
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get_repr(element_layout) {
|
||||
rec
|
||||
} else {
|
||||
element_layout
|
||||
|
@ -742,10 +742,10 @@ fn build_struct_eq_help<'a, 'ctx>(
|
|||
.unwrap();
|
||||
|
||||
let are_equal = if let LayoutRepr::RecursivePointer(rec_layout) =
|
||||
layout_interner.get(*field_layout).repr
|
||||
layout_interner.get_repr(*field_layout)
|
||||
{
|
||||
debug_assert!(
|
||||
matches!(layout_interner.get(rec_layout).repr, LayoutRepr::Union(union_layout) if !matches!(union_layout, UnionLayout::NonRecursive(..)))
|
||||
matches!(layout_interner.get_repr(rec_layout), LayoutRepr::Union(union_layout) if !matches!(union_layout, UnionLayout::NonRecursive(..)))
|
||||
);
|
||||
|
||||
let field_layout = rec_layout;
|
||||
|
@ -973,7 +973,7 @@ fn build_tag_eq_help<'a, 'ctx>(
|
|||
env.builder.position_at_end(block);
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
|
@ -1046,7 +1046,7 @@ fn build_tag_eq_help<'a, 'ctx>(
|
|||
env.builder.position_at_end(block);
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
|
@ -1109,7 +1109,7 @@ fn build_tag_eq_help<'a, 'ctx>(
|
|||
env.builder.position_at_end(compare_other);
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(other_fields));
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(other_fields));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
|
@ -1214,7 +1214,7 @@ fn build_tag_eq_help<'a, 'ctx>(
|
|||
env.builder.position_at_end(block);
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
|
@ -1255,7 +1255,7 @@ fn build_tag_eq_help<'a, 'ctx>(
|
|||
env.builder.position_at_end(compare_fields);
|
||||
|
||||
let struct_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
|
|
|
@ -36,7 +36,7 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
) -> BasicTypeEnum<'ctx> {
|
||||
use LayoutRepr::*;
|
||||
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
Struct(sorted_fields, ..) => basic_type_from_record(env, layout_interner, sorted_fields),
|
||||
LambdaSet(lambda_set) => {
|
||||
basic_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
|
||||
|
@ -150,7 +150,7 @@ pub fn argument_type_from_layout<'a, 'ctx>(
|
|||
) -> BasicTypeEnum<'ctx> {
|
||||
use LayoutRepr::*;
|
||||
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
LambdaSet(lambda_set) => {
|
||||
argument_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
|
||||
}
|
||||
|
|
|
@ -296,7 +296,7 @@ fn build_clone<'a, 'ctx>(
|
|||
value: BasicValueEnum<'ctx>,
|
||||
layout: InLayout<'a>,
|
||||
) -> IntValue<'ctx> {
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(builtin) => build_clone_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -396,7 +396,7 @@ fn build_clone<'a, 'ctx>(
|
|||
"i64_to_opaque",
|
||||
);
|
||||
|
||||
let union_layout = match layout_interner.get(rec_layout).repr {
|
||||
let union_layout = match layout_interner.get_repr(rec_layout) {
|
||||
LayoutRepr::Union(union_layout) => {
|
||||
debug_assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
|
||||
union_layout
|
||||
|
@ -476,7 +476,7 @@ fn build_clone_tag<'a, 'ctx>(
|
|||
value: BasicValueEnum<'ctx>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
) -> IntValue<'ctx> {
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout_id = layout_ids.get(Symbol::CLONE, &layout);
|
||||
let fn_name = layout_id.to_symbol_string(Symbol::CLONE, &env.interns);
|
||||
|
||||
|
@ -690,7 +690,7 @@ fn build_clone_tag_help<'a, 'ctx>(
|
|||
|
||||
// load the tag payload (if any)
|
||||
let payload_layout = LayoutRepr::struct_(field_layouts);
|
||||
let payload_in_layout = layout_interner.insert_no_semantic(payload_layout);
|
||||
let payload_in_layout = layout_interner.insert_direct_no_semantic(payload_layout);
|
||||
|
||||
let opaque_payload_ptr = env
|
||||
.builder
|
||||
|
@ -748,11 +748,12 @@ fn build_clone_tag_help<'a, 'ctx>(
|
|||
|
||||
let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
|
||||
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let layout = if union_layout.stores_tag_id_in_pointer(env.target_info) {
|
||||
layout
|
||||
} else {
|
||||
layout_interner.insert_no_semantic(LayoutRepr::struct_(
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(
|
||||
env.arena.alloc([layout, union_layout.tag_id_layout()]),
|
||||
))
|
||||
};
|
||||
|
@ -797,7 +798,7 @@ fn build_clone_tag_help<'a, 'ctx>(
|
|||
|
||||
build_copy(env, ptr, offset, extra_offset.into());
|
||||
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(fields));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(fields));
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
@ -853,7 +854,8 @@ fn build_clone_tag_help<'a, 'ctx>(
|
|||
other_tags[i]
|
||||
};
|
||||
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(fields));
|
||||
let layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(fields));
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
let (width, _) =
|
||||
|
@ -928,7 +930,8 @@ fn build_clone_tag_help<'a, 'ctx>(
|
|||
// write the "pointer" af the current offset
|
||||
build_copy(env, ptr, offset, extra_offset.into());
|
||||
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(other_fields));
|
||||
let layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(other_fields));
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
let cursors = Cursors {
|
||||
|
|
|
@ -200,13 +200,13 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
// Str.toNum : Str -> Result (Num *) {}
|
||||
arguments!(string);
|
||||
|
||||
let number_layout = match layout_interner.get(layout).repr {
|
||||
let number_layout = match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Struct(field_layouts) => field_layouts[0], // TODO: why is it sometimes a struct?
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// match on the return layout to figure out which zig builtin we need
|
||||
let intrinsic = match layout_interner.get(number_layout).repr {
|
||||
let intrinsic = match layout_interner.get_repr(number_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
|
||||
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
|
||||
&bitcode::STR_TO_FLOAT[float_width]
|
||||
|
@ -229,7 +229,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
intrinsic,
|
||||
),
|
||||
None => {
|
||||
let return_type_name = match layout_interner.get(number_layout).repr {
|
||||
let return_type_name = match layout_interner.get_repr(number_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
|
||||
int_width.type_name()
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
}
|
||||
}
|
||||
PtrWidth::Bytes8 => {
|
||||
let cc_return_by_pointer = match layout_interner.get(number_layout).repr {
|
||||
let cc_return_by_pointer = match layout_interner.get_repr(number_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
|
||||
(int_width.stack_size() as usize > env.target_info.ptr_size())
|
||||
.then_some(int_width.type_name())
|
||||
|
@ -325,7 +325,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
let (int, int_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let int = int.into_int_value();
|
||||
|
||||
let int_width = match layout_interner.get(int_layout).repr {
|
||||
let int_width = match layout_interner.get_repr(int_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -344,7 +344,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
|
||||
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
||||
let float_width = match layout_interner.get(float_layout).repr {
|
||||
let float_width = match layout_interner.get_repr(float_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Float(float_width)) => float_width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -854,7 +854,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
// Num.toStr : Num a -> Str
|
||||
arguments_with_layouts!((num, num_layout));
|
||||
|
||||
match layout_interner.get(num_layout).repr {
|
||||
match layout_interner.get_repr(num_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
|
||||
let int = num.into_int_value();
|
||||
|
||||
|
@ -869,7 +869,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
LayoutRepr::Builtin(Builtin::Float(_float_width)) => {
|
||||
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
||||
let float_width = match layout_interner.get(float_layout).repr {
|
||||
let float_width = match layout_interner.get_repr(float_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Float(float_width)) => float_width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -908,7 +908,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
| NumCountOneBits => {
|
||||
arguments_with_layouts!((arg, arg_layout));
|
||||
|
||||
match layout_interner.get(arg_layout).repr {
|
||||
match layout_interner.get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(arg_builtin) => {
|
||||
use roc_mono::layout::Builtin::*;
|
||||
|
||||
|
@ -996,8 +996,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
|
||||
use inkwell::FloatPredicate;
|
||||
match (
|
||||
layout_interner.get(lhs_layout).repr,
|
||||
layout_interner.get(rhs_layout).repr,
|
||||
layout_interner.get_repr(lhs_layout),
|
||||
layout_interner.get_repr(rhs_layout),
|
||||
) {
|
||||
(LayoutRepr::Builtin(lhs_builtin), LayoutRepr::Builtin(rhs_builtin))
|
||||
if lhs_builtin == rhs_builtin =>
|
||||
|
@ -1152,7 +1152,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
NumToFloatCast => {
|
||||
arguments_with_layouts!((arg, arg_layout));
|
||||
|
||||
match layout_interner.get(arg_layout).repr {
|
||||
match layout_interner.get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
// Converting from int to float
|
||||
let int_val = arg.into_int_value();
|
||||
|
@ -1291,7 +1291,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
"cast_to_i8_ptr",
|
||||
);
|
||||
|
||||
let value_ptr = match layout_interner.get(data_layout).repr {
|
||||
let value_ptr = match layout_interner.get_repr(data_layout) {
|
||||
LayoutRepr::Union(union_layout)
|
||||
if union_layout.stores_tag_id_in_pointer(env.target_info) =>
|
||||
{
|
||||
|
@ -1562,8 +1562,8 @@ pub fn build_num_binop<'a, 'ctx>(
|
|||
op: LowLevel,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match (
|
||||
layout_interner.get(lhs_layout).repr,
|
||||
layout_interner.get(rhs_layout).repr,
|
||||
layout_interner.get_repr(lhs_layout),
|
||||
layout_interner.get_repr(rhs_layout),
|
||||
) {
|
||||
(LayoutRepr::Builtin(lhs_builtin), LayoutRepr::Builtin(rhs_builtin))
|
||||
if lhs_builtin == rhs_builtin =>
|
||||
|
@ -2031,7 +2031,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
NumToFrac => {
|
||||
// This is an Int, so we need to convert it.
|
||||
|
||||
let target_float_type = match layout_interner.get(return_layout).repr {
|
||||
let target_float_type = match layout_interner.get_repr(return_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
|
||||
convert::float_type_from_float_width(env, float_width)
|
||||
}
|
||||
|
@ -2048,7 +2048,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
NumToIntChecked => {
|
||||
// return_layout : Result N [OutOfBounds]* ~ { result: N, out_of_bounds: bool }
|
||||
|
||||
let target_int_width = match layout_interner.get(return_layout).repr {
|
||||
let target_int_width = match layout_interner.get_repr(return_layout) {
|
||||
LayoutRepr::Struct(field_layouts) if field_layouts.len() == 2 => {
|
||||
debug_assert!(layout_interner.eq_repr(field_layouts[1], Layout::BOOL));
|
||||
field_layouts[0].to_int_width()
|
||||
|
@ -2328,7 +2328,7 @@ fn build_float_unary_op<'a, 'ctx>(
|
|||
NumSqrtUnchecked => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_SQRT[float_width]),
|
||||
NumLogUnchecked => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_LOG[float_width]),
|
||||
NumToFrac => {
|
||||
let return_width = match layout_interner.get(layout).repr {
|
||||
let return_width = match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Float(return_width)) => return_width,
|
||||
_ => internal_error!("Layout for returning is not Float : {:?}", layout),
|
||||
};
|
||||
|
@ -2350,7 +2350,7 @@ fn build_float_unary_op<'a, 'ctx>(
|
|||
}
|
||||
}
|
||||
NumCeiling => {
|
||||
let int_width = match layout_interner.get(layout).repr {
|
||||
let int_width = match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
|
||||
};
|
||||
|
@ -2364,7 +2364,7 @@ fn build_float_unary_op<'a, 'ctx>(
|
|||
}
|
||||
}
|
||||
NumFloor => {
|
||||
let int_width = match layout_interner.get(layout).repr {
|
||||
let int_width = match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
_ => internal_error!("Floor return layout is not int: {:?}", layout),
|
||||
};
|
||||
|
@ -2378,7 +2378,7 @@ fn build_float_unary_op<'a, 'ctx>(
|
|||
}
|
||||
}
|
||||
NumRound => {
|
||||
let int_width = match layout_interner.get(layout).repr {
|
||||
let int_width = match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
_ => internal_error!("Round return layout is not int: {:?}", layout),
|
||||
};
|
||||
|
@ -2465,8 +2465,8 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (
|
||||
layout_interner.get(list_layout).repr,
|
||||
layout_interner.get(return_layout).repr,
|
||||
layout_interner.get_repr(list_layout),
|
||||
layout_interner.get_repr(return_layout),
|
||||
) {
|
||||
(
|
||||
LayoutRepr::Builtin(Builtin::List(element_layout)),
|
||||
|
@ -2505,9 +2505,9 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (
|
||||
layout_interner.get(list1_layout).repr,
|
||||
layout_interner.get(list2_layout).repr,
|
||||
layout_interner.get(return_layout).repr,
|
||||
layout_interner.get_repr(list1_layout),
|
||||
layout_interner.get_repr(list2_layout),
|
||||
layout_interner.get_repr(return_layout),
|
||||
) {
|
||||
(
|
||||
LayoutRepr::Builtin(Builtin::List(element1_layout)),
|
||||
|
@ -2551,10 +2551,10 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (
|
||||
layout_interner.get(list1_layout).repr,
|
||||
layout_interner.get(list2_layout).repr,
|
||||
layout_interner.get(list3_layout).repr,
|
||||
layout_interner.get(return_layout).repr,
|
||||
layout_interner.get_repr(list1_layout),
|
||||
layout_interner.get_repr(list2_layout),
|
||||
layout_interner.get_repr(list3_layout),
|
||||
layout_interner.get_repr(return_layout),
|
||||
) {
|
||||
(
|
||||
LayoutRepr::Builtin(Builtin::List(element1_layout)),
|
||||
|
@ -2602,11 +2602,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (
|
||||
layout_interner.get(list1_layout).repr,
|
||||
layout_interner.get(list2_layout).repr,
|
||||
layout_interner.get(list3_layout).repr,
|
||||
layout_interner.get(list4_layout).repr,
|
||||
layout_interner.get(return_layout).repr,
|
||||
layout_interner.get_repr(list1_layout),
|
||||
layout_interner.get_repr(list2_layout),
|
||||
layout_interner.get_repr(list3_layout),
|
||||
layout_interner.get_repr(list4_layout),
|
||||
layout_interner.get_repr(return_layout),
|
||||
) {
|
||||
(
|
||||
LayoutRepr::Builtin(Builtin::List(element1_layout)),
|
||||
|
@ -2659,7 +2659,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
|
|||
|
||||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match layout_interner.get(list_layout).repr {
|
||||
match layout_interner.get_repr(list_layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
|
||||
use crate::llvm::bitcode::build_compare_wrapper;
|
||||
|
||||
|
@ -2710,7 +2710,7 @@ fn load_symbol_and_lambda_set<'a, 'ctx>(
|
|||
) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) {
|
||||
match scope
|
||||
.get(symbol)
|
||||
.map(|(l, v)| (layout_interner.get(*l).repr, v))
|
||||
.map(|(l, v)| (layout_interner.get_repr(*l), v))
|
||||
{
|
||||
Some((LayoutRepr::LambdaSet(lambda_set), ptr)) => (*ptr, lambda_set),
|
||||
Some((other, ptr)) => panic!("Not a lambda set: {:?}, {:?}", other, ptr),
|
||||
|
|
|
@ -267,7 +267,7 @@ fn modify_refcount_struct<'a, 'ctx>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::struct_(layouts));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(layouts));
|
||||
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
|
@ -470,7 +470,7 @@ fn modify_refcount_layout_help<'a, 'ctx>(
|
|||
None => return,
|
||||
};
|
||||
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::RecursivePointer(rec_layout) => {
|
||||
let layout = rec_layout;
|
||||
|
||||
|
@ -527,7 +527,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx>(
|
|||
) -> Option<FunctionValue<'ctx>> {
|
||||
use LayoutRepr::*;
|
||||
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
Builtin(builtin) => {
|
||||
modify_refcount_builtin(env, layout_interner, layout_ids, mode, layout, &builtin)
|
||||
}
|
||||
|
@ -603,14 +603,14 @@ fn modify_refcount_list<'a, 'ctx>(
|
|||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let element_layout =
|
||||
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get(element_layout).repr {
|
||||
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get_repr(element_layout) {
|
||||
rec
|
||||
} else {
|
||||
element_layout
|
||||
};
|
||||
|
||||
let list_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(element_layout)));
|
||||
let list_layout = layout_interner
|
||||
.insert_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(element_layout)));
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
&env.interns,
|
||||
|
@ -859,7 +859,7 @@ fn modify_refcount_boxed<'a, 'ctx>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let boxed_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(inner_layout));
|
||||
let boxed_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(inner_layout));
|
||||
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
|
@ -921,7 +921,7 @@ fn modify_refcount_box_help<'a, 'ctx>(
|
|||
let boxed = arg_val.into_pointer_value();
|
||||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
let boxed_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(inner_layout));
|
||||
let boxed_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(inner_layout));
|
||||
|
||||
match mode {
|
||||
Mode::Inc => {
|
||||
|
@ -1065,7 +1065,7 @@ fn build_rec_union<'a, 'ctx>(
|
|||
mode: Mode,
|
||||
union_layout: UnionLayout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
|
@ -1168,7 +1168,7 @@ fn build_rec_union_help<'a, 'ctx>(
|
|||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, value_ptr);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
|
||||
match mode {
|
||||
Mode::Inc => {
|
||||
|
@ -1223,7 +1223,7 @@ enum DecOrReuse {
|
|||
|
||||
fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[InLayout]) -> bool {
|
||||
!field_layouts.iter().any(|x| {
|
||||
let x = interner.get(*x);
|
||||
let x = interner.get_repr(*x);
|
||||
x.is_refcounted() || x.contains_refcounted(interner)
|
||||
})
|
||||
}
|
||||
|
@ -1274,7 +1274,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
|
|||
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let fields_struct = layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let fields_struct =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let wrapper_type = basic_type_from_layout(env, layout_interner, fields_struct);
|
||||
|
||||
// cast the opaque pointer to a pointer of the correct shape
|
||||
|
@ -1290,7 +1291,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
|
|||
let mut deferred_nonrec = Vec::new_in(env.arena);
|
||||
|
||||
for (i, field_layout) in field_layouts.iter().enumerate() {
|
||||
if let LayoutRepr::RecursivePointer(_) = layout_interner.get(*field_layout).repr {
|
||||
if let LayoutRepr::RecursivePointer(_) = layout_interner.get_repr(*field_layout) {
|
||||
// this field has type `*i64`, but is really a pointer to the data we want
|
||||
let elem_pointer = env
|
||||
.builder
|
||||
|
@ -1312,7 +1313,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
|
|||
|
||||
// therefore we must cast it to our desired type
|
||||
let union_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let union_type = basic_type_from_layout(env, layout_interner, union_layout);
|
||||
let recursive_field_ptr = cast_basic_basic(env.builder, ptr_as_i64_ptr, union_type);
|
||||
|
||||
|
@ -1351,7 +1352,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
|
|||
DecOrReuse::Reuse => {}
|
||||
DecOrReuse::Dec => {
|
||||
let union_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
|
||||
}
|
||||
}
|
||||
|
@ -1410,7 +1411,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
|
|||
// increment/decrement the cons-cell itself
|
||||
if let DecOrReuse::Dec = decrement_or_reuse {
|
||||
let union_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
|
||||
}
|
||||
}
|
||||
|
@ -1470,7 +1471,8 @@ pub fn build_reset<'a, 'ctx>(
|
|||
) -> FunctionValue<'ctx> {
|
||||
let mode = Mode::Dec;
|
||||
|
||||
let union_layout_in = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let union_layout_in =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout_id = layout_ids.get(Symbol::DEC, &union_layout_in);
|
||||
let fn_name = layout_id.to_symbol_string(Symbol::DEC, &env.interns);
|
||||
let fn_name = format!("{}_reset", fn_name);
|
||||
|
@ -1566,7 +1568,7 @@ fn build_reuse_rec_union_help<'a, 'ctx>(
|
|||
|
||||
env.builder.position_at_end(should_recurse_block);
|
||||
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
|
||||
let do_recurse_block = env.context.append_basic_block(parent, "do_recurse");
|
||||
let no_recurse_block = env.context.append_basic_block(parent, "no_recurse");
|
||||
|
@ -1628,7 +1630,7 @@ fn modify_refcount_nonrecursive<'a, 'ctx>(
|
|||
fields: &'a [&'a [InLayout<'a>]],
|
||||
) -> FunctionValue<'ctx> {
|
||||
let union_layout = UnionLayout::NonRecursive(fields);
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
@ -1698,7 +1700,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
|
|||
let before_block = env.builder.get_insert_block().expect("to be in a function");
|
||||
|
||||
let union_layout = UnionLayout::NonRecursive(tags);
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let union_struct_type = basic_type_from_layout(env, layout_interner, layout).into_struct_type();
|
||||
|
||||
// read the tag_id
|
||||
|
@ -1735,7 +1737,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
|
|||
for (tag_id, field_layouts) in tags.iter().enumerate() {
|
||||
// if none of the fields are or contain anything refcounted, just move on
|
||||
if !field_layouts.iter().any(|x| {
|
||||
let x = layout_interner.get(*x);
|
||||
let x = layout_interner.get_repr(*x);
|
||||
x.is_refcounted() || x.contains_refcounted(layout_interner)
|
||||
}) {
|
||||
continue;
|
||||
|
@ -1744,7 +1746,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
|
|||
let block = env.context.append_basic_block(parent, "tag_id_modify");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let fields_struct = layout_interner.insert_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let fields_struct =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::struct_(field_layouts));
|
||||
let data_struct_type = basic_type_from_layout(env, layout_interner, fields_struct);
|
||||
|
||||
debug_assert!(data_struct_type.is_struct_type());
|
||||
|
@ -1767,7 +1770,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
|
|||
|
||||
for (i, field_layout) in field_layouts.iter().enumerate() {
|
||||
if let LayoutRepr::RecursivePointer(union_layout) =
|
||||
layout_interner.get(*field_layout).repr
|
||||
layout_interner.get_repr(*field_layout)
|
||||
{
|
||||
// This field is a pointer to the recursive pointer.
|
||||
let field_ptr = env
|
||||
|
|
|
@ -507,7 +507,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
let heap_return_ptr_id = LocalId(wrapper_arg_layouts.len() as u32 - 1);
|
||||
let inner_ret_layout = match wrapper_arg_layouts
|
||||
.last()
|
||||
.map(|l| self.layout_interner.get(*l).repr)
|
||||
.map(|l| self.layout_interner.get_repr(*l))
|
||||
{
|
||||
Some(LayoutRepr::Boxed(inner)) => WasmLayout::new(self.layout_interner, inner),
|
||||
x => internal_error!("Higher-order wrapper: invalid return layout {:?}", x),
|
||||
|
@ -539,7 +539,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
continue;
|
||||
}
|
||||
|
||||
let inner_layout = match self.layout_interner.get(*wrapper_arg).repr {
|
||||
let inner_layout = match self.layout_interner.get_repr(*wrapper_arg) {
|
||||
LayoutRepr::Boxed(inner) => inner,
|
||||
x => internal_error!("Expected a Boxed layout, got {:?}", x),
|
||||
};
|
||||
|
@ -558,7 +558,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
if self.layout_interner.stack_size(closure_data_layout) > 0 {
|
||||
// The closure data exists, and will have been passed in to the wrapper as a
|
||||
// one-element struct.
|
||||
let inner_closure_data_layout = match self.layout_interner.get(closure_data_layout).repr
|
||||
let inner_closure_data_layout = match self.layout_interner.get_repr(closure_data_layout)
|
||||
{
|
||||
LayoutRepr::Struct([inner]) => inner,
|
||||
other => internal_error!(
|
||||
|
@ -633,7 +633,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
n_inner_args += 1;
|
||||
}
|
||||
|
||||
let inner_layout = match self.layout_interner.get(value_layout).repr {
|
||||
let inner_layout = match self.layout_interner.get_repr(value_layout) {
|
||||
LayoutRepr::Boxed(inner) => inner,
|
||||
x => internal_error!("Expected a Boxed layout, got {:?}", x),
|
||||
};
|
||||
|
@ -662,7 +662,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
fn dereference_boxed_value(&mut self, inner: InLayout) {
|
||||
use Align::*;
|
||||
|
||||
match self.layout_interner.get(inner).repr {
|
||||
match self.layout_interner.get_repr(inner) {
|
||||
LayoutRepr::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8)) => {
|
||||
self.code_builder.i32_load8_u(Bytes1, 0);
|
||||
}
|
||||
|
@ -1367,7 +1367,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
arguments,
|
||||
ret_symbol,
|
||||
ret_layout,
|
||||
ret_layout_raw: self.layout_interner.get(ret_layout),
|
||||
ret_layout_raw: self.layout_interner.get_repr(ret_layout),
|
||||
ret_storage: ret_storage.to_owned(),
|
||||
};
|
||||
low_level_call.generate(self);
|
||||
|
@ -1445,7 +1445,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
storage: &StoredValue,
|
||||
fields: &'a [Symbol],
|
||||
) {
|
||||
match self.layout_interner.get(layout).repr {
|
||||
match self.layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Struct { .. } => {
|
||||
match storage {
|
||||
StoredValue::StackMemory { location, size, .. } => {
|
||||
|
@ -1903,7 +1903,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
};
|
||||
|
||||
// allocate heap memory and load its data address onto the value stack
|
||||
let arg_layout = match self.layout_interner.get(layout).repr {
|
||||
let arg_layout = match self.layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Boxed(arg) => arg,
|
||||
_ => internal_error!("ExprBox should always produce a Boxed layout"),
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@ impl WasmLayout {
|
|||
|
||||
let (size, alignment_bytes) = interner.stack_size_and_alignment(layout);
|
||||
|
||||
match interner.get(layout).repr {
|
||||
match interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Int(int_width)) => {
|
||||
use IntWidth::*;
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ pub struct LowLevelCall<'a> {
|
|||
pub arguments: &'a [Symbol],
|
||||
pub ret_symbol: Symbol,
|
||||
pub ret_layout: InLayout<'a>,
|
||||
pub ret_layout_raw: Layout<'a>,
|
||||
pub ret_layout_raw: LayoutRepr<'a>,
|
||||
pub ret_storage: StoredValue,
|
||||
}
|
||||
|
||||
|
@ -237,14 +237,14 @@ impl<'a> LowLevelCall<'a> {
|
|||
}
|
||||
StrGetCapacity => self.load_args_and_call_zig(backend, bitcode::STR_CAPACITY),
|
||||
StrToNum => {
|
||||
let number_layout = match backend.layout_interner.get(self.ret_layout).repr {
|
||||
let number_layout = match backend.layout_interner.get_repr(self.ret_layout) {
|
||||
LayoutRepr::Struct(field_layouts) => field_layouts[0],
|
||||
_ => {
|
||||
internal_error!("Unexpected mono layout {:?} for StrToNum", self.ret_layout)
|
||||
}
|
||||
};
|
||||
// match on the return layout to figure out which zig builtin we need
|
||||
let intrinsic = match backend.layout_interner.get(number_layout).repr {
|
||||
let intrinsic = match backend.layout_interner.get_repr(number_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
|
||||
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
|
||||
&bitcode::STR_TO_FLOAT[float_width]
|
||||
|
@ -388,14 +388,13 @@ impl<'a> LowLevelCall<'a> {
|
|||
};
|
||||
|
||||
// Byte offsets of each field in the return struct
|
||||
let (ret_list_offset, ret_elem_offset, elem_layout) = match self.ret_layout_raw.repr
|
||||
{
|
||||
let (ret_list_offset, ret_elem_offset, elem_layout) = match self.ret_layout_raw {
|
||||
LayoutRepr::Struct(&[f1, f2]) => {
|
||||
let l1 = backend.layout_interner.get(f1);
|
||||
let l2 = backend.layout_interner.get(f2);
|
||||
match (l1.repr, l2.repr) {
|
||||
let l1 = backend.layout_interner.get_repr(f1);
|
||||
let l2 = backend.layout_interner.get_repr(f2);
|
||||
match (l1, l2) {
|
||||
(LayoutRepr::Builtin(Builtin::List(list_elem)), _)
|
||||
if l2.repr == backend.layout_interner.get(list_elem).repr =>
|
||||
if l2 == backend.layout_interner.get_repr(list_elem) =>
|
||||
{
|
||||
let list_offset = 0;
|
||||
let elem_offset = LayoutRepr::Builtin(Builtin::List(list_elem))
|
||||
|
@ -403,7 +402,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
(list_offset, elem_offset, f2)
|
||||
}
|
||||
(_, LayoutRepr::Builtin(Builtin::List(list_elem)))
|
||||
if l1.repr == backend.layout_interner.get(list_elem).repr =>
|
||||
if l1 == backend.layout_interner.get_repr(list_elem) =>
|
||||
{
|
||||
let list_offset =
|
||||
l1.stack_size(backend.layout_interner, TARGET_INFO);
|
||||
|
@ -467,7 +466,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
let capacity: Symbol = self.arguments[0];
|
||||
let elem_layout = unwrap_list_elem_layout(self.ret_layout_raw);
|
||||
let elem_layout = backend.layout_interner.get(elem_layout);
|
||||
let elem_layout = backend.layout_interner.get_repr(elem_layout);
|
||||
let (elem_width, elem_align) =
|
||||
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
|
||||
|
||||
|
@ -506,7 +505,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
// Load monomorphization constants
|
||||
let elem_layout = unwrap_list_elem_layout(self.ret_layout_raw);
|
||||
let elem_layout = backend.layout_interner.get(elem_layout);
|
||||
let elem_layout = backend.layout_interner.get_repr(elem_layout);
|
||||
let (elem_width, elem_align) =
|
||||
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
|
||||
backend.code_builder.i32_const(elem_align as i32);
|
||||
|
@ -522,7 +521,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
let spare: Symbol = self.arguments[1];
|
||||
|
||||
let elem_layout = unwrap_list_elem_layout(self.ret_layout_raw);
|
||||
let elem_layout = backend.layout_interner.get(elem_layout);
|
||||
let elem_layout = backend.layout_interner.get_repr(elem_layout);
|
||||
let (elem_width, elem_align) =
|
||||
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
|
||||
|
||||
|
@ -563,7 +562,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
let list: Symbol = self.arguments[0];
|
||||
|
||||
let elem_layout = unwrap_list_elem_layout(self.ret_layout_raw);
|
||||
let elem_layout = backend.layout_interner.get(elem_layout);
|
||||
let elem_layout = backend.layout_interner.get_repr(elem_layout);
|
||||
let (elem_width, elem_align) =
|
||||
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
|
||||
|
||||
|
@ -690,9 +689,12 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
// The refcount function receives a pointer to an element in the list
|
||||
// This is the same as a Struct containing the element
|
||||
let in_memory_layout = backend
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([elem_layout])));
|
||||
let in_memory_layout =
|
||||
backend
|
||||
.layout_interner
|
||||
.insert_direct_no_semantic(LayoutRepr::Struct(
|
||||
backend.env.arena.alloc([elem_layout]),
|
||||
));
|
||||
let dec_fn = backend.get_refcount_fn_index(in_memory_layout, HelperOp::Dec);
|
||||
let dec_fn_ptr = backend.get_fn_ptr(dec_fn);
|
||||
|
||||
|
@ -735,9 +737,12 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
// The refcount function receives a pointer to an element in the list
|
||||
// This is the same as a Struct containing the element
|
||||
let in_memory_layout = backend
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([elem_layout])));
|
||||
let in_memory_layout =
|
||||
backend
|
||||
.layout_interner
|
||||
.insert_direct_no_semantic(LayoutRepr::Struct(
|
||||
backend.env.arena.alloc([elem_layout]),
|
||||
));
|
||||
let dec_fn = backend.get_refcount_fn_index(in_memory_layout, HelperOp::Dec);
|
||||
let dec_fn_ptr = backend.get_fn_ptr(dec_fn);
|
||||
|
||||
|
@ -809,7 +814,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
}
|
||||
|
||||
// Num
|
||||
NumAdd => match self.ret_layout_raw.repr {
|
||||
NumAdd => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_OR_PANIC_INT[width])
|
||||
}
|
||||
|
@ -829,7 +834,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
_ => panic_ret_type(),
|
||||
},
|
||||
|
||||
NumAddWrap => match self.ret_layout_raw.repr {
|
||||
NumAddWrap => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
|
||||
IntWidth::I128 | IntWidth::U128 => {
|
||||
// TODO: don't panic
|
||||
|
@ -869,7 +874,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
NumToStr => self.num_to_str(backend),
|
||||
NumAddChecked => {
|
||||
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
|
||||
match backend.layout_interner.get(arg_layout).repr {
|
||||
match backend.layout_interner.get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_CHECKED_INT[width])
|
||||
}
|
||||
|
@ -882,7 +887,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
x => internal_error!("NumAddChecked is not defined for {:?}", x),
|
||||
}
|
||||
}
|
||||
NumAddSaturated => match self.ret_layout_raw.repr {
|
||||
NumAddSaturated => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_SATURATED_INT[width])
|
||||
}
|
||||
|
@ -900,7 +905,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
_ => panic_ret_type(),
|
||||
},
|
||||
|
||||
NumSub => match self.ret_layout_raw.repr {
|
||||
NumSub => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_OR_PANIC_INT[width])
|
||||
}
|
||||
|
@ -920,7 +925,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
_ => panic_ret_type(),
|
||||
},
|
||||
|
||||
NumSubWrap => match self.ret_layout_raw.repr {
|
||||
NumSubWrap => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
|
||||
IntWidth::I128 | IntWidth::U128 => {
|
||||
// TODO: don't panic
|
||||
|
@ -958,7 +963,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
},
|
||||
NumSubChecked => {
|
||||
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
|
||||
match backend.layout_interner.get(arg_layout).repr {
|
||||
match backend.layout_interner.get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_CHECKED_INT[width])
|
||||
}
|
||||
|
@ -971,7 +976,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
x => internal_error!("NumSubChecked is not defined for {:?}", x),
|
||||
}
|
||||
}
|
||||
NumSubSaturated => match self.ret_layout_raw.repr {
|
||||
NumSubSaturated => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_SATURATED_INT[width])
|
||||
}
|
||||
|
@ -989,7 +994,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
_ => panic_ret_type(),
|
||||
},
|
||||
|
||||
NumMul => match self.ret_layout_raw.repr {
|
||||
NumMul => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_OR_PANIC_INT[width])
|
||||
}
|
||||
|
@ -1008,7 +1013,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
}
|
||||
_ => panic_ret_type(),
|
||||
},
|
||||
NumMulWrap => match self.ret_layout_raw.repr {
|
||||
NumMulWrap => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
|
||||
IntWidth::I128 | IntWidth::U128 => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_WRAP_INT[width])
|
||||
|
@ -1043,7 +1048,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
}
|
||||
_ => panic_ret_type(),
|
||||
},
|
||||
NumMulSaturated => match self.ret_layout_raw.repr {
|
||||
NumMulSaturated => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_SATURATED_INT[width])
|
||||
}
|
||||
|
@ -1063,7 +1068,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
NumMulChecked => {
|
||||
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
|
||||
match backend.layout_interner.get(arg_layout).repr {
|
||||
match backend.layout_interner.get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_CHECKED_INT[width])
|
||||
}
|
||||
|
@ -1245,7 +1250,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
x => todo!("{:?} for {:?}", self.lowlevel, x),
|
||||
}
|
||||
}
|
||||
NumDivCeilUnchecked => match self.ret_layout_raw.repr {
|
||||
NumDivCeilUnchecked => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_DIV_CEIL[width])
|
||||
}
|
||||
|
@ -1456,13 +1461,13 @@ impl<'a> LowLevelCall<'a> {
|
|||
_ => todo!("{:?} for {:?}", self.lowlevel, self.ret_layout),
|
||||
}
|
||||
}
|
||||
NumSin => match self.ret_layout_raw.repr {
|
||||
NumSin => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_SIN[width]);
|
||||
}
|
||||
_ => panic_ret_type(),
|
||||
},
|
||||
NumCos => match self.ret_layout_raw.repr {
|
||||
NumCos => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_COS[width]);
|
||||
}
|
||||
|
@ -1470,7 +1475,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
},
|
||||
NumSqrtUnchecked => {
|
||||
self.load_args(backend);
|
||||
match self.ret_layout_raw.repr {
|
||||
match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
|
||||
backend.code_builder.f32_sqrt()
|
||||
}
|
||||
|
@ -1480,7 +1485,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
_ => panic_ret_type(),
|
||||
}
|
||||
}
|
||||
NumLogUnchecked => match self.ret_layout_raw.repr {
|
||||
NumLogUnchecked => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_LOG[width]);
|
||||
}
|
||||
|
@ -1504,7 +1509,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
_ => todo!("{:?}: {:?} -> {:?}", self.lowlevel, arg_type, ret_type),
|
||||
}
|
||||
}
|
||||
NumPow => match self.ret_layout_raw.repr {
|
||||
NumPow => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_POW[width]);
|
||||
}
|
||||
|
@ -1513,8 +1518,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
NumCountLeadingZeroBits => match backend
|
||||
.layout_interner
|
||||
.get(backend.storage.symbol_layouts[&self.arguments[0]])
|
||||
.repr
|
||||
.get_repr(backend.storage.symbol_layouts[&self.arguments[0]])
|
||||
{
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(
|
||||
|
@ -1526,8 +1530,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
},
|
||||
NumCountTrailingZeroBits => match backend
|
||||
.layout_interner
|
||||
.get(backend.storage.symbol_layouts[&self.arguments[0]])
|
||||
.repr
|
||||
.get_repr(backend.storage.symbol_layouts[&self.arguments[0]])
|
||||
{
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(
|
||||
|
@ -1539,8 +1542,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
},
|
||||
NumCountOneBits => match backend
|
||||
.layout_interner
|
||||
.get(backend.storage.symbol_layouts[&self.arguments[0]])
|
||||
.repr
|
||||
.get_repr(backend.storage.symbol_layouts[&self.arguments[0]])
|
||||
{
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_COUNT_ONE_BITS[width]);
|
||||
|
@ -1617,19 +1619,19 @@ impl<'a> LowLevelCall<'a> {
|
|||
NumIsInfinite => num_is_infinite(backend, self.arguments[0]),
|
||||
NumIsFinite => num_is_finite(backend, self.arguments[0]),
|
||||
|
||||
NumAtan => match self.ret_layout_raw.repr {
|
||||
NumAtan => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_ATAN[width]);
|
||||
}
|
||||
_ => panic_ret_type(),
|
||||
},
|
||||
NumAcos => match self.ret_layout_raw.repr {
|
||||
NumAcos => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_ACOS[width]);
|
||||
}
|
||||
_ => panic_ret_type(),
|
||||
},
|
||||
NumAsin => match self.ret_layout_raw.repr {
|
||||
NumAsin => match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Float(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::NUM_ASIN[width]);
|
||||
}
|
||||
|
@ -1777,14 +1779,14 @@ impl<'a> LowLevelCall<'a> {
|
|||
NumIntCast => {
|
||||
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
|
||||
let arg_type = CodeGenNumType::from(arg_layout);
|
||||
let arg_width = match backend.layout_interner.get(arg_layout).repr {
|
||||
let arg_width = match backend.layout_interner.get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(w)) => w,
|
||||
LayoutRepr::Builtin(Builtin::Bool) => IntWidth::U8,
|
||||
x => internal_error!("Num.intCast is not defined for {:?}", x),
|
||||
};
|
||||
|
||||
let ret_type = CodeGenNumType::from(self.ret_layout);
|
||||
let ret_width = match self.ret_layout_raw.repr {
|
||||
let ret_width = match self.ret_layout_raw {
|
||||
LayoutRepr::Builtin(Builtin::Int(w)) => w,
|
||||
x => internal_error!("Num.intCast is not defined for {:?}", x),
|
||||
};
|
||||
|
@ -1847,7 +1849,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
NumToFloatCast => {
|
||||
self.load_args(backend);
|
||||
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
|
||||
let arg_signed = match backend.layout_interner.get(arg_layout).repr {
|
||||
let arg_signed = match backend.layout_interner.get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(w)) => w.is_signed(),
|
||||
LayoutRepr::Builtin(Builtin::Float(_)) => true, // unused
|
||||
LayoutRepr::Builtin(Builtin::Decimal) => true,
|
||||
|
@ -1895,13 +1897,13 @@ impl<'a> LowLevelCall<'a> {
|
|||
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
|
||||
|
||||
let (arg_width, ret_width) = match (
|
||||
backend.layout_interner.get(arg_layout).repr,
|
||||
self.ret_layout_raw.repr,
|
||||
backend.layout_interner.get_repr(arg_layout),
|
||||
self.ret_layout_raw,
|
||||
) {
|
||||
(
|
||||
LayoutRepr::Builtin(Builtin::Int(arg_width)),
|
||||
LayoutRepr::Struct(&[ret, ..]),
|
||||
) => match backend.layout_interner.get(ret).repr {
|
||||
) => match backend.layout_interner.get_repr(ret) {
|
||||
LayoutRepr::Builtin(Builtin::Int(ret_width)) => (arg_width, ret_width),
|
||||
_ => {
|
||||
internal_error!(
|
||||
|
@ -1993,19 +1995,19 @@ impl<'a> LowLevelCall<'a> {
|
|||
let arg_layout = backend
|
||||
.layout_interner
|
||||
.runtime_representation_in(backend.storage.symbol_layouts[&self.arguments[0]]);
|
||||
let arg_layout_raw = backend.layout_interner.get(arg_layout);
|
||||
let arg_layout_raw = backend.layout_interner.get_repr(arg_layout);
|
||||
let other_arg_layout = backend
|
||||
.layout_interner
|
||||
.runtime_representation(backend.storage.symbol_layouts[&self.arguments[1]]);
|
||||
debug_assert_eq!(
|
||||
arg_layout_raw.repr, other_arg_layout.repr,
|
||||
arg_layout_raw, other_arg_layout,
|
||||
"Cannot do `==` comparison on different types: {:?} vs {:?}",
|
||||
arg_layout, other_arg_layout
|
||||
);
|
||||
|
||||
let invert_result = matches!(self.lowlevel, LowLevel::NotEq);
|
||||
|
||||
match arg_layout_raw.repr {
|
||||
match arg_layout_raw {
|
||||
LayoutRepr::Builtin(
|
||||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
|
||||
) => self.eq_or_neq_number(backend),
|
||||
|
@ -2147,7 +2149,7 @@ impl<'a> LowLevelCall<'a> {
|
|||
|
||||
fn num_to_str(&self, backend: &mut WasmBackend<'a, '_>) {
|
||||
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
|
||||
match backend.layout_interner.get(arg_layout).repr {
|
||||
match backend.layout_interner.get_repr(arg_layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => {
|
||||
self.load_args_and_call_zig(backend, &bitcode::STR_FROM_INT[width])
|
||||
}
|
||||
|
@ -2355,8 +2357,7 @@ pub fn call_higher_order_lowlevel<'a>(
|
|||
// The wrapper around the passed function will access the actual closure data in the struct.
|
||||
let (closure_data_layout, closure_data_exists) = match backend
|
||||
.layout_interner
|
||||
.get(backend.storage.symbol_layouts[captured_environment])
|
||||
.repr
|
||||
.get_repr(backend.storage.symbol_layouts[captured_environment])
|
||||
{
|
||||
LayoutRepr::LambdaSet(lambda_set) => {
|
||||
if lambda_set.is_represented(backend.layout_interner).is_some() {
|
||||
|
@ -2379,7 +2380,7 @@ pub fn call_higher_order_lowlevel<'a>(
|
|||
let wrapped_captures_layout =
|
||||
backend
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::struct_(
|
||||
.insert_direct_no_semantic(LayoutRepr::struct_(
|
||||
backend.env.arena.alloc([closure_data_layout]),
|
||||
));
|
||||
|
||||
|
@ -2454,7 +2455,7 @@ pub fn call_higher_order_lowlevel<'a>(
|
|||
argument_layouts.iter().take(n_non_closure_args).map(|lay| {
|
||||
backend
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Boxed(*lay))
|
||||
.insert_direct_no_semantic(LayoutRepr::Boxed(*lay))
|
||||
});
|
||||
|
||||
wrapper_arg_layouts.push(wrapped_captures_layout);
|
||||
|
@ -2466,7 +2467,7 @@ pub fn call_higher_order_lowlevel<'a>(
|
|||
wrapper_arg_layouts.push(
|
||||
backend
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Boxed(*result_layout)),
|
||||
.insert_direct_no_semantic(LayoutRepr::Boxed(*result_layout)),
|
||||
);
|
||||
ProcLayout {
|
||||
arguments: wrapper_arg_layouts.into_bump_slice(),
|
||||
|
@ -2556,9 +2557,9 @@ pub fn call_higher_order_lowlevel<'a>(
|
|||
let elem_layout = unwrap_list_elem_layout(
|
||||
backend
|
||||
.layout_interner
|
||||
.get(backend.storage.symbol_layouts[xs]),
|
||||
.get_repr(backend.storage.symbol_layouts[xs]),
|
||||
);
|
||||
let elem_layout = backend.layout_interner.get(elem_layout);
|
||||
let elem_layout = backend.layout_interner.get_repr(elem_layout);
|
||||
let (element_width, alignment) =
|
||||
elem_layout.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
|
||||
|
||||
|
@ -2595,8 +2596,8 @@ pub fn call_higher_order_lowlevel<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn unwrap_list_elem_layout(list_layout: Layout) -> InLayout {
|
||||
match list_layout.repr {
|
||||
fn unwrap_list_elem_layout(list_layout: LayoutRepr) -> InLayout {
|
||||
match list_layout {
|
||||
LayoutRepr::Builtin(Builtin::List(x)) => x,
|
||||
e => internal_error!("expected List layout, got {:?}", e),
|
||||
}
|
||||
|
@ -2620,14 +2621,14 @@ fn list_map_n<'a>(
|
|||
unwrap_list_elem_layout(
|
||||
backend
|
||||
.layout_interner
|
||||
.get(backend.storage.symbol_layouts[sym]),
|
||||
.get_repr(backend.storage.symbol_layouts[sym]),
|
||||
)
|
||||
}),
|
||||
backend.env.arena,
|
||||
);
|
||||
|
||||
let elem_ret = unwrap_list_elem_layout(backend.layout_interner.get(return_layout));
|
||||
let elem_ret = backend.layout_interner.get(elem_ret);
|
||||
let elem_ret = unwrap_list_elem_layout(backend.layout_interner.get_repr(return_layout));
|
||||
let elem_ret = backend.layout_interner.get_repr(elem_ret);
|
||||
let (elem_ret_size, elem_ret_align) =
|
||||
elem_ret.stack_size_and_alignment(backend.layout_interner, TARGET_INFO);
|
||||
|
||||
|
@ -2661,7 +2662,7 @@ fn list_map_n<'a>(
|
|||
// Here we wrap the layout in a Struct to ensure we get the right code gen
|
||||
let el_ptr = backend
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([*el])));
|
||||
.insert_direct_no_semantic(LayoutRepr::Struct(backend.env.arena.alloc([*el])));
|
||||
let idx = backend.get_refcount_fn_index(el_ptr, HelperOp::Dec);
|
||||
let ptr = backend.get_fn_ptr(idx);
|
||||
backend.code_builder.i32_const(ptr);
|
||||
|
@ -2700,7 +2701,7 @@ fn ensure_symbol_is_in_memory<'a>(
|
|||
);
|
||||
let in_memory_layout = backend
|
||||
.layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Struct(arena.alloc([layout])));
|
||||
.insert_direct_no_semantic(LayoutRepr::Struct(arena.alloc([layout])));
|
||||
(frame_ptr, offset, in_memory_layout)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ pub fn insert_wrapper_for_layout<'a>(
|
|||
}
|
||||
};
|
||||
|
||||
match interner.get(layout).repr {
|
||||
match interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8)) => {
|
||||
i8::insert_wrapper(arena, module, wrapper_name, main_fn_index);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::hash::Hash;
|
|||
use crate::ir::{
|
||||
Expr, HigherOrderLowLevel, JoinPointId, Param, PassedFunction, Proc, ProcLayout, Stmt,
|
||||
};
|
||||
use crate::layout::{InLayout, Layout, LayoutInterner, STLayoutInterner};
|
||||
use crate::layout::{InLayout, LayoutInterner, LayoutRepr, STLayoutInterner};
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
|
@ -29,7 +29,7 @@ impl Ownership {
|
|||
|
||||
/// For reference-counted types (lists, (big) strings, recursive tags), owning a value
|
||||
/// means incrementing its reference count. Hence, we prefer borrowing for these types
|
||||
fn from_layout(layout: &Layout) -> Self {
|
||||
fn from_layout(layout: &LayoutRepr) -> Self {
|
||||
match layout.is_refcounted() {
|
||||
true => Ownership::Borrowed,
|
||||
false => Ownership::Owned,
|
||||
|
@ -265,7 +265,7 @@ impl<'a> ParamMap<'a> {
|
|||
) -> &'a [Param<'a>] {
|
||||
Vec::from_iter_in(
|
||||
ps.iter().map(|p| Param {
|
||||
ownership: Ownership::from_layout(&interner.get(p.layout)),
|
||||
ownership: Ownership::from_layout(&interner.get_repr(p.layout)),
|
||||
layout: p.layout,
|
||||
symbol: p.symbol,
|
||||
}),
|
||||
|
@ -281,7 +281,7 @@ impl<'a> ParamMap<'a> {
|
|||
) -> &'a [Param<'a>] {
|
||||
Vec::from_iter_in(
|
||||
ps.iter().map(|(layout, symbol)| Param {
|
||||
ownership: Ownership::from_layout(&interner.get(*layout)),
|
||||
ownership: Ownership::from_layout(&interner.get_repr(*layout)),
|
||||
layout: *layout,
|
||||
symbol: *symbol,
|
||||
}),
|
||||
|
|
|
@ -24,7 +24,7 @@ pub fn eq_generic<'a>(
|
|||
) -> Stmt<'a> {
|
||||
use crate::layout::Builtin::*;
|
||||
use LayoutRepr::*;
|
||||
let main_body = match layout_interner.get(layout).repr {
|
||||
let main_body = match layout_interner.get_repr(layout) {
|
||||
Builtin(Int(_) | Float(_) | Bool | Decimal) => {
|
||||
unreachable!(
|
||||
"No generated proc for `==`. Use direct code gen for {:?}",
|
||||
|
@ -434,7 +434,8 @@ fn eq_tag_union_help<'a>(
|
|||
if is_non_recursive {
|
||||
compare_ptr_or_value
|
||||
} else {
|
||||
let union_layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let union_layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let loop_params_iter = operands.iter().map(|arg| Param {
|
||||
symbol: *arg,
|
||||
ownership: Ownership::Borrowed,
|
||||
|
@ -468,7 +469,7 @@ fn eq_tag_fields<'a>(
|
|||
// (If there are more than one, the others will use non-tail recursion)
|
||||
let rec_ptr_index = field_layouts.iter().position(|field| {
|
||||
matches!(
|
||||
layout_interner.get(*field).repr,
|
||||
layout_interner.get_repr(*field),
|
||||
LayoutRepr::RecursivePointer(_)
|
||||
)
|
||||
});
|
||||
|
@ -657,7 +658,7 @@ fn eq_list<'a>(
|
|||
let arena = root.arena;
|
||||
|
||||
// A "Box" layout (heap pointer to a single list element)
|
||||
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(elem_layout));
|
||||
let box_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(elem_layout));
|
||||
|
||||
// Compare lengths
|
||||
|
||||
|
@ -703,7 +704,7 @@ fn eq_list<'a>(
|
|||
let size = root.create_symbol(ident_ids, "size");
|
||||
let size_expr = Expr::Literal(Literal::Int(
|
||||
(layout_interner
|
||||
.get(elem_layout)
|
||||
.get_repr(elem_layout)
|
||||
.stack_size(layout_interner, root.target_info) as i128)
|
||||
.to_ne_bytes(),
|
||||
));
|
||||
|
|
|
@ -10,8 +10,8 @@ use crate::ir::{
|
|||
Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, Niche, STLayoutInterner,
|
||||
UnionLayout,
|
||||
Builtin, InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, LayoutWrapper, Niche,
|
||||
STLayoutInterner, UnionLayout,
|
||||
};
|
||||
|
||||
mod equality;
|
||||
|
@ -286,11 +286,11 @@ impl<'a> CodeGenHelp<'a> {
|
|||
self.debug_recursion_depth += 1;
|
||||
|
||||
let layout = if matches!(
|
||||
layout_interner.get(called_layout).repr,
|
||||
layout_interner.get_repr(called_layout),
|
||||
LayoutRepr::RecursivePointer(_)
|
||||
) {
|
||||
let union_layout = ctx.recursive_union.unwrap();
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout))
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout))
|
||||
} else {
|
||||
called_layout
|
||||
};
|
||||
|
@ -301,7 +301,7 @@ impl<'a> CodeGenHelp<'a> {
|
|||
|
||||
let (ret_layout, arg_layouts): (InLayout<'a>, &'a [InLayout<'a>]) = {
|
||||
let arg = self.replace_rec_ptr(ctx, layout_interner, layout);
|
||||
let box_arg = layout_interner.insert_no_semantic(LayoutRepr::Boxed(arg));
|
||||
let box_arg = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(arg));
|
||||
|
||||
match ctx.op {
|
||||
Dec | DecRef(_) => (LAYOUT_UNIT, self.arena.alloc([arg])),
|
||||
|
@ -430,12 +430,14 @@ impl<'a> CodeGenHelp<'a> {
|
|||
}
|
||||
Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]),
|
||||
IndirectInc => {
|
||||
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(layout));
|
||||
let box_layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
|
||||
let inc_amount = (self.layout_isize, ARG_2);
|
||||
self.arena.alloc([(box_layout, ARG_1), inc_amount])
|
||||
}
|
||||
IndirectDec => {
|
||||
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(layout));
|
||||
let box_layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
|
||||
self.arena.alloc([(box_layout, ARG_1)])
|
||||
}
|
||||
Eq => self.arena.alloc([roc_value, (layout, ARG_2)]),
|
||||
|
@ -483,7 +485,8 @@ impl<'a> CodeGenHelp<'a> {
|
|||
niche: Niche::NONE,
|
||||
},
|
||||
HelperOp::IndirectInc => {
|
||||
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(layout));
|
||||
let box_layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
|
||||
|
||||
ProcLayout {
|
||||
arguments: self.arena.alloc([box_layout, self.layout_isize]),
|
||||
|
@ -492,7 +495,8 @@ impl<'a> CodeGenHelp<'a> {
|
|||
}
|
||||
}
|
||||
HelperOp::IndirectDec => {
|
||||
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(layout));
|
||||
let box_layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(layout));
|
||||
|
||||
ProcLayout {
|
||||
arguments: self.arena.alloc([box_layout]),
|
||||
|
@ -532,8 +536,9 @@ impl<'a> CodeGenHelp<'a> {
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> InLayout<'a> {
|
||||
let lay = layout_interner.get(layout);
|
||||
let repr = match lay.repr {
|
||||
let lay = layout_interner.get_repr(layout);
|
||||
let semantic = layout_interner.get_semantic(layout);
|
||||
let repr = match lay {
|
||||
LayoutRepr::Builtin(Builtin::List(v)) => {
|
||||
let v = self.replace_rec_ptr(ctx, layout_interner, v);
|
||||
LayoutRepr::Builtin(Builtin::List(v))
|
||||
|
@ -580,7 +585,7 @@ impl<'a> CodeGenHelp<'a> {
|
|||
LayoutRepr::RecursivePointer(_) => LayoutRepr::Union(ctx.recursive_union.unwrap()),
|
||||
};
|
||||
|
||||
layout_interner.insert(Layout::new(repr, lay.semantic()))
|
||||
layout_interner.insert(Layout::new(LayoutWrapper::Direct(repr), semantic))
|
||||
}
|
||||
|
||||
fn union_tail_recursion_fields(
|
||||
|
@ -664,16 +669,16 @@ impl<'a> CallerProc<'a> {
|
|||
};
|
||||
|
||||
let box_capture_layout = if let Some(capture_layout) = capture_layout {
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Boxed(capture_layout))
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(capture_layout))
|
||||
} else {
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Boxed(Layout::UNIT))
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(Layout::UNIT))
|
||||
};
|
||||
|
||||
let box_argument_layout = layout_interner
|
||||
.insert_no_semantic(LayoutRepr::Boxed(passed_function.argument_layouts[0]));
|
||||
.insert_direct_no_semantic(LayoutRepr::Boxed(passed_function.argument_layouts[0]));
|
||||
|
||||
let box_return_layout =
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Boxed(passed_function.return_layout));
|
||||
let box_return_layout = layout_interner
|
||||
.insert_direct_no_semantic(LayoutRepr::Boxed(passed_function.return_layout));
|
||||
|
||||
let proc_layout = ProcLayout {
|
||||
arguments: arena.alloc([box_capture_layout, box_argument_layout, box_return_layout]),
|
||||
|
@ -822,7 +827,7 @@ fn layout_needs_helper_proc<'a>(
|
|||
layout: InLayout<'a>,
|
||||
op: HelperOp,
|
||||
) -> bool {
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(
|
||||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
|
||||
) => false,
|
||||
|
|
|
@ -75,7 +75,7 @@ pub fn refcount_stmt<'a>(
|
|||
}
|
||||
|
||||
ModifyRc::DecRef(structure) => {
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
// Str has no children, so Dec is the same as DecRef.
|
||||
LayoutRepr::Builtin(Builtin::Str) => {
|
||||
ctx.op = HelperOp::Dec;
|
||||
|
@ -182,7 +182,7 @@ pub fn refcount_generic<'a>(
|
|||
layout: InLayout<'a>,
|
||||
structure: Symbol,
|
||||
) -> Stmt<'a> {
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(
|
||||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
|
||||
) => {
|
||||
|
@ -301,7 +301,7 @@ pub fn refcount_reset_proc_body<'a>(
|
|||
let is_unique = root.create_symbol(ident_ids, "is_unique");
|
||||
let addr = root.create_symbol(ident_ids, "addr");
|
||||
|
||||
let union_layout = match layout_interner.get(layout).repr {
|
||||
let union_layout = match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Union(u) => u,
|
||||
_ => unimplemented!("Reset is only implemented for UnionLayout"),
|
||||
};
|
||||
|
@ -309,7 +309,8 @@ pub fn refcount_reset_proc_body<'a>(
|
|||
// Whenever we recurse into a child layout we will want to Decrement
|
||||
ctx.op = HelperOp::Dec;
|
||||
ctx.recursive_union = Some(union_layout);
|
||||
let recursion_ptr = layout_interner.insert_no_semantic(LayoutRepr::RecursivePointer(layout));
|
||||
let recursion_ptr =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::RecursivePointer(layout));
|
||||
|
||||
// Reset structure is unique. Decrement its children and return a pointer to the allocation.
|
||||
let then_stmt = {
|
||||
|
@ -483,7 +484,7 @@ pub fn refcount_resetref_proc_body<'a>(
|
|||
let is_unique = root.create_symbol(ident_ids, "is_unique");
|
||||
let addr = root.create_symbol(ident_ids, "addr");
|
||||
|
||||
let union_layout = match layout_interner.get(layout).repr {
|
||||
let union_layout = match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Union(u) => u,
|
||||
_ => unimplemented!("Resetref is only implemented for UnionLayout"),
|
||||
};
|
||||
|
@ -491,7 +492,8 @@ pub fn refcount_resetref_proc_body<'a>(
|
|||
// Whenever we recurse into a child layout we will want to Decrement
|
||||
ctx.op = HelperOp::Dec;
|
||||
ctx.recursive_union = Some(union_layout);
|
||||
let recursion_ptr = layout_interner.insert_no_semantic(LayoutRepr::RecursivePointer(layout));
|
||||
let recursion_ptr =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::RecursivePointer(layout));
|
||||
|
||||
// Reset structure is unique. Return a pointer to the allocation.
|
||||
let then_stmt = Stmt::Ret(addr);
|
||||
|
@ -979,7 +981,7 @@ fn refcount_list<'a>(
|
|||
let arena = root.arena;
|
||||
|
||||
// A "Box" layout (heap pointer to a single list element)
|
||||
let box_layout = layout_interner.insert_no_semantic(LayoutRepr::Boxed(elem_layout));
|
||||
let box_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Boxed(elem_layout));
|
||||
|
||||
//
|
||||
// Check if the list is empty
|
||||
|
@ -1106,7 +1108,7 @@ fn refcount_list<'a>(
|
|||
|
||||
let is_relevant_op = ctx.op.is_dec() || ctx.op.is_inc();
|
||||
let modify_elems_and_list =
|
||||
if is_relevant_op && layout_interner.get(elem_layout).is_refcounted() {
|
||||
if is_relevant_op && layout_interner.get_repr(elem_layout).is_refcounted() {
|
||||
refcount_list_elems(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1742,7 +1744,7 @@ fn refcount_union_tailrec<'a>(
|
|||
let tailrec_loop = JoinPointId(root.create_symbol(ident_ids, "tailrec_loop"));
|
||||
let current = root.create_symbol(ident_ids, "current");
|
||||
let next_ptr = root.create_symbol(ident_ids, "next_ptr");
|
||||
let layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
|
||||
let tag_id_layout = union_layout.tag_id_layout();
|
||||
|
||||
|
@ -1887,7 +1889,7 @@ fn refcount_union_tailrec<'a>(
|
|||
let jump_with_null_ptr = Stmt::Let(
|
||||
null_pointer,
|
||||
Expr::NullPointer,
|
||||
layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout)),
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout)),
|
||||
root.arena.alloc(Stmt::Jump(
|
||||
jp_modify_union,
|
||||
root.arena.alloc([null_pointer]),
|
||||
|
@ -1931,7 +1933,7 @@ fn refcount_union_tailrec<'a>(
|
|||
));
|
||||
|
||||
let loop_init = Stmt::Jump(tailrec_loop, root.arena.alloc([initial_structure]));
|
||||
let union_layout = layout_interner.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let union_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let loop_param = Param {
|
||||
symbol: current,
|
||||
ownership: Ownership::Borrowed,
|
||||
|
|
|
@ -199,7 +199,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
// lazily.
|
||||
loop {
|
||||
layout = self.interner.chase_recursive_in(layout);
|
||||
match self.interner.get(layout).repr {
|
||||
match self.interner.get_repr(layout) {
|
||||
LayoutRepr::LambdaSet(ls) => layout = ls.representation,
|
||||
_ => return layout,
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
} => {
|
||||
self.check_sym_layout(*cond_symbol, *cond_layout, UseKind::SwitchCond);
|
||||
let layout = self.resolve(*cond_layout);
|
||||
match self.interner.get(layout).repr {
|
||||
match self.interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(_)) => {}
|
||||
LayoutRepr::Builtin(Builtin::Bool) => {}
|
||||
_ => self.problem(ProblemKind::BadSwitchConditionLayout {
|
||||
|
@ -400,7 +400,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
} => {
|
||||
let interned_layout = self
|
||||
.interner
|
||||
.insert_no_semantic(LayoutRepr::Union(tag_layout));
|
||||
.insert_direct_no_semantic(LayoutRepr::Union(tag_layout));
|
||||
self.check_tag_expr(interned_layout, tag_layout, tag_id, arguments);
|
||||
Some(interned_layout)
|
||||
}
|
||||
|
@ -440,7 +440,9 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
}
|
||||
Some(
|
||||
self.interner
|
||||
.insert_no_semantic(LayoutRepr::Builtin(Builtin::List(*elem_layout))),
|
||||
.insert_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(
|
||||
*elem_layout,
|
||||
))),
|
||||
)
|
||||
}
|
||||
Expr::EmptyArray => {
|
||||
|
@ -449,11 +451,14 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
}
|
||||
&Expr::ExprBox { symbol } => self.with_sym_layout(symbol, |ctx, _def_line, layout| {
|
||||
let inner = layout;
|
||||
Some(ctx.interner.insert_no_semantic(LayoutRepr::Boxed(inner)))
|
||||
Some(
|
||||
ctx.interner
|
||||
.insert_direct_no_semantic(LayoutRepr::Boxed(inner)),
|
||||
)
|
||||
}),
|
||||
&Expr::ExprUnbox { symbol } => self.with_sym_layout(symbol, |ctx, def_line, layout| {
|
||||
let layout = ctx.resolve(layout);
|
||||
match ctx.interner.get(layout).repr {
|
||||
match ctx.interner.get_repr(layout) {
|
||||
LayoutRepr::Boxed(inner) => Some(inner),
|
||||
_ => {
|
||||
ctx.problem(ProblemKind::UnboxNotABox { symbol, def_line });
|
||||
|
@ -471,7 +476,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
} => {
|
||||
let union = self
|
||||
.interner
|
||||
.insert_no_semantic(LayoutRepr::Union(tag_layout));
|
||||
.insert_direct_no_semantic(LayoutRepr::Union(tag_layout));
|
||||
self.check_sym_layout(symbol, union, UseKind::TagReuse);
|
||||
// TODO also check update arguments
|
||||
Some(union)
|
||||
|
@ -494,7 +499,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
fn check_struct_at_index(&mut self, structure: Symbol, index: u64) -> Option<InLayout<'a>> {
|
||||
self.with_sym_layout(structure, |ctx, def_line, layout| {
|
||||
let layout = ctx.resolve(layout);
|
||||
match ctx.interner.get(layout).repr {
|
||||
match ctx.interner.get_repr(layout) {
|
||||
LayoutRepr::Struct(field_layouts) => {
|
||||
if index as usize >= field_layouts.len() {
|
||||
ctx.problem(ProblemKind::StructIndexOOB {
|
||||
|
@ -529,7 +534,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
) -> Option<InLayout<'a>> {
|
||||
let union = self
|
||||
.interner
|
||||
.insert_no_semantic(LayoutRepr::Union(union_layout));
|
||||
.insert_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
self.with_sym_layout(structure, |ctx, def_line, _layout| {
|
||||
ctx.check_sym_layout(structure, union, UseKind::TagExpr);
|
||||
|
||||
|
|
|
@ -483,9 +483,9 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
|
||||
// This decremented symbol was not incremented before, perhaps the children were.
|
||||
let in_layout = environment.get_symbol_layout(symbol);
|
||||
let runtime_layout = layout_interner.runtime_representation(*in_layout);
|
||||
let runtime_repr = layout_interner.runtime_representation(*in_layout);
|
||||
|
||||
let updated_stmt = match runtime_layout.repr {
|
||||
let updated_stmt = match runtime_repr {
|
||||
// Layout has children, try to inline them.
|
||||
LayoutRepr::Struct(field_layouts) => specialize_struct(
|
||||
arena,
|
||||
|
|
|
@ -677,10 +677,17 @@ fn insert_refcount_operations_stmt<'v, 'a>(
|
|||
} => {
|
||||
let new_remainder = insert_refcount_operations_stmt(arena, environment, remainder);
|
||||
|
||||
let newer_remainder = consume_and_insert_dec_stmts(
|
||||
arena,
|
||||
environment,
|
||||
environment.borrowed_usages([*symbol]),
|
||||
new_remainder,
|
||||
);
|
||||
|
||||
arena.alloc(Stmt::Dbg {
|
||||
symbol: *symbol,
|
||||
variable: *variable,
|
||||
remainder: new_remainder,
|
||||
remainder: newer_remainder,
|
||||
})
|
||||
}
|
||||
Stmt::Join {
|
||||
|
|
|
@ -1066,7 +1066,7 @@ impl<'a> Procs<'a> {
|
|||
let is_self_recursive = match top_level
|
||||
.arguments
|
||||
.last()
|
||||
.map(|l| layout_cache.get_in(*l).repr)
|
||||
.map(|l| layout_cache.get_repr(*l))
|
||||
{
|
||||
Some(LayoutRepr::LambdaSet(lambda_set)) => lambda_set.contains(name.name()),
|
||||
_ => false,
|
||||
|
@ -3509,10 +3509,10 @@ fn specialize_proc_help<'a>(
|
|||
|
||||
combined.sort_by(|(_, layout1), (_, layout2)| {
|
||||
let size1 = layout_cache
|
||||
.get_in(**layout1)
|
||||
.get_repr(**layout1)
|
||||
.alignment_bytes(&layout_cache.interner, ptr_bytes);
|
||||
let size2 = layout_cache
|
||||
.get_in(**layout2)
|
||||
.get_repr(**layout2)
|
||||
.alignment_bytes(&layout_cache.interner, ptr_bytes);
|
||||
|
||||
size2.cmp(&size1)
|
||||
|
@ -3557,10 +3557,10 @@ fn specialize_proc_help<'a>(
|
|||
|
||||
combined.sort_by(|(_, layout1), (_, layout2)| {
|
||||
let size1 = layout_cache
|
||||
.get_in(**layout1)
|
||||
.get_repr(**layout1)
|
||||
.alignment_bytes(&layout_cache.interner, ptr_bytes);
|
||||
let size2 = layout_cache
|
||||
.get_in(**layout2)
|
||||
.get_repr(**layout2)
|
||||
.alignment_bytes(&layout_cache.interner, ptr_bytes);
|
||||
|
||||
size2.cmp(&size1)
|
||||
|
@ -4145,9 +4145,9 @@ pub fn with_hole<'a>(
|
|||
|
||||
IngestedFile(_, bytes, var) => {
|
||||
let interned = layout_cache.from_var(env.arena, var, env.subs).unwrap();
|
||||
let layout = layout_cache.get_in(interned);
|
||||
let layout = layout_cache.get_repr(interned);
|
||||
|
||||
match layout.repr {
|
||||
match layout {
|
||||
LayoutRepr::Builtin(Builtin::List(elem_layout)) if elem_layout == Layout::U8 => {
|
||||
let mut elements = Vec::with_capacity_in(bytes.len(), env.arena);
|
||||
for byte in bytes.iter() {
|
||||
|
@ -4422,7 +4422,32 @@ pub fn with_hole<'a>(
|
|||
|
||||
Expect { .. } => unreachable!("I think this is unreachable"),
|
||||
ExpectFx { .. } => unreachable!("I think this is unreachable"),
|
||||
Dbg { .. } => unreachable!("I think this is unreachable"),
|
||||
Dbg {
|
||||
loc_condition,
|
||||
loc_continuation,
|
||||
variable: cond_variable,
|
||||
symbol: dbg_symbol,
|
||||
} => {
|
||||
let rest = with_hole(
|
||||
env,
|
||||
loc_continuation.value,
|
||||
variable,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned,
|
||||
hole,
|
||||
);
|
||||
|
||||
compile_dbg(
|
||||
env,
|
||||
procs,
|
||||
layout_cache,
|
||||
dbg_symbol,
|
||||
*loc_condition,
|
||||
cond_variable,
|
||||
rest,
|
||||
)
|
||||
}
|
||||
|
||||
If {
|
||||
cond_var,
|
||||
|
@ -4627,13 +4652,14 @@ pub fn with_hole<'a>(
|
|||
Ok(elem_layout) => {
|
||||
let expr = Expr::EmptyArray;
|
||||
let list_layout = layout_cache
|
||||
.put_in_no_semantic(LayoutRepr::Builtin(Builtin::List(elem_layout)));
|
||||
.put_in_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(elem_layout)));
|
||||
Stmt::Let(assigned, expr, list_layout, hole)
|
||||
}
|
||||
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
||||
let expr = Expr::EmptyArray;
|
||||
let list_layout = layout_cache
|
||||
.put_in_no_semantic(LayoutRepr::Builtin(Builtin::List(Layout::VOID)));
|
||||
let list_layout = layout_cache.put_in_direct_no_semantic(LayoutRepr::Builtin(
|
||||
Builtin::List(Layout::VOID),
|
||||
));
|
||||
Stmt::Let(assigned, expr, list_layout, hole)
|
||||
}
|
||||
Err(LayoutProblem::Erroneous) => panic!("list element is error type"),
|
||||
|
@ -4679,8 +4705,8 @@ pub fn with_hole<'a>(
|
|||
elems: elements.into_bump_slice(),
|
||||
};
|
||||
|
||||
let list_layout =
|
||||
layout_cache.put_in_no_semantic(LayoutRepr::Builtin(Builtin::List(elem_layout)));
|
||||
let list_layout = layout_cache
|
||||
.put_in_direct_no_semantic(LayoutRepr::Builtin(Builtin::List(elem_layout)));
|
||||
|
||||
let stmt = Stmt::Let(assigned, expr, list_layout, hole);
|
||||
|
||||
|
@ -4994,7 +5020,7 @@ pub fn with_hole<'a>(
|
|||
.from_var(env.arena, record_var, env.subs)
|
||||
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
|
||||
|
||||
let field_layouts = match layout_cache.get_in(record_layout).repr {
|
||||
let field_layouts = match layout_cache.get_repr(record_layout) {
|
||||
LayoutRepr::Struct(field_layouts) => field_layouts,
|
||||
_ => arena.alloc([record_layout]),
|
||||
};
|
||||
|
@ -5620,6 +5646,53 @@ pub fn with_hole<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Compiles a `dbg` expression.
|
||||
fn compile_dbg<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
procs: &mut Procs<'a>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
dbg_symbol: Symbol,
|
||||
loc_condition: Loc<roc_can::expr::Expr>,
|
||||
variable: Variable,
|
||||
continuation: Stmt<'a>,
|
||||
) -> Stmt<'a> {
|
||||
let spec_var = env
|
||||
.expectation_subs
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.fresh_unnamed_flex_var();
|
||||
|
||||
let dbg_stmt = Stmt::Dbg {
|
||||
symbol: dbg_symbol,
|
||||
variable: spec_var,
|
||||
remainder: env.arena.alloc(continuation),
|
||||
};
|
||||
|
||||
// Now that the dbg value has been specialized, export its specialized type into the
|
||||
// expectations subs.
|
||||
store_specialized_expectation_lookups(env, [variable], &[spec_var]);
|
||||
|
||||
let symbol_is_reused = matches!(
|
||||
can_reuse_symbol(env, layout_cache, procs, &loc_condition.value, variable),
|
||||
ReuseSymbol::Value(_)
|
||||
);
|
||||
|
||||
// skip evaluating the condition if it's just a symbol
|
||||
if symbol_is_reused {
|
||||
dbg_stmt
|
||||
} else {
|
||||
with_hole(
|
||||
env,
|
||||
loc_condition.value,
|
||||
variable,
|
||||
procs,
|
||||
layout_cache,
|
||||
dbg_symbol,
|
||||
env.arena.alloc(dbg_stmt),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compiles an access into a tuple or record.
|
||||
fn compile_struct_like_access<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
|
@ -5917,10 +5990,10 @@ where
|
|||
|
||||
combined.sort_by(|(_, layout1), (_, layout2)| {
|
||||
let size1 = layout_cache
|
||||
.get_in(**layout1)
|
||||
.get_repr(**layout1)
|
||||
.alignment_bytes(&layout_cache.interner, ptr_bytes);
|
||||
let size2 = layout_cache
|
||||
.get_in(**layout2)
|
||||
.get_repr(**layout2)
|
||||
.alignment_bytes(&layout_cache.interner, ptr_bytes);
|
||||
|
||||
size2.cmp(&size1)
|
||||
|
@ -5951,10 +6024,10 @@ where
|
|||
|
||||
combined.sort_by(|(_, layout1), (_, layout2)| {
|
||||
let size1 = layout_cache
|
||||
.get_in(**layout1)
|
||||
.get_repr(**layout1)
|
||||
.alignment_bytes(&layout_cache.interner, ptr_bytes);
|
||||
let size2 = layout_cache
|
||||
.get_in(**layout2)
|
||||
.get_repr(**layout2)
|
||||
.alignment_bytes(&layout_cache.interner, ptr_bytes);
|
||||
|
||||
size2.cmp(&size1)
|
||||
|
@ -5967,9 +6040,7 @@ where
|
|||
|
||||
debug_assert_eq!(
|
||||
LayoutRepr::struct_(field_layouts),
|
||||
layout_cache
|
||||
.get_in(lambda_set.runtime_representation())
|
||||
.repr
|
||||
layout_cache.get_repr(lambda_set.runtime_representation())
|
||||
);
|
||||
|
||||
let expr = Expr::Struct(symbols);
|
||||
|
@ -6170,7 +6241,7 @@ fn convert_tag_union<'a>(
|
|||
layout_cache.from_var(env.arena, variant_var, env.subs),
|
||||
"Wrapped"
|
||||
);
|
||||
let union_layout = match layout_cache.interner.chase_recursive(variant_layout).repr {
|
||||
let union_layout = match layout_cache.interner.chase_recursive(variant_layout) {
|
||||
LayoutRepr::Union(ul) => ul,
|
||||
other => internal_error!(
|
||||
"unexpected layout {:?} for {:?}",
|
||||
|
@ -6301,7 +6372,8 @@ fn convert_tag_union<'a>(
|
|||
}
|
||||
};
|
||||
|
||||
let union_layout = layout_cache.put_in_no_semantic(LayoutRepr::Union(union_layout));
|
||||
let union_layout =
|
||||
layout_cache.put_in_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
|
||||
let stmt = Stmt::Let(assigned, tag, union_layout, hole);
|
||||
let iter = field_symbols_temp
|
||||
|
@ -6440,7 +6512,7 @@ fn sorted_field_symbols<'a>(
|
|||
};
|
||||
|
||||
let alignment = layout_cache
|
||||
.get_in(layout)
|
||||
.get_repr(layout)
|
||||
.alignment_bytes(&layout_cache.interner, env.target_info);
|
||||
|
||||
let symbol = possible_reuse_symbol_or_specialize(env, procs, layout_cache, &arg.value, var);
|
||||
|
@ -6824,41 +6896,15 @@ pub fn from_can<'a>(
|
|||
} => {
|
||||
let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
|
||||
|
||||
let spec_var = env
|
||||
.expectation_subs
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.fresh_unnamed_flex_var();
|
||||
|
||||
let dbg_stmt = Stmt::Dbg {
|
||||
symbol: dbg_symbol,
|
||||
variable: spec_var,
|
||||
remainder: env.arena.alloc(rest),
|
||||
};
|
||||
|
||||
// Now that the dbg value has been specialized, export its specialized type into the
|
||||
// expectations subs.
|
||||
store_specialized_expectation_lookups(env, [variable], &[spec_var]);
|
||||
|
||||
let symbol_is_reused = matches!(
|
||||
can_reuse_symbol(env, layout_cache, procs, &loc_condition.value, variable),
|
||||
ReuseSymbol::Value(_)
|
||||
);
|
||||
|
||||
// skip evaluating the condition if it's just a symbol
|
||||
if symbol_is_reused {
|
||||
dbg_stmt
|
||||
} else {
|
||||
with_hole(
|
||||
env,
|
||||
loc_condition.value,
|
||||
variable,
|
||||
procs,
|
||||
layout_cache,
|
||||
dbg_symbol,
|
||||
env.arena.alloc(dbg_stmt),
|
||||
)
|
||||
}
|
||||
compile_dbg(
|
||||
env,
|
||||
procs,
|
||||
layout_cache,
|
||||
dbg_symbol,
|
||||
*loc_condition,
|
||||
variable,
|
||||
rest,
|
||||
)
|
||||
}
|
||||
|
||||
LetRec(defs, cont, _cycle_mark) => {
|
||||
|
@ -7887,7 +7933,7 @@ fn specialize_symbol<'a>(
|
|||
let layout = match raw {
|
||||
RawFunctionLayout::ZeroArgumentThunk(layout) => layout,
|
||||
RawFunctionLayout::Function(_, lambda_set, _) => layout_cache
|
||||
.put_in_no_semantic(LayoutRepr::LambdaSet(lambda_set)),
|
||||
.put_in_direct_no_semantic(LayoutRepr::LambdaSet(lambda_set)),
|
||||
};
|
||||
|
||||
let raw = RawFunctionLayout::ZeroArgumentThunk(layout);
|
||||
|
@ -9764,7 +9810,7 @@ where
|
|||
($tag_id:expr, $layout:expr, $union_layout:expr, $field_layouts: expr) => {{
|
||||
if $field_layouts.iter().any(|l| {
|
||||
layout_interner
|
||||
.get(*l)
|
||||
.get_repr(*l)
|
||||
.has_varying_stack_size(layout_interner, arena)
|
||||
}) {
|
||||
let procs = generate_glue_procs_for_tag_fields(
|
||||
|
@ -9789,7 +9835,7 @@ where
|
|||
}
|
||||
|
||||
while let Some(layout) = stack.pop() {
|
||||
match layout.repr {
|
||||
match layout.repr(layout_interner) {
|
||||
LayoutRepr::Builtin(builtin) => match builtin {
|
||||
Builtin::Int(_)
|
||||
| Builtin::Float(_)
|
||||
|
@ -9801,7 +9847,7 @@ where
|
|||
LayoutRepr::Struct(field_layouts) => {
|
||||
if field_layouts.iter().any(|l| {
|
||||
layout_interner
|
||||
.get(*l)
|
||||
.get_repr(*l)
|
||||
.has_varying_stack_size(layout_interner, arena)
|
||||
}) {
|
||||
let procs = generate_glue_procs_for_struct_fields(
|
||||
|
@ -9892,11 +9938,11 @@ where
|
|||
{
|
||||
let interned_unboxed_struct_layout = layout_interner.insert(*unboxed_struct_layout);
|
||||
let boxed_struct_layout =
|
||||
Layout::no_semantic(LayoutRepr::Boxed(interned_unboxed_struct_layout));
|
||||
Layout::no_semantic(LayoutRepr::Boxed(interned_unboxed_struct_layout).direct());
|
||||
let boxed_struct_layout = layout_interner.insert(boxed_struct_layout);
|
||||
let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena);
|
||||
|
||||
let field_layouts = match layout_interner.get(interned_unboxed_struct_layout).repr {
|
||||
let field_layouts = match layout_interner.get_repr(interned_unboxed_struct_layout) {
|
||||
LayoutRepr::Struct(field_layouts) => field_layouts,
|
||||
other => {
|
||||
unreachable!(
|
||||
|
@ -10003,7 +10049,7 @@ where
|
|||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let interned = layout_interner.insert(*unboxed_struct_layout);
|
||||
let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Boxed(interned));
|
||||
let boxed_struct_layout = Layout::no_semantic(LayoutRepr::Boxed(interned).direct());
|
||||
let boxed_struct_layout = layout_interner.insert(boxed_struct_layout);
|
||||
let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena);
|
||||
|
||||
|
|
|
@ -1014,7 +1014,7 @@ fn to_relevant_branch_help<'a>(
|
|||
// the test matches the constructor of this pattern
|
||||
match layout {
|
||||
UnionLayout::NonRecursive([[arg]])
|
||||
if matches!(interner.get(*arg).repr, LayoutRepr::Struct([_],)) =>
|
||||
if matches!(interner.get_repr(*arg), LayoutRepr::Struct([_],)) =>
|
||||
{
|
||||
// a one-element record equivalent
|
||||
// Theory: Unbox doesn't have any value for us
|
||||
|
@ -1573,7 +1573,7 @@ fn path_to_expr_help<'a>(
|
|||
PathInstruction::TagIndex { index, tag_id } => {
|
||||
let index = *index;
|
||||
|
||||
match layout_interner.chase_recursive(layout).repr {
|
||||
match layout_interner.chase_recursive(layout) {
|
||||
LayoutRepr::Union(union_layout) => {
|
||||
let inner_expr = Expr::UnionAtIndex {
|
||||
tag_id: *tag_id,
|
||||
|
@ -1626,7 +1626,7 @@ fn path_to_expr_help<'a>(
|
|||
PathInstruction::ListIndex { index } => {
|
||||
let list_sym = symbol;
|
||||
|
||||
match layout_interner.get(layout).repr {
|
||||
match layout_interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(elem_layout)) => {
|
||||
let (index_sym, new_stores) = build_list_index_probe(env, list_sym, index);
|
||||
|
||||
|
@ -1673,7 +1673,7 @@ fn test_to_comparison<'a>(
|
|||
// (e.g. record pattern guard matches)
|
||||
debug_assert!(union.alternatives.len() > 1);
|
||||
|
||||
match layout_interner.chase_recursive(test_layout).repr {
|
||||
match layout_interner.chase_recursive(test_layout) {
|
||||
LayoutRepr::Union(union_layout) => {
|
||||
let lhs = Expr::Literal(Literal::Int((tag_id as i128).to_ne_bytes()));
|
||||
|
||||
|
@ -1763,7 +1763,7 @@ fn test_to_comparison<'a>(
|
|||
let list_layout = test_layout;
|
||||
let list_sym = rhs_symbol;
|
||||
|
||||
match layout_interner.get(list_layout).repr {
|
||||
match layout_interner.get_repr(list_layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(_elem_layout)) => {
|
||||
let real_len_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
|
@ -2310,7 +2310,7 @@ fn decide_to_branching<'a>(
|
|||
// We have learned more about the exact layout of the cond (based on the path)
|
||||
// but tests are still relative to the original cond symbol
|
||||
let inner_cond_layout_raw = layout_cache.interner.chase_recursive(inner_cond_layout);
|
||||
let mut switch = if let LayoutRepr::Union(union_layout) = inner_cond_layout_raw.repr {
|
||||
let mut switch = if let LayoutRepr::Union(union_layout) = inner_cond_layout_raw {
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
|
||||
let temp = Stmt::Switch {
|
||||
|
@ -2332,7 +2332,7 @@ fn decide_to_branching<'a>(
|
|||
union_layout.tag_id_layout(),
|
||||
env.arena.alloc(temp),
|
||||
)
|
||||
} else if let LayoutRepr::Builtin(Builtin::List(_)) = inner_cond_layout_raw.repr {
|
||||
} else if let LayoutRepr::Builtin(Builtin::List(_)) = inner_cond_layout_raw {
|
||||
let len_symbol = env.unique_symbol();
|
||||
|
||||
let switch = Stmt::Switch {
|
||||
|
|
|
@ -83,7 +83,7 @@ pub fn make_num_literal<'a>(
|
|||
num_str: &str,
|
||||
num_value: IntOrFloatValue,
|
||||
) -> NumLiteral {
|
||||
match interner.get(layout).repr {
|
||||
match interner.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Int(width)) => match num_value {
|
||||
IntOrFloatValue::Int(IntValue::I128(n)) => NumLiteral::Int(n, width),
|
||||
IntOrFloatValue::Int(IntValue::U128(n)) => NumLiteral::U128(n),
|
||||
|
|
|
@ -344,7 +344,7 @@ fn from_can_pattern_help<'a>(
|
|||
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
|
||||
SingleQuote(var, _, c, _) => {
|
||||
let layout = layout_cache.from_var(env.arena, *var, env.subs);
|
||||
match layout.map(|l| layout_cache.get_in(l).repr) {
|
||||
match layout.map(|l| layout_cache.get_repr(l)) {
|
||||
Ok(LayoutRepr::Builtin(Builtin::Int(width))) => {
|
||||
Ok(Pattern::IntLiteral((*c as i128).to_ne_bytes(), width))
|
||||
}
|
||||
|
@ -583,12 +583,11 @@ fn from_can_pattern_help<'a>(
|
|||
// problems down the line because we hash layouts and an unrolled
|
||||
// version is not the same as the minimal version.
|
||||
let whole_var_layout = layout_cache.from_var(env.arena, *whole_var, env.subs);
|
||||
let layout = match whole_var_layout
|
||||
.map(|l| layout_cache.interner.chase_recursive(l).repr)
|
||||
{
|
||||
Ok(LayoutRepr::Union(ul)) => ul,
|
||||
_ => internal_error!(),
|
||||
};
|
||||
let layout =
|
||||
match whole_var_layout.map(|l| layout_cache.interner.chase_recursive(l)) {
|
||||
Ok(LayoutRepr::Union(ul)) => ul,
|
||||
_ => internal_error!(),
|
||||
};
|
||||
|
||||
use WrappedVariant::*;
|
||||
match variant {
|
||||
|
@ -1207,8 +1206,8 @@ fn store_pattern_help<'a>(
|
|||
let mut fields = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||
fields.extend(arguments.iter().map(|x| x.1));
|
||||
|
||||
let layout =
|
||||
layout_cache.put_in_no_semantic(LayoutRepr::struct_(fields.into_bump_slice()));
|
||||
let layout = layout_cache
|
||||
.put_in_direct_no_semantic(LayoutRepr::struct_(fields.into_bump_slice()));
|
||||
|
||||
return store_newtype_pattern(
|
||||
env,
|
||||
|
@ -1552,9 +1551,9 @@ fn store_tag_pattern<'a>(
|
|||
for (index, (argument, arg_layout)) in arguments.iter().enumerate().rev() {
|
||||
let mut arg_layout = *arg_layout;
|
||||
|
||||
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_in(arg_layout).repr {
|
||||
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_repr(arg_layout) {
|
||||
// TODO(recursive-layouts): fix after disjoint rec ptrs
|
||||
arg_layout = layout_cache.put_in_no_semantic(LayoutRepr::Union(union_layout));
|
||||
arg_layout = layout_cache.put_in_direct_no_semantic(LayoutRepr::Union(union_layout));
|
||||
}
|
||||
|
||||
let load = Expr::UnionAtIndex {
|
||||
|
@ -1630,7 +1629,7 @@ fn store_newtype_pattern<'a>(
|
|||
for (index, (argument, arg_layout)) in arguments.iter().enumerate().rev() {
|
||||
let mut arg_layout = *arg_layout;
|
||||
|
||||
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_in(arg_layout).repr {
|
||||
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_repr(arg_layout) {
|
||||
arg_layout = layout;
|
||||
}
|
||||
|
||||
|
|
|
@ -328,12 +328,15 @@ impl<'a> LayoutCache<'a> {
|
|||
pub fn get_in(&self, interned: InLayout<'a>) -> Layout<'a> {
|
||||
self.interner.get(interned)
|
||||
}
|
||||
pub fn get_repr(&self, interned: InLayout<'a>) -> LayoutRepr<'a> {
|
||||
self.interner.get_repr(interned)
|
||||
}
|
||||
|
||||
pub fn put_in(&mut self, layout: Layout<'a>) -> InLayout<'a> {
|
||||
self.interner.insert(layout)
|
||||
}
|
||||
pub fn put_in_no_semantic(&mut self, repr: LayoutRepr<'a>) -> InLayout<'a> {
|
||||
self.interner.insert_no_semantic(repr)
|
||||
pub(crate) fn put_in_direct_no_semantic(&mut self, repr: LayoutRepr<'a>) -> InLayout<'a> {
|
||||
self.interner.insert_direct_no_semantic(repr)
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -656,10 +659,16 @@ impl<'a> RawFunctionLayout<'a> {
|
|||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Layout<'a> {
|
||||
pub repr: LayoutRepr<'a>,
|
||||
repr: LayoutWrapper<'a>,
|
||||
semantic: SemanticRepr<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub(crate) enum LayoutWrapper<'a> {
|
||||
Direct(LayoutRepr<'a>),
|
||||
Newtype(InLayout<'a>),
|
||||
}
|
||||
|
||||
/// Types for code gen must be monomorphic. No type variables allowed!
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub enum LayoutRepr<'a> {
|
||||
|
@ -873,8 +882,8 @@ impl<'a> UnionLayout<'a> {
|
|||
};
|
||||
|
||||
// TODO(recursive-layouts): simplify after we have disjoint recursive pointers
|
||||
if let LayoutRepr::RecursivePointer(_) = interner.get(result).repr {
|
||||
interner.insert_no_semantic(LayoutRepr::Union(self))
|
||||
if let LayoutRepr::RecursivePointer(_) = interner.get_repr(result) {
|
||||
interner.insert_direct_no_semantic(LayoutRepr::Union(self))
|
||||
} else {
|
||||
result
|
||||
}
|
||||
|
@ -1417,7 +1426,7 @@ impl<'a> LambdaSet<'a> {
|
|||
None
|
||||
} else {
|
||||
let repr = self.representation;
|
||||
match interner.get(repr).repr {
|
||||
match interner.get_repr(repr) {
|
||||
LayoutRepr::Struct(&[]) => None,
|
||||
_ => Some(repr),
|
||||
}
|
||||
|
@ -1533,7 +1542,7 @@ impl<'a> LambdaSet<'a> {
|
|||
|
||||
let repr_layout = interner.chase_recursive(self.representation);
|
||||
|
||||
match repr_layout.repr {
|
||||
match repr_layout {
|
||||
LayoutRepr::Union(union) => {
|
||||
// here we rely on the fact that a union in a closure would be stored in a one-element record.
|
||||
// a closure representation that is itself union must be a of the shape `Closure1 ... | Closure2 ...`
|
||||
|
@ -1660,9 +1669,9 @@ impl<'a> LambdaSet<'a> {
|
|||
|
||||
let repr_layout = interner.chase_recursive(self.representation);
|
||||
|
||||
match repr_layout.repr {
|
||||
match repr_layout {
|
||||
LayoutRepr::Union(union_layout) => {
|
||||
if repr_layout == Layout::VOID_NAKED {
|
||||
if repr_layout == Layout::VOID_NAKED.repr(interner) {
|
||||
debug_assert!(self.set.is_empty());
|
||||
return ClosureCallOptions::Void;
|
||||
}
|
||||
|
@ -1747,7 +1756,7 @@ impl<'a> LambdaSet<'a> {
|
|||
Cacheable(result, criteria)
|
||||
});
|
||||
|
||||
match result.map(|l| env.cache.interner.chase_recursive(l).repr) {
|
||||
match result.map(|l| env.cache.interner.chase_recursive(l)) {
|
||||
Ok(LayoutRepr::LambdaSet(lambda_set)) => Cacheable(Ok(lambda_set), criteria),
|
||||
Err(err) => Cacheable(Err(err), criteria),
|
||||
Ok(layout) => internal_error!("other layout found for lambda set: {:?}", layout),
|
||||
|
@ -1923,7 +1932,7 @@ impl<'a> LambdaSet<'a> {
|
|||
I: LayoutInterner<'a>,
|
||||
{
|
||||
interner
|
||||
.get(self.representation)
|
||||
.get_repr(self.representation)
|
||||
.stack_size(interner, target_info)
|
||||
}
|
||||
pub fn contains_refcounted<I>(&self, interner: &I) -> bool
|
||||
|
@ -1931,14 +1940,16 @@ impl<'a> LambdaSet<'a> {
|
|||
I: LayoutInterner<'a>,
|
||||
{
|
||||
interner
|
||||
.get(self.representation)
|
||||
.get_repr(self.representation)
|
||||
.contains_refcounted(interner)
|
||||
}
|
||||
pub fn safe_to_memcpy<I>(&self, interner: &I) -> bool
|
||||
where
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
interner.get(self.representation).safe_to_memcpy(interner)
|
||||
interner
|
||||
.get_repr(self.representation)
|
||||
.safe_to_memcpy(interner)
|
||||
}
|
||||
|
||||
pub fn alignment_bytes<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
|
@ -1946,7 +1957,7 @@ impl<'a> LambdaSet<'a> {
|
|||
I: LayoutInterner<'a>,
|
||||
{
|
||||
interner
|
||||
.get(self.representation)
|
||||
.get_repr(self.representation)
|
||||
.alignment_bytes(interner, target_info)
|
||||
}
|
||||
}
|
||||
|
@ -2125,7 +2136,7 @@ pub enum Builtin<'a> {
|
|||
#[macro_export]
|
||||
macro_rules! list_element_layout {
|
||||
($interner:expr, $list_layout:expr) => {
|
||||
match $interner.get($list_layout).repr {
|
||||
match $interner.get_repr($list_layout) {
|
||||
LayoutRepr::Builtin(Builtin::List(list_layout)) => list_layout,
|
||||
_ => internal_error!("invalid list layout"),
|
||||
}
|
||||
|
@ -2326,19 +2337,30 @@ pub fn is_any_float_range(subs: &Subs, var: Variable) -> bool {
|
|||
}
|
||||
|
||||
impl<'a> Layout<'a> {
|
||||
pub const fn new(repr: LayoutRepr<'a>, semantic: SemanticRepr<'a>) -> Self {
|
||||
pub(crate) const fn new(repr: LayoutWrapper<'a>, semantic: SemanticRepr<'a>) -> Self {
|
||||
Self { repr, semantic }
|
||||
}
|
||||
|
||||
pub const fn no_semantic(repr: LayoutRepr<'a>) -> Self {
|
||||
pub(crate) const fn no_semantic(repr: LayoutWrapper<'a>) -> Self {
|
||||
Self {
|
||||
repr,
|
||||
semantic: SemanticRepr::NONE,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn semantic(&self) -> SemanticRepr<'a> {
|
||||
self.semantic
|
||||
pub(crate) fn repr<I>(&self, interner: &I) -> LayoutRepr<'a>
|
||||
where
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let mut lay = *self;
|
||||
loop {
|
||||
match lay.repr {
|
||||
LayoutWrapper::Direct(repr) => return repr,
|
||||
LayoutWrapper::Newtype(real) => {
|
||||
lay = interner.get(real);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_help<'b>(
|
||||
|
@ -2457,7 +2479,7 @@ impl<'a> Layout<'a> {
|
|||
let mut total = 0;
|
||||
for layout in tag.iter() {
|
||||
let (stack_size, alignment) = interner
|
||||
.get(*layout)
|
||||
.get_repr(*layout)
|
||||
.stack_size_and_alignment(interner, target_info);
|
||||
total += stack_size;
|
||||
data_align = data_align.max(alignment);
|
||||
|
@ -2476,7 +2498,7 @@ impl<'a> Layout<'a> {
|
|||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use LayoutRepr::*;
|
||||
match self.repr {
|
||||
match self.repr(interner) {
|
||||
LambdaSet(lambda_set) => interner.get(lambda_set.runtime_representation()),
|
||||
_ => *self,
|
||||
}
|
||||
|
@ -2487,21 +2509,13 @@ impl<'a> Layout<'a> {
|
|||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use LayoutRepr::*;
|
||||
match interner.get(layout).repr {
|
||||
match interner.get_repr(layout) {
|
||||
LambdaSet(lambda_set) => lambda_set.runtime_representation(),
|
||||
_ => layout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> std::ops::Deref for Layout<'a> {
|
||||
type Target = LayoutRepr<'a>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.repr
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> LayoutRepr<'a> {
|
||||
pub const UNIT: Self = LayoutRepr::struct_(&[]);
|
||||
pub const BOOL: Self = LayoutRepr::Builtin(Builtin::Bool);
|
||||
|
@ -2525,6 +2539,10 @@ impl<'a> LayoutRepr<'a> {
|
|||
Self::Struct(field_layouts)
|
||||
}
|
||||
|
||||
pub(crate) const fn direct(self) -> LayoutWrapper<'a> {
|
||||
LayoutWrapper::Direct(self)
|
||||
}
|
||||
|
||||
pub fn safe_to_memcpy<I>(&self, interner: &I) -> bool
|
||||
where
|
||||
I: LayoutInterner<'a>,
|
||||
|
@ -2535,7 +2553,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
Builtin(builtin) => builtin.safe_to_memcpy(),
|
||||
Struct(field_layouts) => field_layouts
|
||||
.iter()
|
||||
.all(|field_layout| interner.get(*field_layout).safe_to_memcpy(interner)),
|
||||
.all(|field_layout| interner.get_repr(*field_layout).safe_to_memcpy(interner)),
|
||||
Union(variant) => {
|
||||
use UnionLayout::*;
|
||||
|
||||
|
@ -2543,7 +2561,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
NonRecursive(tags) => tags.iter().all(|tag_layout| {
|
||||
tag_layout
|
||||
.iter()
|
||||
.all(|field| interner.get(*field).safe_to_memcpy(interner))
|
||||
.all(|field| interner.get_repr(*field).safe_to_memcpy(interner))
|
||||
}),
|
||||
Recursive(_)
|
||||
| NullableWrapped { .. }
|
||||
|
@ -2555,7 +2573,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
}
|
||||
}
|
||||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.get_repr(lambda_set.runtime_representation())
|
||||
.safe_to_memcpy(interner),
|
||||
Boxed(_) | RecursivePointer(_) => {
|
||||
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
||||
|
@ -2592,7 +2610,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
}
|
||||
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => true,
|
||||
LayoutRepr::LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.get_repr(lambda_set.runtime_representation())
|
||||
.is_passed_by_reference(interner, target_info),
|
||||
_ => false,
|
||||
}
|
||||
|
@ -2633,7 +2651,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
|
||||
for field_layout in *field_layouts {
|
||||
sum += interner
|
||||
.get(*field_layout)
|
||||
.get_repr(*field_layout)
|
||||
.stack_size(interner, target_info);
|
||||
}
|
||||
|
||||
|
@ -2641,7 +2659,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
}
|
||||
Union(variant) => variant.stack_size_without_alignment(interner, target_info),
|
||||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.get_repr(lambda_set.runtime_representation())
|
||||
.stack_size_without_alignment(interner, target_info),
|
||||
RecursivePointer(_) => target_info.ptr_width() as u32,
|
||||
Boxed(_) => target_info.ptr_width() as u32,
|
||||
|
@ -2656,7 +2674,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
match self {
|
||||
Struct(field_layouts) => field_layouts
|
||||
.iter()
|
||||
.map(|x| interner.get(*x).alignment_bytes(interner, target_info))
|
||||
.map(|x| interner.get_repr(*x).alignment_bytes(interner, target_info))
|
||||
.max()
|
||||
.unwrap_or(0),
|
||||
|
||||
|
@ -2669,7 +2687,9 @@ impl<'a> LayoutRepr<'a> {
|
|||
.iter()
|
||||
.flat_map(|layouts| {
|
||||
layouts.iter().map(|layout| {
|
||||
interner.get(*layout).alignment_bytes(interner, target_info)
|
||||
interner
|
||||
.get_repr(*layout)
|
||||
.alignment_bytes(interner, target_info)
|
||||
})
|
||||
})
|
||||
.max();
|
||||
|
@ -2693,7 +2713,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
}
|
||||
}
|
||||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.get_repr(lambda_set.runtime_representation())
|
||||
.alignment_bytes(interner, target_info),
|
||||
Builtin(builtin) => builtin.alignment_bytes(target_info),
|
||||
RecursivePointer(_) => target_info.ptr_width() as u32,
|
||||
|
@ -2713,14 +2733,16 @@ impl<'a> LayoutRepr<'a> {
|
|||
Struct { .. } => self.alignment_bytes(interner, target_info).max(ptr_width),
|
||||
Union(union_layout) => union_layout.allocation_alignment_bytes(interner, target_info),
|
||||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.get_repr(lambda_set.runtime_representation())
|
||||
.allocation_alignment_bytes(interner, target_info),
|
||||
RecursivePointer(_) => {
|
||||
unreachable!("should be looked up to get an actual layout")
|
||||
}
|
||||
Boxed(inner) => Ord::max(
|
||||
ptr_width,
|
||||
interner.get(*inner).alignment_bytes(interner, target_info),
|
||||
interner
|
||||
.get_repr(*inner)
|
||||
.alignment_bytes(interner, target_info),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -2755,7 +2777,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
Builtin(builtin) => builtin.is_refcounted(),
|
||||
Struct(field_layouts) => field_layouts
|
||||
.iter()
|
||||
.any(|f| interner.get(*f).contains_refcounted(interner)),
|
||||
.any(|f| interner.get_repr(*f).contains_refcounted(interner)),
|
||||
Union(variant) => {
|
||||
use UnionLayout::*;
|
||||
|
||||
|
@ -2763,7 +2785,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
NonRecursive(fields) => fields
|
||||
.iter()
|
||||
.flat_map(|ls| ls.iter())
|
||||
.any(|f| interner.get(*f).contains_refcounted(interner)),
|
||||
.any(|f| interner.get_repr(*f).contains_refcounted(interner)),
|
||||
Recursive(_)
|
||||
| NullableWrapped { .. }
|
||||
| NullableUnwrapped { .. }
|
||||
|
@ -2771,7 +2793,7 @@ impl<'a> LayoutRepr<'a> {
|
|||
}
|
||||
}
|
||||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.get_repr(lambda_set.runtime_representation())
|
||||
.contains_refcounted(interner),
|
||||
RecursivePointer(_) => true,
|
||||
Boxed(_) => true,
|
||||
|
@ -2805,27 +2827,27 @@ impl<'a> LayoutRepr<'a> {
|
|||
Struct(field_layouts) => stack.extend(
|
||||
field_layouts
|
||||
.iter()
|
||||
.map(|interned| interner.get(*interned).repr),
|
||||
.map(|interned| interner.get_repr(*interned)),
|
||||
),
|
||||
Union(tag_union) => match tag_union {
|
||||
UnionLayout::NonRecursive(tags) | UnionLayout::Recursive(tags) => {
|
||||
for tag in tags {
|
||||
stack.extend(tag.iter().map(|interned| interner.get(*interned).repr));
|
||||
stack.extend(tag.iter().map(|interned| interner.get_repr(*interned)));
|
||||
}
|
||||
}
|
||||
UnionLayout::NonNullableUnwrapped(fields) => {
|
||||
stack.extend(fields.iter().map(|interned| interner.get(*interned).repr));
|
||||
stack.extend(fields.iter().map(|interned| interner.get_repr(*interned)));
|
||||
}
|
||||
UnionLayout::NullableWrapped { other_tags, .. } => {
|
||||
for tag in other_tags {
|
||||
stack.extend(tag.iter().map(|interned| interner.get(*interned).repr));
|
||||
stack.extend(tag.iter().map(|interned| interner.get_repr(*interned)));
|
||||
}
|
||||
}
|
||||
UnionLayout::NullableUnwrapped { other_fields, .. } => {
|
||||
stack.extend(
|
||||
other_fields
|
||||
.iter()
|
||||
.map(|interned| interner.get(*interned).repr),
|
||||
.map(|interned| interner.get_repr(*interned)),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -2894,9 +2916,12 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_recursive_tag_union(self) -> bool {
|
||||
pub fn is_recursive_tag_union<I>(self, interner: &I) -> bool
|
||||
where
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
matches!(
|
||||
self.repr,
|
||||
self.repr(interner),
|
||||
LayoutRepr::Union(
|
||||
UnionLayout::NullableUnwrapped { .. }
|
||||
| UnionLayout::Recursive(_)
|
||||
|
@ -3044,7 +3069,7 @@ impl<'a> Builtin<'a> {
|
|||
let allocation = match self {
|
||||
Builtin::Str => ptr_width,
|
||||
Builtin::List(e) => {
|
||||
let e = interner.get(*e);
|
||||
let e = interner.get_repr(*e);
|
||||
e.alignment_bytes(interner, target_info).max(ptr_width)
|
||||
}
|
||||
// The following are usually not heap-allocated, but they might be when inside a Box.
|
||||
|
@ -3157,7 +3182,7 @@ fn layout_from_flat_type<'a>(
|
|||
let inner_layout =
|
||||
cached!(Layout::from_var(env, inner_var), criteria, env.subs);
|
||||
let boxed_layout = env.cache.put_in(Layout {
|
||||
repr: LayoutRepr::Boxed(inner_layout),
|
||||
repr: LayoutRepr::Boxed(inner_layout).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
});
|
||||
|
||||
|
@ -3233,22 +3258,22 @@ fn layout_from_flat_type<'a>(
|
|||
.iter()
|
||||
.map(|(label, _)| &*arena.alloc_str(label.as_str())),
|
||||
arena,
|
||||
);
|
||||
)
|
||||
.into_bump_slice();
|
||||
let semantic = SemanticRepr::record(ordered_field_names);
|
||||
|
||||
let result = if sortables.len() == 1 {
|
||||
let repr = if sortables.len() == 1 {
|
||||
// If the record has only one field that isn't zero-sized,
|
||||
// unwrap it.
|
||||
Ok(sortables.pop().unwrap().1)
|
||||
let inner_repr = sortables.pop().unwrap().1;
|
||||
inner_repr.newtype()
|
||||
} else {
|
||||
let layouts = Vec::from_iter_in(sortables.into_iter().map(|t| t.1), arena);
|
||||
let struct_layout = Layout {
|
||||
repr: LayoutRepr::Struct(layouts.into_bump_slice()),
|
||||
semantic: SemanticRepr::record(ordered_field_names.into_bump_slice()),
|
||||
};
|
||||
|
||||
Ok(env.cache.put_in(struct_layout))
|
||||
LayoutRepr::Struct(layouts.into_bump_slice()).direct()
|
||||
};
|
||||
|
||||
let result = Ok(env.cache.put_in(Layout { repr, semantic }));
|
||||
|
||||
Cacheable(result, criteria)
|
||||
}
|
||||
Tuple(elems, ext_var) => {
|
||||
|
@ -3285,7 +3310,7 @@ fn layout_from_flat_type<'a>(
|
|||
let field_layouts =
|
||||
Vec::from_iter_in(sortables.into_iter().map(|t| t.1), arena).into_bump_slice();
|
||||
let struct_layout = Layout {
|
||||
repr: LayoutRepr::Struct(field_layouts),
|
||||
repr: LayoutRepr::Struct(field_layouts).direct(),
|
||||
semantic: SemanticRepr::tuple(field_layouts.len()),
|
||||
};
|
||||
|
||||
|
@ -3720,11 +3745,11 @@ where
|
|||
layouts.sort_by(|layout1, layout2| {
|
||||
let size1 = env
|
||||
.cache
|
||||
.get_in(*layout1)
|
||||
.get_repr(*layout1)
|
||||
.alignment_bytes(&env.cache.interner, env.target_info);
|
||||
let size2 = env
|
||||
.cache
|
||||
.get_in(*layout2)
|
||||
.get_repr(*layout2)
|
||||
.alignment_bytes(&env.cache.interner, env.target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
|
@ -3782,11 +3807,11 @@ where
|
|||
arg_layouts.sort_by(|layout1, layout2| {
|
||||
let size1 = env
|
||||
.cache
|
||||
.get_in(*layout1)
|
||||
.get_repr(*layout1)
|
||||
.alignment_bytes(&env.cache.interner, env.target_info);
|
||||
let size2 = env
|
||||
.cache
|
||||
.get_in(*layout2)
|
||||
.get_repr(*layout2)
|
||||
.alignment_bytes(&env.cache.interner, env.target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
|
@ -3964,7 +3989,7 @@ where
|
|||
== env
|
||||
.subs
|
||||
.get_root_key_without_compacting(opt_rec_var.unwrap())
|
||||
&& layout.is_recursive_tag_union();
|
||||
&& layout.is_recursive_tag_union(&env.cache.interner);
|
||||
|
||||
let arg_layout = if self_recursion {
|
||||
Layout::NAKED_RECURSIVE_PTR
|
||||
|
@ -3994,11 +4019,11 @@ where
|
|||
arg_layouts.sort_by(|layout1, layout2| {
|
||||
let size1 = env
|
||||
.cache
|
||||
.get_in(*layout1)
|
||||
.get_repr(*layout1)
|
||||
.alignment_bytes(&env.cache.interner, env.target_info);
|
||||
let size2 = env
|
||||
.cache
|
||||
.get_in(*layout2)
|
||||
.get_repr(*layout2)
|
||||
.alignment_bytes(&env.cache.interner, env.target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
|
@ -4133,13 +4158,13 @@ where
|
|||
Never => Layout::VOID,
|
||||
Unit => env
|
||||
.cache
|
||||
.put_in(Layout::new(LayoutRepr::UNIT, compute_semantic())),
|
||||
.put_in(Layout::new(LayoutRepr::UNIT.direct(), compute_semantic())),
|
||||
BoolUnion { .. } => env
|
||||
.cache
|
||||
.put_in(Layout::new(LayoutRepr::BOOL, compute_semantic())),
|
||||
.put_in(Layout::new(LayoutRepr::BOOL.direct(), compute_semantic())),
|
||||
ByteUnion(_) => env
|
||||
.cache
|
||||
.put_in(Layout::new(LayoutRepr::U8, compute_semantic())),
|
||||
.put_in(Layout::new(LayoutRepr::U8.direct(), compute_semantic())),
|
||||
Newtype {
|
||||
arguments: field_layouts,
|
||||
..
|
||||
|
@ -4148,7 +4173,7 @@ where
|
|||
field_layouts[0]
|
||||
} else {
|
||||
env.cache
|
||||
.put_in_no_semantic(LayoutRepr::struct_(field_layouts.into_bump_slice()))
|
||||
.put_in_direct_no_semantic(LayoutRepr::struct_(field_layouts.into_bump_slice()))
|
||||
};
|
||||
|
||||
answer1
|
||||
|
@ -4159,8 +4184,9 @@ where
|
|||
if data_tag_arguments.len() == 1 {
|
||||
data_tag_arguments[0]
|
||||
} else {
|
||||
env.cache
|
||||
.put_in_no_semantic(LayoutRepr::struct_(data_tag_arguments.into_bump_slice()))
|
||||
env.cache.put_in_direct_no_semantic(LayoutRepr::struct_(
|
||||
data_tag_arguments.into_bump_slice(),
|
||||
))
|
||||
}
|
||||
}
|
||||
Wrapped(variant) => {
|
||||
|
@ -4176,7 +4202,8 @@ where
|
|||
let layout = Layout {
|
||||
repr: LayoutRepr::Union(UnionLayout::NonRecursive(
|
||||
tag_layouts.into_bump_slice(),
|
||||
)),
|
||||
))
|
||||
.direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
};
|
||||
env.cache.put_in(layout)
|
||||
|
@ -4292,14 +4319,14 @@ where
|
|||
env.cache.interner.insert_recursive(
|
||||
env.arena,
|
||||
Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
repr: LayoutRepr::Union(union_layout).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
// There are no naked recursion pointers, so we can insert the layout as-is.
|
||||
env.cache.interner.insert(Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
repr: LayoutRepr::Union(union_layout).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
})
|
||||
};
|
||||
|
@ -4435,7 +4462,7 @@ pub(crate) fn list_layout_from_elem<'a>(
|
|||
};
|
||||
|
||||
let list_layout = env.cache.put_in(Layout {
|
||||
repr: LayoutRepr::Builtin(Builtin::List(element_layout)),
|
||||
repr: LayoutRepr::Builtin(Builtin::List(element_layout)).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
});
|
||||
|
||||
|
@ -4589,8 +4616,12 @@ pub fn cmp_fields<'a, L: Ord, I>(
|
|||
where
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let size1 = interner.get(layout1).alignment_bytes(interner, target_info);
|
||||
let size2 = interner.get(layout2).alignment_bytes(interner, target_info);
|
||||
let size1 = interner
|
||||
.get_repr(layout1)
|
||||
.alignment_bytes(interner, target_info);
|
||||
let size2 = interner
|
||||
.get_repr(layout2)
|
||||
.alignment_bytes(interner, target_info);
|
||||
|
||||
size2.cmp(&size1).then(label1.cmp(label2))
|
||||
}
|
||||
|
@ -4613,19 +4644,16 @@ mod test {
|
|||
|
||||
let a = &[Layout::UNIT] as &[_];
|
||||
let b = &[interner.insert(Layout {
|
||||
repr: LayoutRepr::LambdaSet(lambda_set),
|
||||
repr: LayoutRepr::LambdaSet(lambda_set).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
})] as &[_];
|
||||
let tt = [a, b];
|
||||
|
||||
let layout = Layout {
|
||||
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&tt)),
|
||||
semantic: SemanticRepr::NONE,
|
||||
};
|
||||
let repr = LayoutRepr::Union(UnionLayout::NonRecursive(&tt));
|
||||
|
||||
let target_info = TargetInfo::default_x86_64();
|
||||
assert_eq!(layout.stack_size(&interner, target_info), 1);
|
||||
assert_eq!(layout.alignment_bytes(&interner, target_info), 1);
|
||||
assert_eq!(repr.stack_size(&interner, target_info), 1);
|
||||
assert_eq!(repr.alignment_bytes(&interner, target_info), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -4633,29 +4661,28 @@ mod test {
|
|||
let mut interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64());
|
||||
|
||||
let ok_tag = &[interner.insert(Layout {
|
||||
repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)),
|
||||
repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
})];
|
||||
let err_tag = &[Layout::UNIT];
|
||||
let tags = [ok_tag as &[_], err_tag as &[_]];
|
||||
let union_layout = UnionLayout::NonRecursive(&tags as &[_]);
|
||||
let layout = Layout {
|
||||
repr: LayoutRepr::Union(union_layout),
|
||||
semantic: SemanticRepr::NONE,
|
||||
};
|
||||
let repr = LayoutRepr::Union(union_layout);
|
||||
|
||||
let target_info = TargetInfo::default_x86_64();
|
||||
assert_eq!(
|
||||
layout.stack_size_without_alignment(&interner, target_info),
|
||||
8
|
||||
);
|
||||
assert_eq!(repr.stack_size_without_alignment(&interner, target_info), 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn void_stack_size() {
|
||||
let interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64());
|
||||
let target_info = TargetInfo::default_x86_64();
|
||||
assert_eq!(Layout::VOID_NAKED.stack_size(&interner, target_info), 0);
|
||||
assert_eq!(
|
||||
Layout::VOID_NAKED
|
||||
.repr(&interner)
|
||||
.stack_size(&interner, target_info),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -14,7 +14,7 @@ use roc_target::TargetInfo;
|
|||
|
||||
use crate::layout::LayoutRepr;
|
||||
|
||||
use super::{LambdaSet, Layout, SeenRecPtrs, SemanticRepr, UnionLayout};
|
||||
use super::{LambdaSet, Layout, LayoutWrapper, SeenRecPtrs, SemanticRepr, UnionLayout};
|
||||
|
||||
macro_rules! cache_interned_layouts {
|
||||
($($i:literal, $name:ident, $vis:vis, $layout:expr)*; $total_constants:literal) => {
|
||||
|
@ -50,7 +50,7 @@ macro_rules! cache_interned_layouts {
|
|||
macro_rules! nosema {
|
||||
($r:expr) => {
|
||||
Layout {
|
||||
repr: $r,
|
||||
repr: $r.direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
}
|
||||
};
|
||||
|
@ -119,11 +119,11 @@ impl_to_from_int_width! {
|
|||
|
||||
impl<'a> Layout<'a> {
|
||||
pub(super) const VOID_NAKED: Self = Layout {
|
||||
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&[])),
|
||||
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&[])).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
};
|
||||
pub(super) const UNIT_NAKED: Self = Layout {
|
||||
repr: LayoutRepr::Struct(&[]),
|
||||
repr: LayoutRepr::Struct(&[]).direct(),
|
||||
semantic: SemanticRepr::EMPTY_RECORD,
|
||||
};
|
||||
|
||||
|
@ -154,8 +154,8 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
|
||||
/// Interns a value with no semantic representation, returning its interned representation.
|
||||
/// If the value has been interned before, the old interned representation will be re-used.
|
||||
fn insert_no_semantic(&mut self, repr: LayoutRepr<'a>) -> InLayout<'a> {
|
||||
self.insert(Layout::no_semantic(repr))
|
||||
fn insert_direct_no_semantic(&mut self, repr: LayoutRepr<'a>) -> InLayout<'a> {
|
||||
self.insert(Layout::no_semantic(repr.direct()))
|
||||
}
|
||||
|
||||
/// Creates a [LambdaSet], including caching the [LayoutRepr::LambdaSet] representation of the
|
||||
|
@ -181,60 +181,78 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
//
|
||||
// Convenience methods
|
||||
|
||||
fn get_repr(&self, mut key: InLayout<'a>) -> LayoutRepr<'a> {
|
||||
loop {
|
||||
match self.get(key).repr {
|
||||
LayoutWrapper::Direct(repr) => return repr,
|
||||
LayoutWrapper::Newtype(inner) => key = inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_semantic(&self, key: InLayout<'a>) -> SemanticRepr<'a> {
|
||||
self.get(key).semantic
|
||||
}
|
||||
|
||||
fn eq_repr(&self, a: InLayout<'a>, b: InLayout<'a>) -> bool {
|
||||
self.get(a).repr == self.get(b).repr
|
||||
self.get_repr(a) == self.get_repr(b)
|
||||
}
|
||||
|
||||
fn target_info(&self) -> TargetInfo;
|
||||
|
||||
fn alignment_bytes(&self, layout: InLayout<'a>) -> u32 {
|
||||
self.get(layout).alignment_bytes(self, self.target_info())
|
||||
self.get_repr(layout)
|
||||
.alignment_bytes(self, self.target_info())
|
||||
}
|
||||
|
||||
fn allocation_alignment_bytes(&self, layout: InLayout<'a>) -> u32 {
|
||||
self.get(layout)
|
||||
self.get_repr(layout)
|
||||
.allocation_alignment_bytes(self, self.target_info())
|
||||
}
|
||||
|
||||
fn stack_size(&self, layout: InLayout<'a>) -> u32 {
|
||||
self.get(layout).stack_size(self, self.target_info())
|
||||
self.get_repr(layout).stack_size(self, self.target_info())
|
||||
}
|
||||
|
||||
fn stack_size_and_alignment(&self, layout: InLayout<'a>) -> (u32, u32) {
|
||||
self.get(layout)
|
||||
self.get_repr(layout)
|
||||
.stack_size_and_alignment(self, self.target_info())
|
||||
}
|
||||
|
||||
fn stack_size_without_alignment(&self, layout: InLayout<'a>) -> u32 {
|
||||
self.get(layout)
|
||||
self.get_repr(layout)
|
||||
.stack_size_without_alignment(self, self.target_info())
|
||||
}
|
||||
|
||||
fn contains_refcounted(&self, layout: InLayout<'a>) -> bool {
|
||||
self.get(layout).contains_refcounted(self)
|
||||
self.get_repr(layout).contains_refcounted(self)
|
||||
}
|
||||
|
||||
fn is_refcounted(&self, layout: InLayout<'a>) -> bool {
|
||||
self.get(layout).is_refcounted()
|
||||
self.get_repr(layout).is_refcounted()
|
||||
}
|
||||
|
||||
fn is_passed_by_reference(&self, layout: InLayout<'a>) -> bool {
|
||||
self.get(layout)
|
||||
self.get_repr(layout)
|
||||
.is_passed_by_reference(self, self.target_info())
|
||||
}
|
||||
|
||||
fn runtime_representation(&self, layout: InLayout<'a>) -> Layout<'a> {
|
||||
self.get(layout).runtime_representation(self)
|
||||
fn runtime_representation(&self, layout: InLayout<'a>) -> LayoutRepr<'a> {
|
||||
self.get_repr(self.runtime_representation_in(layout))
|
||||
}
|
||||
|
||||
fn runtime_representation_in(&self, layout: InLayout<'a>) -> InLayout<'a> {
|
||||
Layout::runtime_representation_in(layout, self)
|
||||
}
|
||||
|
||||
fn chase_recursive(&self, mut layout: InLayout<'a>) -> Layout<'a> {
|
||||
fn has_varying_stack_size(&self, layout: InLayout<'a>, arena: &'a Bump) -> bool {
|
||||
self.get_repr(layout).has_varying_stack_size(self, arena)
|
||||
}
|
||||
|
||||
fn chase_recursive(&self, mut layout: InLayout<'a>) -> LayoutRepr<'a> {
|
||||
loop {
|
||||
let lay = self.get(layout);
|
||||
match lay.repr {
|
||||
let lay = self.get_repr(layout);
|
||||
match lay {
|
||||
LayoutRepr::RecursivePointer(l) => layout = l,
|
||||
_ => return lay,
|
||||
}
|
||||
|
@ -243,7 +261,7 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
|
||||
fn chase_recursive_in(&self, mut layout: InLayout<'a>) -> InLayout<'a> {
|
||||
loop {
|
||||
match self.get(layout).repr {
|
||||
match self.get_repr(layout) {
|
||||
LayoutRepr::RecursivePointer(l) => layout = l,
|
||||
_ => return layout,
|
||||
}
|
||||
|
@ -251,7 +269,7 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
}
|
||||
|
||||
fn safe_to_memcpy(&self, layout: InLayout<'a>) -> bool {
|
||||
self.get(layout).safe_to_memcpy(self)
|
||||
self.get_repr(layout).safe_to_memcpy(self)
|
||||
}
|
||||
|
||||
/// Checks if two layouts are equivalent up to isomorphism.
|
||||
|
@ -298,7 +316,7 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
{
|
||||
use LayoutRepr::*;
|
||||
|
||||
match self.get(layout).repr {
|
||||
match self.get_repr(layout) {
|
||||
Builtin(builtin) => builtin.to_doc(alloc, self, seen_rec, parens),
|
||||
Struct(field_layouts) => {
|
||||
let fields_doc = field_layouts
|
||||
|
@ -455,6 +473,10 @@ impl<'a> InLayout<'a> {
|
|||
Self(index, PhantomData)
|
||||
}
|
||||
|
||||
pub(crate) const fn newtype(self) -> LayoutWrapper<'a> {
|
||||
LayoutWrapper::Newtype(self)
|
||||
}
|
||||
|
||||
pub fn index(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
@ -665,7 +687,7 @@ impl<'a> GlobalLayoutInterner<'a> {
|
|||
..normalized
|
||||
};
|
||||
let lambda_set_layout = Layout {
|
||||
repr: LayoutRepr::LambdaSet(full_lambda_set),
|
||||
repr: LayoutRepr::LambdaSet(full_lambda_set).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
};
|
||||
|
||||
|
@ -974,7 +996,7 @@ macro_rules! st_impl {
|
|||
full_layout: slot,
|
||||
};
|
||||
let lay = Layout {
|
||||
repr: LayoutRepr::LambdaSet(lambda_set),
|
||||
repr: LayoutRepr::LambdaSet(lambda_set).direct(),
|
||||
semantic: SemanticRepr::NONE
|
||||
};
|
||||
self.vec[slot.0] = lay;
|
||||
|
@ -1035,7 +1057,7 @@ mod reify {
|
|||
use bumpalo::{collections::Vec, Bump};
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, UnionLayout};
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, LayoutWrapper, UnionLayout};
|
||||
|
||||
use super::{InLayout, LayoutInterner, NeedsRecursionPointerFixup};
|
||||
|
||||
|
@ -1046,7 +1068,24 @@ mod reify {
|
|||
slot: InLayout<'a>,
|
||||
normalized_layout: Layout<'a>,
|
||||
) -> Layout<'a> {
|
||||
let repr = match normalized_layout.repr {
|
||||
let Layout { repr, semantic } = normalized_layout;
|
||||
let reified_repr = match repr {
|
||||
LayoutWrapper::Direct(repr) => {
|
||||
reify_recursive_layout_repr(arena, interner, slot, repr).direct()
|
||||
}
|
||||
LayoutWrapper::Newtype(inner) => reify_layout(arena, interner, slot, inner).newtype(),
|
||||
};
|
||||
|
||||
Layout::new(reified_repr, semantic)
|
||||
}
|
||||
|
||||
fn reify_recursive_layout_repr<'a>(
|
||||
arena: &'a Bump,
|
||||
interner: &mut impl LayoutInterner<'a>,
|
||||
slot: InLayout<'a>,
|
||||
repr: LayoutRepr<'a>,
|
||||
) -> LayoutRepr<'a> {
|
||||
match repr {
|
||||
LayoutRepr::Builtin(builtin) => {
|
||||
LayoutRepr::Builtin(reify_builtin(arena, interner, slot, builtin))
|
||||
}
|
||||
|
@ -1063,10 +1102,6 @@ mod reify {
|
|||
// another recursive union's layout, do not change it.
|
||||
LayoutRepr::RecursivePointer(if l == Layout::VOID { slot } else { l })
|
||||
}
|
||||
};
|
||||
Layout {
|
||||
repr,
|
||||
semantic: normalized_layout.semantic,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1244,7 +1279,7 @@ mod equiv {
|
|||
continue;
|
||||
}
|
||||
use LayoutRepr::*;
|
||||
match (interner.get(l1).repr, interner.get(l2).repr) {
|
||||
match (interner.get_repr(l1), interner.get_repr(l2)) {
|
||||
(RecursivePointer(rec), _) => stack.push((rec, l2)),
|
||||
(_, RecursivePointer(rec)) => stack.push((l1, rec)),
|
||||
(Builtin(b1), Builtin(b2)) => {
|
||||
|
@ -1340,7 +1375,7 @@ mod equiv {
|
|||
pub mod dbg {
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, UnionLayout};
|
||||
use crate::layout::{Builtin, LambdaSet, LayoutRepr, UnionLayout};
|
||||
|
||||
use super::{InLayout, LayoutInterner};
|
||||
|
||||
|
@ -1348,7 +1383,8 @@ pub mod dbg {
|
|||
|
||||
impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for Dbg<'a, 'r, I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Layout { repr, semantic } = self.0.get(self.1);
|
||||
let repr = self.0.get_repr(self.1);
|
||||
let semantic = self.0.get_semantic(self.1);
|
||||
|
||||
f.debug_struct("Layout")
|
||||
.field("repr", &DbgRepr(self.0, &repr))
|
||||
|
@ -1544,7 +1580,7 @@ mod insert_lambda_set {
|
|||
let lambda_set =
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, TEST_SET, FIXUP, Layout::UNIT);
|
||||
let lambda_set_layout_in = interner.insert(Layout {
|
||||
repr: LayoutRepr::LambdaSet(lambda_set),
|
||||
repr: LayoutRepr::LambdaSet(lambda_set).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
});
|
||||
assert_eq!(lambda_set.full_layout, lambda_set_layout_in);
|
||||
|
@ -1603,15 +1639,16 @@ mod insert_recursive_layout {
|
|||
|
||||
fn make_layout<'a>(arena: &'a Bump, interner: &mut impl LayoutInterner<'a>) -> Layout<'a> {
|
||||
let list_rec = Layout {
|
||||
repr: LayoutRepr::Builtin(Builtin::List(Layout::NAKED_RECURSIVE_PTR)),
|
||||
repr: LayoutRepr::Builtin(Builtin::List(Layout::NAKED_RECURSIVE_PTR)).direct(),
|
||||
semantic: SemanticRepr::NONE,
|
||||
};
|
||||
let repr = LayoutRepr::Union(UnionLayout::Recursive(&*arena.alloc([
|
||||
&*arena.alloc([interner.insert(list_rec)]),
|
||||
&*arena.alloc_slice_fill_iter([interner.insert_no_semantic(LayoutRepr::struct_(
|
||||
&*arena.alloc([Layout::NAKED_RECURSIVE_PTR]),
|
||||
))]),
|
||||
])));
|
||||
&*arena.alloc_slice_fill_iter([interner.insert_direct_no_semantic(
|
||||
LayoutRepr::struct_(&*arena.alloc([Layout::NAKED_RECURSIVE_PTR])),
|
||||
)]),
|
||||
])))
|
||||
.direct();
|
||||
Layout {
|
||||
repr,
|
||||
semantic: SemanticRepr::NONE,
|
||||
|
@ -1619,11 +1656,11 @@ mod insert_recursive_layout {
|
|||
}
|
||||
|
||||
fn get_rec_ptr_index<'a>(interner: &impl LayoutInterner<'a>, layout: InLayout<'a>) -> usize {
|
||||
match interner.chase_recursive(layout).repr {
|
||||
match interner.chase_recursive(layout) {
|
||||
LayoutRepr::Union(UnionLayout::Recursive(&[&[l1], &[l2]])) => {
|
||||
match (interner.get(l1).repr, interner.get(l2).repr) {
|
||||
match (interner.get_repr(l1), interner.get_repr(l2)) {
|
||||
(LayoutRepr::Builtin(Builtin::List(l1)), LayoutRepr::Struct(&[l2])) => {
|
||||
match (interner.get(l1).repr, interner.get(l2).repr) {
|
||||
match (interner.get_repr(l1), interner.get_repr(l2)) {
|
||||
(
|
||||
LayoutRepr::RecursivePointer(i1),
|
||||
LayoutRepr::RecursivePointer(i2),
|
||||
|
|
|
@ -1277,7 +1277,7 @@ fn symbol_layout_reusability<'a>(
|
|||
symbol: &Symbol,
|
||||
layout: &InLayout<'a>,
|
||||
) -> Reuse<'a> {
|
||||
match layout_interner.get(*layout).repr {
|
||||
match layout_interner.get_repr(*layout) {
|
||||
LayoutRepr::Union(union_layout) => {
|
||||
can_reuse_union_layout_tag(union_layout, environment.get_symbol_tag(symbol))
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::parser::{BadInputError, EExpr, ParseResult, Parser};
|
|||
use crate::state::State;
|
||||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_region::all::Position;
|
||||
use roc_region::all::{Position, Region};
|
||||
|
||||
/// A tag, for example. Must start with an uppercase letter
|
||||
/// and then contain only letters and numbers afterwards - no dots allowed!
|
||||
|
@ -254,7 +254,14 @@ pub enum BadIdent {
|
|||
Start(Position),
|
||||
Space(BadInputError, Position),
|
||||
|
||||
Underscore(Position),
|
||||
UnderscoreAlone(Position),
|
||||
UnderscoreInMiddle(Position),
|
||||
UnderscoreAtStart {
|
||||
position: Position,
|
||||
/// If this variable was already declared in a pattern (e.g. \_x -> _x),
|
||||
/// then this is where it was declared.
|
||||
declaration_region: Option<Region>,
|
||||
},
|
||||
QualifiedTag(Position),
|
||||
WeirdAccessor(Position),
|
||||
WeirdDotAccess(Position),
|
||||
|
@ -529,7 +536,7 @@ fn chomp_identifier_chain<'a>(
|
|||
// to give good error messages for this case
|
||||
Err((
|
||||
chomped as u32 + 1,
|
||||
BadIdent::Underscore(pos.bump_column(chomped as u32 + 1)),
|
||||
BadIdent::UnderscoreInMiddle(pos.bump_column(chomped as u32 + 1)),
|
||||
))
|
||||
} else if first_is_uppercase {
|
||||
// just one segment, starting with an uppercase letter; that's a tag
|
||||
|
|
|
@ -335,7 +335,11 @@ impl Problem {
|
|||
})
|
||||
| Problem::RuntimeError(RuntimeError::UnsupportedPattern(region))
|
||||
| Problem::RuntimeError(RuntimeError::MalformedPattern(_, region))
|
||||
| Problem::RuntimeError(RuntimeError::LookupNotInScope(Loc { region, .. }, _))
|
||||
| Problem::RuntimeError(RuntimeError::LookupNotInScope {
|
||||
loc_name: Loc { region, .. },
|
||||
suggestion_options: _,
|
||||
underscored_suggestion_region: _,
|
||||
})
|
||||
| Problem::RuntimeError(RuntimeError::OpaqueNotDefined {
|
||||
usage: Loc { region, .. },
|
||||
..
|
||||
|
@ -505,7 +509,14 @@ pub enum RuntimeError {
|
|||
UnresolvedTypeVar,
|
||||
ErroneousType,
|
||||
|
||||
LookupNotInScope(Loc<Ident>, MutSet<Box<str>>),
|
||||
LookupNotInScope {
|
||||
loc_name: Loc<Ident>,
|
||||
/// All of the names in scope (for the error message)
|
||||
suggestion_options: MutSet<Box<str>>,
|
||||
/// If the unfound variable is `name` and there's an ignored variable called `_name`,
|
||||
/// this is the region where `_name` is defined (for the error message)
|
||||
underscored_suggestion_region: Option<Region>,
|
||||
},
|
||||
OpaqueNotDefined {
|
||||
usage: Loc<Ident>,
|
||||
opaques_in_scope: MutSet<Box<str>>,
|
||||
|
|
|
@ -932,6 +932,29 @@ fn encode_derived_generic_tag_with_different_field_types() {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn specialize_unique_newtype_records() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test"
|
||||
imports [Encode, Json]
|
||||
provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
when Str.fromUtf8 (Encode.toBytes {a: Bool.true} Json.json) is
|
||||
Ok s -> when Str.fromUtf8 (Encode.toBytes {b: Bool.true} Json.json) is
|
||||
Ok t -> "\(s)\(t)"
|
||||
_ -> "<bad>"
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
),
|
||||
RocStr::from(r#"{"a":true}{"b":true}"#),
|
||||
RocStr
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn decode_use_stdlib() {
|
||||
|
|
|
@ -17,6 +17,8 @@ use roc_mono::layout::{LayoutRepr, STLayoutInterner};
|
|||
#[cfg(test)]
|
||||
use roc_std::{RocList, RocStr, U128};
|
||||
|
||||
use crate::helpers::with_larger_debug_stack;
|
||||
|
||||
#[test]
|
||||
fn width_and_alignment_u8_u8() {
|
||||
use roc_mono::layout::Layout;
|
||||
|
@ -28,7 +30,7 @@ fn width_and_alignment_u8_u8() {
|
|||
let t = &[Layout::U8] as &[_];
|
||||
let tt = [t, t];
|
||||
|
||||
let layout = Layout::no_semantic(LayoutRepr::Union(UnionLayout::NonRecursive(&tt)));
|
||||
let layout = LayoutRepr::Union(UnionLayout::NonRecursive(&tt));
|
||||
|
||||
assert_eq!(layout.alignment_bytes(&interner, target_info), 1);
|
||||
assert_eq!(layout.stack_size(&interner, target_info), 2);
|
||||
|
@ -2174,25 +2176,25 @@ fn issue_5162_recast_nested_nullable_unwrapped_layout() {
|
|||
assert_evals_to!(
|
||||
indoc!(
|
||||
r###"
|
||||
app "test" provides [main] to "./platform"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
Concept : [
|
||||
AtomicConcept,
|
||||
ExistentialRestriction { role : Str, concept : Concept }
|
||||
]
|
||||
Concept : [
|
||||
AtomicConcept,
|
||||
ExistentialRestriction { role : Str, concept : Concept }
|
||||
]
|
||||
|
||||
bottom : Concept
|
||||
bottom = AtomicConcept
|
||||
bottom : Concept
|
||||
bottom = AtomicConcept
|
||||
|
||||
main =
|
||||
when Dict.single bottom 0 is
|
||||
_ -> Bool.true
|
||||
"###
|
||||
main =
|
||||
when Dict.single bottom 0 is
|
||||
_ -> Bool.true
|
||||
"###
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -97,7 +97,7 @@ procedure Test.2 (Test.6):
|
|||
decref Test.6;
|
||||
jump #Derived_gen.0;
|
||||
else
|
||||
let Test.9 : List [<r>C List *self, C *self] = UnionAtIndex (Id 0) (Index 0) Test.6;
|
||||
let Test.9 : List [<r>C List [<r>C List *self, C *self], C [<r>C List *self, C *self]] = UnionAtIndex (Id 0) (Index 0) Test.6;
|
||||
joinpoint #Derived_gen.2:
|
||||
let Test.24 : {} = Struct {};
|
||||
let Test.23 : List Str = CallByName List.5 Test.9 Test.24;
|
||||
|
@ -116,7 +116,7 @@ procedure Test.2 (Test.6):
|
|||
jump #Derived_gen.2;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.32 : List [<r>C List *self, C *self] = Array [];
|
||||
let Test.32 : List [<r>C List [<r>C List *self, C *self], C [<r>C List *self, C *self]] = Array [];
|
||||
let Test.15 : [<r>C List *self, C *self] = TagId(0) Test.32;
|
||||
let Test.14 : Str = CallByName Test.2 Test.15;
|
||||
ret Test.14;
|
||||
|
|
12
crates/compiler/test_mono/generated/dbg_in_expect.txt
Normal file
12
crates/compiler/test_mono/generated/dbg_in_expect.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
procedure Bool.2 ():
|
||||
let Bool.23 : Int1 = true;
|
||||
ret Bool.23;
|
||||
|
||||
procedure Test.1 ():
|
||||
let Test.0 : Str = "";
|
||||
dbg Test.0;
|
||||
dec Test.0;
|
||||
let Test.3 : Int1 = CallByName Bool.2;
|
||||
expect Test.3;
|
||||
let Test.2 : {} = Struct {};
|
||||
ret Test.2;
|
|
@ -803,8 +803,8 @@ procedure Json.81 (Json.801, Json.802):
|
|||
|
||||
procedure Json.831 (Json.1492):
|
||||
let Json.1867 : List Str = StructAtIndex 1 Json.1492;
|
||||
let #Derived_gen.28 : List Str = StructAtIndex 0 Json.1492;
|
||||
dec #Derived_gen.28;
|
||||
let #Derived_gen.29 : List Str = StructAtIndex 0 Json.1492;
|
||||
dec #Derived_gen.29;
|
||||
ret Json.1867;
|
||||
|
||||
procedure Json.839 (Json.1213):
|
||||
|
@ -1478,8 +1478,8 @@ procedure Str.9 (Str.79):
|
|||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
let #Derived_gen.29 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.29;
|
||||
let #Derived_gen.28 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.28;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
|
|
@ -725,14 +725,14 @@ procedure Json.81 (Json.801, Json.802):
|
|||
|
||||
procedure Json.831 (Json.1492):
|
||||
let Json.1493 : List Str = StructAtIndex 1 Json.1492;
|
||||
let #Derived_gen.14 : List Str = StructAtIndex 0 Json.1492;
|
||||
dec #Derived_gen.14;
|
||||
let #Derived_gen.16 : List Str = StructAtIndex 0 Json.1492;
|
||||
dec #Derived_gen.16;
|
||||
ret Json.1493;
|
||||
|
||||
procedure Json.839 (Json.1213):
|
||||
let Json.1214 : List Str = StructAtIndex 1 Json.1213;
|
||||
let #Derived_gen.16 : List Str = StructAtIndex 0 Json.1213;
|
||||
dec #Derived_gen.16;
|
||||
let #Derived_gen.15 : List Str = StructAtIndex 0 Json.1213;
|
||||
dec #Derived_gen.15;
|
||||
ret Json.1214;
|
||||
|
||||
procedure Json.86 (Json.808):
|
||||
|
@ -1362,8 +1362,8 @@ procedure Str.9 (Str.79):
|
|||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
let #Derived_gen.15 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.15;
|
||||
let #Derived_gen.14 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.14;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
|
|
@ -732,14 +732,14 @@ procedure Json.81 (Json.801, Json.802):
|
|||
|
||||
procedure Json.831 (Json.1492):
|
||||
let Json.1493 : List Str = StructAtIndex 1 Json.1492;
|
||||
let #Derived_gen.19 : List Str = StructAtIndex 0 Json.1492;
|
||||
dec #Derived_gen.19;
|
||||
let #Derived_gen.20 : List Str = StructAtIndex 0 Json.1492;
|
||||
dec #Derived_gen.20;
|
||||
ret Json.1493;
|
||||
|
||||
procedure Json.839 (Json.1213):
|
||||
let Json.1214 : List Str = StructAtIndex 1 Json.1213;
|
||||
let #Derived_gen.20 : List Str = StructAtIndex 0 Json.1213;
|
||||
dec #Derived_gen.20;
|
||||
let #Derived_gen.19 : List Str = StructAtIndex 0 Json.1213;
|
||||
dec #Derived_gen.19;
|
||||
ret Json.1214;
|
||||
|
||||
procedure Json.86 (Json.808):
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
procedure Test.1 (Test.4):
|
||||
ret Test.4;
|
||||
let Test.13 : [C Str, C Str] = TagId(0) Test.4;
|
||||
ret Test.13;
|
||||
|
||||
procedure Test.5 (Test.12, Test.4):
|
||||
procedure Test.1 (Test.4):
|
||||
let Test.18 : [C Str, C Str] = TagId(0) Test.4;
|
||||
ret Test.18;
|
||||
|
||||
procedure Test.5 (Test.12, #Attr.12):
|
||||
let Test.4 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12;
|
||||
dec Test.4;
|
||||
let Test.14 : Str = "";
|
||||
ret Test.14;
|
||||
|
@ -11,13 +17,13 @@ procedure Test.0 ():
|
|||
joinpoint Test.9 Test.3:
|
||||
ret Test.3;
|
||||
in
|
||||
let Test.19 : Int1 = true;
|
||||
let Test.20 : Int1 = lowlevel Eq Test.19 Test.2;
|
||||
if Test.20 then
|
||||
let Test.20 : Int1 = true;
|
||||
let Test.21 : Int1 = lowlevel Eq Test.20 Test.2;
|
||||
if Test.21 then
|
||||
let Test.15 : Str = "";
|
||||
let Test.10 : Str = CallByName Test.1 Test.15;
|
||||
let Test.10 : [C Str, C Str] = CallByName Test.1 Test.15;
|
||||
jump Test.9 Test.10;
|
||||
else
|
||||
let Test.18 : Str = "";
|
||||
let Test.16 : Str = CallByName Test.1 Test.18;
|
||||
let Test.19 : Str = "";
|
||||
let Test.16 : [C Str, C Str] = CallByName Test.1 Test.19;
|
||||
jump Test.9 Test.16;
|
||||
|
|
|
@ -1854,8 +1854,7 @@ fn instantiate_annotated_as_recursive_alias_multiple_polymorphic_expr() {
|
|||
)
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[mono_test(large_stack = "true")]
|
||||
fn encode_derived_record_one_field_string() {
|
||||
indoc!(
|
||||
r#"
|
||||
|
@ -1872,8 +1871,7 @@ fn encode_derived_record_one_field_string() {
|
|||
)
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[mono_test(large_stack = "true")]
|
||||
fn encode_derived_record_two_field_strings() {
|
||||
indoc!(
|
||||
r#"
|
||||
|
@ -1890,8 +1888,7 @@ fn encode_derived_record_two_field_strings() {
|
|||
)
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[mono_test(large_stack = "true")]
|
||||
fn encode_derived_nested_record_string() {
|
||||
indoc!(
|
||||
r#"
|
||||
|
@ -3078,3 +3075,16 @@ fn record_update() {
|
|||
"#
|
||||
)
|
||||
}
|
||||
|
||||
#[mono_test(mode = "test")]
|
||||
fn dbg_in_expect() {
|
||||
indoc!(
|
||||
r###"
|
||||
interface Test exposes [] imports []
|
||||
|
||||
expect
|
||||
dbg ""
|
||||
Bool.true
|
||||
"###
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
let mut no_check = false;
|
||||
let mut allow_type_errors = false;
|
||||
let mut mode = "exec".to_owned();
|
||||
let mut large_stack = false;
|
||||
for arg in syn::parse_macro_input!(args as syn::AttributeArgs) {
|
||||
use syn::{Lit, Meta, MetaNameValue, NestedMeta};
|
||||
if let NestedMeta::Meta(Meta::NameValue(MetaNameValue {
|
||||
|
@ -26,6 +27,9 @@ pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
if path.is_ident("allow_type_errors") {
|
||||
allow_type_errors = true;
|
||||
}
|
||||
if path.is_ident("large_stack") {
|
||||
large_stack = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,8 +48,11 @@ pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
#[test]
|
||||
#(#attributes)*
|
||||
#visibility fn #name(#args) {
|
||||
compiles_to_ir(#name_str, #body, &#mode, #allow_type_errors, #no_check);
|
||||
|
||||
if #large_stack {
|
||||
with_larger_debug_stack(|| compiles_to_ir(#name_str, #body, &#mode, #allow_type_errors, #no_check));
|
||||
} else {
|
||||
compiles_to_ir(#name_str, #body, &#mode, #allow_type_errors, #no_check);
|
||||
}
|
||||
}
|
||||
};
|
||||
result.into()
|
||||
|
|
|
@ -2,7 +2,7 @@ Closure(
|
|||
[
|
||||
@1-11 MalformedIdent(
|
||||
"the_answer",
|
||||
Underscore(
|
||||
UnderscoreInMiddle(
|
||||
@5,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -31,7 +31,7 @@ Defs(
|
|||
@5-8 SpaceBefore(
|
||||
MalformedIdent(
|
||||
"n_p",
|
||||
Underscore(
|
||||
UnderscoreInMiddle(
|
||||
@7,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -416,9 +416,10 @@ pub fn load_types(
|
|||
|
||||
let layout = layout_cache.interner.get(in_layout);
|
||||
|
||||
// dbg!(layout);
|
||||
|
||||
if layout.has_varying_stack_size(&layout_cache.interner, arena) {
|
||||
if layout_cache
|
||||
.interner
|
||||
.has_varying_stack_size(in_layout, arena)
|
||||
{
|
||||
let ident_ids = interns.all_ident_ids.get_mut(&home).unwrap();
|
||||
let answer = generate_glue_procs(
|
||||
home,
|
||||
|
|
|
@ -1383,28 +1383,26 @@ fn add_type_help<'a>(
|
|||
|
||||
add_tag_union(env, opt_name, tags, var, types, layout, Some(rec_root))
|
||||
}
|
||||
Content::Structure(FlatType::Apply(symbol, _)) => {
|
||||
match env.layout_cache.get_in(layout).repr {
|
||||
LayoutRepr::Builtin(builtin) => {
|
||||
add_builtin_type(env, builtin, var, opt_name, types, layout)
|
||||
}
|
||||
_ => {
|
||||
if symbol.is_builtin() {
|
||||
todo!(
|
||||
"Handle Apply for builtin symbol {:?} and layout {:?}",
|
||||
symbol,
|
||||
layout
|
||||
)
|
||||
} else {
|
||||
todo!(
|
||||
"Handle non-builtin Apply for symbol {:?} and layout {:?}",
|
||||
symbol,
|
||||
layout
|
||||
)
|
||||
}
|
||||
Content::Structure(FlatType::Apply(symbol, _)) => match env.layout_cache.get_repr(layout) {
|
||||
LayoutRepr::Builtin(builtin) => {
|
||||
add_builtin_type(env, builtin, var, opt_name, types, layout)
|
||||
}
|
||||
_ => {
|
||||
if symbol.is_builtin() {
|
||||
todo!(
|
||||
"Handle Apply for builtin symbol {:?} and layout {:?}",
|
||||
symbol,
|
||||
layout
|
||||
)
|
||||
} else {
|
||||
todo!(
|
||||
"Handle non-builtin Apply for symbol {:?} and layout {:?}",
|
||||
symbol,
|
||||
layout
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Content::Structure(FlatType::Func(args, closure_var, ret_var)) => {
|
||||
let is_toplevel = false; // or in any case, we cannot assume that we are
|
||||
|
||||
|
@ -1432,7 +1430,7 @@ fn add_type_help<'a>(
|
|||
}
|
||||
Content::Alias(name, alias_vars, real_var, _) => {
|
||||
if name.is_builtin() {
|
||||
match env.layout_cache.get_in(layout).repr {
|
||||
match env.layout_cache.get_repr(layout) {
|
||||
LayoutRepr::Builtin(builtin) => {
|
||||
add_builtin_type(env, builtin, var, opt_name, types, layout)
|
||||
}
|
||||
|
@ -1687,7 +1685,7 @@ fn add_builtin_type<'a>(
|
|||
Alias(Symbol::DICT_DICT, _alias_variables, alias_var, AliasKind::Opaque),
|
||||
) => {
|
||||
match (
|
||||
env.layout_cache.get_in(elem_layout).repr,
|
||||
env.layout_cache.get_repr(elem_layout),
|
||||
env.subs.get_content_without_compacting(*alias_var),
|
||||
) {
|
||||
(
|
||||
|
@ -1737,7 +1735,7 @@ fn add_builtin_type<'a>(
|
|||
Alias(Symbol::SET_SET, _alias_vars, alias_var, AliasKind::Opaque),
|
||||
) => {
|
||||
match (
|
||||
env.layout_cache.get_in(elem_layout).repr,
|
||||
env.layout_cache.get_repr(elem_layout),
|
||||
env.subs.get_content_without_compacting(*alias_var),
|
||||
) {
|
||||
(
|
||||
|
@ -1842,7 +1840,10 @@ where
|
|||
let layout = env.layout_cache.interner.get(in_layout);
|
||||
let struct_fields = match env.glue_procs_by_layout.get(&layout) {
|
||||
Some(&glue_procs) => {
|
||||
debug_assert!(layout.has_varying_stack_size(&env.layout_cache.interner, arena));
|
||||
debug_assert!(env
|
||||
.layout_cache
|
||||
.interner
|
||||
.has_varying_stack_size(in_layout, arena));
|
||||
|
||||
let fields: Vec<(String, TypeId, Accessors)> = sortables
|
||||
.into_iter()
|
||||
|
@ -1910,7 +1911,7 @@ fn tag_union_type_from_layout<'a>(
|
|||
) -> RocTagUnion {
|
||||
let subs = env.subs;
|
||||
|
||||
match env.layout_cache.get_in(layout).repr {
|
||||
match env.layout_cache.get_repr(layout) {
|
||||
_ if union_tags.is_newtype_wrapper(subs)
|
||||
&& matches!(
|
||||
subs.get_content_without_compacting(var),
|
||||
|
@ -2228,7 +2229,9 @@ fn single_tag_payload_fields<'a, 'b>(
|
|||
// anyway just so we have some warning in case that relationship somehow didn't hold!
|
||||
debug_assert_eq!(
|
||||
env.glue_procs_by_layout.get(&layout).is_some(),
|
||||
layout.has_varying_stack_size(&env.layout_cache.interner, env.arena)
|
||||
env.layout_cache
|
||||
.interner
|
||||
.has_varying_stack_size(in_layout, env.arena)
|
||||
);
|
||||
|
||||
let (tag_name, payload_vars) = single_tag_payload(union_tags, subs);
|
||||
|
@ -2309,7 +2312,7 @@ fn struct_fields_needed<I: IntoIterator<Item = Variable>>(env: &mut Env<'_>, var
|
|||
vars.into_iter().fold(0, |count, var| {
|
||||
let layout = env.layout_cache.from_var(arena, var, subs).unwrap();
|
||||
|
||||
if env.layout_cache.get_in(layout).is_dropped_because_empty() {
|
||||
if env.layout_cache.get_repr(layout).is_dropped_because_empty() {
|
||||
count
|
||||
} else {
|
||||
count + 1
|
||||
|
|
|
@ -353,7 +353,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
|
|||
};
|
||||
}
|
||||
|
||||
let expr = match env.layout_cache.get_in(layout).repr {
|
||||
let expr = match env.layout_cache.get_repr(layout) {
|
||||
LayoutRepr::Builtin(Builtin::Bool) => {
|
||||
app.call_function(main_fn_name, |_mem: &A::Memory, num: bool| {
|
||||
bool_to_ast(env, num, env.subs.get_content_without_compacting(raw_var))
|
||||
|
@ -475,7 +475,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
|
|||
env,
|
||||
mem,
|
||||
addr,
|
||||
layout,
|
||||
env.layout_cache.get_repr(layout),
|
||||
WhenRecursive::Unreachable,
|
||||
env.subs.get_root_key_without_compacting(raw_var),
|
||||
)
|
||||
|
@ -496,7 +496,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
|
|||
env,
|
||||
mem,
|
||||
addr,
|
||||
layout,
|
||||
env.layout_cache.get_repr(layout),
|
||||
WhenRecursive::Loop(layout),
|
||||
env.subs.get_root_key_without_compacting(raw_var),
|
||||
)
|
||||
|
@ -515,7 +515,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
|
|||
env,
|
||||
mem,
|
||||
addr,
|
||||
layout,
|
||||
env.layout_cache.get_repr(layout),
|
||||
WhenRecursive::Unreachable,
|
||||
env.subs.get_root_key_without_compacting(raw_var),
|
||||
)
|
||||
|
@ -542,7 +542,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
|
|||
env: &mut Env<'a, '_>,
|
||||
mem: &'a M,
|
||||
addr: usize,
|
||||
layout: InLayout<'a>,
|
||||
layout: LayoutRepr<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
var: Variable,
|
||||
) -> Expr<'a> {
|
||||
|
@ -557,7 +557,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
|
|||
let (newtype_containers, _alias_content, raw_var) = unroll_newtypes_and_aliases(env, var);
|
||||
let raw_content = env.subs.get_content_without_compacting(raw_var);
|
||||
|
||||
let expr = match (raw_content, env.layout_cache.get_in(layout).repr) {
|
||||
let expr = match (raw_content, layout) {
|
||||
(Content::Structure(FlatType::Func(_, _, _)), _) | (_, LayoutRepr::LambdaSet(_)) => {
|
||||
OPAQUE_FUNCTION
|
||||
}
|
||||
|
@ -650,7 +650,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
|
|||
},
|
||||
WhenRecursive::Loop(union_layout),
|
||||
) => {
|
||||
addr_to_ast(env, mem, addr, union_layout, when_recursive, *structure)
|
||||
addr_to_ast(env, mem, addr, env.layout_cache.get_repr(union_layout), when_recursive, *structure)
|
||||
}
|
||||
|
||||
(
|
||||
|
@ -665,9 +665,9 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
|
|||
let union_layout = env.layout_cache
|
||||
.from_var(env.arena, *structure, env.subs)
|
||||
.expect("no layout for structure");
|
||||
debug_assert!(matches!(env.layout_cache.get_in(union_layout).repr, LayoutRepr::Union(..)));
|
||||
debug_assert!(matches!(env.layout_cache.get_repr(union_layout), LayoutRepr::Union(..)));
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
addr_to_ast(env, mem, addr, union_layout, when_recursive, *structure)
|
||||
addr_to_ast(env, mem, addr, env.layout_cache.get_repr(union_layout), when_recursive, *structure)
|
||||
}
|
||||
other => unreachable!("Something had a RecursivePointer layout, but instead of being a RecursionVar and having a known recursive layout, I found {:?}", other),
|
||||
},
|
||||
|
@ -873,7 +873,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
|
|||
env,
|
||||
mem,
|
||||
addr_of_inner,
|
||||
inner_layout,
|
||||
env.layout_cache.get_repr(inner_layout),
|
||||
WhenRecursive::Unreachable,
|
||||
inner_var,
|
||||
);
|
||||
|
@ -930,7 +930,7 @@ fn list_to_ast<'a, M: ReplAppMemory>(
|
|||
env,
|
||||
mem,
|
||||
elem_addr,
|
||||
elem_layout,
|
||||
env.layout_cache.get_repr(elem_layout),
|
||||
WhenRecursive::Unreachable,
|
||||
elem_content,
|
||||
);
|
||||
|
@ -993,7 +993,14 @@ where
|
|||
let mut field_addr = addr;
|
||||
|
||||
for (var, layout) in sequence {
|
||||
let expr = addr_to_ast(env, mem, field_addr, *layout, when_recursive, var);
|
||||
let expr = addr_to_ast(
|
||||
env,
|
||||
mem,
|
||||
field_addr,
|
||||
env.layout_cache.get_repr(*layout),
|
||||
when_recursive,
|
||||
var,
|
||||
);
|
||||
let loc_expr = Loc::at_zero(expr);
|
||||
|
||||
output.push(&*arena.alloc(loc_expr));
|
||||
|
@ -1029,9 +1036,7 @@ fn struct_to_ast<'a, M: ReplAppMemory>(
|
|||
.unwrap();
|
||||
let inner_layouts = arena.alloc([field_layout]);
|
||||
|
||||
let struct_layout = env
|
||||
.layout_cache
|
||||
.put_in_no_semantic(LayoutRepr::struct_(inner_layouts));
|
||||
let struct_layout = LayoutRepr::struct_(inner_layouts);
|
||||
let loc_expr = &*arena.alloc(Loc {
|
||||
value: addr_to_ast(
|
||||
env,
|
||||
|
@ -1094,7 +1099,7 @@ fn struct_to_ast<'a, M: ReplAppMemory>(
|
|||
env,
|
||||
mem,
|
||||
field_addr,
|
||||
field_layout,
|
||||
env.layout_cache.get_repr(field_layout),
|
||||
WhenRecursive::Unreachable,
|
||||
field_var,
|
||||
),
|
||||
|
@ -1175,7 +1180,7 @@ fn struct_to_ast_tuple<'a, M: ReplAppMemory>(
|
|||
env,
|
||||
mem,
|
||||
field_addr,
|
||||
elem_layout,
|
||||
env.layout_cache.get_repr(elem_layout),
|
||||
WhenRecursive::Unreachable,
|
||||
elem_var,
|
||||
),
|
||||
|
|
|
@ -1256,19 +1256,49 @@ fn to_bad_ident_expr_report<'b>(
|
|||
])
|
||||
}
|
||||
|
||||
Underscore(pos) => {
|
||||
let region = Region::new(surroundings.start(), pos);
|
||||
UnderscoreAlone(_pos) => {
|
||||
alloc.stack([
|
||||
alloc.reflow("An underscore is being used as a variable here:"),
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.concat([alloc
|
||||
.reflow(r"An underscore can be used to ignore a value when pattern matching, but it cannot be used as a variable.")]),
|
||||
])
|
||||
}
|
||||
|
||||
UnderscoreInMiddle(_pos) => {
|
||||
alloc.stack([
|
||||
alloc.reflow("Underscores are not allowed in identifier names:"),
|
||||
alloc.region_with_subregion(
|
||||
lines.convert_region(surroundings),
|
||||
lines.convert_region(region),
|
||||
),
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.concat([alloc
|
||||
.reflow(r"I recommend using camelCase. It's the standard style in Roc code!")]),
|
||||
])
|
||||
}
|
||||
|
||||
UnderscoreAtStart {
|
||||
position: _pos,
|
||||
declaration_region,
|
||||
} => {
|
||||
let line = "This variable's name starts with an underscore:";
|
||||
alloc.stack([
|
||||
match declaration_region {
|
||||
None => alloc.reflow(line),
|
||||
Some(declaration_region) => alloc.stack([
|
||||
alloc.reflow(line),
|
||||
alloc.region(lines.convert_region(declaration_region)),
|
||||
alloc.reflow("But then it is used here:"),
|
||||
])
|
||||
},
|
||||
alloc.region(lines.convert_region(surroundings)),
|
||||
alloc.concat([
|
||||
alloc.reflow(r"A variable's name can only start with an underscore if the variable is unused. "),
|
||||
match declaration_region {
|
||||
None => alloc.reflow(r"But it looks like the variable is being used here!"),
|
||||
Some(_) => alloc.reflow(r"Since you are using this variable, you could remove the underscore from its name in both places."),
|
||||
}
|
||||
]),
|
||||
])
|
||||
}
|
||||
|
||||
BadOpaqueRef(pos) => {
|
||||
use BadIdentNext::*;
|
||||
let kind = "an opaque reference";
|
||||
|
@ -1411,7 +1441,13 @@ fn to_bad_ident_pattern_report<'b>(
|
|||
])
|
||||
}
|
||||
|
||||
Underscore(pos) => {
|
||||
UnderscoreAlone(..) | UnderscoreAtStart { .. } => {
|
||||
unreachable!(
|
||||
"it's fine to have an underscore at the beginning of an identifier in a pattern"
|
||||
)
|
||||
}
|
||||
|
||||
UnderscoreInMiddle(pos) => {
|
||||
let region = Region::from_pos(pos.sub(1));
|
||||
|
||||
alloc.stack([
|
||||
|
@ -1582,8 +1618,19 @@ fn pretty_runtime_error<'b>(
|
|||
(title, doc) = report_shadowing(alloc, lines, original_region, shadow, kind);
|
||||
}
|
||||
|
||||
RuntimeError::LookupNotInScope(loc_name, options) => {
|
||||
doc = not_found(alloc, lines, loc_name.region, &loc_name.value, options);
|
||||
RuntimeError::LookupNotInScope {
|
||||
loc_name,
|
||||
suggestion_options: options,
|
||||
underscored_suggestion_region,
|
||||
} => {
|
||||
doc = not_found(
|
||||
alloc,
|
||||
lines,
|
||||
loc_name.region,
|
||||
&loc_name.value,
|
||||
options,
|
||||
underscored_suggestion_region,
|
||||
);
|
||||
title = UNRECOGNIZED_NAME;
|
||||
}
|
||||
RuntimeError::CircularDef(entries) => {
|
||||
|
@ -2221,6 +2268,7 @@ fn not_found<'b>(
|
|||
region: roc_region::all::Region,
|
||||
name: &Ident,
|
||||
options: MutSet<Box<str>>,
|
||||
underscored_suggestion_region: Option<Region>,
|
||||
) -> RocDocBuilder<'b> {
|
||||
let mut suggestions = suggest::sort(
|
||||
name.as_inline_str().as_str(),
|
||||
|
@ -2236,7 +2284,15 @@ fn not_found<'b>(
|
|||
alloc.reflow(" missing up-top"),
|
||||
]);
|
||||
|
||||
let default_yes = alloc.reflow("Did you mean one of these?");
|
||||
let default_yes = match underscored_suggestion_region {
|
||||
Some(underscored_region) => alloc.stack([
|
||||
alloc.reflow("There is an ignored identifier of a similar name here:"),
|
||||
alloc.region(lines.convert_region(underscored_region)),
|
||||
alloc.reflow("Did you mean to remove the leading underscore?"),
|
||||
alloc.reflow("If not, did you mean one of these?"),
|
||||
]),
|
||||
None => alloc.reflow("Did you mean one of these?"),
|
||||
};
|
||||
|
||||
let to_details = |no_suggestion_details, yes_suggestion_details| {
|
||||
if suggestions.is_empty() {
|
||||
|
|
|
@ -10152,6 +10152,41 @@ In roc, functions are always written as a lambda, like{}
|
|||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
forgot_to_remove_underscore,
|
||||
indoc!(
|
||||
r#"
|
||||
\_foo -> foo
|
||||
"#
|
||||
),
|
||||
|golden| pretty_assertions::assert_eq!(
|
||||
golden,
|
||||
indoc!(
|
||||
r###"── UNRECOGNIZED NAME ───────────────────────────────────── /code/proj/Main.roc ─
|
||||
|
||||
Nothing is named `foo` in this scope.
|
||||
|
||||
4│ \_foo -> foo
|
||||
^^^
|
||||
|
||||
There is an ignored identifier of a similar name here:
|
||||
|
||||
4│ \_foo -> foo
|
||||
^^^^
|
||||
|
||||
Did you mean to remove the leading underscore?
|
||||
|
||||
If not, did you mean one of these?
|
||||
|
||||
Box
|
||||
Bool
|
||||
U8
|
||||
F64
|
||||
"###
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
test_report!(
|
||||
call_with_underscore_identifier,
|
||||
indoc!(
|
||||
|
@ -10163,17 +10198,102 @@ In roc, functions are always written as a lambda, like{}
|
|||
),
|
||||
|golden| pretty_assertions::assert_eq!(
|
||||
golden,
|
||||
&format!(
|
||||
indoc!(
|
||||
r###"── SYNTAX PROBLEM ──────────────────────────────────────── /code/proj/Main.roc ─
|
||||
|
||||
Underscores are not allowed in identifier names:
|
||||
An underscore is being used as a variable here:
|
||||
|
||||
6│ f 1 _ 1
|
||||
{}
|
||||
6│ f 1 _ 1
|
||||
^
|
||||
|
||||
I recommend using camelCase. It's the standard style in Roc code!
|
||||
"###,
|
||||
" " // TODO make the reporter not insert extraneous spaces here in the first place!
|
||||
An underscore can be used to ignore a value when pattern matching, but
|
||||
it cannot be used as a variable.
|
||||
"###
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
test_report!(
|
||||
call_with_declared_identifier_starting_with_underscore,
|
||||
indoc!(
|
||||
r#"
|
||||
f = \x, y, z -> x + y + z
|
||||
|
||||
\a, _b -> f a _b 1
|
||||
"#
|
||||
),
|
||||
|golden| pretty_assertions::assert_eq!(
|
||||
golden,
|
||||
indoc!(
|
||||
r###"── SYNTAX PROBLEM ──────────────────────────────────────── /code/proj/Main.roc ─
|
||||
|
||||
This variable's name starts with an underscore:
|
||||
|
||||
6│ \a, _b -> f a _b 1
|
||||
^^
|
||||
|
||||
But then it is used here:
|
||||
|
||||
6│ \a, _b -> f a _b 1
|
||||
^^
|
||||
|
||||
A variable's name can only start with an underscore if the variable is
|
||||
unused. Since you are using this variable, you could remove the
|
||||
underscore from its name in both places.
|
||||
"###
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
test_report!(
|
||||
call_with_undeclared_identifier_starting_with_underscore,
|
||||
indoc!(
|
||||
r#"
|
||||
f = \x, y, z -> x + y + z
|
||||
|
||||
\a, _b -> f a _r 1
|
||||
"#
|
||||
),
|
||||
|golden| pretty_assertions::assert_eq!(
|
||||
golden,
|
||||
indoc!(
|
||||
r###"
|
||||
── SYNTAX PROBLEM ──────────────────────────────────────── /code/proj/Main.roc ─
|
||||
|
||||
This variable's name starts with an underscore:
|
||||
|
||||
6│ \a, _b -> f a _r 1
|
||||
^^
|
||||
|
||||
A variable's name can only start with an underscore if the variable is
|
||||
unused. But it looks like the variable is being used here!
|
||||
"###
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
test_report!(
|
||||
underscore_in_middle_of_identifier,
|
||||
indoc!(
|
||||
r#"
|
||||
f = \x, y, z -> x + y + z
|
||||
|
||||
\a, _b -> f a var_name 1
|
||||
"#
|
||||
),
|
||||
|golden| pretty_assertions::assert_eq!(
|
||||
golden,
|
||||
indoc!(
|
||||
r###"
|
||||
── SYNTAX PROBLEM ──────────────────────────────────────── /code/proj/Main.roc ─
|
||||
|
||||
Underscores are not allowed in identifier names:
|
||||
|
||||
6│ \a, _b -> f a var_name 1
|
||||
^^^^^^^^
|
||||
|
||||
I recommend using camelCase. It's the standard style in Roc code!
|
||||
"###
|
||||
),
|
||||
)
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue