mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-10 10:02:38 +03:00
Add Expr::ErasedLoad
This commit is contained in:
parent
2c838aa5c2
commit
283b9d53d6
@ -1523,6 +1523,7 @@ fn expr_spec<'a>(
|
||||
}
|
||||
FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
ErasedMake { .. } => todo_lambda_erasure!(),
|
||||
ErasedLoad { .. } => todo_lambda_erasure!(),
|
||||
RuntimeErrorFunction(_) => {
|
||||
let type_id = layout_spec(env, builder, interner, interner.get_repr(layout))?;
|
||||
|
||||
|
@ -159,6 +159,9 @@ impl<'a> LastSeenMap<'a> {
|
||||
value.map(|v| self.set_last_seen(v, stmt));
|
||||
self.set_last_seen(*callee, stmt);
|
||||
}
|
||||
Expr::ErasedLoad { symbol, field: _ } => {
|
||||
self.set_last_seen(*symbol, stmt);
|
||||
}
|
||||
Expr::Struct(syms) => {
|
||||
for sym in *syms {
|
||||
self.set_last_seen(*sym, stmt);
|
||||
@ -857,6 +860,7 @@ trait Backend<'a> {
|
||||
}
|
||||
Expr::FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
Expr::ErasedMake { .. } => todo_lambda_erasure!(),
|
||||
Expr::ErasedLoad { .. } => todo_lambda_erasure!(),
|
||||
Expr::Reset { symbol, .. } => {
|
||||
let layout = *self.layout_map().get(symbol).unwrap();
|
||||
|
||||
|
@ -1126,8 +1126,9 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
||||
)
|
||||
}
|
||||
|
||||
ErasedMake { .. } => todo_lambda_erasure!(),
|
||||
FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
ErasedMake { .. } => todo_lambda_erasure!(),
|
||||
ErasedLoad { .. } => todo_lambda_erasure!(),
|
||||
|
||||
Reset {
|
||||
symbol,
|
||||
|
@ -1142,6 +1142,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
||||
|
||||
Expr::FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
Expr::ErasedMake { .. } => todo_lambda_erasure!(),
|
||||
Expr::ErasedLoad { .. } => todo_lambda_erasure!(),
|
||||
|
||||
Expr::Reset { symbol: arg, .. } => self.expr_reset(*arg, sym, storage),
|
||||
|
||||
|
@ -737,6 +737,14 @@ impl<'a> BorrowInfState<'a> {
|
||||
self.own_var(*callee);
|
||||
}
|
||||
|
||||
ErasedLoad { symbol, field: _ } => {
|
||||
// if the extracted value is owned, the erasure is too
|
||||
self.if_is_owned_then_own(*symbol, z);
|
||||
|
||||
// if the erasure is owned, so is the extracted value
|
||||
self.if_is_owned_then_own(z, *symbol);
|
||||
}
|
||||
|
||||
Reset { symbol: x, .. } | ResetRef { symbol: x, .. } => {
|
||||
self.own_var(z);
|
||||
self.own_var(*x);
|
||||
|
@ -6,8 +6,8 @@ use roc_module::symbol::Symbol;
|
||||
|
||||
use crate::{
|
||||
ir::{
|
||||
Call, CallSpecId, CallType, Expr, HigherOrderLowLevel, JoinPointId, ListLiteralElement,
|
||||
ModifyRc, Param, Proc, ProcLayout, Stmt,
|
||||
Call, CallSpecId, CallType, ErasedField, Expr, HigherOrderLowLevel, JoinPointId,
|
||||
ListLiteralElement, ModifyRc, Param, Proc, ProcLayout, Stmt,
|
||||
},
|
||||
layout::{
|
||||
Builtin, FunctionPointer, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner,
|
||||
@ -15,11 +15,6 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
pub enum ErasedMakeKind {
|
||||
Value,
|
||||
Callee,
|
||||
}
|
||||
|
||||
pub enum UseKind {
|
||||
Ret,
|
||||
TagExpr,
|
||||
@ -32,7 +27,8 @@ pub enum UseKind {
|
||||
SwitchCond,
|
||||
ExpectCond,
|
||||
ExpectLookup,
|
||||
ErasedMake(ErasedMakeKind),
|
||||
ErasedMake(ErasedField),
|
||||
Erased,
|
||||
}
|
||||
|
||||
pub enum ProblemKind<'a> {
|
||||
@ -494,6 +490,7 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
||||
self.check_erased_make(value, callee);
|
||||
Some(Layout::ERASED)
|
||||
}
|
||||
&Expr::ErasedLoad { symbol, field } => Some(self.check_erased_load(symbol, field)),
|
||||
&Expr::FunctionPointer { lambda_name } => {
|
||||
let lambda_symbol = lambda_name.name();
|
||||
if !self.procs.iter().any(|((name, proc), _)| {
|
||||
@ -764,15 +761,24 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
||||
self.check_sym_layout(
|
||||
value,
|
||||
Layout::OPAQUE_PTR,
|
||||
UseKind::ErasedMake(ErasedMakeKind::Value),
|
||||
UseKind::ErasedMake(ErasedField::Value),
|
||||
);
|
||||
}
|
||||
self.check_sym_layout(
|
||||
callee,
|
||||
Layout::OPAQUE_PTR,
|
||||
UseKind::ErasedMake(ErasedMakeKind::Callee),
|
||||
UseKind::ErasedMake(ErasedField::Callee),
|
||||
);
|
||||
}
|
||||
|
||||
fn check_erased_load(&mut self, symbol: Symbol, field: ErasedField) -> InLayout<'a> {
|
||||
self.check_sym_layout(symbol, Layout::ERASED, UseKind::Erased);
|
||||
|
||||
match field {
|
||||
ErasedField::Value => Layout::OPAQUE_PTR,
|
||||
ErasedField::Callee => Layout::OPAQUE_PTR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum TagPayloads<'a> {
|
||||
|
@ -4,12 +4,12 @@ use roc_module::symbol::{Interns, Symbol};
|
||||
use ven_pretty::{text, Arena, DocAllocator, DocBuilder};
|
||||
|
||||
use crate::{
|
||||
ir::{Parens, ProcLayout},
|
||||
ir::{ErasedField, Parens, ProcLayout},
|
||||
layout::LayoutInterner,
|
||||
};
|
||||
|
||||
use super::{
|
||||
checker::{ErasedMakeKind, ProblemKind, UseKind},
|
||||
checker::{ProblemKind, UseKind},
|
||||
Problem, Problems,
|
||||
};
|
||||
|
||||
@ -439,9 +439,10 @@ fn format_use_kind(use_kind: UseKind) -> &'static str {
|
||||
UseKind::ExpectCond => "expect condition",
|
||||
UseKind::ExpectLookup => "lookup for an expect",
|
||||
UseKind::ErasedMake(kind) => match kind {
|
||||
ErasedMakeKind::Value => "erased value",
|
||||
ErasedMakeKind::Callee => "erased callee",
|
||||
ErasedField::Value => "erased value field",
|
||||
ErasedField::Callee => "erased callee field",
|
||||
},
|
||||
UseKind::Erased => "erasure",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,8 @@ use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||
|
||||
use crate::ir::{
|
||||
BranchInfo, Call, CallType, Expr, JoinPointId, ListLiteralElement, Literal, ModifyRc, Proc,
|
||||
ProcLayout, Stmt, UpdateModeId,
|
||||
BranchInfo, Call, CallType, ErasedField, Expr, JoinPointId, ListLiteralElement, Literal,
|
||||
ModifyRc, Proc, ProcLayout, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
|
||||
@ -233,6 +233,16 @@ fn specialize_drops_stmt<'a, 'i>(
|
||||
environment.add_struct_child(*binding, *value, 0);
|
||||
}
|
||||
}
|
||||
ErasedLoad { symbol, field } => {
|
||||
match field {
|
||||
ErasedField::Value => {
|
||||
environment.add_struct_child(*symbol, *binding, 0);
|
||||
}
|
||||
ErasedField::Callee => {
|
||||
// nothing to own
|
||||
}
|
||||
}
|
||||
}
|
||||
Reset { .. } | Expr::ResetRef { .. } => { /* do nothing */ }
|
||||
RuntimeErrorFunction(_)
|
||||
| FunctionPointer { .. }
|
||||
|
@ -14,6 +14,7 @@ use roc_error_macros::internal_error;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::{low_level::LowLevelWrapperType, symbol::Symbol};
|
||||
|
||||
use crate::ir::ErasedField;
|
||||
use crate::{
|
||||
borrow::{lowlevel_borrow_signature, Ownership},
|
||||
ir::{
|
||||
@ -897,6 +898,15 @@ fn insert_refcount_operations_binding<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
Expr::ErasedLoad { symbol, field } => {
|
||||
let new_let = new_let!(stmt);
|
||||
|
||||
match field {
|
||||
ErasedField::Value => inc_owned!([*symbol], new_let),
|
||||
ErasedField::Callee => new_let,
|
||||
}
|
||||
}
|
||||
|
||||
Expr::GetTagId { structure, .. }
|
||||
| Expr::StructAtIndex { structure, .. }
|
||||
| Expr::UnionAtIndex { structure, .. }
|
||||
|
@ -1841,6 +1841,12 @@ pub struct ReuseToken {
|
||||
pub update_mode: UpdateModeId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ErasedField {
|
||||
Value,
|
||||
Callee,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Expr<'a> {
|
||||
Literal(Literal<'a>),
|
||||
@ -1904,6 +1910,14 @@ pub enum Expr<'a> {
|
||||
callee: Symbol,
|
||||
},
|
||||
|
||||
/// Loads a field from a type-erased value.
|
||||
ErasedLoad {
|
||||
/// The erased symbol.
|
||||
symbol: Symbol,
|
||||
/// The field to load.
|
||||
field: ErasedField,
|
||||
},
|
||||
|
||||
/// Returns a pointer to the given function.
|
||||
FunctionPointer {
|
||||
lambda_name: LambdaName<'a>,
|
||||
@ -2112,6 +2126,19 @@ impl<'a> Expr<'a> {
|
||||
.append(" }")
|
||||
}
|
||||
|
||||
ErasedLoad { symbol, field } => {
|
||||
let field = match field {
|
||||
ErasedField::Value => ".Value",
|
||||
ErasedField::Callee => ".Callee",
|
||||
};
|
||||
|
||||
alloc
|
||||
.text("ErasedLoad ")
|
||||
.append(symbol_to_doc(alloc, *symbol, pretty))
|
||||
.append(alloc.text(" "))
|
||||
.append(field)
|
||||
}
|
||||
|
||||
FunctionPointer { lambda_name } => alloc
|
||||
.text("FunctionPointer ")
|
||||
.append(symbol_to_doc(alloc, lambda_name.name(), pretty)),
|
||||
@ -7837,6 +7864,11 @@ fn substitute_in_expr<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
ErasedLoad { symbol, field } => substitute(subs, *symbol).map(|new_symbol| ErasedLoad {
|
||||
symbol: new_symbol,
|
||||
field: *field,
|
||||
}),
|
||||
|
||||
FunctionPointer { .. } => None,
|
||||
|
||||
StructAtIndex {
|
||||
|
@ -1112,6 +1112,7 @@ fn expr_contains_symbol(expr: &Expr, needle: Symbol) -> bool {
|
||||
Expr::ErasedMake { value, callee } => {
|
||||
value.map(|v| v == needle).unwrap_or(false) || needle == *callee
|
||||
}
|
||||
Expr::ErasedLoad { symbol, field: _ } => needle == *symbol,
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user