Add Expr::ErasedLoad

This commit is contained in:
Ayaz Hafiz 2023-07-02 11:48:21 -05:00
parent 2c838aa5c2
commit 283b9d53d6
No known key found for this signature in database
GPG Key ID: 0E2A37416A25EF58
11 changed files with 92 additions and 17 deletions

View File

@ -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))?;

View File

@ -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();

View File

@ -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,

View File

@ -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),

View File

@ -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);

View File

@ -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> {

View File

@ -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",
}
}

View File

@ -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 { .. }

View File

@ -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, .. }

View File

@ -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 {

View File

@ -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,
}
}