Expr::FunctionPointer

This commit is contained in:
Ayaz Hafiz 2023-06-25 18:46:08 -05:00
parent 55fa8098d3
commit cf30f02e01
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
11 changed files with 176 additions and 5 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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