Merge branch 'main' into new-builder-syntax

This commit is contained in:
Sam Mohr 2024-07-07 18:33:36 -07:00 committed by GitHub
commit 618b713ecd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
70 changed files with 1654 additions and 256 deletions

13
Cargo.lock generated
View file

@ -941,6 +941,13 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs"
version = "0.0.1"
dependencies = [
"widestring",
]
[[package]]
name = "fs_at"
version = "0.1.10"
@ -4551,6 +4558,12 @@ version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
[[package]]
name = "widestring"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
[[package]]
name = "winapi"
version = "0.3.9"

View file

@ -1,40 +1,41 @@
[workspace]
members = [
"crates/compiler/*",
"crates/vendor/*",
"crates/glue",
"crates/cli",
"crates/cli_utils",
"crates/highlight",
"crates/error_macros",
"crates/reporting",
"crates/packaging",
"crates/repl_cli",
"crates/repl_eval",
"crates/repl_test",
"crates/repl_ui",
"crates/repl_wasm",
"crates/repl_expect",
"crates/roc_std",
"crates/test_utils",
"crates/test_utils_dir",
"crates/valgrind",
"crates/tracing",
"crates/utils/*",
"crates/docs",
"crates/docs_cli",
"crates/linker",
"crates/wasi-libc-sys",
"crates/wasm_module",
"crates/wasm_interp",
"crates/language_server",
"crates/compiler/*",
"crates/vendor/*",
"crates/fs",
"crates/glue",
"crates/cli",
"crates/cli_utils",
"crates/highlight",
"crates/error_macros",
"crates/reporting",
"crates/packaging",
"crates/repl_cli",
"crates/repl_eval",
"crates/repl_test",
"crates/repl_ui",
"crates/repl_wasm",
"crates/repl_expect",
"crates/roc_std",
"crates/test_utils",
"crates/test_utils_dir",
"crates/valgrind",
"crates/tracing",
"crates/utils/*",
"crates/docs",
"crates/docs_cli",
"crates/linker",
"crates/wasi-libc-sys",
"crates/wasm_module",
"crates/wasm_interp",
"crates/language_server",
]
exclude = [
"ci/benchmarks/bench-runner",
"ci/repl_basic_test",
# Examples sometimes have Rust hosts in their platforms. The compiler should ignore those.
"examples",
"ci/benchmarks/bench-runner",
"ci/repl_basic_test",
# Examples sometimes have Rust hosts in their platforms. The compiler should ignore those.
"examples",
]
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
# see www/build.sh for more.
@ -69,7 +70,9 @@ version = "0.0.1"
# change the tag value in this Cargo.toml to point to that tag, and `cargo update`.
# This way, GitHub Actions works and nobody's builds get broken.
# TODO: Switch this back to roc-lang/inkwell once it is updated
inkwell = { git = "https://github.com/roc-lang/inkwell", branch = "inkwell-llvm-16", features = ["llvm16-0"] }
inkwell = { git = "https://github.com/roc-lang/inkwell", branch = "inkwell-llvm-16", features = [
"llvm16-0",
] }
arrayvec = "0.7.2" # update roc_std/Cargo.toml on change
backtrace = "0.3.67"
@ -78,18 +81,27 @@ bincode = "1.3.3"
bitflags = "1.3.2"
bitvec = "1.0.1"
blake3 = "1.3.3"
brotli = "3.3.4" # used for decompressing tarballs over HTTPS, if the server supports brotli
brotli = "3.3.4" # used for decompressing tarballs over HTTPS, if the server supports brotli
bumpalo = { version = "3.12.0", features = ["collections"] }
bytemuck = { version = "1.13.1", features = ["derive"] }
capstone = { version = "0.11.0", default-features = false }
cgmath = "0.18.0"
chrono = "0.4.26"
clap = { version = "4.2.7", default-features = false, features = ["std", "color", "suggestions", "help", "usage", "error-context"] }
clap = { version = "4.2.7", default-features = false, features = [
"std",
"color",
"suggestions",
"help",
"usage",
"error-context",
] }
colored = "2.0.0"
console_error_panic_hook = "0.1.7"
const_format = { version = "0.2.30", features = ["const_generics"] }
copypasta = "0.8.2"
criterion = { git = "https://github.com/Anton-4/criterion.rs", features = ["html_reports"], rev = "30ea0c5" }
criterion = { git = "https://github.com/Anton-4/criterion.rs", features = [
"html_reports",
], rev = "30ea0c5" }
criterion-perf-events = { git = "https://github.com/Anton-4/criterion-perf-events", rev = "0f38c3e" }
crossbeam = "0.8.2"
dircpy = "0.3.14"
@ -102,7 +114,12 @@ fs_extra = "1.3.0"
futures = "0.3.26"
glyph_brush = "0.7.7"
hashbrown = { version = "0.14.3" }
iced-x86 = { version = "1.18.0", default-features = false, features = ["std", "decoder", "op_code_info", "instr_info"] }
iced-x86 = { version = "1.18.0", default-features = false, features = [
"std",
"decoder",
"op_code_info",
"instr_info",
] }
im = "15.1.0"
im-rc = "15.1.0"
indexmap = "2.1.0"
@ -138,12 +155,17 @@ quote = "1.0.23"
rand = "0.8.5"
regex = "1.7.1"
remove_dir_all = "0.8.1"
reqwest = { version = "0.11.23", default-features = false, features = ["blocking", "rustls-tls"] } # default-features=false removes libopenssl as a dependency on Linux, which might not be available!
reqwest = { version = "0.11.23", default-features = false, features = [
"blocking",
"rustls-tls",
] } # default-features=false removes libopenssl as a dependency on Linux, which might not be available!
rlimit = "0.9.1"
rustyline = { git = "https://github.com/roc-lang/rustyline", rev = "e74333c" }
rustyline-derive = { git = "https://github.com/roc-lang/rustyline", rev = "e74333c" }
schemars = "0.8.12"
serde = { version = "1.0.153", features = ["derive"] } # update roc_std/Cargo.toml on change
serde = { version = "1.0.153", features = [
"derive",
] } # update roc_std/Cargo.toml on change
serde-xml-rs = "0.6.0"
serde_json = "1.0.94" # update roc_std/Cargo.toml on change
serial_test = "1.0.0"
@ -191,7 +213,7 @@ debug = true
[profile.release-with-lto]
inherits = "release"
lto = "thin" # TODO: We could consider full here since this is only used for packaged release on github.
lto = "thin" # TODO: We could consider full here since this is only used for packaged release on github.
[profile.debug-full]
inherits = "dev"

View file

@ -13,15 +13,18 @@ use roc_build::program::{
handle_error_module, handle_loading_problem, standard_load_config, BuildFileError,
BuildOrdering, BuiltFile, CodeGenBackend, CodeGenOptions, DEFAULT_ROC_FILENAME,
};
#[cfg(not(windows))]
use roc_collections::MutMap;
use roc_error_macros::{internal_error, user_error};
use roc_gen_dev::AssemblyBackendMode;
use roc_gen_llvm::llvm::build::LlvmBackendMode;
use roc_load::{ExpectMetadata, Threading};
#[cfg(not(windows))]
use roc_module::symbol::ModuleId;
use roc_mono::ir::OptLevel;
use roc_packaging::cache::RocCacheDir;
use roc_packaging::tarball::Compression;
#[cfg(not(windows))]
use roc_reporting::report::ANSI_STYLE_CODES;
use roc_target::{Architecture, Target};
use std::env;
@ -31,7 +34,9 @@ use std::mem::ManuallyDrop;
use std::os::raw::{c_char, c_int};
use std::path::{Path, PathBuf};
use std::process;
use std::time::{Duration, Instant};
#[cfg(not(windows))]
use std::time::Duration;
use std::time::Instant;
use strum::IntoEnumIterator;
#[cfg(not(target_os = "linux"))]
use tempfile::TempDir;
@ -468,6 +473,7 @@ pub fn test(_matches: &ArgMatches, _target: Target) -> io::Result<i32> {
todo!("running tests does not work on windows right now")
}
#[cfg(not(windows))]
struct ModuleTestResults {
module_id: ModuleId,
failed_count: usize,
@ -516,8 +522,7 @@ pub fn test(matches: &ArgMatches, target: Target) -> io::Result<i32> {
}
let arena = &arena;
// TODO may need to determine this dynamically based on dev builds.
let function_kind = FunctionKind::LambdaSet;
let function_kind = FunctionKind::from_env();
let opt_main_path = matches.get_one::<PathBuf>(FLAG_MAIN);
@ -647,6 +652,7 @@ pub fn test(matches: &ArgMatches, target: Target) -> io::Result<i32> {
}
}
#[cfg(not(windows))]
fn print_test_results(
module_test_results: ModuleTestResults,
sources: &MutMap<ModuleId, (PathBuf, Box<str>)>,
@ -666,6 +672,7 @@ fn print_test_results(
println!("\n{module_name}:\n {test_summary_str}",);
}
#[cfg(not(windows))]
fn test_summary(failed_count: usize, passed_count: usize, tests_duration: Duration) -> String {
let failed_color = if failed_count == 0 {
ANSI_STYLE_CODES.green

View file

@ -126,7 +126,7 @@ fn main() -> io::Result<()> {
.get_one::<String>(FLAG_TARGET)
.and_then(|s| Target::from_str(s).ok())
.unwrap_or_default();
let function_kind = FunctionKind::LambdaSet;
let function_kind = FunctionKind::from_env();
roc_linker::generate_stub_lib(
input_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),

View file

@ -695,20 +695,9 @@ pub fn standard_load_config(
BuildOrdering::AlwaysBuild => ExecutionMode::Executable,
};
// UNSTABLE(lambda-erasure)
let function_kind = if cfg!(debug_assertions) {
if std::env::var("EXPERIMENTAL_ROC_ERASE").is_ok() {
FunctionKind::Erased
} else {
FunctionKind::LambdaSet
}
} else {
FunctionKind::LambdaSet
};
LoadConfig {
target,
function_kind,
function_kind: FunctionKind::from_env(),
render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE,
threading,
@ -1202,8 +1191,7 @@ pub fn check_file<'a>(
let load_config = LoadConfig {
target,
// TODO: we may not want this for just checking.
function_kind: FunctionKind::LambdaSet,
function_kind: FunctionKind::from_env(),
// TODO: expose this from CLI?
render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE,

View file

@ -1,28 +1,223 @@
use bumpalo::{collections::Vec, Bump};
use bumpalo::{
collections::{CollectIn, Vec},
Bump,
};
use roc_collections::{MutMap, ReferenceMatrix};
use roc_module::symbol::Symbol;
use crate::{
inc_dec::Ownership,
ir::{Call, CallType, Expr, Proc, Stmt},
layout::{Builtin, InLayout, LayoutInterner, LayoutRepr},
ir::{Call, CallType, Expr, JoinPointId, Param, Proc, ProcLayout, Stmt},
layout::{Builtin, InLayout, LayoutInterner, LayoutRepr, Niche},
};
#[allow(unused)]
pub(crate) fn infer_borrow_signature<'a>(
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) struct BorrowSignature(u64);
impl std::fmt::Debug for BorrowSignature {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut f = &mut f.debug_struct("BorrowSignature");
for (i, ownership) in self.iter().enumerate() {
f = f.field(&format!("_{i}"), &ownership);
}
f.finish()
}
}
impl BorrowSignature {
fn new(len: usize) -> Self {
assert!(len < 64 - 8);
Self(len as _)
}
fn from_layouts<'a>(
interner: &impl LayoutInterner<'a>,
layouts: impl ExactSizeIterator<Item = &'a InLayout<'a>>,
) -> Self {
let mut signature = BorrowSignature::new(layouts.len());
for (i, layout) in layouts.enumerate() {
signature.set(i, layout_to_ownership(*layout, interner));
}
signature
}
fn len(&self) -> usize {
(self.0 & 0xFF) as usize
}
fn get(&self, index: usize) -> Option<&Ownership> {
if index >= self.len() {
return None;
}
match self.0 & (1 << (index + 8)) {
0 => Some(&Ownership::Borrowed),
_ => Some(&Ownership::Owned),
}
}
fn set(&mut self, index: usize, ownership: Ownership) -> bool {
assert!(index < self.len());
let modified = self.get(index) != Some(&ownership);
let mask = 1 << (index + 8);
match ownership {
Ownership::Owned => self.0 |= mask,
Ownership::Borrowed => self.0 &= !mask,
}
modified
}
pub fn iter(&self) -> impl Iterator<Item = Ownership> + '_ {
let mut i = 0;
std::iter::from_fn(move || {
let value = self.get(i)?;
i += 1;
Some(*value)
})
}
}
impl std::ops::Index<usize> for BorrowSignature {
type Output = Ownership;
fn index(&self, index: usize) -> &Self::Output {
self.get(index).unwrap()
}
}
pub(crate) struct BorrowSignatures<'a> {
pub(crate) procs: MutMap<(Symbol, ProcLayout<'a>), BorrowSignature>,
}
pub(crate) fn infer_borrow_signatures<'a>(
arena: &'a Bump,
interner: &impl LayoutInterner<'a>,
proc: &'a Proc<'a>,
) -> &'a [Ownership] {
let mut state = State::new(arena, interner, proc);
state.inspect_stmt(&proc.body);
procs: &MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
) -> BorrowSignatures<'a> {
let mut borrow_signatures: BorrowSignatures = BorrowSignatures {
procs: procs
.iter()
.map(|(_key, proc)| {
let key = (proc.name.name(), proc.proc_layout(arena));
let signature = BorrowSignature::from_layouts(interner, key.1.arguments.iter());
(key, signature)
})
.collect(),
};
// for every proc (by index) a collection of its join points
let mut join_points: Vec<_> = std::iter::repeat_with(MutMap::default)
.take(procs.len())
.collect_in(arena);
// next we first partition the functions into strongly connected components, then do a
// topological sort on these components, finally run the fix-point borrow analysis on each
// component (in top-sorted order, from primitives (std-lib) to main)
let matrix = construct_reference_matrix(arena, procs);
let sccs = matrix.strongly_connected_components_all();
let mut join_point_stack = Vec::new_in(arena);
let mut proc_join_points = MutMap::default();
for (group, _) in sccs.groups() {
// This is a fixed-point analysis
//
// all functions initially own all their parameters
// through a series of checks and heuristics, some arguments are set to borrowed
// when that doesn't lead to conflicts the change is kept, otherwise it may be reverted
//
// when the signatures no longer change, the analysis stops and returns the signatures
loop {
let mut modified = false;
for index in group.iter_ones() {
let (_, proc) = procs.iter().nth(index).unwrap();
let key = (proc.name.name(), proc.proc_layout(arena));
if proc.args.is_empty() {
continue;
}
std::mem::swap(&mut proc_join_points, &mut join_points[index]);
let mut state = State {
args: proc.args,
borrow_signature: *borrow_signatures.procs.get(&key).unwrap(),
join_point_stack,
join_points: proc_join_points,
modified: false,
};
state.inspect_stmt(interner, &mut borrow_signatures, &proc.body);
// did any proc signature get modified?
//
// NOTE: this does not directly include updates to join point signatures. The
// assumption is that a relevant change in join point signature is immediately
// (i.e. no fixpoint is required) reflected in the proc signature.
//
// TODO: this is a load-bearing assert! There must be UB somewhere, removing this
// assert causes the code to run into an infinite loop that terminates when the
// memory on the system is exhausted.
assert_eq!(
state.modified,
borrow_signatures
.procs
.insert(key, state.borrow_signature)
.unwrap()
!= state.borrow_signature
);
modified |= state.modified;
proc_join_points = state.join_points;
std::mem::swap(&mut proc_join_points, &mut join_points[index]);
join_point_stack = state.join_point_stack;
join_point_stack.clear();
}
if !modified {
break;
}
}
}
borrow_signatures
}
#[allow(unused)]
fn infer_borrow_signature<'a>(
arena: &'a Bump,
interner: &impl LayoutInterner<'a>,
borrow_signatures: &'a mut BorrowSignatures<'a>,
proc: &Proc<'a>,
) -> BorrowSignature {
let mut state = State::new(arena, interner, borrow_signatures, proc);
state.inspect_stmt(interner, borrow_signatures, &proc.body);
state.borrow_signature
}
struct State<'a> {
struct State<'state, 'arena> {
/// Argument symbols with a layout of `List *` or `Str`, i.e. the layouts
/// for which borrow inference might decide to pass as borrowed
args: &'a [(InLayout<'a>, Symbol)],
borrow_signature: &'a mut [Ownership],
args: &'state [(InLayout<'arena>, Symbol)],
borrow_signature: BorrowSignature,
join_point_stack: Vec<'arena, (JoinPointId, &'state [Param<'arena>])>,
join_points: MutMap<JoinPointId, BorrowSignature>,
modified: bool,
}
fn layout_to_ownership<'a>(
@ -30,7 +225,8 @@ fn layout_to_ownership<'a>(
interner: &impl LayoutInterner<'a>,
) -> Ownership {
match interner.get_repr(in_layout) {
LayoutRepr::Builtin(Builtin::Str | Builtin::List(_)) => Ownership::Borrowed,
LayoutRepr::Builtin(Builtin::Str) => Ownership::Borrowed,
LayoutRepr::Builtin(Builtin::List(_)) => Ownership::Borrowed,
LayoutRepr::LambdaSet(inner) => {
layout_to_ownership(inner.runtime_representation(), interner)
}
@ -38,33 +234,61 @@ fn layout_to_ownership<'a>(
}
}
impl<'a> State<'a> {
fn new(arena: &'a Bump, interner: &impl LayoutInterner<'a>, proc: &'a Proc<'a>) -> Self {
let borrow_signature = Vec::from_iter_in(
proc.args
.iter()
.map(|(in_layout, _)| layout_to_ownership(*in_layout, interner)),
arena,
)
.into_bump_slice_mut();
impl<'state, 'a> State<'state, 'a> {
fn new(
arena: &'a Bump,
interner: &impl LayoutInterner<'a>,
borrow_signatures: &mut BorrowSignatures<'a>,
proc: &Proc<'a>,
) -> Self {
let key = (proc.name.name(), proc.proc_layout(arena));
// initialize the borrow signature based on the layout if first time
let borrow_signature = borrow_signatures
.procs
.entry(key)
.or_insert_with(|| BorrowSignature::from_layouts(interner, key.1.arguments.iter()));
Self {
args: proc.args,
borrow_signature,
borrow_signature: *borrow_signature,
join_point_stack: Vec::new_in(arena),
join_points: MutMap::default(),
modified: false,
}
}
/// Mark the given argument symbol as Owned if the symbol participates in borrow inference
///
/// Currently argument symbols participate if `layout_to_ownership` returns `Borrowed` for their layout.
fn mark_owned(&mut self, symbol: Symbol) {
if let Some(index) = self.args.iter().position(|(_, s)| *s == symbol) {
self.borrow_signature[index] = Ownership::Owned;
self.modified |= self.borrow_signature.set(index, Ownership::Owned);
}
// theory: relevant modification to a join point borrow signature is always immediately
// reflected in the borrow signature of its surrounding function. Therefore we don't need
// to include changes to join point signatures in the `modified` flag.
for (id, params) in &self.join_point_stack {
if let Some(index) = params.iter().position(|p| p.symbol == symbol) {
self.join_points
.get_mut(id)
.unwrap()
.set(index, Ownership::Owned);
}
}
}
fn inspect_stmt(&mut self, stmt: &'a Stmt<'a>) {
fn inspect_stmt(
&mut self,
interner: &impl LayoutInterner<'a>,
borrow_signatures: &mut BorrowSignatures<'a>,
stmt: &Stmt<'a>,
) {
match stmt {
Stmt::Let(_, expr, _, stmt) => {
self.inspect_expr(expr);
self.inspect_stmt(stmt);
self.inspect_expr(borrow_signatures, expr);
self.inspect_stmt(interner, borrow_signatures, stmt);
}
Stmt::Switch {
branches,
@ -72,48 +296,110 @@ impl<'a> State<'a> {
..
} => {
for (_, _, stmt) in branches.iter() {
self.inspect_stmt(stmt);
self.inspect_stmt(interner, borrow_signatures, stmt);
}
self.inspect_stmt(default_branch.1);
self.inspect_stmt(interner, borrow_signatures, default_branch.1);
}
Stmt::Ret(_) => todo!(),
Stmt::Refcounting(_, _) => todo!(),
Stmt::Expect { .. } | Stmt::ExpectFx { .. } => {
// TODO do we rely on values being passed by-value here?
// it would be better to pass by-reference in general
Stmt::Ret(s) => {
// to return a value we must own it
// (with the current implementation anyway)
self.mark_owned(*s);
}
Stmt::Dbg { .. } => {
// TODO do we rely on values being passed by-value here?
// it would be better to pass by-reference in general
Stmt::Refcounting(_, _) => unreachable!("not inserted yet"),
Stmt::Expect { remainder, .. } | Stmt::ExpectFx { remainder, .. } => {
// based on my reading of inc_dec.rs, expect borrows the symbols
self.inspect_stmt(interner, borrow_signatures, remainder);
}
Stmt::Dbg { remainder, .. } => {
// based on my reading of inc_dec.rs, expect borrows the symbol
self.inspect_stmt(interner, borrow_signatures, remainder);
}
Stmt::Join {
body, remainder, ..
id,
parameters,
body,
remainder,
} => {
self.inspect_stmt(body);
self.inspect_stmt(remainder);
// insert the default borrow signature if we're seeing this JP for the first time
self.join_points.entry(*id).or_insert_with(|| {
BorrowSignature::from_layouts(interner, parameters.iter().map(|p| &p.layout))
});
// within the body, changes to ownership for symbols introduced by this join point
// must be propagated. An example is
//
// ```roc
// writeIndents = \buf, indents ->
// if indents <= 0 then
// buf
// else
// buf
// |> Str.concat " "
// |> writeIndents (indents - 1)
// ```
//
// where the mono will jump immediately to a (recursive) join point. The fact that
// the `buf` value is owned within the join point for efficient concatentation must
// be propagated to `writeIndents`' function argument
self.join_point_stack.push((*id, parameters));
self.inspect_stmt(interner, borrow_signatures, body);
self.join_point_stack.pop().unwrap();
self.inspect_stmt(interner, borrow_signatures, remainder);
}
Stmt::Jump(_, _) | Stmt::Crash(_, _) => { /* not relevant for ownership */ }
Stmt::Jump(id, arguments) => {
let borrow_signature = match self.join_points.get(id) {
Some(s) => *s,
None => unreachable!("no borrow signature for join point {id:?} layout"),
};
for (argument, ownership) in arguments.iter().zip(borrow_signature.iter()) {
if let Ownership::Owned = ownership {
self.mark_owned(*argument);
}
}
}
Stmt::Crash(_, _) => { /* not relevant for ownership */ }
}
}
fn inspect_expr(&mut self, expr: &'a Expr<'a>) {
fn inspect_expr(&mut self, borrow_signatures: &mut BorrowSignatures<'a>, expr: &Expr<'a>) {
if let Expr::Call(call) = expr {
self.inspect_call(call)
self.inspect_call(borrow_signatures, call)
}
}
fn inspect_call(&mut self, call: &'a Call<'a>) {
fn inspect_call(&mut self, borrow_signatures: &mut BorrowSignatures<'a>, call: &Call<'a>) {
let Call {
call_type,
arguments,
} = call;
match call_type {
CallType::ByName { name: _, .. } => {
// TODO ownership should depend on the borrow signature of the called function
for argument in arguments.iter() {
self.mark_owned(*argument)
CallType::ByName {
name,
arg_layouts,
ret_layout,
..
} => {
let proc_layout = ProcLayout {
arguments: arg_layouts,
result: *ret_layout,
niche: Niche::NONE,
};
let borrow_signature =
match borrow_signatures.procs.get(&(name.name(), proc_layout)) {
Some(s) => s,
None => unreachable!("no borrow signature for {name:?} layout"),
};
for (argument, ownership) in arguments.iter().zip(borrow_signature.iter()) {
if let Ownership::Owned = ownership {
self.mark_owned(*argument);
}
}
}
CallType::LowLevel { op, .. } => {
@ -134,3 +420,110 @@ impl<'a> State<'a> {
}
}
}
fn construct_reference_matrix<'a>(
arena: &'a Bump,
procs: &MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
) -> ReferenceMatrix {
let mut matrix = ReferenceMatrix::new(procs.len());
let mut call_info = CallInfo::new(arena);
for (row, proc) in procs.values().enumerate() {
call_info.clear();
call_info.stmt(arena, &proc.body);
for key in call_info.keys.iter() {
// the same symbol can be in `keys` multiple times (with different layouts)
for (col, (k, _)) in procs.keys().enumerate() {
if k == key {
matrix.set_row_col(row, col, true);
}
}
}
}
matrix
}
struct CallInfo<'a> {
keys: Vec<'a, Symbol>,
}
impl<'a> CallInfo<'a> {
fn new(arena: &'a Bump) -> Self {
CallInfo {
keys: Vec::new_in(arena),
}
}
fn clear(&mut self) {
self.keys.clear()
}
fn call(&mut self, call: &crate::ir::Call<'a>) {
use crate::ir::CallType::*;
use crate::ir::HigherOrderLowLevel;
use crate::ir::PassedFunction;
match call.call_type {
ByName { name, .. } => {
self.keys.push(name.name());
}
ByPointer { .. } => {
// nothing to be done
}
Foreign { .. } => {}
LowLevel { .. } => {}
HigherOrder(HigherOrderLowLevel {
passed_function: PassedFunction { name, .. },
..
}) => {
self.keys.push(name.name());
}
}
}
fn stmt(&mut self, arena: &'a Bump, stmt: &Stmt<'a>) {
use Stmt::*;
let mut stack = bumpalo::vec![in arena; stmt];
while let Some(stmt) = stack.pop() {
match stmt {
Join {
remainder: v,
body: b,
..
} => {
stack.push(v);
stack.push(b);
}
Let(_, expr, _, cont) => {
if let Expr::Call(call) = expr {
self.call(call);
}
stack.push(cont);
}
Switch {
branches,
default_branch,
..
} => {
stack.extend(branches.iter().map(|b| &b.2));
stack.push(default_branch.1);
}
Dbg { remainder, .. } => stack.push(remainder),
Expect { remainder, .. } => stack.push(remainder),
ExpectFx { remainder, .. } => stack.push(remainder),
Refcounting(_, _) => unreachable!("these have not been introduced yet"),
Ret(_) | Jump(_, _) | Crash(..) => {
// these are terminal, do nothing
}
}
}
}
}

View file

@ -20,7 +20,7 @@ use crate::{
BranchInfo, Call, CallType, Expr, HigherOrderLowLevel, JoinPointId, ListLiteralElement,
ModifyRc, Param, Proc, ProcLayout, Stmt,
},
layout::{InLayout, LayoutInterner, STLayoutInterner},
layout::{InLayout, LayoutInterner, Niche, STLayoutInterner},
low_level::HigherOrder,
};
@ -30,8 +30,12 @@ Insert the reference count operations for procedures.
pub fn insert_inc_dec_operations<'a>(
arena: &'a Bump,
layout_interner: &STLayoutInterner<'a>,
procedures: &mut HashMap<(Symbol, ProcLayout), Proc<'a>, BuildHasherDefault<WyHash>>,
procedures: &mut HashMap<(Symbol, ProcLayout<'a>), Proc<'a>, BuildHasherDefault<WyHash>>,
) {
let borrow_signatures =
crate::borrow::infer_borrow_signatures(arena, layout_interner, procedures);
let borrow_signatures = arena.alloc(borrow_signatures);
// All calls to lowlevels are wrapped in another function to help with type inference and return/parameter layouts.
// But this lowlevel might get inlined into the caller of the wrapper and thus removing any reference counting operations.
// Thus, these rc operations are performed on the caller of the wrapper instead, and we skip rc on the lowlevel.
@ -43,15 +47,13 @@ pub fn insert_inc_dec_operations<'a>(
LowLevelWrapperType::NotALowLevelWrapper
) {
let symbol_rc_types_env = SymbolRcTypesEnv::from_layout_interner(layout_interner);
insert_inc_dec_operations_proc(arena, symbol_rc_types_env, proc);
insert_inc_dec_operations_proc(arena, symbol_rc_types_env, borrow_signatures, proc);
}
}
}
/**
Enum indicating whether a symbol should be reference counted or not.
This includes layouts that themselves can be stack allocated but that contain a heap allocated item.
*/
/// Enum indicating whether a symbol should be reference counted or not.
/// This includes layouts that themselves can be stack allocated but that contain a heap allocated item.
#[derive(Copy, Clone)]
enum VarRcType {
ReferenceCounted,
@ -256,6 +258,8 @@ struct RefcountEnvironment<'v> {
// The Koka implementation assumes everything that is not owned to be borrowed.
symbols_ownership: SymbolsOwnership,
jointpoint_closures: MutMap<JoinPointId, JoinPointConsumption>,
// inferred borrow signatures of roc functions
borrow_signatures: &'v crate::borrow::BorrowSignatures<'v>,
}
impl<'v> RefcountEnvironment<'v> {
@ -306,9 +310,13 @@ impl<'v> RefcountEnvironment<'v> {
Add a symbol to the environment if it is reference counted.
*/
fn add_symbol(&mut self, symbol: Symbol) {
self.add_symbol_with(symbol, Ownership::Owned)
}
fn add_symbol_with(&mut self, symbol: Symbol, ownership: Ownership) {
match self.get_symbol_rc_type(&symbol) {
VarRcType::ReferenceCounted => {
self.symbols_ownership.insert(symbol, Ownership::Owned);
self.symbols_ownership.insert(symbol, ownership);
}
VarRcType::NotReferenceCounted => {
// If this symbol is not reference counted, we don't need to do anything.
@ -403,6 +411,7 @@ impl<'v> RefcountEnvironment<'v> {
fn insert_inc_dec_operations_proc<'a>(
arena: &'a Bump,
mut symbol_rc_types_env: SymbolRcTypesEnv<'a, '_>,
borrow_signatures: &'a crate::borrow::BorrowSignatures<'a>,
proc: &mut Proc<'a>,
) {
// Clone the symbol_rc_types_env and insert the symbols in the current procedure.
@ -413,19 +422,26 @@ fn insert_inc_dec_operations_proc<'a>(
symbols_rc_types: &symbol_rc_types_env.symbols_rc_type,
symbols_ownership: MutMap::default(),
jointpoint_closures: MutMap::default(),
borrow_signatures,
};
// Add all arguments to the environment (if they are reference counted)
let proc_symbols = proc.args.iter().map(|(_layout, symbol)| symbol);
for symbol in proc_symbols.clone() {
environment.add_symbol(*symbol);
let borrow_signature = borrow_signatures
.procs
.get(&(proc.name.name(), proc.proc_layout(arena)))
.unwrap();
for ((_, symbol), ownership) in proc.args.iter().zip(borrow_signature.iter()) {
environment.add_symbol_with(*symbol, ownership);
}
// Update the body with reference count statements.
let new_body = insert_refcount_operations_stmt(arena, &mut environment, &proc.body);
// Insert decrement statements for unused parameters (which are still marked as owned).
let rc_proc_symbols = proc_symbols
let rc_proc_symbols = proc
.args
.iter()
.map(|(_layout, symbol)| symbol)
.filter(|symbol| environment.symbols_ownership.contains_key(symbol))
.copied()
.collect_in::<Vec<_>>(arena);
@ -718,12 +734,11 @@ fn insert_refcount_operations_stmt<'v, 'a>(
body,
remainder,
} => {
// Assuming that the values in the closure of the body of this jointpoint are already bound.
// Assuming that all symbols are still owned. (So that we can determine what symbols got consumed in the join point.)
debug_assert!(environment
.symbols_ownership
.iter()
.all(|(_, ownership)| ownership.is_owned()));
// NOTE: Assuming that the values in the closure of the body of this jointpoint are already bound.
// NOTE: this code previously assumed that all symbols bound by the join point are owned.
// With borrow inference, that is no longer true but the analysis here _should_ mirror
// borrow inference and yield the same result.
let mut body_env = environment.clone();
@ -978,12 +993,42 @@ fn insert_refcount_operations_binding<'a>(
call_type,
}) => {
match call_type.clone().replace_lowlevel_wrapper() {
// A by name call refers to a normal function call.
// Normal functions take all their parameters as owned, so we can mark them all as such.
CallType::ByName { .. } => {
let new_let = new_let!(stmt);
CallType::ByName {
name,
arg_layouts,
ret_layout,
..
} => {
let proc_layout = ProcLayout {
arguments: arg_layouts,
result: ret_layout,
niche: Niche::NONE,
};
inc_owned!(arguments.iter().copied(), new_let)
let borrow_signature = match environment
.borrow_signatures
.procs
.get(&(name.name(), proc_layout))
{
Some(s) => s,
None => unreachable!("no borrow signature for {name:?} layout"),
};
let owned_arguments = arguments
.iter()
.copied()
.zip(borrow_signature.iter())
.filter_map(|(symbol, ownership)| ownership.is_owned().then_some(symbol));
let borrowed_arguments = arguments
.iter()
.copied()
.zip(borrow_signature.iter())
.filter_map(|(symbol, ownership)| {
ownership.is_borrowed().then_some(symbol)
});
let new_stmt = dec_borrowed!(borrowed_arguments, stmt);
let new_let = new_let!(new_stmt);
inc_owned!(owned_arguments, new_let)
}
// A normal Roc function call, but we don't actually know where its target is.
// As such, we assume that it takes all parameters as owned, as will the function

View file

@ -396,6 +396,16 @@ impl<'a> Proc<'a> {
w.push(b'\n');
String::from_utf8(w).unwrap()
}
pub fn proc_layout(&self, arena: &'a Bump) -> ProcLayout<'a> {
let args = Vec::from_iter_in(self.args.iter().map(|(a, _)| *a), arena);
ProcLayout {
arguments: args.into_bump_slice(),
result: self.ret_layout,
niche: Niche::NONE,
}
}
}
/// A host-exposed function must be specialized; it's a seed for subsequent specializations

View file

@ -3362,32 +3362,36 @@ fn layout_from_flat_type<'a>(
}
}
sortables.sort_by(|(label1, layout1), (label2, layout2)| {
cmp_fields(&env.cache.interner, label1, *layout1, label2, *layout2)
});
let ordered_field_names = Vec::from_iter_in(
sortables
.iter()
.map(|(label, _)| &*arena.alloc_str(label.as_str())),
arena,
)
.into_bump_slice();
let semantic = SemanticRepr::record(ordered_field_names);
let repr = if sortables.len() == 1 {
// If the record has only one field that isn't zero-sized,
// unwrap it.
let inner_repr = sortables.pop().unwrap().1;
inner_repr.newtype()
if sortables.is_empty() {
Cacheable(Ok(Layout::UNIT), criteria)
} else {
let layouts = Vec::from_iter_in(sortables.into_iter().map(|t| t.1), arena);
LayoutRepr::Struct(layouts.into_bump_slice()).direct()
};
sortables.sort_by(|(label1, layout1), (label2, layout2)| {
cmp_fields(&env.cache.interner, label1, *layout1, label2, *layout2)
});
let result = Ok(env.cache.put_in(Layout { repr, semantic }));
let ordered_field_names = Vec::from_iter_in(
sortables
.iter()
.map(|(label, _)| &*arena.alloc_str(label.as_str())),
arena,
)
.into_bump_slice();
let semantic = SemanticRepr::record(ordered_field_names);
Cacheable(result, criteria)
let repr = if sortables.len() == 1 {
// If the record has only one field that isn't zero-sized,
// unwrap it.
let inner_repr = sortables.pop().unwrap().1;
inner_repr.newtype()
} else {
let layouts = Vec::from_iter_in(sortables.into_iter().map(|t| t.1), arena);
LayoutRepr::struct_(layouts.into_bump_slice()).direct()
};
let result = Ok(env.cache.put_in(Layout { repr, semantic }));
Cacheable(result, criteria)
}
}
Tuple(elems, ext_var) => {
let mut criteria = CACHEABLE;

View file

@ -63,9 +63,14 @@ pub fn loc_pattern_help<'a>() -> impl Parser<'a, Loc<Pattern<'a>>, EPattern<'a>>
},
Ok((_, pattern_as, state)) => {
let region = Region::span_across(&pattern.region, &pattern_as.identifier.region);
let pattern = arena
.alloc(pattern.value)
.with_spaces_after(pattern_spaces, pattern.region);
let mut pattern = pattern;
if !pattern_spaces.is_empty() {
pattern = arena
.alloc(pattern.value)
.with_spaces_after(pattern_spaces, pattern.region)
}
let as_pattern = Pattern::As(arena.alloc(pattern), pattern_as);
Ok((MadeProgress, Loc::at(region, as_pattern), state))

View file

@ -6,3 +6,17 @@ pub enum FunctionKind {
/// Function values are erased, no kind is introduced.
Erased,
}
impl FunctionKind {
pub fn from_env() -> Self {
if cfg!(debug_assertions) {
if std::env::var("EXPERIMENTAL_ROC_ERASE").is_ok() {
FunctionKind::Erased
} else {
FunctionKind::LambdaSet
}
} else {
FunctionKind::LambdaSet
}
}
}

View file

@ -75,6 +75,7 @@ procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
let List.595 : [C U64, C U64] = TagId(1) List.492;
ret List.595;
in
inc #Derived_gen.0;
jump List.594 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4;
procedure Num.22 (#Attr.2, #Attr.3):
@ -92,7 +93,6 @@ procedure Num.77 (#Attr.2, #Attr.3):
procedure Test.1 (Test.2):
let Test.13 : U64 = 0i64;
let Test.14 : {} = Struct {};
inc Test.2;
let Test.3 : U64 = CallByName List.26 Test.2 Test.13 Test.14;
let Test.12 : U64 = 0i64;
let Test.10 : Int1 = CallByName Bool.11 Test.3 Test.12;

View file

@ -25,6 +25,7 @@ procedure List.92 (#Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.11;
jump List.577 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15;
procedure Num.22 (#Attr.2, #Attr.3):
@ -163,4 +164,5 @@ procedure Test.0 ():
let Test.35 : List [] = Array [];
let Test.36 : {} = Struct {};
let Test.34 : [<r>C {}, C *self {{}, []}] = CallByName Test.6 Test.35 Test.36;
dec Test.35;
ret Test.34;

View file

@ -8,11 +8,9 @@ procedure List.2 (List.108, List.109):
if List.584 then
let List.586 : Str = CallByName List.66 List.108 List.109;
inc List.586;
dec List.108;
let List.585 : [C {}, C Str] = TagId(1) List.586;
ret List.585;
else
dec List.108;
let List.583 : {} = Struct {};
let List.582 : [C {}, C Str] = TagId(0) List.583;
ret List.582;
@ -102,6 +100,7 @@ procedure Test.2 (Test.6):
let Test.24 : {} = Struct {};
let Test.23 : List Str = CallByName List.5 Test.9 Test.24;
let Test.21 : [C {}, C Str] = CallByName List.9 Test.23;
dec Test.23;
let Test.22 : Str = "foo";
let Test.20 : Str = CallByName Result.5 Test.21 Test.22;
ret Test.20;

View file

@ -29,6 +29,7 @@ procedure List.92 (#Derived_gen.5, #Derived_gen.6, #Derived_gen.7, #Derived_gen.
dec List.163;
ret List.164;
in
inc #Derived_gen.5;
jump List.577 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8 #Derived_gen.9;
procedure Num.22 (#Attr.2, #Attr.3):
@ -162,6 +163,7 @@ procedure Test.0 ():
let Test.23 : Int1 = CallByName Bool.2;
let Test.22 : Int1 = CallByName Test.1 Test.23;
let Test.16 : [<rnw><null>, C *self Int1, C *self Int1] = CallByName List.18 Test.20 Test.21 Test.22;
dec Test.20;
let Test.18 : Str = "hello";
let Test.19 : U8 = GetTagId Test.16;
switch Test.19:

View file

@ -5,9 +5,11 @@ procedure Bool.2 ():
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.319 : Str = "\"";
let Inspect.318 : Str = CallByName Inspect.59 Inspect.247 Inspect.319;
dec Inspect.319;
let Inspect.314 : Str = CallByName Inspect.59 Inspect.318 Inspect.245;
let Inspect.315 : Str = "\"";
let Inspect.313 : Str = CallByName Inspect.59 Inspect.314 Inspect.315;
dec Inspect.315;
ret Inspect.313;
procedure Inspect.30 (Inspect.143):
@ -31,11 +33,11 @@ procedure Inspect.5 (Inspect.146):
let Inspect.305 : {} = Struct {};
let Inspect.304 : Str = CallByName Inspect.35 Inspect.305;
let Inspect.303 : Str = CallByName Inspect.246 Inspect.304 Inspect.308;
dec Inspect.308;
ret Inspect.303;
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.317 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.317;
procedure Inspect.60 (Inspect.298):

View file

@ -1,9 +1,11 @@
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.319 : Str = "\"";
let Inspect.318 : Str = CallByName Inspect.59 Inspect.247 Inspect.319;
dec Inspect.319;
let Inspect.314 : Str = CallByName Inspect.59 Inspect.318 Inspect.245;
let Inspect.315 : Str = "\"";
let Inspect.313 : Str = CallByName Inspect.59 Inspect.314 Inspect.315;
dec Inspect.315;
ret Inspect.313;
procedure Inspect.30 (Inspect.143):
@ -27,11 +29,11 @@ procedure Inspect.5 (Inspect.146):
let Inspect.305 : {} = Struct {};
let Inspect.304 : Str = CallByName Inspect.35 Inspect.305;
let Inspect.303 : Str = CallByName Inspect.246 Inspect.304 Inspect.308;
dec Inspect.308;
ret Inspect.303;
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.317 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.317;
procedure Inspect.60 (Inspect.298):

View file

@ -7,11 +7,9 @@ procedure List.2 (List.108, List.109):
let List.576 : Int1 = CallByName Num.22 List.109 List.580;
if List.576 then
let List.578 : {} = CallByName List.66 List.108 List.109;
dec List.108;
let List.577 : [C {}, C {}] = TagId(1) List.578;
ret List.577;
else
dec List.108;
let List.575 : {} = Struct {};
let List.574 : [C {}, C {}] = TagId(0) List.575;
ret List.574;
@ -29,7 +27,6 @@ procedure Num.22 (#Attr.2, #Attr.3):
ret Num.279;
procedure Test.2 (Test.5):
dec Test.5;
let Test.17 : Str = "bar";
ret Test.17;
@ -38,6 +35,7 @@ procedure Test.0 ():
joinpoint Test.15 Test.3:
let Test.13 : U64 = 0i64;
let Test.6 : [C {}, C {}] = CallByName List.2 Test.3 Test.13;
dec Test.3;
let Test.10 : U8 = 1i64;
let Test.11 : U8 = GetTagId Test.6;
let Test.12 : Int1 = lowlevel Eq Test.10 Test.11;
@ -45,6 +43,7 @@ procedure Test.0 ():
let Test.4 : {} = UnionAtIndex (Id 1) (Index 0) Test.6;
let Test.8 : Str = "foo";
let Test.7 : Str = CallByName Test.2 Test.8;
dec Test.8;
ret Test.7;
else
let Test.9 : Str = "bad!";

View file

@ -9,6 +9,7 @@ procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6];
let #Derived_gen.4 : List {Str, Str} = CallByName Test.21 #Derived_gen.5;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.3 #Derived_gen.4 #Derived.4;
dec #Derived_gen.4;
ret #Derived_gen.3;
procedure #Derived.5 (#Derived.6):
@ -22,6 +23,7 @@ procedure #Derived.7 (#Derived.8, #Derived.9, #Derived.6):
let #Derived_gen.15 : List {Str, Str} = Array [#Derived_gen.16];
let #Derived_gen.14 : List {Str, Str} = CallByName Test.21 #Derived_gen.15;
let #Derived_gen.13 : List U8 = CallByName Encode.24 #Derived.8 #Derived_gen.14 #Derived.9;
dec #Derived_gen.14;
ret #Derived_gen.13;
procedure Encode.23 (Encode.98):
@ -125,6 +127,7 @@ procedure List.92 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.29;
jump List.603 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33;
procedure List.92 (#Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_gen.40, #Derived_gen.41):
@ -141,6 +144,7 @@ procedure List.92 (#Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.37;
jump List.577 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39 #Derived_gen.40 #Derived_gen.41;
procedure Num.127 (#Attr.2):

View file

@ -9,6 +9,7 @@ procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6];
let #Derived_gen.4 : List {Str, Str} = CallByName Test.21 #Derived_gen.5;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.3 #Derived_gen.4 #Derived.4;
dec #Derived_gen.4;
ret #Derived_gen.3;
procedure Encode.23 (Encode.98):
@ -84,6 +85,7 @@ procedure List.92 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.13;
jump List.577 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17;
procedure Num.127 (#Attr.2):

View file

@ -16,6 +16,7 @@ procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6, #Derived_gen.7];
let #Derived_gen.4 : List {Str, Str} = CallByName Test.21 #Derived_gen.5;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.3 #Derived_gen.4 #Derived.4;
dec #Derived_gen.4;
ret #Derived_gen.3;
procedure Encode.23 (Encode.98):
@ -91,6 +92,7 @@ procedure List.92 (#Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.17;
jump List.577 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21;
procedure Num.127 (#Attr.2):

View file

@ -90,6 +90,7 @@ procedure List.92 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.13;
jump List.577 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17;
procedure Num.127 (#Attr.2):
@ -145,6 +146,7 @@ procedure Test.2 ():
ret Test.258;
procedure Test.20 (Test.58, Test.59):
inc Test.58;
let Test.265 : {List Str, {}} = Struct {Test.58, Test.59};
let Test.264 : {List Str, {}} = CallByName Encode.23 Test.265;
ret Test.264;
@ -158,6 +160,7 @@ procedure Test.23 (Test.77, Test.78):
let Test.284 : Str = CallByName Test.19 Test.77;
let Test.261 : List Str = CallByName List.13 Test.78 Test.284;
let Test.260 : {List Str, {}} = CallByName Test.22 Test.261;
dec Test.261;
ret Test.260;
procedure Test.3 (Test.48, Test.49, Test.50):
@ -187,6 +190,7 @@ procedure Test.60 (Test.61, Test.266, #Attr.12):
let Test.275 : U64 = CallByName List.6 Test.58;
let Test.62 : List U8 = CallByName Test.3 Test.61 Test.274 Test.275;
let Test.268 : List U8 = CallByName List.18 Test.58 Test.62 Test.59;
dec Test.58;
ret Test.268;
procedure Test.63 (Test.64, Test.65, Test.59):

View file

@ -93,6 +93,7 @@ procedure List.92 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.14;
jump List.577 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18;
procedure Num.127 (#Attr.2):
@ -148,6 +149,7 @@ procedure Test.2 ():
ret Test.258;
procedure Test.20 (Test.58, Test.59):
inc Test.58;
let Test.266 : {List Str, {}} = Struct {Test.58, Test.59};
let Test.265 : {List Str, {}} = CallByName Encode.23 Test.266;
ret Test.265;
@ -161,6 +163,7 @@ procedure Test.23 (Test.77, Test.78):
let Test.285 : Str = CallByName Test.19 Test.77;
let Test.262 : List Str = CallByName List.13 Test.78 Test.285;
let Test.261 : {List Str, {}} = CallByName Test.22 Test.262;
dec Test.262;
ret Test.261;
procedure Test.3 (Test.48, Test.49, Test.50):
@ -190,6 +193,7 @@ procedure Test.60 (Test.61, Test.267, #Attr.12):
let Test.276 : U64 = CallByName List.6 Test.58;
let Test.62 : List U8 = CallByName Test.3 Test.61 Test.275 Test.276;
let Test.269 : List U8 = CallByName List.18 Test.58 Test.62 Test.59;
dec Test.58;
ret Test.269;
procedure Test.63 (Test.64, Test.65, Test.59):

View file

@ -1,9 +1,9 @@
procedure Test.1 (Test.2, Test.3):
dec Test.3;
ret Test.2;
procedure Test.0 ():
let Test.5 : List I64 = Array [1i64, 2i64, 3i64];
let Test.6 : List I64 = Array [3i64, 2i64, 1i64];
let Test.4 : List I64 = CallByName Test.1 Test.5 Test.6;
dec Test.6;
ret Test.4;

View file

@ -48,6 +48,7 @@ procedure Dict.10 (Dict.724, Dict.179, Dict.180):
let #Derived_gen.68 : List {U32, U32} = StructAtIndex 0 Dict.724;
dec #Derived_gen.68;
let Dict.1101 : {Str, Int1} = CallByName List.18 Dict.178 Dict.179 Dict.180;
dec Dict.178;
ret Dict.1101;
procedure Dict.12 (Dict.151):
@ -148,11 +149,11 @@ procedure Dict.38 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
let Dict.239 : U32 = CallByName Dict.48 Dict.224;
jump Dict.736 Dict.221 Dict.222 Dict.238 Dict.239 Dict.225 Dict.226 Dict.227 Dict.228 Dict.229;
in
inc #Derived_gen.4;
jump Dict.736 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8;
procedure Dict.398 (Dict.399, Dict.840, Dict.401, Dict.397):
let Dict.400 : Str = StructAtIndex 0 Dict.840;
inc Dict.399;
let Dict.845 : {U64, U32} = CallByName Dict.65 Dict.399 Dict.400 Dict.397;
let Dict.402 : U64 = StructAtIndex 0 Dict.845;
let Dict.403 : U32 = StructAtIndex 1 Dict.845;
@ -222,7 +223,6 @@ procedure Dict.59 (Dict.719):
let Dict.877 : U64 = CallByName Dict.47;
let Dict.836 : Int1 = CallByName Bool.7 Dict.377 Dict.877;
if Dict.836 then
inc Dict.376;
let Dict.876 : U8 = 1i64;
let Dict.380 : U8 = CallByName Num.75 Dict.379 Dict.876;
let Dict.855 : {List {U32, U32}, U64} = CallByName Dict.60 Dict.380 Dict.378;
@ -298,6 +298,7 @@ procedure Dict.66 (#Derived_gen.40, #Derived_gen.41, #Derived_gen.42):
let Dict.848 : {U64, U32} = Struct {Dict.411, Dict.412};
ret Dict.848;
in
inc #Derived_gen.40;
jump Dict.847 #Derived_gen.40 #Derived_gen.41 #Derived_gen.42;
procedure Dict.67 (#Derived_gen.28, #Derived_gen.29, #Derived_gen.30):
@ -416,6 +417,7 @@ procedure Dict.8 (Dict.210, Dict.211, Dict.212):
let Dict.219 : U32 = CallByName Dict.70 Dict.218;
let Dict.220 : U64 = CallByName Dict.71 Dict.218 Dict.217;
let Dict.735 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.38 Dict.213 Dict.214 Dict.220 Dict.219 Dict.211 Dict.212 Dict.215 Dict.216 Dict.217;
dec Dict.211;
ret Dict.735;
in
inc 2 Dict.210;
@ -455,7 +457,6 @@ procedure Dict.82 (Dict.702, Dict.480):
let Dict.1089 : U8 = 2i64;
let Dict.483 : U64 = CallByName Num.72 Dict.1088 Dict.1089;
let Dict.1087 : U64 = 0i64;
inc 3 Dict.480;
let Dict.1085 : U64 = CallByName Dict.92 Dict.480 Dict.1087;
let Dict.1086 : U8 = 32i64;
let Dict.1083 : U64 = CallByName Num.72 Dict.1085 Dict.1086;
@ -483,7 +484,6 @@ procedure Dict.82 (Dict.702, Dict.480):
let Dict.1033 : {U64, U64, U64} = Struct {Dict.1038, Dict.1039, Dict.478};
jump Dict.1034 Dict.1033;
else
dec Dict.480;
let Dict.1035 : U64 = 0i64;
let Dict.1036 : U64 = 0i64;
let Dict.1033 : {U64, U64, U64} = Struct {Dict.1035, Dict.1036, Dict.478};
@ -502,7 +502,6 @@ procedure Dict.82 (Dict.702, Dict.480):
procedure Dict.83 (#Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14):
joinpoint Dict.920 Dict.486 Dict.487 Dict.488 Dict.489 Dict.490 Dict.491:
inc 6 Dict.489;
let Dict.1027 : U64 = CallByName Dict.91 Dict.489 Dict.490;
let Dict.1028 : U64 = CallByName Dict.86;
let Dict.1022 : U64 = CallByName Num.70 Dict.1027 Dict.1028;
@ -546,9 +545,9 @@ procedure Dict.83 (#Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_ge
let Dict.995 : U64 = CallByName Num.70 Dict.493 Dict.492;
let Dict.497 : U64 = CallByName Num.70 Dict.494 Dict.995;
let Dict.972 : {U64, U64, U64} = CallByName Dict.84 Dict.497 Dict.489 Dict.496 Dict.495;
dec Dict.489;
ret Dict.972;
else
inc Dict.489;
let Dict.970 : U64 = CallByName Num.70 Dict.493 Dict.492;
let Dict.498 : U64 = CallByName Num.70 Dict.494 Dict.970;
let Dict.969 : U64 = 16i64;
@ -559,14 +558,15 @@ procedure Dict.83 (#Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_ge
let Dict.965 : U64 = CallByName Num.75 Dict.495 Dict.966;
let Dict.924 : U64 = CallByName Num.51 Dict.965 Dict.496;
let Dict.923 : U64 = CallByName Dict.91 Dict.489 Dict.924;
dec Dict.489;
let Dict.921 : {U64, U64, U64} = Struct {Dict.922, Dict.923, Dict.498};
ret Dict.921;
in
inc #Derived_gen.12;
jump Dict.920 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14;
procedure Dict.84 (#Derived_gen.43, #Derived_gen.44, #Derived_gen.45, #Derived_gen.46):
joinpoint Dict.973 Dict.499 Dict.500 Dict.501 Dict.502:
inc 2 Dict.500;
let Dict.993 : U64 = CallByName Dict.91 Dict.500 Dict.501;
let Dict.994 : U64 = CallByName Dict.86;
let Dict.988 : U64 = CallByName Num.70 Dict.993 Dict.994;
@ -582,7 +582,6 @@ procedure Dict.84 (#Derived_gen.43, #Derived_gen.44, #Derived_gen.45, #Derived_g
let Dict.985 : U64 = 16i64;
let Dict.975 : Int1 = CallByName Num.23 Dict.504 Dict.985;
if Dict.975 then
inc Dict.500;
let Dict.984 : U64 = 16i64;
let Dict.983 : U64 = CallByName Num.75 Dict.504 Dict.984;
let Dict.982 : U64 = CallByName Num.51 Dict.983 Dict.505;
@ -591,11 +590,13 @@ procedure Dict.84 (#Derived_gen.43, #Derived_gen.44, #Derived_gen.45, #Derived_g
let Dict.980 : U64 = CallByName Num.75 Dict.504 Dict.981;
let Dict.979 : U64 = CallByName Num.51 Dict.980 Dict.505;
let Dict.978 : U64 = CallByName Dict.91 Dict.500 Dict.979;
dec Dict.500;
let Dict.976 : {U64, U64, U64} = Struct {Dict.977, Dict.978, Dict.503};
ret Dict.976;
else
jump Dict.973 Dict.503 Dict.500 Dict.505 Dict.504;
in
inc #Derived_gen.44;
jump Dict.973 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45 #Derived_gen.46;
procedure Dict.85 ():
@ -662,7 +663,6 @@ procedure Dict.91 (Dict.515, Dict.516):
let Dict.945 : U64 = 7i64;
let Dict.943 : U64 = CallByName Num.51 Dict.516 Dict.945;
let Dict.942 : U8 = CallByName Dict.22 Dict.515 Dict.943;
dec Dict.515;
let Dict.524 : U64 = CallByName Num.133 Dict.942;
let Dict.941 : U8 = 8i64;
let Dict.940 : U64 = CallByName Num.72 Dict.518 Dict.941;
@ -701,7 +701,6 @@ procedure Dict.92 (Dict.529, Dict.530):
let Dict.1069 : U64 = 3i64;
let Dict.1068 : U64 = CallByName Num.51 Dict.530 Dict.1069;
let Dict.1067 : U8 = CallByName Dict.22 Dict.529 Dict.1068;
dec Dict.529;
let Dict.534 : U64 = CallByName Num.133 Dict.1067;
let Dict.1066 : U8 = 8i64;
let Dict.1065 : U64 = CallByName Num.72 Dict.532 Dict.1066;
@ -726,7 +725,6 @@ procedure Dict.93 (Dict.537, Dict.538, Dict.539):
let Dict.1048 : U64 = CallByName Num.75 Dict.539 Dict.1049;
let Dict.1047 : U64 = CallByName Num.51 Dict.1048 Dict.538;
let Dict.1046 : U8 = CallByName Dict.22 Dict.537 Dict.1047;
dec Dict.537;
let Dict.542 : U64 = CallByName Num.133 Dict.1046;
let Dict.1045 : U8 = 16i64;
let Dict.1042 : U64 = CallByName Num.72 Dict.540 Dict.1045;
@ -739,6 +737,7 @@ procedure Dict.93 (Dict.537, Dict.538, Dict.539):
procedure Hash.19 (Hash.38, Hash.39):
let Hash.71 : List U8 = CallByName Str.12 Hash.39;
let Hash.70 : {U64, U64} = CallByName Dict.82 Hash.38 Hash.71;
dec Hash.71;
ret Hash.70;
procedure Inspect.183 (Inspect.184, #Attr.12):
@ -748,12 +747,15 @@ procedure Inspect.183 (Inspect.184, #Attr.12):
let Inspect.179 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = StructAtIndex 0 #Attr.12;
let Inspect.351 : Str = "{";
let Inspect.324 : Str = CallByName Inspect.59 Inspect.184 Inspect.351;
dec Inspect.351;
let Inspect.325 : {{List {U32, U32}, List {Str, I64}, U64, Float32, U8}, {}, {}, {}} = Struct {Inspect.179, Inspect.180, Inspect.181, Inspect.182};
let Inspect.320 : {Str, Int1} = CallByName Inspect.185 Inspect.324 Inspect.325;
dec Inspect.324;
let Inspect.321 : {} = Struct {};
let Inspect.316 : Str = CallByName Inspect.197 Inspect.320;
let Inspect.317 : Str = "}";
let Inspect.315 : Str = CallByName Inspect.59 Inspect.316 Inspect.317;
dec Inspect.317;
ret Inspect.315;
procedure Inspect.185 (Inspect.186, #Attr.12):
@ -762,6 +764,7 @@ procedure Inspect.185 (Inspect.186, #Attr.12):
let Inspect.180 : {} = StructAtIndex 1 #Attr.12;
let Inspect.179 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = StructAtIndex 0 #Attr.12;
let Inspect.350 : Int1 = CallByName Bool.1;
inc Inspect.186;
let Inspect.328 : {Str, Int1} = Struct {Inspect.186, Inspect.350};
let Inspect.329 : {{}, {}} = Struct {Inspect.181, Inspect.182};
let Inspect.327 : {Str, Int1} = CallByName Dict.10 Inspect.179 Inspect.328 Inspect.329;
@ -775,17 +778,21 @@ procedure Inspect.187 (Inspect.330, Inspect.190, Inspect.191, #Attr.12):
joinpoint Inspect.348 Inspect.192:
let Inspect.345 : Str = CallByName Inspect.43 Inspect.190;
let Inspect.343 : Str = CallByName Inspect.31 Inspect.345 Inspect.192;
dec Inspect.345;
let Inspect.344 : Str = ": ";
let Inspect.337 : Str = CallByName Inspect.59 Inspect.343 Inspect.344;
dec Inspect.344;
let Inspect.338 : {I64, {}} = Struct {Inspect.191, Inspect.182};
let Inspect.333 : Str = CallByName Inspect.193 Inspect.337 Inspect.338;
let Inspect.334 : {} = Struct {};
let Inspect.332 : {Str, Int1} = CallByName Inspect.195 Inspect.333;
dec Inspect.333;
ret Inspect.332;
in
if Inspect.189 then
let Inspect.349 : Str = ", ";
let Inspect.347 : Str = CallByName Inspect.59 Inspect.188 Inspect.349;
dec Inspect.349;
jump Inspect.348 Inspect.347;
else
jump Inspect.348 Inspect.188;
@ -799,6 +806,7 @@ procedure Inspect.193 (Inspect.194, #Attr.12):
procedure Inspect.195 (Inspect.196):
let Inspect.336 : Int1 = CallByName Bool.2;
inc Inspect.196;
let Inspect.335 : {Str, Int1} = Struct {Inspect.196, Inspect.336};
ret Inspect.335;
@ -809,14 +817,17 @@ procedure Inspect.197 (Inspect.322):
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.366 : Str = "\"";
let Inspect.365 : Str = CallByName Inspect.59 Inspect.247 Inspect.366;
dec Inspect.366;
let Inspect.363 : Str = CallByName Inspect.59 Inspect.365 Inspect.245;
let Inspect.364 : Str = "\"";
let Inspect.362 : Str = CallByName Inspect.59 Inspect.363 Inspect.364;
dec Inspect.364;
ret Inspect.362;
procedure Inspect.274 (Inspect.275, Inspect.273):
let Inspect.357 : Str = CallByName Num.96 Inspect.273;
let Inspect.356 : Str = CallByName Inspect.59 Inspect.275 Inspect.357;
dec Inspect.357;
ret Inspect.356;
procedure Inspect.30 (Inspect.143):
@ -874,7 +885,6 @@ procedure Inspect.53 (Inspect.273):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.319 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.319;
procedure Inspect.60 (Inspect.298):
@ -1009,6 +1019,7 @@ procedure List.92 (#Derived_gen.50, #Derived_gen.51, #Derived_gen.52, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.50;
jump List.577 #Derived_gen.50 #Derived_gen.51 #Derived_gen.52 #Derived_gen.53 #Derived_gen.54;
procedure List.92 (#Derived_gen.59, #Derived_gen.60, #Derived_gen.61, #Derived_gen.62, #Derived_gen.63):
@ -1025,6 +1036,7 @@ procedure List.92 (#Derived_gen.59, #Derived_gen.60, #Derived_gen.61, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.59;
jump List.641 #Derived_gen.59 #Derived_gen.60 #Derived_gen.61 #Derived_gen.62 #Derived_gen.63;
procedure List.93 (#Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_gen.26, #Derived_gen.27):
@ -1041,6 +1053,7 @@ procedure List.93 (#Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_g
dec List.172;
ret List.173;
in
inc #Derived_gen.23;
jump List.616 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27;
procedure Num.131 (#Attr.2):
@ -1187,5 +1200,6 @@ procedure Test.0 ():
let Test.5 : {Str, I64} = Struct {Test.6, Test.7};
let Test.3 : List {Str, I64} = Array [Test.4, Test.5];
let Test.2 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.12 Test.3;
dec Test.3;
let Test.1 : Str = CallByName Inspect.33 Test.2;
ret Test.1;

View file

@ -27,12 +27,15 @@ procedure Inspect.152 (Inspect.153, #Attr.12):
let Inspect.149 : List I64 = StructAtIndex 0 #Attr.12;
let Inspect.343 : Str = "[";
let Inspect.324 : Str = CallByName Inspect.59 Inspect.153 Inspect.343;
dec Inspect.343;
let Inspect.325 : {List I64, {}, {}} = Struct {Inspect.149, Inspect.150, Inspect.151};
let Inspect.320 : {Str, Int1} = CallByName Inspect.154 Inspect.324 Inspect.325;
dec Inspect.324;
let Inspect.321 : {} = Struct {};
let Inspect.316 : Str = CallByName Inspect.163 Inspect.320;
let Inspect.317 : Str = "]";
let Inspect.315 : Str = CallByName Inspect.59 Inspect.316 Inspect.317;
dec Inspect.317;
ret Inspect.315;
procedure Inspect.154 (Inspect.155, #Attr.12):
@ -40,8 +43,10 @@ procedure Inspect.154 (Inspect.155, #Attr.12):
let Inspect.150 : {} = StructAtIndex 1 #Attr.12;
let Inspect.149 : List I64 = StructAtIndex 0 #Attr.12;
let Inspect.342 : Int1 = CallByName Bool.1;
inc Inspect.155;
let Inspect.328 : {Str, Int1} = Struct {Inspect.155, Inspect.342};
let Inspect.327 : {Str, Int1} = CallByName List.18 Inspect.149 Inspect.328 Inspect.151;
dec Inspect.149;
ret Inspect.327;
procedure Inspect.156 (Inspect.330, Inspect.159, Inspect.151):
@ -52,17 +57,20 @@ procedure Inspect.156 (Inspect.330, Inspect.159, Inspect.151):
let Inspect.333 : Str = CallByName Inspect.31 Inspect.337 Inspect.160;
let Inspect.334 : {} = Struct {};
let Inspect.332 : {Str, Int1} = CallByName Inspect.161 Inspect.333;
dec Inspect.333;
ret Inspect.332;
in
if Inspect.158 then
let Inspect.341 : Str = ", ";
let Inspect.339 : Str = CallByName Inspect.59 Inspect.157 Inspect.341;
dec Inspect.341;
jump Inspect.340 Inspect.339;
else
jump Inspect.340 Inspect.157;
procedure Inspect.161 (Inspect.162):
let Inspect.336 : Int1 = CallByName Bool.2;
inc Inspect.162;
let Inspect.335 : {Str, Int1} = Struct {Inspect.162, Inspect.336};
ret Inspect.335;
@ -73,6 +81,7 @@ procedure Inspect.163 (Inspect.322):
procedure Inspect.274 (Inspect.275, Inspect.273):
let Inspect.349 : Str = CallByName Num.96 Inspect.273;
let Inspect.348 : Str = CallByName Inspect.59 Inspect.275 Inspect.349;
dec Inspect.349;
ret Inspect.348;
procedure Inspect.30 (Inspect.143):
@ -102,6 +111,7 @@ procedure Inspect.35 (Inspect.297):
ret Inspect.307;
procedure Inspect.36 (Inspect.149, Inspect.150, Inspect.151):
inc Inspect.149;
let Inspect.312 : {List I64, {}, {}} = Struct {Inspect.149, Inspect.150, Inspect.151};
let Inspect.311 : {List I64, {}, {}} = CallByName Inspect.30 Inspect.312;
ret Inspect.311;
@ -111,6 +121,7 @@ procedure Inspect.5 (Inspect.146):
let Inspect.305 : {} = Struct {};
let Inspect.304 : Str = CallByName Inspect.35 Inspect.305;
let Inspect.303 : Str = CallByName #Derived.4 Inspect.304 Inspect.308;
dec Inspect.308;
ret Inspect.303;
procedure Inspect.53 (Inspect.273):
@ -119,7 +130,6 @@ procedure Inspect.53 (Inspect.273):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.319 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.319;
procedure Inspect.60 (Inspect.298):
@ -152,6 +162,7 @@ procedure List.92 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.19;
jump List.577 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23;
procedure Num.22 (#Attr.2, #Attr.3):

View file

@ -9,6 +9,7 @@ procedure #Derived.2 (#Derived.3, #Derived.1):
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6];
let #Derived_gen.4 : List {Str, Str} = CallByName Inspect.41 #Derived_gen.5;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.3;
dec #Derived_gen.4;
ret #Derived_gen.3;
procedure #Derived.4 (#Derived.5):
@ -22,6 +23,7 @@ procedure #Derived.6 (#Derived.7, #Derived.5):
let #Derived_gen.15 : List {Str, Str} = Array [#Derived_gen.16];
let #Derived_gen.14 : List {Str, Str} = CallByName Inspect.41 #Derived_gen.15;
let #Derived_gen.13 : Str = CallByName Inspect.31 #Derived_gen.14 #Derived.7;
dec #Derived_gen.14;
ret #Derived_gen.13;
procedure Bool.1 ():
@ -35,25 +37,32 @@ procedure Bool.2 ():
procedure Inspect.225 (Inspect.226, Inspect.224):
let Inspect.348 : Str = "{";
let Inspect.324 : Str = CallByName Inspect.59 Inspect.226 Inspect.348;
dec Inspect.348;
let Inspect.320 : {Str, Int1} = CallByName Inspect.227 Inspect.324 Inspect.224;
dec Inspect.324;
let Inspect.321 : {} = Struct {};
let Inspect.316 : Str = CallByName Inspect.239 Inspect.320;
let Inspect.317 : Str = "}";
let Inspect.315 : Str = CallByName Inspect.59 Inspect.316 Inspect.317;
dec Inspect.317;
ret Inspect.315;
procedure Inspect.225 (Inspect.226, Inspect.224):
let Inspect.388 : Str = "{";
let Inspect.364 : Str = CallByName Inspect.59 Inspect.226 Inspect.388;
dec Inspect.388;
let Inspect.360 : {Str, Int1} = CallByName Inspect.227 Inspect.364 Inspect.224;
dec Inspect.364;
let Inspect.361 : {} = Struct {};
let Inspect.356 : Str = CallByName Inspect.239 Inspect.360;
let Inspect.357 : Str = "}";
let Inspect.355 : Str = CallByName Inspect.59 Inspect.356 Inspect.357;
dec Inspect.357;
ret Inspect.355;
procedure Inspect.227 (Inspect.228, Inspect.224):
let Inspect.347 : Int1 = CallByName Bool.1;
inc Inspect.228;
let Inspect.328 : {Str, Int1} = Struct {Inspect.228, Inspect.347};
let Inspect.329 : {} = Struct {};
let Inspect.327 : {Str, Int1} = CallByName List.18 Inspect.224 Inspect.328 Inspect.329;
@ -61,6 +70,7 @@ procedure Inspect.227 (Inspect.228, Inspect.224):
procedure Inspect.227 (Inspect.228, Inspect.224):
let Inspect.387 : Int1 = CallByName Bool.1;
inc Inspect.228;
let Inspect.368 : {Str, Int1} = Struct {Inspect.228, Inspect.387};
let Inspect.369 : {} = Struct {};
let Inspect.367 : {Str, Int1} = CallByName List.18 Inspect.224 Inspect.368 Inspect.369;
@ -73,16 +83,20 @@ procedure Inspect.229 (Inspect.330, Inspect.331):
let Inspect.231 : Int1 = StructAtIndex 1 Inspect.330;
joinpoint Inspect.345 Inspect.234:
let Inspect.342 : Str = CallByName Inspect.59 Inspect.234 Inspect.232;
dec Inspect.232;
let Inspect.343 : Str = ": ";
let Inspect.337 : Str = CallByName Inspect.59 Inspect.342 Inspect.343;
dec Inspect.343;
let Inspect.333 : Str = CallByName Inspect.235 Inspect.337 Inspect.233;
let Inspect.334 : {} = Struct {};
let Inspect.332 : {Str, Int1} = CallByName Inspect.237 Inspect.333;
dec Inspect.333;
ret Inspect.332;
in
if Inspect.231 then
let Inspect.346 : Str = ", ";
let Inspect.344 : Str = CallByName Inspect.59 Inspect.230 Inspect.346;
dec Inspect.346;
jump Inspect.345 Inspect.344;
else
jump Inspect.345 Inspect.230;
@ -94,16 +108,21 @@ procedure Inspect.229 (Inspect.330, Inspect.331):
let Inspect.231 : Int1 = StructAtIndex 1 Inspect.330;
joinpoint Inspect.385 Inspect.234:
let Inspect.382 : Str = CallByName Inspect.59 Inspect.234 Inspect.232;
dec Inspect.232;
let Inspect.383 : Str = ": ";
let Inspect.377 : Str = CallByName Inspect.59 Inspect.382 Inspect.383;
dec Inspect.383;
let Inspect.373 : Str = CallByName Inspect.235 Inspect.377 Inspect.233;
dec Inspect.233;
let Inspect.374 : {} = Struct {};
let Inspect.372 : {Str, Int1} = CallByName Inspect.237 Inspect.373;
dec Inspect.373;
ret Inspect.372;
in
if Inspect.231 then
let Inspect.386 : Str = ", ";
let Inspect.384 : Str = CallByName Inspect.59 Inspect.230 Inspect.386;
dec Inspect.386;
jump Inspect.385 Inspect.384;
else
jump Inspect.385 Inspect.230;
@ -118,6 +137,7 @@ procedure Inspect.235 (Inspect.236, Inspect.233):
procedure Inspect.237 (Inspect.238):
let Inspect.376 : Int1 = CallByName Bool.2;
inc Inspect.238;
let Inspect.375 : {Str, Int1} = Struct {Inspect.238, Inspect.376};
ret Inspect.375;
@ -128,9 +148,11 @@ procedure Inspect.239 (Inspect.322):
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.397 : Str = "\"";
let Inspect.396 : Str = CallByName Inspect.59 Inspect.247 Inspect.397;
dec Inspect.397;
let Inspect.394 : Str = CallByName Inspect.59 Inspect.396 Inspect.245;
let Inspect.395 : Str = "\"";
let Inspect.393 : Str = CallByName Inspect.59 Inspect.394 Inspect.395;
dec Inspect.395;
ret Inspect.393;
procedure Inspect.30 (Inspect.143):
@ -194,7 +216,6 @@ procedure Inspect.5 (Inspect.146):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.359 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.359;
procedure Inspect.60 (Inspect.298):
@ -242,6 +263,7 @@ procedure List.92 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.26;
jump List.589 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30;
procedure List.92 (#Derived_gen.39, #Derived_gen.40, #Derived_gen.41, #Derived_gen.42, #Derived_gen.43):
@ -258,6 +280,7 @@ procedure List.92 (#Derived_gen.39, #Derived_gen.40, #Derived_gen.41, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.39;
jump List.577 #Derived_gen.39 #Derived_gen.40 #Derived_gen.41 #Derived_gen.42 #Derived_gen.43;
procedure Num.22 (#Attr.2, #Attr.3):

View file

@ -14,6 +14,7 @@ procedure #Derived.2 (#Derived.3, #Derived.1):
let #Derived_gen.5 : List {[C I64, C Decimal], Str} = Array [#Derived_gen.6, #Derived_gen.7];
let #Derived_gen.4 : List {[C I64, C Decimal], Str} = CallByName Inspect.41 #Derived_gen.5;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.3;
dec #Derived_gen.4;
ret #Derived_gen.3;
procedure Bool.1 ():
@ -27,15 +28,19 @@ procedure Bool.2 ():
procedure Inspect.225 (Inspect.226, Inspect.224):
let Inspect.349 : Str = "{";
let Inspect.324 : Str = CallByName Inspect.59 Inspect.226 Inspect.349;
dec Inspect.349;
let Inspect.320 : {Str, Int1} = CallByName Inspect.227 Inspect.324 Inspect.224;
dec Inspect.324;
let Inspect.321 : {} = Struct {};
let Inspect.316 : Str = CallByName Inspect.239 Inspect.320;
let Inspect.317 : Str = "}";
let Inspect.315 : Str = CallByName Inspect.59 Inspect.316 Inspect.317;
dec Inspect.317;
ret Inspect.315;
procedure Inspect.227 (Inspect.228, Inspect.224):
let Inspect.348 : Int1 = CallByName Bool.1;
inc Inspect.228;
let Inspect.328 : {Str, Int1} = Struct {Inspect.228, Inspect.348};
let Inspect.329 : {} = Struct {};
let Inspect.327 : {Str, Int1} = CallByName List.18 Inspect.224 Inspect.328 Inspect.329;
@ -48,16 +53,20 @@ procedure Inspect.229 (Inspect.330, Inspect.331):
let Inspect.231 : Int1 = StructAtIndex 1 Inspect.330;
joinpoint Inspect.346 Inspect.234:
let Inspect.343 : Str = CallByName Inspect.59 Inspect.234 Inspect.232;
dec Inspect.232;
let Inspect.344 : Str = ": ";
let Inspect.337 : Str = CallByName Inspect.59 Inspect.343 Inspect.344;
dec Inspect.344;
let Inspect.333 : Str = CallByName Inspect.235 Inspect.337 Inspect.233;
let Inspect.334 : {} = Struct {};
let Inspect.332 : {Str, Int1} = CallByName Inspect.237 Inspect.333;
dec Inspect.333;
ret Inspect.332;
in
if Inspect.231 then
let Inspect.347 : Str = ", ";
let Inspect.345 : Str = CallByName Inspect.59 Inspect.230 Inspect.347;
dec Inspect.347;
jump Inspect.346 Inspect.345;
else
jump Inspect.346 Inspect.230;
@ -68,6 +77,7 @@ procedure Inspect.235 (Inspect.236, Inspect.233):
procedure Inspect.237 (Inspect.238):
let Inspect.336 : Int1 = CallByName Bool.2;
inc Inspect.238;
let Inspect.335 : {Str, Int1} = Struct {Inspect.238, Inspect.336};
ret Inspect.335;
@ -79,12 +89,14 @@ procedure Inspect.274 (Inspect.275, #Attr.12):
let Inspect.362 : I64 = UnionAtIndex (Id 0) (Index 0) #Attr.12;
let Inspect.361 : Str = CallByName Num.96 Inspect.362;
let Inspect.360 : Str = CallByName Inspect.59 Inspect.275 Inspect.361;
dec Inspect.361;
ret Inspect.360;
procedure Inspect.289 (Inspect.290, #Attr.12):
let Inspect.356 : Decimal = UnionAtIndex (Id 1) (Index 0) #Attr.12;
let Inspect.355 : Str = CallByName Num.96 Inspect.356;
let Inspect.354 : Str = CallByName Inspect.59 Inspect.290 Inspect.355;
dec Inspect.355;
ret Inspect.354;
procedure Inspect.30 (Inspect.143):
@ -144,7 +156,6 @@ procedure Inspect.58 (Inspect.288):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.319 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.319;
procedure Inspect.60 (Inspect.298):
@ -178,6 +189,7 @@ procedure List.92 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.26;
jump List.577 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30;
procedure Num.22 (#Attr.2, #Attr.3):

View file

@ -9,6 +9,7 @@ procedure #Derived.2 (#Derived.3, #Derived.1):
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6];
let #Derived_gen.4 : List {Str, Str} = CallByName Inspect.41 #Derived_gen.5;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.3;
dec #Derived_gen.4;
ret #Derived_gen.3;
procedure Bool.1 ():
@ -22,15 +23,19 @@ procedure Bool.2 ():
procedure Inspect.225 (Inspect.226, Inspect.224):
let Inspect.348 : Str = "{";
let Inspect.324 : Str = CallByName Inspect.59 Inspect.226 Inspect.348;
dec Inspect.348;
let Inspect.320 : {Str, Int1} = CallByName Inspect.227 Inspect.324 Inspect.224;
dec Inspect.324;
let Inspect.321 : {} = Struct {};
let Inspect.316 : Str = CallByName Inspect.239 Inspect.320;
let Inspect.317 : Str = "}";
let Inspect.315 : Str = CallByName Inspect.59 Inspect.316 Inspect.317;
dec Inspect.317;
ret Inspect.315;
procedure Inspect.227 (Inspect.228, Inspect.224):
let Inspect.347 : Int1 = CallByName Bool.1;
inc Inspect.228;
let Inspect.328 : {Str, Int1} = Struct {Inspect.228, Inspect.347};
let Inspect.329 : {} = Struct {};
let Inspect.327 : {Str, Int1} = CallByName List.18 Inspect.224 Inspect.328 Inspect.329;
@ -43,16 +48,21 @@ procedure Inspect.229 (Inspect.330, Inspect.331):
let Inspect.231 : Int1 = StructAtIndex 1 Inspect.330;
joinpoint Inspect.345 Inspect.234:
let Inspect.342 : Str = CallByName Inspect.59 Inspect.234 Inspect.232;
dec Inspect.232;
let Inspect.343 : Str = ": ";
let Inspect.337 : Str = CallByName Inspect.59 Inspect.342 Inspect.343;
dec Inspect.343;
let Inspect.333 : Str = CallByName Inspect.235 Inspect.337 Inspect.233;
dec Inspect.233;
let Inspect.334 : {} = Struct {};
let Inspect.332 : {Str, Int1} = CallByName Inspect.237 Inspect.333;
dec Inspect.333;
ret Inspect.332;
in
if Inspect.231 then
let Inspect.346 : Str = ", ";
let Inspect.344 : Str = CallByName Inspect.59 Inspect.230 Inspect.346;
dec Inspect.346;
jump Inspect.345 Inspect.344;
else
jump Inspect.345 Inspect.230;
@ -63,6 +73,7 @@ procedure Inspect.235 (Inspect.236, Inspect.233):
procedure Inspect.237 (Inspect.238):
let Inspect.336 : Int1 = CallByName Bool.2;
inc Inspect.238;
let Inspect.335 : {Str, Int1} = Struct {Inspect.238, Inspect.336};
ret Inspect.335;
@ -73,9 +84,11 @@ procedure Inspect.239 (Inspect.322):
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.357 : Str = "\"";
let Inspect.356 : Str = CallByName Inspect.59 Inspect.247 Inspect.357;
dec Inspect.357;
let Inspect.354 : Str = CallByName Inspect.59 Inspect.356 Inspect.245;
let Inspect.355 : Str = "\"";
let Inspect.353 : Str = CallByName Inspect.59 Inspect.354 Inspect.355;
dec Inspect.355;
ret Inspect.353;
procedure Inspect.30 (Inspect.143):
@ -121,7 +134,6 @@ procedure Inspect.5 (Inspect.146):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.319 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.319;
procedure Inspect.60 (Inspect.298):
@ -155,6 +167,7 @@ procedure List.92 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.10;
jump List.577 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14;
procedure Num.22 (#Attr.2, #Attr.3):

View file

@ -16,6 +16,7 @@ procedure #Derived.2 (#Derived.3, #Derived.1):
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6, #Derived_gen.7];
let #Derived_gen.4 : List {Str, Str} = CallByName Inspect.41 #Derived_gen.5;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.3;
dec #Derived_gen.4;
ret #Derived_gen.3;
procedure Bool.1 ():
@ -29,15 +30,19 @@ procedure Bool.2 ():
procedure Inspect.225 (Inspect.226, Inspect.224):
let Inspect.348 : Str = "{";
let Inspect.324 : Str = CallByName Inspect.59 Inspect.226 Inspect.348;
dec Inspect.348;
let Inspect.320 : {Str, Int1} = CallByName Inspect.227 Inspect.324 Inspect.224;
dec Inspect.324;
let Inspect.321 : {} = Struct {};
let Inspect.316 : Str = CallByName Inspect.239 Inspect.320;
let Inspect.317 : Str = "}";
let Inspect.315 : Str = CallByName Inspect.59 Inspect.316 Inspect.317;
dec Inspect.317;
ret Inspect.315;
procedure Inspect.227 (Inspect.228, Inspect.224):
let Inspect.347 : Int1 = CallByName Bool.1;
inc Inspect.228;
let Inspect.328 : {Str, Int1} = Struct {Inspect.228, Inspect.347};
let Inspect.329 : {} = Struct {};
let Inspect.327 : {Str, Int1} = CallByName List.18 Inspect.224 Inspect.328 Inspect.329;
@ -50,16 +55,21 @@ procedure Inspect.229 (Inspect.330, Inspect.331):
let Inspect.231 : Int1 = StructAtIndex 1 Inspect.330;
joinpoint Inspect.345 Inspect.234:
let Inspect.342 : Str = CallByName Inspect.59 Inspect.234 Inspect.232;
dec Inspect.232;
let Inspect.343 : Str = ": ";
let Inspect.337 : Str = CallByName Inspect.59 Inspect.342 Inspect.343;
dec Inspect.343;
let Inspect.333 : Str = CallByName Inspect.235 Inspect.337 Inspect.233;
dec Inspect.233;
let Inspect.334 : {} = Struct {};
let Inspect.332 : {Str, Int1} = CallByName Inspect.237 Inspect.333;
dec Inspect.333;
ret Inspect.332;
in
if Inspect.231 then
let Inspect.346 : Str = ", ";
let Inspect.344 : Str = CallByName Inspect.59 Inspect.230 Inspect.346;
dec Inspect.346;
jump Inspect.345 Inspect.344;
else
jump Inspect.345 Inspect.230;
@ -70,6 +80,7 @@ procedure Inspect.235 (Inspect.236, Inspect.233):
procedure Inspect.237 (Inspect.238):
let Inspect.336 : Int1 = CallByName Bool.2;
inc Inspect.238;
let Inspect.335 : {Str, Int1} = Struct {Inspect.238, Inspect.336};
ret Inspect.335;
@ -80,9 +91,11 @@ procedure Inspect.239 (Inspect.322):
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.357 : Str = "\"";
let Inspect.356 : Str = CallByName Inspect.59 Inspect.247 Inspect.357;
dec Inspect.357;
let Inspect.354 : Str = CallByName Inspect.59 Inspect.356 Inspect.245;
let Inspect.355 : Str = "\"";
let Inspect.353 : Str = CallByName Inspect.59 Inspect.354 Inspect.355;
dec Inspect.355;
ret Inspect.353;
procedure Inspect.30 (Inspect.143):
@ -128,7 +141,6 @@ procedure Inspect.5 (Inspect.146):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.319 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.319;
procedure Inspect.60 (Inspect.298):
@ -162,6 +174,7 @@ procedure List.92 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.14;
jump List.577 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18;
procedure Num.22 (#Attr.2, #Attr.3):

View file

@ -1,9 +1,11 @@
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.319 : Str = "\"";
let Inspect.318 : Str = CallByName Inspect.59 Inspect.247 Inspect.319;
dec Inspect.319;
let Inspect.314 : Str = CallByName Inspect.59 Inspect.318 Inspect.245;
let Inspect.315 : Str = "\"";
let Inspect.313 : Str = CallByName Inspect.59 Inspect.314 Inspect.315;
dec Inspect.315;
ret Inspect.313;
procedure Inspect.30 (Inspect.143):
@ -27,11 +29,11 @@ procedure Inspect.5 (Inspect.146):
let Inspect.305 : {} = Struct {};
let Inspect.304 : Str = CallByName Inspect.35 Inspect.305;
let Inspect.303 : Str = CallByName Inspect.246 Inspect.304 Inspect.308;
dec Inspect.308;
ret Inspect.303;
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.317 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.317;
procedure Inspect.60 (Inspect.298):

View file

@ -11,6 +11,8 @@ procedure #Derived.3 (#Derived.4, #Derived.1):
let #Derived_gen.9 : Str = CallByName Inspect.43 #Derived.1;
let #Derived_gen.8 : List Str = Array [#Derived_gen.9];
let #Derived_gen.6 : [C Str, C Str List Str] = CallByName Inspect.39 #Derived_gen.7 #Derived_gen.8;
dec #Derived_gen.8;
dec #Derived_gen.7;
jump #Derived_gen.5 #Derived_gen.6;
procedure Bool.11 (#Attr.2, #Attr.3):
@ -20,6 +22,7 @@ procedure Bool.11 (#Attr.2, #Attr.3):
procedure Inspect.200 (Inspect.201, #Attr.12):
let Inspect.342 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12;
let Inspect.341 : Str = CallByName Inspect.59 Inspect.201 Inspect.342;
dec Inspect.342;
ret Inspect.341;
procedure Inspect.202 (Inspect.203, #Attr.12):
@ -27,10 +30,14 @@ procedure Inspect.202 (Inspect.203, #Attr.12):
let Inspect.335 : Str = UnionAtIndex (Id 1) (Index 0) #Attr.12;
let Inspect.334 : Str = "(";
let Inspect.333 : Str = CallByName Inspect.59 Inspect.203 Inspect.334;
dec Inspect.334;
let Inspect.321 : Str = CallByName Inspect.59 Inspect.333 Inspect.335;
dec Inspect.335;
let Inspect.317 : Str = CallByName Inspect.204 Inspect.321 Inspect.336;
dec Inspect.336;
let Inspect.318 : Str = ")";
let Inspect.316 : Str = CallByName Inspect.59 Inspect.317 Inspect.318;
dec Inspect.318;
ret Inspect.316;
procedure Inspect.204 (Inspect.205, Inspect.199):
@ -41,6 +48,7 @@ procedure Inspect.204 (Inspect.205, Inspect.199):
procedure Inspect.206 (Inspect.207, Inspect.208):
let Inspect.332 : Str = " ";
let Inspect.327 : Str = CallByName Inspect.59 Inspect.207 Inspect.332;
dec Inspect.332;
let Inspect.326 : Str = CallByName Inspect.209 Inspect.327 Inspect.208;
ret Inspect.326;
@ -51,9 +59,11 @@ procedure Inspect.209 (Inspect.210, Inspect.208):
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.351 : Str = "\"";
let Inspect.350 : Str = CallByName Inspect.59 Inspect.247 Inspect.351;
dec Inspect.351;
let Inspect.348 : Str = CallByName Inspect.59 Inspect.350 Inspect.245;
let Inspect.349 : Str = "\"";
let Inspect.347 : Str = CallByName Inspect.59 Inspect.348 Inspect.349;
dec Inspect.349;
ret Inspect.347;
procedure Inspect.30 (Inspect.143):
@ -91,14 +101,15 @@ procedure Inspect.35 (Inspect.297):
ret Inspect.307;
procedure Inspect.39 (Inspect.198, Inspect.199):
inc Inspect.199;
let Inspect.337 : Int1 = CallByName List.1 Inspect.199;
if Inspect.337 then
dec Inspect.199;
inc Inspect.198;
let Inspect.339 : [C Str, C Str List Str] = TagId(0) Inspect.198;
let Inspect.338 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.339;
ret Inspect.338;
else
inc Inspect.199;
inc Inspect.198;
let Inspect.313 : [C Str, C Str List Str] = TagId(1) Inspect.198 Inspect.199;
let Inspect.312 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.313;
ret Inspect.312;
@ -116,7 +127,6 @@ procedure Inspect.5 (Inspect.146):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.320 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.320;
procedure Inspect.60 (Inspect.298):
@ -124,7 +134,6 @@ procedure Inspect.60 (Inspect.298):
procedure List.1 (List.107):
let List.587 : U64 = CallByName List.6 List.107;
dec List.107;
let List.588 : U64 = 0i64;
let List.586 : Int1 = CallByName Bool.11 List.587 List.588;
ret List.586;
@ -150,6 +159,7 @@ procedure List.92 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_g
let List.583 : Str = CallByName List.66 List.163 List.166;
inc List.583;
let List.168 : Str = CallByName Inspect.206 List.164 List.583;
dec List.583;
let List.582 : U64 = 1i64;
let List.581 : U64 = CallByName Num.51 List.166 List.582;
jump List.577 List.163 List.168 List.165 List.581 List.167;
@ -157,6 +167,7 @@ procedure List.92 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.10;
jump List.577 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14;
procedure Num.22 (#Attr.2, #Attr.3):

View file

@ -14,6 +14,8 @@ procedure #Derived.4 (#Derived.5, #Derived.1):
let #Derived_gen.10 : Str = CallByName Inspect.43 #Derived.3;
let #Derived_gen.8 : List Str = Array [#Derived_gen.9, #Derived_gen.10];
let #Derived_gen.6 : [C Str, C Str List Str] = CallByName Inspect.39 #Derived_gen.7 #Derived_gen.8;
dec #Derived_gen.8;
dec #Derived_gen.7;
jump #Derived_gen.5 #Derived_gen.6;
procedure Bool.11 (#Attr.2, #Attr.3):
@ -23,6 +25,7 @@ procedure Bool.11 (#Attr.2, #Attr.3):
procedure Inspect.200 (Inspect.201, #Attr.12):
let Inspect.342 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12;
let Inspect.341 : Str = CallByName Inspect.59 Inspect.201 Inspect.342;
dec Inspect.342;
ret Inspect.341;
procedure Inspect.202 (Inspect.203, #Attr.12):
@ -30,10 +33,14 @@ procedure Inspect.202 (Inspect.203, #Attr.12):
let Inspect.335 : Str = UnionAtIndex (Id 1) (Index 0) #Attr.12;
let Inspect.334 : Str = "(";
let Inspect.333 : Str = CallByName Inspect.59 Inspect.203 Inspect.334;
dec Inspect.334;
let Inspect.321 : Str = CallByName Inspect.59 Inspect.333 Inspect.335;
dec Inspect.335;
let Inspect.317 : Str = CallByName Inspect.204 Inspect.321 Inspect.336;
dec Inspect.336;
let Inspect.318 : Str = ")";
let Inspect.316 : Str = CallByName Inspect.59 Inspect.317 Inspect.318;
dec Inspect.318;
ret Inspect.316;
procedure Inspect.204 (Inspect.205, Inspect.199):
@ -44,6 +51,7 @@ procedure Inspect.204 (Inspect.205, Inspect.199):
procedure Inspect.206 (Inspect.207, Inspect.208):
let Inspect.332 : Str = " ";
let Inspect.327 : Str = CallByName Inspect.59 Inspect.207 Inspect.332;
dec Inspect.332;
let Inspect.326 : Str = CallByName Inspect.209 Inspect.327 Inspect.208;
ret Inspect.326;
@ -54,9 +62,11 @@ procedure Inspect.209 (Inspect.210, Inspect.208):
procedure Inspect.246 (Inspect.247, Inspect.245):
let Inspect.351 : Str = "\"";
let Inspect.350 : Str = CallByName Inspect.59 Inspect.247 Inspect.351;
dec Inspect.351;
let Inspect.348 : Str = CallByName Inspect.59 Inspect.350 Inspect.245;
let Inspect.349 : Str = "\"";
let Inspect.347 : Str = CallByName Inspect.59 Inspect.348 Inspect.349;
dec Inspect.349;
ret Inspect.347;
procedure Inspect.30 (Inspect.143):
@ -94,14 +104,15 @@ procedure Inspect.35 (Inspect.297):
ret Inspect.307;
procedure Inspect.39 (Inspect.198, Inspect.199):
inc Inspect.199;
let Inspect.337 : Int1 = CallByName List.1 Inspect.199;
if Inspect.337 then
dec Inspect.199;
inc Inspect.198;
let Inspect.339 : [C Str, C Str List Str] = TagId(0) Inspect.198;
let Inspect.338 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.339;
ret Inspect.338;
else
inc Inspect.199;
inc Inspect.198;
let Inspect.313 : [C Str, C Str List Str] = TagId(1) Inspect.198 Inspect.199;
let Inspect.312 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.313;
ret Inspect.312;
@ -119,7 +130,6 @@ procedure Inspect.5 (Inspect.146):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.320 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.320;
procedure Inspect.60 (Inspect.298):
@ -127,7 +137,6 @@ procedure Inspect.60 (Inspect.298):
procedure List.1 (List.107):
let List.587 : U64 = CallByName List.6 List.107;
dec List.107;
let List.588 : U64 = 0i64;
let List.586 : Int1 = CallByName Bool.11 List.587 List.588;
ret List.586;
@ -153,6 +162,7 @@ procedure List.92 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_g
let List.583 : Str = CallByName List.66 List.163 List.166;
inc List.583;
let List.168 : Str = CallByName Inspect.206 List.164 List.583;
dec List.583;
let List.582 : U64 = 1i64;
let List.581 : U64 = CallByName Num.51 List.166 List.582;
jump List.577 List.163 List.168 List.165 List.581 List.167;
@ -160,6 +170,7 @@ procedure List.92 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.13;
jump List.577 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17;
procedure Num.22 (#Attr.2, #Attr.3):

View file

@ -11,11 +11,9 @@ procedure List.2 (List.108, List.109):
let List.584 : Int1 = CallByName Num.22 List.109 List.588;
if List.584 then
let List.586 : I64 = CallByName List.66 List.108 List.109;
dec List.108;
let List.585 : [C {}, C I64] = TagId(1) List.586;
ret List.585;
else
dec List.108;
let List.583 : {} = Struct {};
let List.582 : [C {}, C I64] = TagId(0) List.583;
ret List.582;
@ -57,7 +55,6 @@ procedure Str.42 (#Attr.2):
procedure Str.60 (Str.185):
let Str.186 : {I64, U8} = CallByName Str.42 Str.185;
dec Str.185;
let Str.238 : U8 = StructAtIndex 1 Str.186;
let Str.239 : U8 = 0i64;
let Str.235 : Int1 = CallByName Bool.11 Str.238 Str.239;
@ -75,8 +72,10 @@ procedure Test.0 ():
if Test.3 then
let Test.5 : List I64 = Array [];
let Test.4 : [C Int1, C I64] = CallByName List.9 Test.5;
dec Test.5;
ret Test.4;
else
let Test.2 : Str = "";
let Test.1 : [C Int1, C I64] = CallByName Str.27 Test.2;
dec Test.2;
ret Test.1;

View file

@ -79,6 +79,7 @@ procedure List.80 (#Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.
let List.591 : [C {}, C {}] = TagId(1) List.492;
ret List.591;
in
inc #Derived_gen.1;
jump List.590 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5;
procedure Num.22 (#Attr.2, #Attr.3):
@ -146,6 +147,7 @@ procedure Test.1 (#Derived_gen.0):
let Test.33 : List {[<r>C I64, C List *self], [<r>C I64, C List *self]} = CallByName List.23 Test.12 Test.14 Test.35;
let Test.34 : {} = Struct {};
let Test.29 : Int1 = CallByName List.56 Test.33 Test.34;
dec Test.33;
if Test.29 then
let Test.31 : U64 = CallByName List.6 Test.12;
dec Test.12;

View file

@ -32,7 +32,6 @@ procedure Str.42 (#Attr.2):
procedure Str.60 (Str.185):
let Str.186 : {I64, U8} = CallByName Str.42 Str.185;
dec Str.185;
let Str.238 : U8 = StructAtIndex 1 Str.186;
let Str.239 : U8 = 0i64;
let Str.235 : Int1 = CallByName Bool.11 Str.238 Str.239;
@ -68,6 +67,7 @@ procedure Test.19 ():
let Test.133 : List U8 = CallByName Str.12 Test.135;
let Test.134 : {} = Struct {};
let Test.132 : {List U8, [C {}, C Str]} = CallByName Decode.26 Test.133 Test.134;
dec Test.133;
let Test.93 : List U8 = StructAtIndex 0 Test.132;
let Test.92 : [C {}, C Str] = StructAtIndex 1 Test.132;
let Test.129 : U8 = 1i64;
@ -76,6 +76,7 @@ procedure Test.19 ():
if Test.131 then
let Test.94 : Str = UnionAtIndex (Id 1) (Index 0) Test.92;
let Test.117 : [C {}, C I64] = CallByName Str.27 Test.94;
dec Test.94;
let Test.123 : U8 = 1i64;
let Test.124 : U8 = GetTagId Test.117;
let Test.125 : Int1 = lowlevel Eq Test.123 Test.124;
@ -99,5 +100,6 @@ procedure Test.19 ():
procedure Test.76 (Test.77, Test.138):
let Test.141 : {} = Struct {};
let Test.140 : [C {}, C Str] = TagId(0) Test.141;
inc Test.77;
let Test.139 : {List U8, [C {}, C Str]} = Struct {Test.77, Test.140};
ret Test.139;

View file

@ -37,6 +37,7 @@ procedure Test.1 (#Derived_gen.0, #Derived_gen.1):
let Test.14 : [C {}, C Str] = TagId(0) Test.15;
ret Test.14;
in
inc #Derived_gen.0;
jump Test.12 #Derived_gen.0 #Derived_gen.1;
procedure Test.0 ():
@ -44,4 +45,5 @@ procedure Test.0 ():
let Test.10 : List Str = Array [Test.35];
let Test.11 : U64 = 0i64;
let Test.9 : [C {}, C Str] = CallByName Test.1 Test.10 Test.11;
dec Test.10;
ret Test.9;

View file

@ -3,7 +3,6 @@ procedure Bool.1 ():
ret Bool.24;
procedure Test.1 (Test.4):
dec Test.4;
let Test.9 : I64 = 0i64;
ret Test.9;
@ -18,6 +17,7 @@ procedure Test.0 ():
in
joinpoint Test.13 Test.12:
let Test.8 : I64 = CallByName Test.1 Test.12;
dec Test.12;
jump Test.7 Test.8;
in
let Test.32 : U64 = lowlevel ListLenUsize Test.6;

View file

@ -3,7 +3,6 @@ procedure Bool.1 ():
ret Bool.24;
procedure Test.1 (Test.4):
dec Test.4;
let Test.9 : I64 = 0i64;
ret Test.9;
@ -18,6 +17,7 @@ procedure Test.0 ():
in
joinpoint Test.13 Test.12:
let Test.8 : I64 = CallByName Test.1 Test.12;
dec Test.12;
jump Test.7 Test.8;
in
let Test.44 : U64 = lowlevel ListLenUsize Test.6;

View file

@ -22,7 +22,6 @@ procedure Test.2 (Test.7, Test.8):
ret Test.43;
procedure Test.3 (Test.17):
dec Test.17;
let Test.35 : {} = Struct {};
ret Test.35;
@ -35,6 +34,7 @@ procedure Test.9 (Test.26, #Attr.12):
let Test.32 : {} = Struct {};
let Test.31 : Str = CallByName Test.15 Test.32;
let Test.28 : {} = CallByName Test.3 Test.31;
dec Test.31;
let Test.30 : {} = Struct {};
let Test.29 : Str = CallByName Test.11 Test.30;
ret Test.29;

View file

@ -11,6 +11,7 @@ procedure Test.1 (Test.5):
ret Test.31;
procedure Test.2 (Test.7):
inc Test.7;
let Test.23 : [C {}, C U64, C Str] = TagId(2) Test.7;
ret Test.23;
@ -59,6 +60,7 @@ procedure Test.0 ():
case 1:
let Test.22 : Str = "foo";
let Test.21 : [C {}, C U64, C Str] = CallByName Test.2 Test.22;
dec Test.22;
jump Test.13 Test.21;
default:

View file

@ -1,8 +1,10 @@
procedure Test.1 (Test.4):
inc Test.4;
let Test.13 : [C Str, C Str] = TagId(0) Test.4;
ret Test.13;
procedure Test.1 (Test.4):
inc Test.4;
let Test.19 : [C Str, C Str] = TagId(0) Test.4;
ret Test.19;
@ -22,8 +24,10 @@ procedure Test.0 ():
if Test.22 then
let Test.16 : Str = "";
let Test.10 : [C Str, C Str] = CallByName Test.1 Test.16;
dec Test.16;
jump Test.9 Test.10;
else
let Test.20 : Str = "";
let Test.17 : [C Str, C Str] = CallByName Test.1 Test.20;
dec Test.20;
jump Test.9 Test.17;

View file

@ -26,6 +26,7 @@ procedure List.92 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
dec List.163;
ret List.164;
in
inc #Derived_gen.0;
jump List.577 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4;
procedure Num.22 (#Attr.2, #Attr.3):
@ -46,4 +47,5 @@ procedure Test.0 ():
let Test.8 : List [<rnu>C *self, <null>] = Array [];
let Test.15 : {} = Struct {};
let Test.9 : [<rnu><null>, C {[<rnu>C *self, <null>], *self}] = CallByName List.18 Test.8 Test.6 Test.15;
dec Test.8;
ret Test.9;

View file

@ -3,11 +3,9 @@ procedure List.2 (List.108, List.109):
let List.576 : Int1 = CallByName Num.22 List.109 List.580;
if List.576 then
let List.578 : I64 = CallByName List.66 List.108 List.109;
dec List.108;
let List.577 : [C {}, C I64] = TagId(1) List.578;
ret List.577;
else
dec List.108;
let List.575 : {} = Struct {};
let List.574 : [C {}, C I64] = TagId(0) List.575;
ret List.574;
@ -28,6 +26,7 @@ procedure Test.1 (Test.2):
let Test.6 : List I64 = Array [1i64, 2i64, 3i64];
let Test.7 : U64 = 0i64;
let Test.5 : [C {}, C I64] = CallByName List.2 Test.6 Test.7;
dec Test.6;
ret Test.5;
procedure Test.0 ():

View file

@ -4,11 +4,9 @@ procedure List.2 (List.108, List.109):
if List.576 then
let List.578 : Str = CallByName List.66 List.108 List.109;
inc List.578;
dec List.108;
let List.577 : [C {}, C Str] = TagId(1) List.578;
ret List.577;
else
dec List.108;
let List.575 : {} = Struct {};
let List.574 : [C {}, C Str] = TagId(0) List.575;
ret List.574;
@ -55,13 +53,13 @@ procedure Test.2 ():
procedure Test.3 (Test.4):
let Test.18 : U64 = 2i64;
let Test.17 : Str = CallByName Str.16 Test.4 Test.18;
dec Test.4;
ret Test.17;
procedure Test.0 ():
let Test.12 : List Str = CallByName Test.2;
let Test.13 : U64 = 0i64;
let Test.6 : [C {}, C Str] = CallByName List.2 Test.12 Test.13;
dec Test.12;
let Test.9 : U8 = 1i64;
let Test.10 : U8 = GetTagId Test.6;
let Test.11 : Int1 = lowlevel Eq Test.9 Test.10;

View file

@ -4,11 +4,9 @@ procedure List.2 (List.108, List.109):
if List.576 then
let List.578 : Str = CallByName List.66 List.108 List.109;
inc List.578;
dec List.108;
let List.577 : [C {}, C Str] = TagId(1) List.578;
ret List.577;
else
dec List.108;
let List.575 : {} = Struct {};
let List.574 : [C {}, C Str] = TagId(0) List.575;
ret List.574;
@ -58,6 +56,7 @@ procedure Test.0 ():
let Test.12 : List Str = CallByName Test.2;
let Test.13 : U64 = 0i64;
let Test.6 : [C {}, C Str] = CallByName List.2 Test.12 Test.13;
dec Test.12;
let Test.9 : U8 = 1i64;
let Test.10 : U8 = GetTagId Test.6;
let Test.11 : Int1 = lowlevel Eq Test.9 Test.10;

View file

@ -1,9 +1,10 @@
procedure Test.1 (Test.2):
inc Test.2;
inc 2 Test.2;
let Test.6 : {List I64, List I64} = Struct {Test.2, Test.2};
ret Test.6;
procedure Test.0 ():
let Test.5 : List I64 = Array [1i64, 2i64, 3i64];
let Test.4 : {List I64, List I64} = CallByName Test.1 Test.5;
dec Test.5;
ret Test.4;

View file

@ -7,8 +7,6 @@ procedure Test.1 (Test.3):
ret Test.13;
procedure Test.2 (Test.4, Test.5):
dec Test.5;
dec Test.4;
let Test.9 : U64 = 18i64;
ret Test.9;
@ -18,4 +16,6 @@ procedure Test.0 ():
let Test.10 : {} = Struct {};
let Test.8 : List U16 = CallByName Test.1 Test.10;
let Test.6 : U64 = CallByName Test.2 Test.7 Test.8;
dec Test.8;
dec Test.7;
ret Test.6;

View file

@ -3,11 +3,9 @@ procedure List.2 (List.108, List.109):
let List.593 : Int1 = CallByName Num.22 List.109 List.596;
if List.593 then
let List.595 : I64 = CallByName List.66 List.108 List.109;
dec List.108;
let List.594 : [C {}, C I64] = TagId(1) List.595;
ret List.594;
else
dec List.108;
let List.592 : {} = Struct {};
let List.591 : [C {}, C I64] = TagId(0) List.592;
ret List.591;
@ -45,7 +43,6 @@ procedure Num.22 (#Attr.2, #Attr.3):
procedure Test.1 (Test.2):
let Test.28 : U64 = 0i64;
inc 2 Test.2;
let Test.26 : [C {}, C I64] = CallByName List.2 Test.2 Test.28;
let Test.27 : U64 = 0i64;
let Test.25 : [C {}, C I64] = CallByName List.2 Test.2 Test.27;

View file

@ -3,7 +3,6 @@ procedure Bool.2 ():
ret Bool.23;
procedure Test.10 (Test.26):
dec Test.26;
let Test.30 : Int1 = CallByName Bool.2;
if Test.30 then
let Test.31 : [<rnu><null>, C {}] = CallByName Test.0;
@ -30,6 +29,7 @@ procedure Test.6 (Test.16, #Attr.12):
let Test.19 : {} = Struct {};
let Test.22 : Str = "foobar";
let Test.20 : [<rnu><null>, C {}] = CallByName Test.8 Test.22 Test.23;
dec Test.22;
let Test.21 : U8 = GetTagId Test.20;
switch Test.21:
case 0:

View file

@ -3,11 +3,9 @@ procedure List.2 (List.108, List.109):
let List.593 : Int1 = CallByName Num.22 List.109 List.596;
if List.593 then
let List.595 : I64 = CallByName List.66 List.108 List.109;
dec List.108;
let List.594 : [C {}, C I64] = TagId(1) List.595;
ret List.594;
else
dec List.108;
let List.592 : {} = Struct {};
let List.591 : [C {}, C I64] = TagId(0) List.592;
ret List.591;
@ -44,7 +42,6 @@ procedure Num.22 (#Attr.2, #Attr.3):
ret Num.281;
procedure Test.1 (Test.2, Test.3, Test.4):
inc 2 Test.4;
let Test.29 : [C {}, C I64] = CallByName List.2 Test.4 Test.3;
let Test.28 : [C {}, C I64] = CallByName List.2 Test.4 Test.2;
let Test.13 : {[C {}, C I64], [C {}, C I64]} = Struct {Test.28, Test.29};

View file

@ -1,5 +1,4 @@
procedure Test.1 (Test.2):
dec Test.2;
let Test.11 : Int1 = false;
ret Test.11;
@ -14,6 +13,7 @@ procedure Test.4 (Test.13):
procedure Test.0 ():
let Test.16 : Str = "abc";
let Test.6 : Int1 = CallByName Test.1 Test.16;
dec Test.16;
let Test.9 : {} = Struct {};
switch Test.6:
case 0:

View file

@ -79,6 +79,7 @@ procedure List.92 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
dec List.163;
ret List.164;
in
inc #Derived_gen.0;
jump List.577 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4;
procedure Num.127 (#Attr.2):
@ -110,6 +111,7 @@ procedure Test.20 (Test.58):
ret Test.295;
procedure Test.21 (Test.61, Test.62):
inc Test.61;
let Test.275 : {List Str, {}} = Struct {Test.61, Test.62};
let Test.274 : {List Str, {}} = CallByName Encode.23 Test.275;
ret Test.274;
@ -148,6 +150,7 @@ procedure Test.24 (Test.80, Test.81):
let Test.294 : Str = CallByName Test.20 Test.80;
let Test.271 : List Str = CallByName List.13 Test.81 Test.294;
let Test.270 : {List Str, {}} = CallByName Test.23 Test.271;
dec Test.271;
ret Test.270;
procedure Test.3 ():
@ -191,6 +194,7 @@ procedure Test.63 (Test.64, Test.276, #Attr.12):
let Test.285 : U64 = CallByName List.6 Test.61;
let Test.65 : List U8 = CallByName Test.4 Test.64 Test.284 Test.285;
let Test.278 : List U8 = CallByName List.18 Test.61 Test.65 Test.62;
dec Test.61;
ret Test.278;
procedure Test.66 (Test.67, Test.68, Test.62):

View file

@ -19,7 +19,6 @@ procedure Test.15 (Test.49):
ret Test.70;
procedure Test.16 (Test.48):
dec Test.48;
let Test.79 : {} = Struct {};
let Test.78 : Int1 = CallByName Test.13 Test.79;
ret Test.78;
@ -55,6 +54,7 @@ procedure Test.43 (Test.44, Test.42):
if Test.75 then
let Test.77 : Str = StructAtIndex 0 Test.42;
let Test.76 : Int1 = CallByName Test.16 Test.77;
dec Test.77;
let Test.61 : Int1 = CallByName Test.14 Test.76;
jump Test.62 Test.61;
else

View file

@ -155,6 +155,7 @@ procedure List.92 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.29;
jump List.577 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33;
procedure List.92 (#Derived_gen.52, #Derived_gen.53, #Derived_gen.54, #Derived_gen.55, #Derived_gen.56):
@ -171,6 +172,7 @@ procedure List.92 (#Derived_gen.52, #Derived_gen.53, #Derived_gen.54, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.52;
jump List.604 #Derived_gen.52 #Derived_gen.53 #Derived_gen.54 #Derived_gen.55 #Derived_gen.56;
procedure Num.127 (#Attr.2):
@ -198,6 +200,7 @@ procedure Str.36 (#Attr.2):
ret Str.237;
procedure Test.20 (Test.58):
inc Test.58;
let Test.299 : [C {}, C {}, C Str] = TagId(2) Test.58;
let Test.298 : [C {}, C {}, C Str] = CallByName Encode.23 Test.299;
ret Test.298;
@ -207,11 +210,13 @@ procedure Test.20 (Test.58):
ret Test.342;
procedure Test.21 (Test.61, Test.62):
inc Test.61;
let Test.278 : {List [C {}, C {}, C Str], {}} = Struct {Test.61, Test.62};
let Test.277 : {List [C {}, C {}, C Str], {}} = CallByName Encode.23 Test.278;
ret Test.277;
procedure Test.21 (Test.61, Test.62):
inc Test.61;
let Test.322 : {List Str, {}} = Struct {Test.61, Test.62};
let Test.321 : {List Str, {}} = CallByName Encode.23 Test.322;
ret Test.321;
@ -228,6 +233,7 @@ procedure Test.213 (Test.214, Test.215, Test.212):
let Test.315 : [C {}, C {}, C Str] = CallByName #Derived.0 Test.316;
let Test.314 : List [C {}, C {}, C Str] = Array [Test.315];
let Test.269 : {List [C {}, C {}, C Str], {}} = CallByName Test.24 Test.313 Test.314;
dec Test.313;
jump Test.270 Test.269;
else
let Test.271 : Str = "B";
@ -235,6 +241,7 @@ procedure Test.213 (Test.214, Test.215, Test.212):
let Test.310 : [C {}, C {}, C Str] = CallByName #Derived.5 Test.311;
let Test.272 : List [C {}, C {}, C Str] = Array [Test.310];
let Test.269 : {List [C {}, C {}, C Str], {}} = CallByName Test.24 Test.271 Test.272;
dec Test.271;
jump Test.270 Test.269;
procedure Test.23 (Test.77):
@ -251,12 +258,14 @@ procedure Test.24 (Test.80, Test.81):
let Test.297 : [C {}, C {}, C Str] = CallByName Test.20 Test.80;
let Test.274 : List [C {}, C {}, C Str] = CallByName List.13 Test.81 Test.297;
let Test.273 : {List [C {}, C {}, C Str], {}} = CallByName Test.23 Test.274;
dec Test.274;
ret Test.273;
procedure Test.24 (Test.80, Test.81):
let Test.355 : Str = CallByName Test.20 Test.80;
let Test.354 : List Str = CallByName List.13 Test.81 Test.355;
let Test.353 : {List Str, {}} = CallByName Test.23 Test.354;
dec Test.354;
ret Test.353;
procedure Test.3 ():
@ -311,6 +320,7 @@ procedure Test.63 (Test.64, Test.279, #Attr.12):
let Test.332 : U64 = CallByName List.6 Test.61;
let Test.65 : List U8 = CallByName Test.4 Test.64 Test.331 Test.332;
let Test.325 : List U8 = CallByName List.18 Test.61 Test.65 Test.62;
dec Test.61;
ret Test.325;
procedure Test.63 (Test.64, Test.279, #Attr.12):
@ -320,6 +330,7 @@ procedure Test.63 (Test.64, Test.279, #Attr.12):
let Test.288 : U64 = CallByName List.6 Test.61;
let Test.65 : List U8 = CallByName Test.4 Test.64 Test.287 Test.288;
let Test.281 : List U8 = CallByName List.18 Test.61 Test.65 Test.62;
dec Test.61;
ret Test.281;
procedure Test.66 (Test.67, Test.68, Test.62):

View file

@ -75,6 +75,7 @@ procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
let List.595 : [C U64, C U64] = TagId(1) List.492;
ret List.595;
in
inc #Derived_gen.0;
jump List.594 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4;
procedure Num.22 (#Attr.2, #Attr.3):
@ -96,7 +97,6 @@ procedure Test.3 (Test.4, Test.12):
procedure Test.0 (Test.1):
let Test.10 : U64 = 0i64;
let Test.11 : {} = Struct {};
inc Test.1;
let Test.2 : U64 = CallByName List.26 Test.1 Test.10 Test.11;
let Test.9 : U64 = 0i64;
let Test.7 : Int1 = CallByName Bool.11 Test.2 Test.9;

View file

@ -7,11 +7,8 @@ When(
patterns: [
@14-20 SpaceBefore(
As(
@14-15 SpaceAfter(
Underscore(
"",
),
[],
@14-15 Underscore(
"",
),
PatternAs {
spaces_before: [],

View file

@ -6205,6 +6205,31 @@ mod test_fmt {
);
}
#[test]
fn issue_6215() {
expr_formats_to(
indoc!(
r"
when list is
[first as last]
| [first, last] ->
first
_->Not
"
),
indoc!(
r"
when list is
[first as last]
| [first, last] ->
first
_ -> Not
"
),
);
}
// this is a parse error atm
// #[test]
// fn multiline_apply() {

View file

@ -11,6 +11,7 @@ main =
procedure Inspect.248 (Inspect.249):
let Inspect.313 : Str = "<opaque>";
let Inspect.312 : Str = CallByName Inspect.59 Inspect.249 Inspect.313;
dec Inspect.313;
ret Inspect.312;
procedure Inspect.30 (Inspect.143):
@ -39,7 +40,6 @@ procedure Inspect.5 (Inspect.146):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.315 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.315;
procedure Inspect.60 (Inspect.298):

View file

@ -14,6 +14,7 @@ main =
procedure Inspect.248 (Inspect.249):
let Inspect.313 : Str = "<opaque>";
let Inspect.312 : Str = CallByName Inspect.59 Inspect.249 Inspect.313;
dec Inspect.313;
ret Inspect.312;
procedure Inspect.30 (Inspect.143):
@ -42,7 +43,6 @@ procedure Inspect.5 (Inspect.146):
procedure Inspect.59 (Inspect.296, Inspect.292):
let Inspect.315 : Str = CallByName Str.3 Inspect.296 Inspect.292;
dec Inspect.292;
ret Inspect.315;
procedure Inspect.60 (Inspect.298):

View file

@ -20,11 +20,11 @@ procedure Bool.2 ():
procedure Test.1 (Test.2):
let Test.34 : Int1 = CallByName Bool.2;
if Test.34 then
dec Test.2;
let Test.38 : FunPtr(({}) -> Str) = FunctionPointer Test.3;
let Test.35 : ?Erased = ErasedMake { value: <null>, callee: Test.38 };
ret Test.35;
else
inc Test.2;
let Test.33 : {Str} = Struct {Test.2};
let Test.31 : [<rnu><null>, C {Str}] = TagId(0) Test.33;
let Test.32 : FunPtr(({}, ?Erased) -> Str) = FunctionPointer Test.4;

View file

@ -109,13 +109,16 @@ pub const INTERNAL_ERROR_MESSAGE: &str = concat!(
#[macro_export]
macro_rules! internal_error {
() => ({
$crate::error_and_exit(format_args!("{}", $crate::INTERNAL_ERROR_MESSAGE))
$crate::error_and_exit(format_args!("{}\nLocation: {}:{}:{}", $crate::INTERNAL_ERROR_MESSAGE, file!(), line!(), column!()))
});
($($arg:tt)*) => ({
$crate::error_and_exit(format_args!(
"{}{}",
"{}{}\nLocation: {}:{}:{}",
$crate::INTERNAL_ERROR_MESSAGE,
format_args!($($arg)*)
format_args!($($arg)*),
file!(),
line!(),
column!(),
))
})
}
@ -132,13 +135,16 @@ pub const USER_ERROR_MESSAGE: &str = concat!(
#[macro_export]
macro_rules! user_error {
() => ({
$crate::error_and_exit(format_args!("{}", $crate::USER_ERROR_MESSAGE))
$crate::error_and_exit(format_args!("{}\nLocation: {}:{}:{}", $crate::USER_ERROR_MESSAGE, file!(), line!(), column!()))
});
($($arg:tt)*) => ({
$crate::error_and_exit(format_args!(
"{}{}",
"{}{}\nLocation: {}:{}:{}",
$crate::USER_ERROR_MESSAGE,
format_args!($($arg)*)
format_args!($($arg)*),
file!(),
line!(),
column!(),
))
})
}

11
crates/fs/Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "fs"
description = "no_std filesystem access. These operations all use native OS strings and do not allocate."
authors.workspace = true
edition.workspace = true
license.workspace = true
version.workspace = true
[target.'cfg(windows)'.dependencies]
widestring = { version = "1.1.0", default-features = false }

607
crates/fs/src/file.rs Normal file
View file

@ -0,0 +1,607 @@
use crate::native_path::NativePath;
use core::{fmt, mem::MaybeUninit};
#[cfg(windows)]
use widestring::U16CStr;
#[cfg(unix)]
use core::ffi::{c_char, c_int, CStr};
#[cfg(unix)]
pub struct File {
fd: i32,
}
#[cfg(windows)]
pub struct File {
handle: isize,
}
#[cfg(unix)]
extern "C" {
fn open(pathname: *const c_char, flags: c_int, ...) -> c_int;
fn close(fd: c_int) -> c_int;
fn read(fd: c_int, buf: *mut MaybeUninit<u8>, count: usize) -> isize;
fn write(fd: c_int, buf: *const u8, count: usize) -> isize;
fn mkstemp(template: *mut c_char) -> c_int;
fn unlink(pathname: *const c_char) -> c_int;
}
#[cfg(unix)]
impl Drop for File {
fn drop(&mut self) {
unsafe {
close(self.fd);
}
}
}
#[cfg(windows)]
extern "system" {
fn CreateFileW(
lpFileName: *const u16,
dwDesiredAccess: u32,
dwShareMode: u32,
lpSecurityAttributes: *mut core::ffi::c_void,
dwCreationDisposition: u32,
dwFlagsAndAttributes: u32,
hTemplateFile: isize,
) -> isize;
fn CloseHandle(hObject: isize) -> i32;
fn ReadFile(
hFile: isize,
lpBuffer: *mut MaybeUninit<u8>,
nNumberOfBytesToRead: u32,
lpNumberOfBytesRead: *mut u32,
lpOverlapped: *mut core::ffi::c_void,
) -> i32;
fn WriteFile(
hFile: isize,
lpBuffer: *const u8,
nNumberOfBytesToWrite: u32,
lpNumberOfBytesWritten: *mut u32,
lpOverlapped: *mut core::ffi::c_void,
) -> i32;
fn DeleteFileW(lpFileName: *const u16) -> i32;
fn GetTempPath2W(nBufferLength: u32, lpBuffer: *mut u16) -> u32;
fn GetTempFileNameW(
lpPathName: *const u16,
lpPrefixString: *const u16,
uUnique: u32,
lpTempFileName: *mut u16,
) -> u32;
fn CreateDirectoryW(
lpPathName: *const u16,
lpSecurityAttributes: *mut core::ffi::c_void,
) -> i32;
}
#[cfg(windows)]
impl Drop for File {
fn drop(&mut self) {
unsafe {
CloseHandle(self.handle);
}
}
}
#[cfg_attr(unix, repr(i32))]
#[cfg_attr(windows, repr(u32))]
#[derive(Copy, Clone, PartialEq, Eq)]
#[non_exhaustive] // There are tons of other error numbers that functions which return this might return!
pub enum FileIoErr {
/// "File not found" is the same code (namely, 2) on both UNIX and Windows:
/// ENOENT on UNIX: https://www.man7.org/linux/man-pages/man3/errno.3.html
/// ERROR_FILE_NOT_FOUND on Windows: // https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
NotFound = 2,
#[cfg(unix)]
/// EACCES: https://www.man7.org/linux/man-pages/man3/errno.3.html
AccessDenied = 13,
#[cfg(windows)]
/// ERROR_ACCESS_DENIED: https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
AccessDenied = 5,
#[cfg(unix)]
/// EEXIST: https://www.man7.org/linux/man-pages/man3/errno.3.html
AlreadyExists = 17,
#[cfg(windows)]
/// ERROR_FILE_EXISTS: https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
AlreadyExists = 80,
}
impl fmt::Debug for FileIoErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FileIoErr::NotFound => write!(f, "NotFound ({})", *self as i32),
#[cfg(unix)]
FileIoErr::AccessDenied => write!(f, "AccessDenied ({})", *self as i32),
#[cfg(windows)]
FileIoErr::AccessDenied => write!(f, "AccessDenied ({})", *self as i32),
FileIoErr::AlreadyExists => write!(f, "AlreadyExists ({})", *self as i32),
}
}
}
impl FileIoErr {
#[cfg(target_os = "macos")]
fn most_recent() -> FileIoErr {
extern "C" {
fn __error() -> *mut FileIoErr;
}
unsafe { *__error() }
}
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
fn most_recent() -> FileIoErr {
extern "C" {
fn __errno_location() -> *mut FileIoErr;
}
unsafe { *__errno_location() }
}
#[cfg(windows)]
fn most_recent() -> FileIoErr {
extern "system" {
fn GetLastError() -> FileIoErr;
}
unsafe { GetLastError() }
}
}
// OPEN FILE //
#[cfg(unix)]
impl File {
const O_WRONLY: c_int = 1;
const O_RDWR: c_int = 2;
/// source: https://github.com/apple-open-source/macos/blob/8038f956fee603c486e75adbf93cac7a66064f02/Libc/exclave/sys/fcntl.h#L104
#[cfg(target_os = "macos")]
const O_CREAT: c_int = 512;
#[cfg(not(target_os = "macos"))]
const O_CREAT: c_int = 64;
/// source: https://github.com/apple-open-source/macos/blob/8038f956fee603c486e75adbf93cac7a66064f02/Libc/exclave/sys/fcntl.h#L106
#[cfg(target_os = "macos")]
const O_EXCL: c_int = 2048;
#[cfg(not(target_os = "macos"))]
const O_EXCL: c_int = 128;
pub fn open(path: &NativePath) -> Result<Self, FileIoErr> {
let fd = unsafe { open(path.inner.as_ptr(), Self::O_RDWR) };
if fd != -1 {
Ok(File { fd })
} else {
Err(FileIoErr::most_recent())
}
}
pub fn create(path: &NativePath) -> Result<Self, FileIoErr> {
let fd = unsafe {
open(
path.inner.as_ptr(),
Self::O_CREAT | Self::O_WRONLY | Self::O_EXCL, // O_EXCL means fail if it already exists
// read/write mode
0o644,
)
};
if fd != -1 {
Ok(File { fd })
} else {
Err(FileIoErr::most_recent())
}
}
}
#[cfg(windows)]
impl File {
const GENERIC_READ: u32 = 0x80000000;
const GENERIC_WRITE: u32 = 0x40000000;
const FILE_SHARE_READ: u32 = 1;
const FILE_SHARE_WRITE: u32 = 2;
const CREATE_NEW: u32 = 1;
const CREATE_ALWAYS: u32 = 2;
const OPEN_EXISTING: u32 = 3;
pub fn open(path: &NativePath) -> Result<Self, FileIoErr> {
let handle = unsafe {
CreateFileW(
path.inner.as_ptr(),
Self::GENERIC_READ | Self::GENERIC_WRITE,
Self::FILE_SHARE_READ | Self::FILE_SHARE_WRITE,
core::ptr::null_mut(),
Self::OPEN_EXISTING,
0,
0,
)
};
if handle != -1 {
Ok(File { handle })
} else {
Err(FileIoErr::most_recent())
}
}
pub fn create(path: &NativePath) -> Result<Self, FileIoErr> {
let handle = unsafe {
CreateFileW(
path.inner.as_ptr(),
Self::GENERIC_READ | Self::GENERIC_WRITE,
Self::FILE_SHARE_READ | Self::FILE_SHARE_WRITE,
core::ptr::null_mut(),
Self::CREATE_ALWAYS,
0,
0,
)
};
if handle != -1 {
Ok(File { handle })
} else {
Err(FileIoErr::most_recent())
}
}
}
// REMOVE //
#[cfg(unix)]
impl File {
/// Returns whether it succeeded.
pub fn remove(path: &NativePath) -> bool {
unsafe { unlink(path.inner.as_ptr()) == 0 }
}
}
#[cfg(windows)]
impl File {
/// Source: https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Foundation/constant.MAX_PATH.html
const MAX_PATH: u32 = 260;
/// Returns whether it succeeded.
pub fn remove(path: &NativePath) -> bool {
unsafe { DeleteFileW(path.inner.as_ptr()) != 0 }
}
}
// TEMPFILE //
#[cfg(unix)]
impl File {
/// Create a tempfile, open it as a File, pass that File and its generated path
/// to the given function, and then delete it after the function returns.
pub fn with_tempfile<T>(
run: impl FnOnce(Result<(&NativePath, &mut Self), FileIoErr>) -> T,
) -> T {
const TEMPLATE: &[u8] = b"/tmp/roc_tempfile_XXXXXX\0";
let mut template = [0; TEMPLATE.len()];
template.copy_from_slice(TEMPLATE);
// mkstemp replaces the Xs in the template with chars that result in a unique path.
let fd = unsafe { mkstemp(template.as_mut_ptr().cast()) };
if fd != -1 {
let path_cstr = unsafe { CStr::from_bytes_with_nul_unchecked(&template) };
let native_path: &NativePath = path_cstr.into();
let mut file = File { fd };
// Since we pass an owned File, it will get closed automatically once dropped.
// This in turn will result in the file getting deleted, since we already unlinked it.
let answer = run(Ok((native_path, &mut file)));
// Unlink the file now that we're done with it.
unsafe {
unlink(template.as_ptr().cast());
}
answer
} else {
// Here we assume that since mkstemp errored out, the file was not created
// and we shouldn't attempt to unlink it.
run(Err(FileIoErr::most_recent()))
}
}
}
#[cfg(windows)]
impl File {
/// Create a tempfile, open it as a File, pass that File and its generated path
/// to the given function, and then delete it after the function returns.
pub fn with_tempfile<T>(
run: impl FnOnce(Result<(&NativePath, &mut Self), FileIoErr>) -> T,
) -> T {
let tempdir_path: &mut [MaybeUninit<u16>] =
&mut [MaybeUninit::uninit(); Self::MAX_PATH as usize + 1];
let tempdir_path_len =
unsafe { GetTempPath2W(tempdir_path.len() as u32, tempdir_path.as_mut_ptr().cast()) };
if tempdir_path_len == 0 {
return run(Err(FileIoErr::most_recent()));
}
let suffix =
// Note: only up to the first 3 chars of this string will be used,
// so we only give it 3.
//
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettempfilenamew
widestring::u16cstr!("roc").as_slice_with_nul();
let tempfile_path: &mut [MaybeUninit<u16>] =
&mut [MaybeUninit::uninit(); Self::MAX_PATH as usize + 1];
let result = unsafe {
GetTempFileNameW(
tempdir_path.as_ptr().cast(),
suffix.as_ptr(),
0,
tempfile_path.as_mut_ptr().cast(),
)
};
if result == 0 {
return run(Err(FileIoErr::most_recent()));
}
let handle = unsafe {
CreateFileW(
tempfile_path.as_mut_ptr().cast(),
Self::GENERIC_WRITE,
Self::FILE_SHARE_READ | Self::FILE_SHARE_WRITE,
core::ptr::null_mut(),
Self::CREATE_ALWAYS,
0x80, // FILE_ATTRIBUTE_TEMPORARY
0,
)
};
if handle != -1 {
let mut file = File { handle };
let native_path = unsafe { U16CStr::from_ptr_str(tempfile_path.as_ptr().cast()) };
// Windows automatically deletes tempfiles when the last handle
// to them is closed, so we don't need to delete this explicitly.
run(Ok((native_path.into(), &mut file)))
} else {
run(Err(FileIoErr::most_recent()))
}
}
}
// READ FILE //
impl File {
#[cfg(unix)]
pub fn read_into<'buf>(
&mut self,
buf: &'buf mut [MaybeUninit<u8>],
) -> Result<&'buf mut [u8], FileIoErr> {
let bytes_read = unsafe { read(self.fd, buf.as_mut_ptr(), buf.len()) };
if bytes_read >= 0 {
// Return the subset of the buf that we actually initialized.
let buf_ptr = buf.as_mut_ptr();
let len = bytes_read as usize;
Ok(unsafe { core::slice::from_raw_parts_mut(buf_ptr.cast(), len) })
} else {
Err(FileIoErr::most_recent())
}
}
#[cfg(windows)]
pub fn read_into<'buf>(
&mut self,
buf: &'buf mut [MaybeUninit<u8>],
) -> Result<&'buf mut [u8], FileIoErr> {
let mut bytes_read: u32 = 0;
let result = unsafe {
ReadFile(
self.handle,
buf.as_mut_ptr(),
buf.len() as u32,
&mut bytes_read,
core::ptr::null_mut(),
)
};
if result >= 0 {
let buf_ptr = buf.as_mut_ptr();
let len = bytes_read as usize;
Ok(unsafe { core::slice::from_raw_parts_mut(buf_ptr.cast(), len) })
} else {
Err(FileIoErr::most_recent())
}
}
}
// WRITE FILE //
impl File {
#[cfg(unix)]
pub fn write(&mut self, buf: &[u8]) -> Result<usize, FileIoErr> {
let bytes_written = unsafe { write(self.fd, buf.as_ptr(), buf.len()) };
if bytes_written >= 0 {
Ok(bytes_written as usize)
} else {
Err(FileIoErr::most_recent())
}
}
#[cfg(windows)]
pub fn write(&mut self, buf: &[u8]) -> Result<usize, FileIoErr> {
let mut bytes_written: u32 = 0;
let result = unsafe {
WriteFile(
self.handle,
buf.as_ptr(),
buf.len() as u32,
&mut bytes_written,
core::ptr::null_mut(),
)
};
if result != 0 {
Ok(bytes_written as usize)
} else {
Err(FileIoErr::most_recent())
}
}
}
#[cfg(test)]
mod tests {
use super::{File, FileIoErr};
use crate::native_path::NativePath;
use core::mem::MaybeUninit;
#[cfg(unix)]
use core::ffi::CStr;
#[cfg(windows)]
use widestring::U16CStr;
#[cfg(unix)]
fn str_to_cstr(s: &str) -> &CStr {
CStr::from_bytes_with_nul(s.as_bytes()).expect("CStr conversion failed")
}
#[cfg(windows)]
fn str_to_u16cstr(s: &str) -> &widestring::U16CStr {
let wide_str: Vec<u16> = s.encode_utf16().collect::<Vec<_>>();
unsafe { U16CStr::from_ptr_str(wide_str.as_ptr()) }
}
#[cfg(unix)]
fn mock_path(path: &str) -> &NativePath {
str_to_cstr(path).into()
}
#[cfg(windows)]
fn mock_path(path: &str) -> &NativePath {
str_to_u16cstr(path).into()
}
#[test]
fn file_not_found() {
let file_result = File::open(mock_path("test_file_that_should_not_exist\0"));
assert_eq!(
file_result.map(|_| ()),
Err(FileIoErr::NotFound),
"File should not exist: test_file_that_should_not_exist"
);
}
#[test]
fn create_write_read_delete() {
let path = mock_path("roc_test_read_file\0");
let mut file = File::create(path).unwrap();
// Write some data to the file
let write_data: &[u8] = &[42u8; 10];
let write_result = file.write(write_data);
assert_eq!(
write_result,
Ok(write_data.len()),
"Failed to write all data to the file: roc_test_read_file"
);
// Close the file by dropping the file descriptor
drop(file);
// Reopen the file
let mut file = File::open(path).unwrap();
let mut input_buf = [MaybeUninit::uninit(); 10];
let result = file.read_into(&mut input_buf);
assert_eq!(
result.map(|mut_slice| &*mut_slice),
Ok(write_data),
"Failed to read all the data from the file: roc_test_read_file"
);
// Close the file by dropping the file descriptor
drop(file);
// Remove the file
let result = File::remove(path);
assert!(result, "Failed to remove the file: roc_test_read_file");
// Verify that the file no longer exists
let file_result = File::open(path);
assert_eq!(
file_result.map(|_| ()),
Err(FileIoErr::NotFound),
"File should not exist after removal: roc_test_read_file"
);
}
#[test]
fn tempfile() {
const DATA: &[u8] = &[42; 10];
let buf = &mut [MaybeUninit::uninit(); DATA.len()];
let answer = File::with_tempfile(|result| {
let (native_path, file) = result.unwrap();
// Write some data to the tempfile
assert_eq!(
Ok(DATA.len()),
file.write(DATA),
"Failed to write all the bytes to the tempfile"
);
// Reopen the tempfile with a fresh file descriptor, and read the data back in from it
File::open(native_path).unwrap().read_into(buf)
});
// The data read should match the data written
assert_eq!(
Ok(DATA),
answer.map(|mut_slice| &*mut_slice),
"Data read from the file does not match data written to the file"
);
}
#[test]
fn create_file_that_already_exists() {
let path = mock_path("roc_test_already_exists\0");
let first = File::create(path); // Create the file for the first time
let second = File::create(path); // Attempt to create the same file again
let removed = File::remove(path); // Remove the file now that we're done with it (before we do any assertions!)
assert!(
first.is_ok(),
"Failed to create the file: roc_test_already_exists"
);
assert_eq!(
second.map(|_| ()),
Err(FileIoErr::AlreadyExists),
"File should already exist: roc_test_already_exists"
);
assert!(
removed,
"Failed to remove the file: roc_test_already_exists"
);
}
}

7
crates/fs/src/lib.rs Normal file
View file

@ -0,0 +1,7 @@
#![cfg_attr(not(any(debug_assertions, test)), no_std)]
mod file;
mod native_path;
pub use file::*;
pub use native_path::*;

View file

@ -0,0 +1,41 @@
use core::{fmt, mem};
#[cfg(unix)]
use core::ffi::CStr;
#[cfg(windows)]
use widestring::U16CStr;
#[cfg(unix)]
#[repr(transparent)]
pub struct NativePath {
pub(crate) inner: CStr,
}
#[cfg(windows)]
#[repr(transparent)]
pub struct NativePath {
pub(crate) inner: U16CStr,
}
impl fmt::Debug for NativePath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
#[cfg(unix)]
impl<'a> From<&'a CStr> for &'a NativePath {
fn from(c_str: &'a CStr) -> Self {
// Safety: Self is repr(transparent)
unsafe { mem::transmute(c_str) }
}
}
#[cfg(windows)]
impl<'a> From<&'a U16CStr> for &'a NativePath {
fn from(u16_c_str: &'a U16CStr) -> Self {
// Safety: Self is repr(transparent)
unsafe { mem::transmute(u16_c_str) }
}
}

View file

@ -1,21 +1,18 @@
app "rust-glue"
packages { pf: "../platform/main.roc" }
imports [
pf.Types.{ Types },
pf.Shape.{ Shape, RocFn },
pf.File.{ File },
pf.TypeId.{ TypeId },
"../static/Cargo.toml" as rocAppCargoToml : Str,
"../../roc_std/Cargo.toml" as rocStdCargoToml : Str,
"../../roc_std/src/lib.rs" as rocStdLib : Str,
"../../roc_std/src/roc_box.rs" as rocStdBox : Str,
"../../roc_std/src/roc_list.rs" as rocStdList : Str,
"../../roc_std/src/roc_dict.rs" as rocStdDict : Str,
"../../roc_std/src/roc_set.rs" as rocStdSet : Str,
"../../roc_std/src/roc_str.rs" as rocStdStr : Str,
"../../roc_std/src/storage.rs" as rocStdStorage : Str,
]
provides [makeGlue] to pf
app [makeGlue] { pf: platform "../platform/main.roc" }
import pf.Types exposing [Types]
import pf.Shape exposing [Shape, RocFn]
import pf.File exposing [File]
import pf.TypeId exposing [TypeId]
import "../static/Cargo.toml" as rocAppCargoToml : Str
import "../../roc_std/Cargo.toml" as rocStdCargoToml : Str
import "../../roc_std/src/lib.rs" as rocStdLib : Str
import "../../roc_std/src/roc_box.rs" as rocStdBox : Str
import "../../roc_std/src/roc_list.rs" as rocStdList : Str
import "../../roc_std/src/roc_dict.rs" as rocStdDict : Str
import "../../roc_std/src/roc_set.rs" as rocStdSet : Str
import "../../roc_std/src/roc_str.rs" as rocStdStr : Str
import "../../roc_std/src/storage.rs" as rocStdStorage : Str
makeGlue : List Types -> Result (List File) Str
makeGlue = \typesByArch ->
@ -167,6 +164,7 @@ generateEntryPoint = \buf, types, name, id ->
when Types.shape types rocFn.ret is
Function _ ->
("(_: *mut u8, $(arguments))", ret, Bool.true)
_ ->
("(_: *mut $(ret), $(arguments))", ret, Bool.false)
@ -646,6 +644,30 @@ generateDestructorFunction = \buf, types, tagUnionType, name, optPayload ->
else
"unsafe { core::mem::ManuallyDrop::take(&mut self.payload.$(name)) }"
(borrow, borrowType) =
if canDeriveCopy types shape then
("unsafe { self.payload.$(name) }", payloadType)
else
(
"""
use core::borrow::Borrow;
unsafe { self.payload.$(name).borrow() }
""",
"&$(payloadType)",
)
(borrowMut, borrowMutType) =
if canDeriveCopy types shape then
("unsafe { &mut self.payload.$(name) }", "&mut $(payloadType)")
else
(
"""
use core::borrow::BorrowMut;
unsafe { self.payload.$(name).borrow_mut() }
""",
"&mut $(payloadType)",
)
"""
$(buf)
@ -654,6 +676,16 @@ generateDestructorFunction = \buf, types, tagUnionType, name, optPayload ->
$(take)
}
pub fn borrow_$(name)(&self) -> $(borrowType) {
debug_assert_eq!(self.discriminant, discriminant_$(tagUnionType)::$(name));
$(borrow)
}
pub fn borrow_mut_$(name)(&mut self) -> $(borrowMutType) {
debug_assert_eq!(self.discriminant, discriminant_$(tagUnionType)::$(name));
$(borrowMut)
}
pub fn is_$(name)(&self) -> bool {
matches!(self.discriminant, discriminant_$(tagUnionType)::$(name))
}
@ -1286,6 +1318,7 @@ writeIndents = \buf, indents ->
|> Str.concat indent
|> writeIndents (indents - 1)
writeTagImpls : Str, List { name : Str, payload : [Some TypeId, None] }, Str, U64, (Str, [Some TypeId, None] -> Str) -> Str
writeTagImpls = \buf, tags, discriminantName, indents, f ->
buf
|> writeIndents indents

View file

@ -399,8 +399,7 @@ pub fn load_types(
ignore_errors: IgnoreErrors,
target: Target,
) -> Result<Vec<Types>, io::Error> {
// TODO the function kind may need to be parameterizable.
let function_kind = FunctionKind::LambdaSet;
let function_kind = FunctionKind::from_env();
let arena = &Bump::new();
let LoadedModule {
module_id: home,

View file

@ -117,7 +117,7 @@ mod glue_cli_run {
`Bar 123` is: NonRecursive::Bar(123)
`Baz` is: NonRecursive::Baz(())
`Blah 456` is: NonRecursive::Blah(456)
"#),
"#),
nullable_wrapped:"nullable-wrapped" => indoc!(r#"
tag_union was: StrFingerTree::More("foo", StrFingerTree::More("bar", StrFingerTree::Empty))
`More "small str" (Single "other str")` is: StrFingerTree::More("small str", StrFingerTree::Single("other str"))
@ -232,7 +232,7 @@ mod glue_cli_run {
.join("RustGlue.roc");
// Generate a fresh test_glue for this platform
let glue_out = run_glue(
let parts : Vec<_> =
// converting these all to String avoids lifetime issues
std::iter::once("glue".to_string()).chain(
args.into_iter().map(|arg| arg.to_string()).chain([
@ -240,12 +240,13 @@ mod glue_cli_run {
glue_dir.to_str().unwrap().to_string(),
platform_module_path.to_str().unwrap().to_string(),
]),
),
);
).collect();
let glue_out = run_glue(parts.iter());
if has_error(&glue_out.stderr) {
panic!(
"`roc glue` command had unexpected stderr: {}",
"`roc {}` command had unexpected stderr: {}",
parts.join(" "),
glue_out.stderr
);
}

View file

@ -566,3 +566,22 @@ fn freeing_boxes() {
"#
));
}
#[test]
fn joinpoint_that_owns() {
valgrind_test(indoc!(
r#"
(
writeIndents = \buf, indents ->
if indents <= 0 then
buf
else
buf
|> Str.concat " "
|> writeIndents (indents - 1)
List.walk [{}, {}] "" \accum, {} -> accum |> writeIndents 4
)
"#
));
}