mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-31 00:57:24 +00:00
Expr::FunctionPointer
This commit is contained in:
parent
55fa8098d3
commit
cf30f02e01
11 changed files with 176 additions and 5 deletions
|
@ -1521,6 +1521,7 @@ fn expr_spec<'a>(
|
|||
let value = with_new_heap_cell(builder, block, union_data)?;
|
||||
builder.add_make_named(block, MOD_APP, type_name, value)
|
||||
}
|
||||
FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
RuntimeErrorFunction(_) => {
|
||||
let type_id = layout_spec(env, builder, interner, interner.get_repr(layout))?;
|
||||
|
||||
|
|
|
@ -176,6 +176,7 @@ impl<'a> LastSeenMap<'a> {
|
|||
Expr::Reset { symbol, .. } | Expr::ResetRef { symbol, .. } => {
|
||||
self.set_last_seen(*symbol, stmt);
|
||||
}
|
||||
Expr::FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
Expr::EmptyArray => {}
|
||||
Expr::RuntimeErrorFunction(_) => {}
|
||||
}
|
||||
|
@ -844,6 +845,17 @@ trait Backend<'a> {
|
|||
Expr::NullPointer => {
|
||||
self.load_literal_i64(sym, 0);
|
||||
}
|
||||
Expr::FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
Expr::Reuse {
|
||||
tag_layout,
|
||||
tag_id,
|
||||
symbol: reused,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
self.load_literal_symbols(arguments);
|
||||
self.tag(sym, arguments, tag_layout, *tag_id, Some(*reused));
|
||||
}
|
||||
Expr::Reset { symbol, .. } => {
|
||||
let layout = *self.layout_map().get(symbol).unwrap();
|
||||
|
||||
|
|
|
@ -1090,6 +1090,44 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
|||
)
|
||||
}
|
||||
|
||||
ExprBox { symbol } => {
|
||||
let (value, layout) = scope.load_symbol_and_layout(symbol);
|
||||
let basic_type =
|
||||
basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout));
|
||||
let allocation = reserve_with_refcount_help(
|
||||
env,
|
||||
basic_type,
|
||||
layout_interner.stack_size(layout),
|
||||
layout_interner.alignment_bytes(layout),
|
||||
);
|
||||
|
||||
store_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_interner.get_repr(layout),
|
||||
allocation,
|
||||
value,
|
||||
);
|
||||
|
||||
allocation.into()
|
||||
}
|
||||
|
||||
ExprUnbox { symbol } => {
|
||||
let value = scope.load_symbol(symbol);
|
||||
|
||||
debug_assert!(value.is_pointer_value());
|
||||
|
||||
load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_interner.get_repr(layout),
|
||||
value.into_pointer_value(),
|
||||
"load_boxed_value",
|
||||
)
|
||||
}
|
||||
|
||||
FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
|
||||
Reset {
|
||||
symbol,
|
||||
update_mode,
|
||||
|
|
|
@ -1136,6 +1136,20 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
storage,
|
||||
),
|
||||
|
||||
Expr::ExprBox { symbol: arg_sym } => self.expr_box(sym, *arg_sym, layout, storage),
|
||||
|
||||
Expr::ExprUnbox { symbol: arg_sym } => self.expr_unbox(sym, *arg_sym),
|
||||
|
||||
Expr::FunctionPointer { .. } => todo_lambda_erasure!(),
|
||||
|
||||
Expr::Reuse {
|
||||
tag_layout,
|
||||
tag_id,
|
||||
arguments,
|
||||
symbol: reused,
|
||||
..
|
||||
} => self.expr_tag(tag_layout, *tag_id, arguments, sym, storage, Some(*reused)),
|
||||
|
||||
Expr::Reset { symbol: arg, .. } => self.expr_reset(*arg, sym, storage),
|
||||
|
||||
Expr::ResetRef { symbol: arg, .. } => self.expr_resetref(*arg, sym, storage),
|
||||
|
|
|
@ -719,7 +719,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
|
||||
Call(call) => self.collect_call(interner, param_map, z, call),
|
||||
|
||||
Literal(_) | NullPointer | RuntimeErrorFunction(_) => {}
|
||||
Literal(_) | NullPointer | RuntimeErrorFunction(_) | FunctionPointer { .. } => {}
|
||||
|
||||
StructAtIndex { structure: x, .. } => {
|
||||
// if the structure (record/tag/array) is owned, the extracted value is
|
||||
|
|
|
@ -70,6 +70,9 @@ pub enum ProblemKind<'a> {
|
|||
proc_layout: ProcLayout<'a>,
|
||||
similar: Vec<ProcLayout<'a>>,
|
||||
},
|
||||
PtrToUndefinedProc {
|
||||
symbol: Symbol,
|
||||
},
|
||||
DuplicateCallSpecId {
|
||||
old_call_line: usize,
|
||||
},
|
||||
|
@ -464,6 +467,49 @@ impl<'a, 'r> Ctx<'a, 'r> {
|
|||
// TODO don't know what the element layout is
|
||||
None
|
||||
}
|
||||
&Expr::ExprBox { symbol } => self.with_sym_layout(symbol, |ctx, _def_line, layout| {
|
||||
let inner = layout;
|
||||
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_repr(layout) {
|
||||
LayoutRepr::Boxed(inner) => Some(inner),
|
||||
_ => {
|
||||
ctx.problem(ProblemKind::UnboxNotABox { symbol, def_line });
|
||||
None
|
||||
}
|
||||
}
|
||||
}),
|
||||
&Expr::FunctionPointer { lambda_name } => {
|
||||
let lambda_symbol = lambda_name.name();
|
||||
if !self.procs.iter().any(|((name, proc), _)| {
|
||||
*name == lambda_symbol && proc.niche == lambda_name.niche()
|
||||
}) {
|
||||
self.problem(ProblemKind::PtrToUndefinedProc {
|
||||
symbol: lambda_symbol,
|
||||
});
|
||||
}
|
||||
Some(Layout::OPAQUE_PTR)
|
||||
}
|
||||
&Expr::Reuse {
|
||||
symbol,
|
||||
update_tag_id: _,
|
||||
update_mode: _,
|
||||
tag_layout,
|
||||
tag_id: _,
|
||||
arguments: _,
|
||||
} => {
|
||||
let union = self
|
||||
.interner
|
||||
.insert_direct_no_semantic(LayoutRepr::Union(tag_layout));
|
||||
self.check_sym_layout(symbol, union, UseKind::TagReuse);
|
||||
// TODO also check update arguments
|
||||
Some(union)
|
||||
}
|
||||
&Expr::Reset {
|
||||
symbol,
|
||||
update_mode: _,
|
||||
|
|
|
@ -265,6 +265,15 @@ where
|
|||
};
|
||||
stack(f, [no_spec_doc, similar_doc])
|
||||
}
|
||||
ProblemKind::PtrToUndefinedProc { symbol } => {
|
||||
title = "PROC SPECIALIZATION NOT DEFINED";
|
||||
docs_before = vec![];
|
||||
f.concat([
|
||||
f.reflow("The proc "),
|
||||
format_symbol(f, interns, symbol),
|
||||
f.reflow(" is not defined"),
|
||||
])
|
||||
}
|
||||
ProblemKind::DuplicateCallSpecId { old_call_line } => {
|
||||
title = "DUPLICATE CALL SPEC ID";
|
||||
docs_before = vec![(old_call_line, f.reflow("This call has a specialization ID"))];
|
||||
|
|
|
@ -229,8 +229,11 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
}
|
||||
}
|
||||
Reset { .. } | Expr::ResetRef { .. } => { /* do nothing */ }
|
||||
RuntimeErrorFunction(_) | GetTagId { .. } | EmptyArray | NullPointer => { /* do nothing */
|
||||
}
|
||||
RuntimeErrorFunction(_)
|
||||
| FunctionPointer { .. }
|
||||
| GetTagId { .. }
|
||||
| EmptyArray
|
||||
| NullPointer => { /* do nothing */ }
|
||||
}
|
||||
|
||||
// now store the let binding for later
|
||||
|
|
|
@ -872,7 +872,11 @@ fn insert_refcount_operations_binding<'a>(
|
|||
}
|
||||
|
||||
match expr {
|
||||
Expr::Literal(_) | Expr::NullPointer | Expr::EmptyArray | Expr::RuntimeErrorFunction(_) => {
|
||||
Expr::Literal(_)
|
||||
| Expr::NullPointer
|
||||
| Expr::FunctionPointer { .. }
|
||||
| Expr::EmptyArray
|
||||
| Expr::RuntimeErrorFunction(_) => {
|
||||
// Literals, empty arrays, and runtime errors are not (and have nothing) reference counted.
|
||||
new_let!(stmt)
|
||||
}
|
||||
|
|
|
@ -1885,6 +1885,28 @@ pub enum Expr<'a> {
|
|||
},
|
||||
EmptyArray,
|
||||
|
||||
ExprBox {
|
||||
symbol: Symbol,
|
||||
},
|
||||
|
||||
ExprUnbox {
|
||||
symbol: Symbol,
|
||||
},
|
||||
|
||||
/// Returns a pointer to the given function.
|
||||
FunctionPointer {
|
||||
lambda_name: LambdaName<'a>,
|
||||
},
|
||||
|
||||
Reuse {
|
||||
symbol: Symbol,
|
||||
update_tag_id: bool,
|
||||
update_mode: UpdateModeId,
|
||||
// normal Tag fields
|
||||
tag_layout: UnionLayout<'a>,
|
||||
tag_id: TagIdIntType,
|
||||
arguments: &'a [Symbol],
|
||||
},
|
||||
Reset {
|
||||
symbol: Symbol,
|
||||
update_mode: UpdateModeId,
|
||||
|
@ -2066,6 +2088,18 @@ impl<'a> Expr<'a> {
|
|||
.text("GetTagId ")
|
||||
.append(symbol_to_doc(alloc, *structure, pretty)),
|
||||
|
||||
ExprBox { symbol, .. } => alloc
|
||||
.text("Box ")
|
||||
.append(symbol_to_doc(alloc, *symbol, pretty)),
|
||||
|
||||
ExprUnbox { symbol, .. } => alloc
|
||||
.text("Unbox ")
|
||||
.append(symbol_to_doc(alloc, *symbol, pretty)),
|
||||
|
||||
FunctionPointer { lambda_name } => alloc
|
||||
.text("FunctionPointer ")
|
||||
.append(symbol_to_doc(alloc, lambda_name.name(), pretty)),
|
||||
|
||||
UnionAtIndex {
|
||||
tag_id,
|
||||
structure,
|
||||
|
@ -7706,6 +7740,16 @@ fn substitute_in_expr<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
ExprBox { symbol } => {
|
||||
substitute(subs, *symbol).map(|new_symbol| ExprBox { symbol: new_symbol })
|
||||
}
|
||||
|
||||
ExprUnbox { symbol } => {
|
||||
substitute(subs, *symbol).map(|new_symbol| ExprUnbox { symbol: new_symbol })
|
||||
}
|
||||
|
||||
FunctionPointer { .. } => None,
|
||||
|
||||
StructAtIndex {
|
||||
index,
|
||||
structure,
|
||||
|
|
|
@ -1097,7 +1097,7 @@ fn expr_contains_symbol(expr: &Expr, needle: Symbol) -> bool {
|
|||
Some(ru) => ru.symbol == needle || arguments.contains(&needle),
|
||||
},
|
||||
Expr::Struct(fields) => fields.contains(&needle),
|
||||
Expr::NullPointer => false,
|
||||
Expr::NullPointer | Expr::FunctionPointer { .. } => false,
|
||||
Expr::StructAtIndex { structure, .. }
|
||||
| Expr::GetTagId { structure, .. }
|
||||
| Expr::UnionAtIndex { structure, .. }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue