mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
First pass update erasure IR
This commit is contained in:
parent
7ea85e44d2
commit
dc56a0ffef
4 changed files with 128 additions and 151 deletions
|
@ -2119,9 +2119,9 @@ impl<'a> Expr<'a> {
|
||||||
};
|
};
|
||||||
let callee = symbol_to_doc(alloc, *callee, pretty);
|
let callee = symbol_to_doc(alloc, *callee, pretty);
|
||||||
alloc
|
alloc
|
||||||
.text("ErasedMake { value:")
|
.text("ErasedMake { value: ")
|
||||||
.append(value)
|
.append(value)
|
||||||
.append(", callee:")
|
.append(", callee: ")
|
||||||
.append(callee)
|
.append(callee)
|
||||||
.append(" }")
|
.append(" }")
|
||||||
}
|
}
|
||||||
|
@ -4091,7 +4091,7 @@ impl<'a> ProcLayout<'a> {
|
||||||
arguments
|
arguments
|
||||||
} else {
|
} else {
|
||||||
let mut extended_args = Vec::with_capacity_in(arguments.len(), arena);
|
let mut extended_args = Vec::with_capacity_in(arguments.len(), arena);
|
||||||
extended_args.extend(arguments.iter().chain(&[Layout::OPAQUE_PTR]).copied());
|
extended_args.extend(arguments.iter().chain(&[Layout::ERASED]).copied());
|
||||||
extended_args.into_bump_slice()
|
extended_args.into_bump_slice()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,30 +4,26 @@ use roc_types::subs::Variable;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
borrow::Ownership,
|
borrow::Ownership,
|
||||||
layout::{ErasedIndex, FunctionPointer, InLayout, LambdaName, Layout, LayoutCache, LayoutRepr},
|
layout::{FunctionPointer, InLayout, LambdaName, Layout, LayoutCache, LayoutRepr},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
with_hole, BranchInfo, Call, CallType, CapturedSymbols, Env, Expr, JoinPointId, Param, Procs,
|
with_hole, BranchInfo, Call, CallType, CapturedSymbols, Env, ErasedField, Expr, JoinPointId,
|
||||||
Stmt, UpdateModeId,
|
Param, Procs, Stmt, UpdateModeId,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ERASED_FUNCTION_FIELD_LAYOUTS: &[InLayout] =
|
|
||||||
&[Layout::OPAQUE_PTR, Layout::OPAQUE_PTR, Layout::OPAQUE_PTR];
|
|
||||||
|
|
||||||
fn index_erased_function<'a>(
|
fn index_erased_function<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
assign_to: Symbol,
|
assign_to: Symbol,
|
||||||
erased_function: Symbol,
|
erased_function: Symbol,
|
||||||
index: ErasedIndex,
|
field: ErasedField,
|
||||||
) -> impl FnOnce(Stmt<'a>) -> Stmt<'a> {
|
) -> impl FnOnce(Stmt<'a>) -> Stmt<'a> {
|
||||||
move |rest| {
|
move |rest| {
|
||||||
Stmt::Let(
|
Stmt::Let(
|
||||||
assign_to,
|
assign_to,
|
||||||
Expr::StructAtIndex {
|
Expr::ErasedLoad {
|
||||||
index: index as _,
|
symbol: erased_function,
|
||||||
structure: erased_function,
|
field,
|
||||||
field_layouts: ERASED_FUNCTION_FIELD_LAYOUTS,
|
|
||||||
},
|
},
|
||||||
Layout::OPAQUE_PTR,
|
Layout::OPAQUE_PTR,
|
||||||
arena.alloc(rest),
|
arena.alloc(rest),
|
||||||
|
@ -153,30 +149,30 @@ pub fn call_erased_function<'a>(
|
||||||
|
|
||||||
let join_point_id = JoinPointId(env.unique_symbol());
|
let join_point_id = JoinPointId(env.unique_symbol());
|
||||||
|
|
||||||
// f_value = f.value
|
// f_value = ErasedLoad(f, .value)
|
||||||
let f_value = env.unique_symbol();
|
let f_value = env.unique_symbol();
|
||||||
let let_f_value = index_erased_function(arena, f_value, f, ErasedIndex::Value);
|
let let_f_value = index_erased_function(arena, f_value, f, ErasedField::Value);
|
||||||
|
|
||||||
// f_callee = f.callee
|
// f_callee = ErasedLoad(f, .callee)
|
||||||
let f_callee = env.unique_symbol();
|
let f_callee = env.unique_symbol();
|
||||||
let let_f_callee = index_erased_function(arena, f_callee, f, ErasedIndex::Callee);
|
let let_f_callee = index_erased_function(arena, f_callee, f, ErasedField::Callee);
|
||||||
|
|
||||||
let mut build_closure_data_branch = |env: &mut Env, pass_closure| {
|
let mut build_closure_data_branch = |env: &mut Env, pass_closure| {
|
||||||
// f_callee = cast(f_callee, (..params) -> ret);
|
// f_callee = Cast(f_callee, (..params) -> ret);
|
||||||
// result = f_callee ..args
|
// result = f_callee ..args
|
||||||
// jump join result
|
// jump join result
|
||||||
|
|
||||||
let (f_args, function_argument_symbols) = if pass_closure {
|
let (f_args, function_argument_symbols) = if pass_closure {
|
||||||
// f_args = ...args, f.value
|
// f_args = ...args, f
|
||||||
// function_argument_symbols = ...args, f.value
|
// function_argument_symbols = ...args, f.value
|
||||||
let f_args = {
|
let f_args = {
|
||||||
let mut args = AVec::with_capacity_in(f_args.len() + 1, arena);
|
let mut args = AVec::with_capacity_in(f_args.len() + 1, arena);
|
||||||
args.extend(f_args.iter().chain(&[Layout::OPAQUE_PTR]).copied());
|
args.extend(f_args.iter().chain(&[Layout::ERASED]).copied());
|
||||||
args.into_bump_slice()
|
args.into_bump_slice()
|
||||||
};
|
};
|
||||||
let function_argument_symbols = {
|
let function_argument_symbols = {
|
||||||
let mut args = AVec::with_capacity_in(function_argument_symbols.len() + 1, arena);
|
let mut args = AVec::with_capacity_in(function_argument_symbols.len() + 1, arena);
|
||||||
args.extend(function_argument_symbols.iter().chain(&[f_value]));
|
args.extend(function_argument_symbols.iter().chain(&[f]));
|
||||||
args.into_bump_slice()
|
args.into_bump_slice()
|
||||||
};
|
};
|
||||||
(f_args, function_argument_symbols)
|
(f_args, function_argument_symbols)
|
||||||
|
@ -239,9 +235,9 @@ pub fn call_erased_function<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let remainder =
|
let remainder =
|
||||||
// f_value = f.value
|
// f_value = ErasedLoad(f, .value)
|
||||||
let_f_value(
|
let_f_value(
|
||||||
// f_callee = f.callee
|
// f_callee = ErasedLoad(f, .callee)
|
||||||
let_f_callee(
|
let_f_callee(
|
||||||
//
|
//
|
||||||
call_and_jump_on_value,
|
call_and_jump_on_value,
|
||||||
|
@ -302,33 +298,27 @@ pub fn build_erased_function<'a>(
|
||||||
assigned: Symbol,
|
assigned: Symbol,
|
||||||
hole: &'a Stmt<'a>,
|
hole: &'a Stmt<'a>,
|
||||||
) -> Stmt<'a> {
|
) -> Stmt<'a> {
|
||||||
let value = env.unique_symbol();
|
|
||||||
let callee = env.unique_symbol();
|
|
||||||
let refcounter = env.unique_symbol();
|
|
||||||
|
|
||||||
// assigned = Expr::Struct({ value, callee, refcounter })
|
|
||||||
// hole <assigned>
|
|
||||||
let result = Stmt::Let(
|
|
||||||
assigned,
|
|
||||||
Expr::Struct(env.arena.alloc([value, callee, refcounter])),
|
|
||||||
Layout::ERASED,
|
|
||||||
hole,
|
|
||||||
);
|
|
||||||
|
|
||||||
// refcounter = TODO
|
|
||||||
// <hole>
|
|
||||||
let result = Stmt::Let(
|
|
||||||
refcounter,
|
|
||||||
Expr::NullPointer,
|
|
||||||
Layout::OPAQUE_PTR,
|
|
||||||
env.arena.alloc(result),
|
|
||||||
);
|
|
||||||
|
|
||||||
let ResolvedErasedLambda {
|
let ResolvedErasedLambda {
|
||||||
captures,
|
captures,
|
||||||
lambda_name,
|
lambda_name,
|
||||||
} = resolved_lambda;
|
} = resolved_lambda;
|
||||||
|
|
||||||
|
let value = match captures {
|
||||||
|
None => None,
|
||||||
|
Some(_) => Some(env.unique_symbol()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let callee = env.unique_symbol();
|
||||||
|
|
||||||
|
// assigned = Expr::ErasedMake({ value, callee })
|
||||||
|
// hole <assigned>
|
||||||
|
let result = Stmt::Let(
|
||||||
|
assigned,
|
||||||
|
Expr::ErasedMake { value, callee },
|
||||||
|
Layout::ERASED,
|
||||||
|
hole,
|
||||||
|
);
|
||||||
|
|
||||||
// callee = Expr::FunctionPointer(f)
|
// callee = Expr::FunctionPointer(f)
|
||||||
let result = Stmt::Let(
|
let result = Stmt::Let(
|
||||||
callee,
|
callee,
|
||||||
|
@ -339,16 +329,7 @@ pub fn build_erased_function<'a>(
|
||||||
|
|
||||||
// value = Expr::Box({s})
|
// value = Expr::Box({s})
|
||||||
match captures {
|
match captures {
|
||||||
None => {
|
None => result,
|
||||||
// value = nullptr
|
|
||||||
// <hole>
|
|
||||||
Stmt::Let(
|
|
||||||
value,
|
|
||||||
Expr::NullPointer,
|
|
||||||
Layout::OPAQUE_PTR,
|
|
||||||
env.arena.alloc(result),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Some(ResolvedErasedCaptures { layouts, symbols }) => {
|
Some(ResolvedErasedCaptures { layouts, symbols }) => {
|
||||||
// captures = {...captures}
|
// captures = {...captures}
|
||||||
// captures = Box(captures)
|
// captures = Box(captures)
|
||||||
|
@ -364,7 +345,7 @@ pub fn build_erased_function<'a>(
|
||||||
layout_cache.put_in_direct_no_semantic(LayoutRepr::Boxed(stack_captures_layout));
|
layout_cache.put_in_direct_no_semantic(LayoutRepr::Boxed(stack_captures_layout));
|
||||||
|
|
||||||
let result = Stmt::Let(
|
let result = Stmt::Let(
|
||||||
value,
|
value.unwrap(),
|
||||||
Expr::Call(Call {
|
Expr::Call(Call {
|
||||||
call_type: CallType::LowLevel {
|
call_type: CallType::LowLevel {
|
||||||
op: LowLevel::PtrCast,
|
op: LowLevel::PtrCast,
|
||||||
|
@ -473,6 +454,7 @@ pub fn unpack_closure_data<'a>(
|
||||||
captures: &[(Symbol, Variable)],
|
captures: &[(Symbol, Variable)],
|
||||||
mut hole: Stmt<'a>,
|
mut hole: Stmt<'a>,
|
||||||
) -> Stmt<'a> {
|
) -> Stmt<'a> {
|
||||||
|
let loaded_captures = env.unique_symbol();
|
||||||
let heap_captures = env.unique_symbol();
|
let heap_captures = env.unique_symbol();
|
||||||
let stack_captures = env.unique_symbol();
|
let stack_captures = env.unique_symbol();
|
||||||
|
|
||||||
|
@ -525,5 +507,12 @@ pub fn unpack_closure_data<'a>(
|
||||||
env.arena.alloc(hole),
|
env.arena.alloc(hole),
|
||||||
);
|
);
|
||||||
|
|
||||||
hole
|
let let_loaded_captures = index_erased_function(
|
||||||
|
env.arena,
|
||||||
|
loaded_captures,
|
||||||
|
captures_symbol,
|
||||||
|
ErasedField::Value,
|
||||||
|
);
|
||||||
|
|
||||||
|
let_loaded_captures(hole)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1413,7 +1413,7 @@ impl<'a> ClosureDataKind<'a> {
|
||||||
pub fn data_layout(&self) -> InLayout<'a> {
|
pub fn data_layout(&self) -> InLayout<'a> {
|
||||||
match self {
|
match self {
|
||||||
Self::LambdaSet(lambda_set) => lambda_set.full_layout,
|
Self::LambdaSet(lambda_set) => lambda_set.full_layout,
|
||||||
Self::Erased => Layout::OPAQUE_PTR,
|
Self::Erased => Layout::ERASED,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2603,14 +2603,6 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Index into an [Erased layout][Layout::ERASED].
|
|
||||||
#[repr(u8)]
|
|
||||||
pub(crate) enum ErasedIndex {
|
|
||||||
Value = 0,
|
|
||||||
Callee = 1,
|
|
||||||
RefCounter = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> LayoutRepr<'a> {
|
impl<'a> LayoutRepr<'a> {
|
||||||
pub const UNIT: Self = LayoutRepr::struct_(&[]);
|
pub const UNIT: Self = LayoutRepr::struct_(&[]);
|
||||||
pub const BOOL: Self = LayoutRepr::Builtin(Builtin::Bool);
|
pub const BOOL: Self = LayoutRepr::Builtin(Builtin::Bool);
|
||||||
|
|
|
@ -13,101 +13,97 @@ main = (f "") {}
|
||||||
# ^^^^ {} -?-> Str
|
# ^^^^ {} -?-> Str
|
||||||
|
|
||||||
# -emit:mono
|
# -emit:mono
|
||||||
procedure : `#UserApp.3` Str
|
procedure Bool.2 ():
|
||||||
procedure = `#UserApp.3` (`#UserApp.40`: {}):
|
let Bool.23 : Int1 = true;
|
||||||
let `#UserApp.41` : Str = "";
|
ret Bool.23;
|
||||||
ret `#UserApp.41`;
|
|
||||||
|
|
||||||
procedure : `#UserApp.4` Str
|
procedure Test.1 (Test.2):
|
||||||
procedure = `#UserApp.4` (`#UserApp.29`: {}, `#Attr.#arg_closure`: Boxed([])):
|
let Test.38 : Int1 = CallByName Bool.2;
|
||||||
let `#UserApp.31` : Boxed({Str}) = lowlevel PtrCast `#Attr.#arg_closure`;
|
if Test.38 then
|
||||||
let `#UserApp.32` : {Str} = Unbox `#UserApp.31`;
|
dec Test.2;
|
||||||
joinpoint `#Derived_gen.IdentId(0)`:
|
let Test.44 : {} = Struct {};
|
||||||
let `#UserApp.s` : Str = StructAtIndex 0 `#UserApp.32`;
|
let Test.45 : Boxed({}) = Box Test.44;
|
||||||
ret `#UserApp.s`;
|
let Test.42 : Boxed([]) = lowlevel PtrCast Test.45;
|
||||||
|
let Test.43 : Boxed([]) = FunctionPointer Test.3;
|
||||||
|
dec Test.43;
|
||||||
|
let Test.39 : ?Erased = ErasedMake { value: Test.42, callee: Test.43 };
|
||||||
|
ret Test.39;
|
||||||
|
else
|
||||||
|
let Test.36 : {Str} = Struct {Test.2};
|
||||||
|
let Test.37 : Boxed({Str}) = Box Test.36;
|
||||||
|
let Test.34 : Boxed([]) = lowlevel PtrCast Test.37;
|
||||||
|
let Test.35 : Boxed([]) = FunctionPointer Test.4;
|
||||||
|
dec Test.35;
|
||||||
|
let Test.28 : ?Erased = ErasedMake { value: Test.34, callee: Test.35 };
|
||||||
|
ret Test.28;
|
||||||
|
|
||||||
|
procedure Test.3 (Test.40):
|
||||||
|
let Test.41 : Str = "";
|
||||||
|
ret Test.41;
|
||||||
|
|
||||||
|
procedure Test.4 (Test.29, #Attr.12):
|
||||||
|
inc #Attr.12;
|
||||||
|
let Test.31 : Boxed([]) = ErasedLoad #Attr.12 .Value;
|
||||||
|
dec Test.31;
|
||||||
|
let Test.32 : Boxed({Str}) = lowlevel PtrCast #Attr.12;
|
||||||
|
let Test.33 : {Str} = Unbox Test.32;
|
||||||
|
joinpoint #Derived_gen.0:
|
||||||
|
let Test.2 : Str = StructAtIndex 0 Test.33;
|
||||||
|
ret Test.2;
|
||||||
in
|
in
|
||||||
let `#Derived_gen.IdentId(1)` : Int1 = lowlevel RefCountIsUnique `#UserApp.31`;
|
let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.32;
|
||||||
if `#Derived_gen.IdentId(1)` then
|
if #Derived_gen.1 then
|
||||||
decref `#UserApp.31`;
|
free Test.32;
|
||||||
jump `#Derived_gen.IdentId(0)`;
|
jump #Derived_gen.0;
|
||||||
else
|
else
|
||||||
inc `#UserApp.32`;
|
inc Test.33;
|
||||||
decref `#UserApp.31`;
|
decref Test.32;
|
||||||
jump `#Derived_gen.IdentId(0)`;
|
jump #Derived_gen.0;
|
||||||
|
|
||||||
procedure : `#UserApp.f` {Boxed([]), Boxed([]), Boxed([])}
|
procedure Test.0 ():
|
||||||
procedure = `#UserApp.f` (`#UserApp.s`: Str):
|
let Test.6 : {} = Struct {};
|
||||||
let `#UserApp.38` : Int1 = CallByName `Bool.true`;
|
let Test.17 : Str = "";
|
||||||
if `#UserApp.38` then
|
let Test.46 : Boxed([]) = FunctionPointer Test.1;
|
||||||
dec `#UserApp.s`;
|
dec Test.46;
|
||||||
let `#UserApp.45` : {} = Struct {};
|
let Test.18 : ?Erased = ErasedMake { value: <null>, callee: Test.46 };
|
||||||
let `#UserApp.46` : Boxed({}) = Box `#UserApp.45`;
|
joinpoint Test.19 Test.7:
|
||||||
let `#UserApp.42` : Boxed([]) = lowlevel PtrCast `#UserApp.46`;
|
joinpoint Test.8 Test.5:
|
||||||
let `#UserApp.43` : Boxed([]) = FunctionPointer `#UserApp.3`;
|
ret Test.5;
|
||||||
let `#UserApp.44` : Boxed([]) = NullPointer;
|
|
||||||
let `#UserApp.39` : {Boxed([]), Boxed([]), Boxed([])} = Struct {`#UserApp.42`, `#UserApp.43`, `#UserApp.44`};
|
|
||||||
ret `#UserApp.39`;
|
|
||||||
else
|
|
||||||
let `#UserApp.36` : {Str} = Struct {`#UserApp.s`};
|
|
||||||
let `#UserApp.37` : Boxed({Str}) = Box `#UserApp.36`;
|
|
||||||
let `#UserApp.33` : Boxed([]) = lowlevel PtrCast `#UserApp.37`;
|
|
||||||
let `#UserApp.34` : Boxed([]) = FunctionPointer `#UserApp.4`;
|
|
||||||
let `#UserApp.35` : Boxed([]) = NullPointer;
|
|
||||||
let `#UserApp.28` : {Boxed([]), Boxed([]), Boxed([])} = Struct {`#UserApp.33`, `#UserApp.34`, `#UserApp.35`};
|
|
||||||
ret `#UserApp.28`;
|
|
||||||
|
|
||||||
procedure : `Bool.true` Int1
|
|
||||||
procedure = `Bool.true` ():
|
|
||||||
let `Bool.23` : Int1 = true;
|
|
||||||
ret `Bool.23`;
|
|
||||||
|
|
||||||
procedure : `#UserApp.main` Str
|
|
||||||
procedure = `#UserApp.main` ():
|
|
||||||
let `#UserApp.6` : {} = Struct {};
|
|
||||||
let `#UserApp.17` : Str = "";
|
|
||||||
let `#UserApp.47` : Boxed([]) = NullPointer;
|
|
||||||
let `#UserApp.48` : Boxed([]) = FunctionPointer `#UserApp.f`;
|
|
||||||
let `#UserApp.49` : Boxed([]) = NullPointer;
|
|
||||||
let `#UserApp.18` : {Boxed([]), Boxed([]), Boxed([])} = Struct {`#UserApp.47`, `#UserApp.48`, `#UserApp.49`};
|
|
||||||
joinpoint `#UserApp.19` `#UserApp.7`:
|
|
||||||
joinpoint `#UserApp.8` `#UserApp.5`:
|
|
||||||
ret `#UserApp.5`;
|
|
||||||
in
|
in
|
||||||
let `#UserApp.9` : Boxed([]) = StructAtIndex 0 `#UserApp.7`;
|
let Test.9 : Boxed([]) = ErasedLoad Test.7 .Value;
|
||||||
let `#UserApp.10` : Boxed([]) = StructAtIndex 1 `#UserApp.7`;
|
let Test.10 : Boxed([]) = ErasedLoad Test.7 .Callee;
|
||||||
let `#Derived_gen.IdentId(4)` : Boxed([]) = StructAtIndex 2 `#UserApp.7`;
|
let Test.12 : Boxed([]) = NullPointer;
|
||||||
dec `#Derived_gen.IdentId(4)`;
|
let Test.11 : Int1 = lowlevel Eq Test.9 Test.12;
|
||||||
let `#UserApp.12` : Boxed([]) = NullPointer;
|
dec Test.12;
|
||||||
let `#UserApp.11` : Int1 = lowlevel Eq `#UserApp.9` `#UserApp.12`;
|
dec Test.9;
|
||||||
dec `#UserApp.12`;
|
switch Test.11:
|
||||||
switch `#UserApp.11`:
|
|
||||||
case 0:
|
case 0:
|
||||||
dec `#UserApp.9`;
|
let Test.13 : FunPtr({} -> Str) = lowlevel PtrCast Test.10;
|
||||||
let `#UserApp.13` : FunPtr({} -> Str) = lowlevel PtrCast `#UserApp.10`;
|
let Test.14 : Str = CallByPtr Test.13 Test.6;
|
||||||
let `#UserApp.14` : Str = CallByPtr `#UserApp.13` `#UserApp.6`;
|
jump Test.8 Test.14;
|
||||||
jump `#UserApp.8` `#UserApp.14`;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
let `#UserApp.15` : FunPtr({}, Boxed([]) -> Str) = lowlevel PtrCast `#UserApp.10`;
|
inc Test.7;
|
||||||
let `#UserApp.16` : Str = CallByPtr `#UserApp.15` `#UserApp.6` `#UserApp.9`;
|
let Test.15 : FunPtr({}, ?Erased -> Str) = lowlevel PtrCast Test.10;
|
||||||
jump `#UserApp.8` `#UserApp.16`;
|
let Test.16 : Str = CallByPtr Test.15 Test.6 Test.7;
|
||||||
|
jump Test.8 Test.16;
|
||||||
|
|
||||||
in
|
in
|
||||||
let `#UserApp.20` : Boxed([]) = StructAtIndex 0 `#UserApp.18`;
|
let Test.20 : Boxed([]) = ErasedLoad Test.18 .Value;
|
||||||
let `#UserApp.21` : Boxed([]) = StructAtIndex 1 `#UserApp.18`;
|
let Test.21 : Boxed([]) = ErasedLoad Test.18 .Callee;
|
||||||
dec `#UserApp.49`;
|
let Test.23 : Boxed([]) = NullPointer;
|
||||||
let `#UserApp.23` : Boxed([]) = NullPointer;
|
let Test.22 : Int1 = lowlevel Eq Test.20 Test.23;
|
||||||
let `#UserApp.22` : Int1 = lowlevel Eq `#UserApp.20` `#UserApp.23`;
|
dec Test.20;
|
||||||
dec `#UserApp.23`;
|
dec Test.23;
|
||||||
switch `#UserApp.22`:
|
switch Test.22:
|
||||||
case 0:
|
case 0:
|
||||||
dec `#UserApp.20`;
|
let Test.24 : FunPtr(Str -> ?Erased) = lowlevel PtrCast Test.21;
|
||||||
let `#UserApp.24` : FunPtr(Str -> {Boxed([]), Boxed([]), Boxed([])}) = lowlevel PtrCast `#UserApp.21`;
|
let Test.25 : ?Erased = CallByPtr Test.24 Test.17;
|
||||||
let `#UserApp.25` : {Boxed([]), Boxed([]), Boxed([])} = CallByPtr `#UserApp.24` `#UserApp.17`;
|
jump Test.19 Test.25;
|
||||||
jump `#UserApp.19` `#UserApp.25`;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
let `#UserApp.26` : FunPtr(Str, Boxed([]) -> {Boxed([]), Boxed([]), Boxed([])}) = lowlevel PtrCast `#UserApp.21`;
|
inc Test.18;
|
||||||
let `#UserApp.27` : {Boxed([]), Boxed([]), Boxed([])} = CallByPtr `#UserApp.26` `#UserApp.17` `#UserApp.20`;
|
let Test.26 : FunPtr(Str, ?Erased -> ?Erased) = lowlevel PtrCast Test.21;
|
||||||
jump `#UserApp.19` `#UserApp.27`;
|
let Test.27 : ?Erased = CallByPtr Test.26 Test.17 Test.18;
|
||||||
|
jump Test.19 Test.27;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue