From b934ac2e50316a64ba1a168ccc2fb7510eafd7fe Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 27 Feb 2025 10:58:57 +0100 Subject: [PATCH 01/57] main.rs first step -> input file to output ptx --- Cargo.toml | 4 ++++ src/lib.rs | 20 ++++++++++++++++++++ src/main.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 6c81127a..865caf96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,5 +16,9 @@ features = ["color"] [dependencies.descend_derive] path = "./descend_derive" +[dependencies.clap] +version = "4.3" +features = ["derive"] + [workspace] members = ["descend_derive"] \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 87a0c26d..13c174eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ extern crate core; use crate::error::ErrorReported; +use std::fs::write; mod ast; mod codegen; @@ -8,9 +9,28 @@ pub mod error; pub mod parser; pub mod ty_check; +/** pub fn compile(file_path: &str) -> Result { let source = parser::SourceCode::from_file(file_path)?; let mut compil_unit = parser::parse(&source)?; ty_check::ty_check(&mut compil_unit)?; Ok(codegen::gen(&compil_unit, false)) } +*/ + +pub fn compile(file_path: &str, output_path: Option<&str>) -> Result { + let source = parser::SourceCode::from_file(file_path)?; + let mut compil_unit = parser::parse(&source)?; + ty_check::ty_check(&mut compil_unit)?; + let generated_code = codegen::gen(&compil_unit, false); + + if let Some(out) = output_path { + write(out, &generated_code).map_err(|e| { + eprintln!("Error writing output file {}: {}", out, e); + ErrorReported + })?; + } + + Ok(generated_code) +} + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 00000000..2c9862ed --- /dev/null +++ b/src/main.rs @@ -0,0 +1,47 @@ +use clap::{Parser}; +use descend::{compile, error::ErrorReported}; +use std::process::exit; + +/// Descend Compiler CLI +#[derive(Parser, Debug)] +#[command(name = "descendc", version = "1.0", about = "Descend GPU Compiler")] +struct Cli { + pub input: String, + + #[arg(short, long)] + pub output: Option, + + #[arg(short, long)] + pub debug: bool, + + #[arg(short, long)] + pub verbose: bool, +} + +fn main() { + let args = Cli::parse(); + + println!("Compiling: {}", args.input); + + if args.debug { + println!("Debug mode enabled."); + } + + if args.verbose { + println!("Verbose output enabled."); + } + + match compile(&args.input, args.output.as_deref()) { + Ok(ptx_code) => { + if args.output.is_none() { + println!("{}", ptx_code); + } else { + println!("Compilation successful! Output written to {:?}", args.output); + } + } + Err(ErrorReported) => { + eprintln!("Compilation failed."); + exit(1); + } + } +} From 7bd9c008cc2aef1ca9f0a2db5deeb2df9bb566de Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 27 Feb 2025 17:14:36 +0100 Subject: [PATCH 02/57] new compile function, updated testcases to new compile function, added new flags to main.rs, fixed typo in readme --- README.md | 2 +- src/lib.rs | 9 --- src/main.rs | 108 +++++++++++++++++++++++++++++++++--- tests/example_infer_apps.rs | 38 ++++++------- tests/rodinia.rs | 2 +- 5 files changed, 120 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 6a1773a1..2281bb7d 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ codegen cuda-examples/ --------------------- -* Contains handwritte or generated CUDA programs +* Contains handwritten or generated CUDA programs * Contains `descend.cuh`; the header file which is required in order to compile Descend programs, that were translated to CUDA, with `nvcc` (contains for example the implementation of `exec`) diff --git a/src/lib.rs b/src/lib.rs index 13c174eb..4246b6ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,14 +9,6 @@ pub mod error; pub mod parser; pub mod ty_check; -/** -pub fn compile(file_path: &str) -> Result { - let source = parser::SourceCode::from_file(file_path)?; - let mut compil_unit = parser::parse(&source)?; - ty_check::ty_check(&mut compil_unit)?; - Ok(codegen::gen(&compil_unit, false)) -} -*/ pub fn compile(file_path: &str, output_path: Option<&str>) -> Result { let source = parser::SourceCode::from_file(file_path)?; @@ -33,4 +25,3 @@ pub fn compile(file_path: &str, output_path: Option<&str>) -> Result, + /// Print CUDA code to stdout instead of saving + #[arg(long)] + pub emit_cuda: bool, + + /// Compile CUDA code with `nvcc` + #[arg(long)] + pub compile: bool, + + /// Run the compiled executable + #[arg(long)] + pub run: bool, + + /// Specify CUDA architecture (e.g., `sm_75`, `sm_80`) + #[arg(long, default_value = "sm_75")] + pub arch: String, + + /// Optimization level for `nvcc` (`0-3`) + #[arg(long, default_value = "3")] + pub optimize: u8, + + /// Additional flags to pass directly to `nvcc` + #[arg(long, default_value = "")] + pub nvcc_flags: String, + + /// Enable debug mode #[arg(short, long)] pub debug: bool, + /// Enable verbose output #[arg(short, long)] pub verbose: bool, } @@ -26,21 +55,82 @@ fn main() { if args.debug { println!("Debug mode enabled."); } - if args.verbose { println!("Verbose output enabled."); } - match compile(&args.input, args.output.as_deref()) { - Ok(ptx_code) => { - if args.output.is_none() { - println!("{}", ptx_code); - } else { - println!("Compilation successful! Output written to {:?}", args.output); + // Step 1: Compile Descend to CUDA code + match compile(&args.input, None) { + Ok(cuda_code) => { + // Step 2: Print CUDA code instead of saving it if `--emit-cuda` is set + if args.emit_cuda { + println!("Generated CUDA Code:\n{}", cuda_code); + return; // Exit early, no further processing needed + } + + // Step 3: Compile CUDA code with `nvcc` if `--compile` is set + if args.compile { + let cuda_file = args.output.clone().unwrap_or_else(|| args.input.replace(".desc", ".cu")); + let executable = cuda_file.replace(".cu", ""); // Remove .cu for output binary + + // Save CUDA file before compilation + if let Err(e) = write(&cuda_file, &cuda_code) { + eprintln!("Error writing CUDA file {}: {}", cuda_file, e); + exit(1); + } + println!("CUDA code saved to: {}", cuda_file); + + println!("Compiling CUDA with nvcc..."); + + // Include `descend.cuh` directory in the compilation command + let mut nvcc_cmd = Command::new("nvcc"); + nvcc_cmd.arg(&cuda_file) + .arg(&cuda_file) // Input CUDA file + .arg("-o").arg(&executable) // Output executable + .arg(format!("-O{}", args.optimize)) // Pass `--optimize` + .arg("-I").arg("cuda-examples/") // Include path for `descend.cuh` + .args(args.nvcc_flags.split_whitespace()); // Pass custom `--nvcc-flags` + + if args.arch != "none" { + nvcc_cmd.arg(format!("-arch={}", args.arch)); // Only add `-arch` if not "none" + } + + let nvcc_output = nvcc_cmd.output(); + + match nvcc_output { + Ok(output) if output.status.success() => { + println!("Successfully compiled: {}", executable); + + // Step 4: Run the executable if `--run` is set + if args.run { + println!("Running {}...", executable); + let run_output = Command::new(format!("./{}", executable)).output(); + + match run_output { + Ok(run) => { + println!("Program output:\n{}", String::from_utf8_lossy(&run.stdout)); + println!("Program errors:\n{}", String::from_utf8_lossy(&run.stderr)); + } + Err(e) => { + eprintln!("Error running executable: {}", e); + exit(1); + } + } + } + } + Ok(output) => { + eprintln!("nvcc compilation failed:\n{}", String::from_utf8_lossy(&output.stderr)); + exit(1); + } + Err(e) => { + eprintln!("Failed to run nvcc: {}", e); + exit(1); + } + } } } Err(ErrorReported) => { - eprintln!("Compilation failed."); + eprintln!("Descend compilation failed."); exit(1); } } diff --git a/tests/example_infer_apps.rs b/tests/example_infer_apps.rs index 75516f9d..77b8da44 100644 --- a/tests/example_infer_apps.rs +++ b/tests/example_infer_apps.rs @@ -8,7 +8,7 @@ type Res = Result<(), descend::error::ErrorReported>; fn transpose() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/transpose.desc")? + descend::compile("examples/infer/transpose.desc", None)? )) } @@ -16,7 +16,7 @@ fn transpose() -> Res { fn transpose_shrd_mem() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/transpose_shrd_mem.desc")? + descend::compile("examples/infer/transpose_shrd_mem.desc", None)? )) } @@ -24,7 +24,7 @@ fn transpose_shrd_mem() -> Res { fn matmul() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/matmul.desc")? + descend::compile("examples/infer/matmul.desc", None)? )) } @@ -32,7 +32,7 @@ fn matmul() -> Res { fn scale_vec() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/scale_vec.desc")? + descend::compile("examples/infer/scale_vec.desc", None)? )) } @@ -40,7 +40,7 @@ fn scale_vec() -> Res { fn reverse_vec() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/reverse_vec.desc")? + descend::compile("examples/infer/reverse_vec.desc", None)? )) } @@ -49,7 +49,7 @@ fn reverse_vec() -> Res { fn bitonic_sort() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/bitonic_sort/bitonic_sort.desc")? + descend::compile("examples/infer/bitonic_sort/bitonic_sort.desc", None)? )) } @@ -62,7 +62,7 @@ fn scan() -> Res { ); Ok(println!( "{}", - descend::compile("examples/infer/scan.desc")? + descend::compile("examples/infer/scan.desc", None)? )) } @@ -70,7 +70,7 @@ fn scan() -> Res { fn reduce_shared_mem() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/reduce_shared_mem.desc")? + descend::compile("examples/infer/reduce_shared_mem.desc", None)? )) } @@ -78,7 +78,7 @@ fn reduce_shared_mem() -> Res { fn vlc_encode() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/huffman/vlc_encode.desc")? + descend::compile("examples/infer/huffman/vlc_encode.desc", None)? )) } @@ -86,7 +86,7 @@ fn vlc_encode() -> Res { fn vlc_encode_cg() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/huffman/vlc_encode_cg.desc")? + descend::compile("examples/infer/huffman/vlc_encode_cg.desc", None)? )) } @@ -94,7 +94,7 @@ fn vlc_encode_cg() -> Res { fn vlc_encode_reuse() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/huffman/vlc_encode_reuse.desc")? + descend::compile("examples/infer/huffman/vlc_encode_reuse.desc", None)? )) } @@ -102,7 +102,7 @@ fn vlc_encode_reuse() -> Res { fn histogram() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/huffman/histogram.desc")? + descend::compile("examples/infer/huffman/histogram.desc", None)? )) } @@ -110,7 +110,7 @@ fn histogram() -> Res { fn tree_reduce() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/tree_reduce.desc")? + descend::compile("examples/infer/tree_reduce.desc", None)? )) } @@ -118,21 +118,21 @@ fn tree_reduce() -> Res { fn vector_add() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/vec_add.desc")? + descend::compile("examples/infer/vec_add.desc", None)? )) } #[ignore] #[test] fn bfs() -> Res { - Ok(println!("{}", descend::compile("examples/infer/bfs.desc")?)) + Ok(println!("{}", descend::compile("examples/infer/bfs.desc", None)?)) } #[test] fn sgemm() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/sgemm.desc")? + descend::compile("examples/infer/sgemm.desc", None)? )) } @@ -140,7 +140,7 @@ fn sgemm() -> Res { fn shrd_mem_acc_equiv_exec() -> Res { Ok(println!( "{}", - descend::compile("examples/shrd_mem_acc_equiv_exec.desc")? + descend::compile("examples/shrd_mem_acc_equiv_exec.desc", None)? )) } @@ -148,7 +148,7 @@ fn shrd_mem_acc_equiv_exec() -> Res { fn sssp_ffi_unsafe() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/sssp-ffi.desc")? + descend::compile("examples/infer/sssp-ffi.desc", None)? )) } @@ -156,6 +156,6 @@ fn sssp_ffi_unsafe() -> Res { fn jacobisvd() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/jacobisvd.desc")? + descend::compile("examples/infer/jacobisvd.desc", None)? )) } diff --git a/tests/rodinia.rs b/tests/rodinia.rs index 985991d3..999be076 100644 --- a/tests/rodinia.rs +++ b/tests/rodinia.rs @@ -9,6 +9,6 @@ type Res = Result<(), descend::error::ErrorReported>; fn gaussian() -> Res { Ok(println!( "{}", - descend::compile("examples/rodinia/gaussian.desc")? + descend::compile("examples/rodinia/gaussian.desc", None)? )) } From 4faa22743f3e7eb9544f14deffeb62b11931b8c2 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 6 Mar 2025 16:10:31 +0100 Subject: [PATCH 03/57] removed comments --- src/main.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/main.rs b/src/main.rs index 22f61eb5..80394df9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,26 +3,20 @@ use descend::{compile, error::ErrorReported}; use std::fs::write; use std::process::{Command, exit}; -/// Descend Compiler CLI #[derive(Parser, Debug)] #[command(name = "descendc", version = "1.0", about = "Descend GPU Compiler")] struct Cli { - /// Input Descend source file pub input: String, - /// Output CUDA file (optional, default: input_name.cu) #[arg(short, long)] pub output: Option, - /// Print CUDA code to stdout instead of saving #[arg(long)] pub emit_cuda: bool, - /// Compile CUDA code with `nvcc` #[arg(long)] pub compile: bool, - /// Run the compiled executable #[arg(long)] pub run: bool, @@ -38,11 +32,9 @@ struct Cli { #[arg(long, default_value = "")] pub nvcc_flags: String, - /// Enable debug mode #[arg(short, long)] pub debug: bool, - /// Enable verbose output #[arg(short, long)] pub verbose: bool, } @@ -59,21 +51,18 @@ fn main() { println!("Verbose output enabled."); } - // Step 1: Compile Descend to CUDA code match compile(&args.input, None) { Ok(cuda_code) => { - // Step 2: Print CUDA code instead of saving it if `--emit-cuda` is set + // Print CUDA code instead of saving it if `--emit-cuda` is set if args.emit_cuda { println!("Generated CUDA Code:\n{}", cuda_code); - return; // Exit early, no further processing needed + return; } - // Step 3: Compile CUDA code with `nvcc` if `--compile` is set if args.compile { let cuda_file = args.output.clone().unwrap_or_else(|| args.input.replace(".desc", ".cu")); let executable = cuda_file.replace(".cu", ""); // Remove .cu for output binary - // Save CUDA file before compilation if let Err(e) = write(&cuda_file, &cuda_code) { eprintln!("Error writing CUDA file {}: {}", cuda_file, e); exit(1); @@ -101,7 +90,6 @@ fn main() { Ok(output) if output.status.success() => { println!("Successfully compiled: {}", executable); - // Step 4: Run the executable if `--run` is set if args.run { println!("Running {}...", executable); let run_output = Command::new(format!("./{}", executable)).output(); From c0986cab565818fe213c17b152aefdee097b7ac7 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 6 Mar 2025 16:32:15 +0100 Subject: [PATCH 04/57] removed print statements and added bin entry to toml --- Cargo.toml | 4 ++++ src/main.rs | 7 ------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 865caf96..ef945967 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[[bin]] +name = "descendc" +path = "src/main.rs" + [dependencies.peg] version = "0.8.0" diff --git a/src/main.rs b/src/main.rs index 80394df9..3aea182d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,8 +42,6 @@ struct Cli { fn main() { let args = Cli::parse(); - println!("Compiling: {}", args.input); - if args.debug { println!("Debug mode enabled."); } @@ -67,9 +65,6 @@ fn main() { eprintln!("Error writing CUDA file {}: {}", cuda_file, e); exit(1); } - println!("CUDA code saved to: {}", cuda_file); - - println!("Compiling CUDA with nvcc..."); // Include `descend.cuh` directory in the compilation command let mut nvcc_cmd = Command::new("nvcc"); @@ -88,10 +83,8 @@ fn main() { match nvcc_output { Ok(output) if output.status.success() => { - println!("Successfully compiled: {}", executable); if args.run { - println!("Running {}...", executable); let run_output = Command::new(format!("./{}", executable)).output(); match run_output { From e983c341899af6684dbb46856973fb0bcbe8d6c9 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 20 Mar 2025 15:47:37 +0100 Subject: [PATCH 05/57] added error msg for not missing clang and nvcc --- src/main.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 3aea182d..b95b9d21 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,6 +37,14 @@ struct Cli { #[arg(short, long)] pub verbose: bool, + + #[arg(long)] + pub suppress_warnings: bool, +} + +// maybe there is a better way to do this? +fn check_command_exists(cmd: &str) -> bool { + Command::new(cmd).arg("--version").output().is_ok() } fn main() { @@ -45,10 +53,25 @@ fn main() { if args.debug { println!("Debug mode enabled."); } + if args.verbose { println!("Verbose output enabled."); } + if !check_command_exists("clang-format") { + eprintln!("Error: 'clang-format' is not installed. Please install clang-format to proceed."); + exit(1); + } + + if args.compile && !check_command_exists("nvcc") { + if args.suppress_warnings { + eprintln!("Warning: 'nvcc' not found, but warnings are suppressed. Compilation will likely fail."); + } else { + eprintln!("Error: 'nvcc' is not installed. Please install the CUDA Toolkit to compile the code."); + exit(1); + } + } + match compile(&args.input, None) { Ok(cuda_code) => { // Print CUDA code instead of saving it if `--emit-cuda` is set @@ -56,7 +79,8 @@ fn main() { println!("Generated CUDA Code:\n{}", cuda_code); return; } - + + // compilation output is .cu file with the same name if args.compile { let cuda_file = args.output.clone().unwrap_or_else(|| args.input.replace(".desc", ".cu")); let executable = cuda_file.replace(".cu", ""); // Remove .cu for output binary From 5e08465a934acf0e92cd79f60973dacb303a2094 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Fri, 21 Mar 2025 19:06:51 +0100 Subject: [PATCH 06/57] new cli design --- Cargo.toml | 3 + src/main.rs | 264 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 160 insertions(+), 107 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef945967..c6e5d63e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,9 @@ features = ["color"] [dependencies.descend_derive] path = "./descend_derive" +[dependencies.anyhow] +version = "1.0" + [dependencies.clap] version = "4.3" features = ["derive"] diff --git a/src/main.rs b/src/main.rs index b95b9d21..42ca9789 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,142 +1,192 @@ -use clap::{Parser}; +use clap::{Parser, Subcommand}; use descend::{compile, error::ErrorReported}; use std::fs::write; use std::process::{Command, exit}; +use anyhow::{Context, Result}; #[derive(Parser, Debug)] #[command(name = "descendc", version = "1.0", about = "Descend GPU Compiler")] struct Cli { - pub input: String, - + /// Enable debug mode #[arg(short, long)] - pub output: Option, - + debug: bool, + + /// Enable verbose output + #[arg(short, long)] + verbose: bool, + + /// Suppress warning if nvcc (CUDA Toolkit) is not installed (only applicable for build/run) #[arg(long)] - pub emit_cuda: bool, + suppress_cuda_warning: bool, - #[arg(long)] - pub compile: bool, + #[command(subcommand)] + command: Commands, +} - #[arg(long)] - pub run: bool, +#[derive(Subcommand, Debug)] +enum Commands { + /// Emit the generated CUDA code without compiling. + Emit { + /// Input file (.desc) + input: String, + /// Optionally write the CUDA code to a file (if not provided, it is printed) + #[arg(short, long)] + output: Option, + }, + /// Compile the generated CUDA code into a binary. + Build { + /// Input file (.desc) + input: String, + /// Optionally specify output file for the CUDA code (if not provided, uses the input name with a .cu extension) + #[arg(short, long)] + output: Option, + /// Specify CUDA architecture (e.g., `sm_75`, `sm_80`) + #[arg(long, default_value = "sm_75")] + arch: String, + /// Optimization level for `nvcc` (`0-3`) + #[arg(long, default_value = "3")] + optimize: u8, + /// Additional flags to pass directly to `nvcc` + #[arg(long, default_value = "")] + nvcc_flags: String, + }, + /// Compile the generated CUDA code and run the resulting binary. + Run { + /// Input file (.desc) + input: String, + /// Optionally specify output file for the CUDA code (if not provided, uses the input name with a .cu extension) + #[arg(short, long)] + output: Option, + /// Specify CUDA architecture (e.g., `sm_75`, `sm_80`) + #[arg(long, default_value = "sm_75")] + arch: String, + /// Optimization level for `nvcc` (`0-3`) + #[arg(long, default_value = "3")] + optimize: u8, + /// Additional flags to pass directly to `nvcc` + #[arg(long, default_value = "")] + nvcc_flags: String, + }, +} - /// Specify CUDA architecture (e.g., `sm_75`, `sm_80`) - #[arg(long, default_value = "sm_75")] - pub arch: String, +/// Helper function to check if a command exists by attempting to run ` --version` +fn check_command_exists(cmd: &str) -> bool { + Command::new(cmd).arg("--version").output().is_ok() +} - /// Optimization level for `nvcc` (`0-3`) - #[arg(long, default_value = "3")] - pub optimize: u8, +/// Generates the CUDA code from the .desc file. +fn generate_cuda(input: &str) -> Result { + compile(input, None) + .map_err(|_| anyhow::anyhow!("Descend compilation failed for input '{}'", input)) +} - /// Additional flags to pass directly to `nvcc` - #[arg(long, default_value = "")] - pub nvcc_flags: String, +/// Writes the generated CUDA code to a file. +fn write_cuda_file(cuda_code: &str, filename: &str) -> Result<()> { + write(filename, cuda_code).with_context(|| format!("Error writing CUDA file {}", filename)) +} - #[arg(short, long)] - pub debug: bool, +/// Builds the CUDA file using nvcc. +fn build_cuda(cuda_file: &str, executable: &str, optimize: u8, arch: &str, nvcc_flags: &str) -> Result<()> { + let mut nvcc_cmd = Command::new("nvcc"); + nvcc_cmd.arg(cuda_file) + .arg(cuda_file) // Retaining the original behavior: passing the same file twice. + .arg("-o") + .arg(executable) + .arg(format!("-O{}", optimize)) + .arg("-I") + .arg("cuda-examples/") + .args(nvcc_flags.split_whitespace()); + if arch != "none" { + nvcc_cmd.arg(format!("-arch={}", arch)); + } + let output = nvcc_cmd.output().with_context(|| "Failed to run nvcc command")?; + if !output.status.success() { + return Err(anyhow::anyhow!("nvcc compilation failed:\n{}", String::from_utf8_lossy(&output.stderr))); + } + Ok(()) +} - #[arg(short, long)] - pub verbose: bool, +/// Runs the generated executable. +fn run_executable(executable: &str) -> Result<()> { + let output = Command::new(format!("./{}", executable)) + .output() + .with_context(|| "Failed to run the executable")?; + println!("Program output:\n{}", String::from_utf8_lossy(&output.stdout)); + eprintln!("Program errors:\n{}", String::from_utf8_lossy(&output.stderr)); + Ok(()) +} - #[arg(long)] - pub suppress_warnings: bool, +/// Handles the Emit subcommand. +fn handle_emit(input: String, output: Option) -> Result<()> { + let cuda_code = generate_cuda(&input)?; + if let Some(file) = output { + write_cuda_file(&cuda_code, &file)?; + println!("CUDA code written to {}", file); + } else { + println!("Generated CUDA Code:\n{}", cuda_code); + } + Ok(()) } -// maybe there is a better way to do this? -fn check_command_exists(cmd: &str) -> bool { - Command::new(cmd).arg("--version").output().is_ok() +/// Handles the Build and Run subcommands. +fn handle_build_run( + input: String, + output: Option, + arch: String, + optimize: u8, + nvcc_flags: String, + run_after: bool, + suppress_cuda_warning: bool, +) -> Result<()> { + if !check_command_exists("nvcc") { + if suppress_cuda_warning { + eprintln!("Warning: 'nvcc' not found, but warnings are suppressed. Compilation will likely fail."); + } else { + return Err(anyhow::anyhow!("Error: 'nvcc' is not installed. Please install the CUDA Toolkit to compile the code.")); + } + } + let cuda_code = generate_cuda(&input)?; + let cuda_file = output.unwrap_or_else(|| input.replace(".desc", ".cu")); + let executable = cuda_file.replace(".cu", ""); + write_cuda_file(&cuda_code, &cuda_file)?; + println!("CUDA code written to {}", cuda_file); + build_cuda(&cuda_file, &executable, optimize, &arch, &nvcc_flags)?; + println!("Compilation successful: {}", executable); + if run_after { + run_executable(&executable)?; + } + Ok(()) } fn main() { - let args = Cli::parse(); + let cli = Cli::parse(); - if args.debug { + if cli.debug { println!("Debug mode enabled."); } - - if args.verbose { + if cli.verbose { println!("Verbose output enabled."); } + // Always require clang-format. if !check_command_exists("clang-format") { eprintln!("Error: 'clang-format' is not installed. Please install clang-format to proceed."); exit(1); } - if args.compile && !check_command_exists("nvcc") { - if args.suppress_warnings { - eprintln!("Warning: 'nvcc' not found, but warnings are suppressed. Compilation will likely fail."); - } else { - eprintln!("Error: 'nvcc' is not installed. Please install the CUDA Toolkit to compile the code."); - exit(1); - } - } - - match compile(&args.input, None) { - Ok(cuda_code) => { - // Print CUDA code instead of saving it if `--emit-cuda` is set - if args.emit_cuda { - println!("Generated CUDA Code:\n{}", cuda_code); - return; - } - - // compilation output is .cu file with the same name - if args.compile { - let cuda_file = args.output.clone().unwrap_or_else(|| args.input.replace(".desc", ".cu")); - let executable = cuda_file.replace(".cu", ""); // Remove .cu for output binary - - if let Err(e) = write(&cuda_file, &cuda_code) { - eprintln!("Error writing CUDA file {}: {}", cuda_file, e); - exit(1); - } - - // Include `descend.cuh` directory in the compilation command - let mut nvcc_cmd = Command::new("nvcc"); - nvcc_cmd.arg(&cuda_file) - .arg(&cuda_file) // Input CUDA file - .arg("-o").arg(&executable) // Output executable - .arg(format!("-O{}", args.optimize)) // Pass `--optimize` - .arg("-I").arg("cuda-examples/") // Include path for `descend.cuh` - .args(args.nvcc_flags.split_whitespace()); // Pass custom `--nvcc-flags` - - if args.arch != "none" { - nvcc_cmd.arg(format!("-arch={}", args.arch)); // Only add `-arch` if not "none" - } - - let nvcc_output = nvcc_cmd.output(); - - match nvcc_output { - Ok(output) if output.status.success() => { - - if args.run { - let run_output = Command::new(format!("./{}", executable)).output(); - - match run_output { - Ok(run) => { - println!("Program output:\n{}", String::from_utf8_lossy(&run.stdout)); - println!("Program errors:\n{}", String::from_utf8_lossy(&run.stderr)); - } - Err(e) => { - eprintln!("Error running executable: {}", e); - exit(1); - } - } - } - } - Ok(output) => { - eprintln!("nvcc compilation failed:\n{}", String::from_utf8_lossy(&output.stderr)); - exit(1); - } - Err(e) => { - eprintln!("Failed to run nvcc: {}", e); - exit(1); - } - } - } - } - Err(ErrorReported) => { - eprintln!("Descend compilation failed."); - exit(1); - } + // Process the subcommand. + let result = match cli.command { + Commands::Emit { input, output } => handle_emit(input, output), + Commands::Build { input, output, arch, optimize, nvcc_flags } => { + handle_build_run(input, output, arch, optimize, nvcc_flags, false, cli.suppress_cuda_warning) + }, + Commands::Run { input, output, arch, optimize, nvcc_flags } => { + handle_build_run(input, output, arch, optimize, nvcc_flags, true, cli.suppress_cuda_warning) + }, + }; + + if let Err(e) = result { + eprintln!("{:#}", e); + exit(1); } } From 060b505384c69a8e75cf2e3ee0011e6b744e4bdb Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 25 Mar 2025 22:35:29 +0100 Subject: [PATCH 07/57] restructured the cli --- Cargo.toml | 21 ++++++- src/main.rs | 144 ++++++++++++++++++++++------------------------ tests/cli_test.rs | 13 +++++ 3 files changed, 101 insertions(+), 77 deletions(-) create mode 100644 tests/cli_test.rs diff --git a/Cargo.toml b/Cargo.toml index c6e5d63e..cc67017f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,12 +20,27 @@ features = ["color"] [dependencies.descend_derive] path = "./descend_derive" -[dependencies.anyhow] -version = "1.0" - [dependencies.clap] version = "4.3" features = ["derive"] +[dependencies.anyhow] +version = "1.0" + +[dependencies.which] +version = "7.0.2" + +[dependencies.log] +version = "0.4.27" + +[dependencies.env_logger] +version = "0.11.7" + +[dependencies.predicates] +version= "3.1.3" + +[dependencies.assert_cmd] +version = "2.0.16" + [workspace] members = ["descend_derive"] \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 42ca9789..96c7d813 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,23 @@ -use clap::{Parser, Subcommand}; +use clap::{Parser, Subcommand, Args}; use descend::{compile, error::ErrorReported}; use std::fs::write; use std::process::{Command, exit}; use anyhow::{Context, Result}; +use log::{debug, error, info, warn}; +use which::which; #[derive(Parser, Debug)] -#[command(name = "descendc", version = "1.0", about = "Descend GPU Compiler")] +#[command(name = "descendc", version = "1.0", about = "Descend Compiler")] struct Cli { - /// Enable debug mode + /// Enable debug mode. #[arg(short, long)] debug: bool, - - /// Enable verbose output + + /// Enable verbose output. #[arg(short, long)] verbose: bool, - - /// Suppress warning if nvcc (CUDA Toolkit) is not installed (only applicable for build/run) + + /// Suppress warning if nvcc (CUDA Toolkit) is not installed. #[arg(long)] suppress_cuda_warning: bool, @@ -27,69 +29,70 @@ struct Cli { enum Commands { /// Emit the generated CUDA code without compiling. Emit { - /// Input file (.desc) - input: String, - /// Optionally write the CUDA code to a file (if not provided, it is printed) - #[arg(short, long)] - output: Option, + #[clap(flatten)] + common: CommonArgs, }, /// Compile the generated CUDA code into a binary. Build { - /// Input file (.desc) - input: String, - /// Optionally specify output file for the CUDA code (if not provided, uses the input name with a .cu extension) - #[arg(short, long)] - output: Option, - /// Specify CUDA architecture (e.g., `sm_75`, `sm_80`) - #[arg(long, default_value = "sm_75")] - arch: String, - /// Optimization level for `nvcc` (`0-3`) - #[arg(long, default_value = "3")] - optimize: u8, - /// Additional flags to pass directly to `nvcc` - #[arg(long, default_value = "")] - nvcc_flags: String, + #[clap(flatten)] + common: CommonArgs, + #[clap(flatten)] + build_run: BuildRunArgs, }, /// Compile the generated CUDA code and run the resulting binary. Run { - /// Input file (.desc) - input: String, - /// Optionally specify output file for the CUDA code (if not provided, uses the input name with a .cu extension) - #[arg(short, long)] - output: Option, - /// Specify CUDA architecture (e.g., `sm_75`, `sm_80`) - #[arg(long, default_value = "sm_75")] - arch: String, - /// Optimization level for `nvcc` (`0-3`) - #[arg(long, default_value = "3")] - optimize: u8, - /// Additional flags to pass directly to `nvcc` - #[arg(long, default_value = "")] - nvcc_flags: String, + #[clap(flatten)] + common: CommonArgs, + #[clap(flatten)] + build_run: BuildRunArgs, }, } -/// Helper function to check if a command exists by attempting to run ` --version` -fn check_command_exists(cmd: &str) -> bool { - Command::new(cmd).arg("--version").output().is_ok() +/// Arguments common to all subcommands. +#[derive(Args, Debug)] +struct CommonArgs { + /// Input file (.desc) + input: String, + + /// Optionally write the CUDA code to a file (if not provided, uses default naming) + #[arg(short, long)] + output: Option, +} + +/// Arguments only applicable to Build and Run. +#[derive(Args, Debug)] +struct BuildRunArgs { + /// Specify CUDA architecture (e.g., sm_75, sm_80) + #[arg(long, default_value = "sm_75")] + arch: String, + + /// Optimization level for nvcc (0-3) + #[arg(long, default_value = "3")] + optimize: u8, + + /// Additional flags to pass directly to nvcc + #[arg(long, default_value = "")] + nvcc_flags: String, +} + +/// Checks if a command exists using the which crate +fn command_exists(cmd: &str) -> bool { + which(cmd).is_ok() } -/// Generates the CUDA code from the .desc file. fn generate_cuda(input: &str) -> Result { compile(input, None) .map_err(|_| anyhow::anyhow!("Descend compilation failed for input '{}'", input)) } -/// Writes the generated CUDA code to a file. fn write_cuda_file(cuda_code: &str, filename: &str) -> Result<()> { - write(filename, cuda_code).with_context(|| format!("Error writing CUDA file {}", filename)) + write(filename, cuda_code) + .with_context(|| format!("Error writing CUDA file {}", filename)) } -/// Builds the CUDA file using nvcc. fn build_cuda(cuda_file: &str, executable: &str, optimize: u8, arch: &str, nvcc_flags: &str) -> Result<()> { let mut nvcc_cmd = Command::new("nvcc"); nvcc_cmd.arg(cuda_file) - .arg(cuda_file) // Retaining the original behavior: passing the same file twice. .arg("-o") .arg(executable) .arg(format!("-O{}", optimize)) @@ -99,14 +102,15 @@ fn build_cuda(cuda_file: &str, executable: &str, optimize: u8, arch: &str, nvcc_ if arch != "none" { nvcc_cmd.arg(format!("-arch={}", arch)); } - let output = nvcc_cmd.output().with_context(|| "Failed to run nvcc command")?; + debug!("Running NVCC command: {:?}", nvcc_cmd); + let output = nvcc_cmd.output() + .with_context(|| "Failed to run nvcc command")?; if !output.status.success() { return Err(anyhow::anyhow!("nvcc compilation failed:\n{}", String::from_utf8_lossy(&output.stderr))); } Ok(()) } -/// Runs the generated executable. fn run_executable(executable: &str) -> Result<()> { let output = Command::new(format!("./{}", executable)) .output() @@ -116,10 +120,9 @@ fn run_executable(executable: &str) -> Result<()> { Ok(()) } -/// Handles the Emit subcommand. -fn handle_emit(input: String, output: Option) -> Result<()> { - let cuda_code = generate_cuda(&input)?; - if let Some(file) = output { +fn handle_emit(common: CommonArgs) -> Result<()> { + let cuda_code = generate_cuda(&common.input)?; + if let Some(file) = common.output { write_cuda_file(&cuda_code, &file)?; println!("CUDA code written to {}", file); } else { @@ -128,29 +131,25 @@ fn handle_emit(input: String, output: Option) -> Result<()> { Ok(()) } -/// Handles the Build and Run subcommands. fn handle_build_run( - input: String, - output: Option, - arch: String, - optimize: u8, - nvcc_flags: String, + common: CommonArgs, + build_run: BuildRunArgs, run_after: bool, suppress_cuda_warning: bool, ) -> Result<()> { - if !check_command_exists("nvcc") { + if !command_exists("nvcc") { if suppress_cuda_warning { eprintln!("Warning: 'nvcc' not found, but warnings are suppressed. Compilation will likely fail."); } else { return Err(anyhow::anyhow!("Error: 'nvcc' is not installed. Please install the CUDA Toolkit to compile the code.")); } } - let cuda_code = generate_cuda(&input)?; - let cuda_file = output.unwrap_or_else(|| input.replace(".desc", ".cu")); + let cuda_code = generate_cuda(&common.input)?; + let cuda_file = common.output.unwrap_or_else(|| common.input.replace(".desc", ".cu")); let executable = cuda_file.replace(".cu", ""); write_cuda_file(&cuda_code, &cuda_file)?; println!("CUDA code written to {}", cuda_file); - build_cuda(&cuda_file, &executable, optimize, &arch, &nvcc_flags)?; + build_cuda(&cuda_file, &executable, build_run.optimize, &build_run.arch, &build_run.nvcc_flags)?; println!("Compilation successful: {}", executable); if run_after { run_executable(&executable)?; @@ -159,6 +158,7 @@ fn handle_build_run( } fn main() { + env_logger::init(); let cli = Cli::parse(); if cli.debug { @@ -168,21 +168,17 @@ fn main() { println!("Verbose output enabled."); } - // Always require clang-format. - if !check_command_exists("clang-format") { + if !command_exists("clang-format") { eprintln!("Error: 'clang-format' is not installed. Please install clang-format to proceed."); exit(1); } - // Process the subcommand. let result = match cli.command { - Commands::Emit { input, output } => handle_emit(input, output), - Commands::Build { input, output, arch, optimize, nvcc_flags } => { - handle_build_run(input, output, arch, optimize, nvcc_flags, false, cli.suppress_cuda_warning) - }, - Commands::Run { input, output, arch, optimize, nvcc_flags } => { - handle_build_run(input, output, arch, optimize, nvcc_flags, true, cli.suppress_cuda_warning) - }, + Commands::Emit { common } => handle_emit(common), + Commands::Build { common, build_run } => + handle_build_run(common, build_run, false, cli.suppress_cuda_warning), + Commands::Run { common, build_run } => + handle_build_run(common, build_run, true, cli.suppress_cuda_warning), }; if let Err(e) = result { diff --git a/tests/cli_test.rs b/tests/cli_test.rs new file mode 100644 index 00000000..2075d772 --- /dev/null +++ b/tests/cli_test.rs @@ -0,0 +1,13 @@ +use assert_cmd::Command; +use predicates::prelude::*; + +#[test] +fn test_emit_cuda_on_transpose_desc() { + let mut cmd = Command::cargo_bin("descendc").expect("Failed to find descendc binary"); + + cmd.arg("emit").arg("examples/infer/transpose.desc"); + + cmd.assert() + .success() + .stdout(predicate::str::contains("Generated CUDA Code")); +} From 0f7cd44e8363a1ad59430448618863a3734e8887 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 26 Mar 2025 11:36:19 +0100 Subject: [PATCH 08/57] format everything nicely --- src/lib.rs | 1 - src/main.rs | 66 ++++++++++++++++++++++++++----------- src/parser/mod.rs | 11 +++++-- tests/cli_test.rs | 4 +-- tests/example_infer_apps.rs | 5 ++- 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4246b6ce..fa57bd0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,6 @@ pub mod error; pub mod parser; pub mod ty_check; - pub fn compile(file_path: &str, output_path: Option<&str>) -> Result { let source = parser::SourceCode::from_file(file_path)?; let mut compil_unit = parser::parse(&source)?; diff --git a/src/main.rs b/src/main.rs index 96c7d813..eaf8940c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@ -use clap::{Parser, Subcommand, Args}; -use descend::{compile, error::ErrorReported}; -use std::fs::write; -use std::process::{Command, exit}; use anyhow::{Context, Result}; +use clap::{Args, Parser, Subcommand}; +use descend::{compile, error::ErrorReported}; use log::{debug, error, info, warn}; +use std::fs::write; +use std::process::{exit, Command}; use which::which; #[derive(Parser, Debug)] @@ -86,13 +86,19 @@ fn generate_cuda(input: &str) -> Result { } fn write_cuda_file(cuda_code: &str, filename: &str) -> Result<()> { - write(filename, cuda_code) - .with_context(|| format!("Error writing CUDA file {}", filename)) + write(filename, cuda_code).with_context(|| format!("Error writing CUDA file {}", filename)) } -fn build_cuda(cuda_file: &str, executable: &str, optimize: u8, arch: &str, nvcc_flags: &str) -> Result<()> { +fn build_cuda( + cuda_file: &str, + executable: &str, + optimize: u8, + arch: &str, + nvcc_flags: &str, +) -> Result<()> { let mut nvcc_cmd = Command::new("nvcc"); - nvcc_cmd.arg(cuda_file) + nvcc_cmd + .arg(cuda_file) .arg("-o") .arg(executable) .arg(format!("-O{}", optimize)) @@ -103,10 +109,14 @@ fn build_cuda(cuda_file: &str, executable: &str, optimize: u8, arch: &str, nvcc_ nvcc_cmd.arg(format!("-arch={}", arch)); } debug!("Running NVCC command: {:?}", nvcc_cmd); - let output = nvcc_cmd.output() + let output = nvcc_cmd + .output() .with_context(|| "Failed to run nvcc command")?; if !output.status.success() { - return Err(anyhow::anyhow!("nvcc compilation failed:\n{}", String::from_utf8_lossy(&output.stderr))); + return Err(anyhow::anyhow!( + "nvcc compilation failed:\n{}", + String::from_utf8_lossy(&output.stderr) + )); } Ok(()) } @@ -115,8 +125,14 @@ fn run_executable(executable: &str) -> Result<()> { let output = Command::new(format!("./{}", executable)) .output() .with_context(|| "Failed to run the executable")?; - println!("Program output:\n{}", String::from_utf8_lossy(&output.stdout)); - eprintln!("Program errors:\n{}", String::from_utf8_lossy(&output.stderr)); + println!( + "Program output:\n{}", + String::from_utf8_lossy(&output.stdout) + ); + eprintln!( + "Program errors:\n{}", + String::from_utf8_lossy(&output.stderr) + ); Ok(()) } @@ -145,11 +161,19 @@ fn handle_build_run( } } let cuda_code = generate_cuda(&common.input)?; - let cuda_file = common.output.unwrap_or_else(|| common.input.replace(".desc", ".cu")); + let cuda_file = common + .output + .unwrap_or_else(|| common.input.replace(".desc", ".cu")); let executable = cuda_file.replace(".cu", ""); write_cuda_file(&cuda_code, &cuda_file)?; println!("CUDA code written to {}", cuda_file); - build_cuda(&cuda_file, &executable, build_run.optimize, &build_run.arch, &build_run.nvcc_flags)?; + build_cuda( + &cuda_file, + &executable, + build_run.optimize, + &build_run.arch, + &build_run.nvcc_flags, + )?; println!("Compilation successful: {}", executable); if run_after { run_executable(&executable)?; @@ -169,16 +193,20 @@ fn main() { } if !command_exists("clang-format") { - eprintln!("Error: 'clang-format' is not installed. Please install clang-format to proceed."); + eprintln!( + "Error: 'clang-format' is not installed. Please install clang-format to proceed." + ); exit(1); } let result = match cli.command { Commands::Emit { common } => handle_emit(common), - Commands::Build { common, build_run } => - handle_build_run(common, build_run, false, cli.suppress_cuda_warning), - Commands::Run { common, build_run } => - handle_build_run(common, build_run, true, cli.suppress_cuda_warning), + Commands::Build { common, build_run } => { + handle_build_run(common, build_run, false, cli.suppress_cuda_warning) + } + Commands::Run { common, build_run } => { + handle_build_run(common, build_run, true, cli.suppress_cuda_warning) + } }; if let Err(e) = result { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index b2297a3c..935fef89 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1063,7 +1063,6 @@ peg::parser! { mod tests { use super::*; - #[test] fn nat_literal() { assert_eq!(descend::nat("0"), Ok(Nat::Lit(0)), "cannot parse 0"); @@ -2471,12 +2470,18 @@ mod tests { #[test] fn empty_annotate_snippet() { let source = SourceCode::new("fn\n".to_string()); - assert!(parse(&source).is_err(), "Expected a parsing error and specifically not a panic!"); + assert!( + parse(&source).is_err(), + "Expected a parsing error and specifically not a panic!" + ); } #[test] fn empty_annotate_snippet2() { let source = SourceCode::new("fn ".to_string()); - assert!(parse(&source).is_err(), "Expected a parsing error and specifically not a panic!"); + assert!( + parse(&source).is_err(), + "Expected a parsing error and specifically not a panic!" + ); } } diff --git a/tests/cli_test.rs b/tests/cli_test.rs index 2075d772..680ab3ff 100644 --- a/tests/cli_test.rs +++ b/tests/cli_test.rs @@ -8,6 +8,6 @@ fn test_emit_cuda_on_transpose_desc() { cmd.arg("emit").arg("examples/infer/transpose.desc"); cmd.assert() - .success() - .stdout(predicate::str::contains("Generated CUDA Code")); + .success() + .stdout(predicate::str::contains("Generated CUDA Code")); } diff --git a/tests/example_infer_apps.rs b/tests/example_infer_apps.rs index 77b8da44..404beaec 100644 --- a/tests/example_infer_apps.rs +++ b/tests/example_infer_apps.rs @@ -125,7 +125,10 @@ fn vector_add() -> Res { #[ignore] #[test] fn bfs() -> Res { - Ok(println!("{}", descend::compile("examples/infer/bfs.desc", None)?)) + Ok(println!( + "{}", + descend::compile("examples/infer/bfs.desc", None)? + )) } #[test] From f345208f026cf8326fe0a54c6566ca9e97fab557 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 15 Apr 2025 08:50:24 +0200 Subject: [PATCH 09/57] remove compile function output path argument --- src/lib.rs | 14 ++----------- src/main.rs | 3 +-- tests/example_infer_apps.rs | 41 +++++++++++++++++-------------------- tests/rodinia.rs | 2 +- 4 files changed, 23 insertions(+), 37 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fa57bd0d..87a0c26d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ extern crate core; use crate::error::ErrorReported; -use std::fs::write; mod ast; mod codegen; @@ -9,18 +8,9 @@ pub mod error; pub mod parser; pub mod ty_check; -pub fn compile(file_path: &str, output_path: Option<&str>) -> Result { +pub fn compile(file_path: &str) -> Result { let source = parser::SourceCode::from_file(file_path)?; let mut compil_unit = parser::parse(&source)?; ty_check::ty_check(&mut compil_unit)?; - let generated_code = codegen::gen(&compil_unit, false); - - if let Some(out) = output_path { - write(out, &generated_code).map_err(|e| { - eprintln!("Error writing output file {}: {}", out, e); - ErrorReported - })?; - } - - Ok(generated_code) + Ok(codegen::gen(&compil_unit, false)) } diff --git a/src/main.rs b/src/main.rs index eaf8940c..7f9a57ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -81,8 +81,7 @@ fn command_exists(cmd: &str) -> bool { } fn generate_cuda(input: &str) -> Result { - compile(input, None) - .map_err(|_| anyhow::anyhow!("Descend compilation failed for input '{}'", input)) + compile(input).map_err(|_| anyhow::anyhow!("Descend compilation failed for input '{}'", input)) } fn write_cuda_file(cuda_code: &str, filename: &str) -> Result<()> { diff --git a/tests/example_infer_apps.rs b/tests/example_infer_apps.rs index 404beaec..75516f9d 100644 --- a/tests/example_infer_apps.rs +++ b/tests/example_infer_apps.rs @@ -8,7 +8,7 @@ type Res = Result<(), descend::error::ErrorReported>; fn transpose() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/transpose.desc", None)? + descend::compile("examples/infer/transpose.desc")? )) } @@ -16,7 +16,7 @@ fn transpose() -> Res { fn transpose_shrd_mem() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/transpose_shrd_mem.desc", None)? + descend::compile("examples/infer/transpose_shrd_mem.desc")? )) } @@ -24,7 +24,7 @@ fn transpose_shrd_mem() -> Res { fn matmul() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/matmul.desc", None)? + descend::compile("examples/infer/matmul.desc")? )) } @@ -32,7 +32,7 @@ fn matmul() -> Res { fn scale_vec() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/scale_vec.desc", None)? + descend::compile("examples/infer/scale_vec.desc")? )) } @@ -40,7 +40,7 @@ fn scale_vec() -> Res { fn reverse_vec() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/reverse_vec.desc", None)? + descend::compile("examples/infer/reverse_vec.desc")? )) } @@ -49,7 +49,7 @@ fn reverse_vec() -> Res { fn bitonic_sort() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/bitonic_sort/bitonic_sort.desc", None)? + descend::compile("examples/infer/bitonic_sort/bitonic_sort.desc")? )) } @@ -62,7 +62,7 @@ fn scan() -> Res { ); Ok(println!( "{}", - descend::compile("examples/infer/scan.desc", None)? + descend::compile("examples/infer/scan.desc")? )) } @@ -70,7 +70,7 @@ fn scan() -> Res { fn reduce_shared_mem() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/reduce_shared_mem.desc", None)? + descend::compile("examples/infer/reduce_shared_mem.desc")? )) } @@ -78,7 +78,7 @@ fn reduce_shared_mem() -> Res { fn vlc_encode() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/huffman/vlc_encode.desc", None)? + descend::compile("examples/infer/huffman/vlc_encode.desc")? )) } @@ -86,7 +86,7 @@ fn vlc_encode() -> Res { fn vlc_encode_cg() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/huffman/vlc_encode_cg.desc", None)? + descend::compile("examples/infer/huffman/vlc_encode_cg.desc")? )) } @@ -94,7 +94,7 @@ fn vlc_encode_cg() -> Res { fn vlc_encode_reuse() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/huffman/vlc_encode_reuse.desc", None)? + descend::compile("examples/infer/huffman/vlc_encode_reuse.desc")? )) } @@ -102,7 +102,7 @@ fn vlc_encode_reuse() -> Res { fn histogram() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/huffman/histogram.desc", None)? + descend::compile("examples/infer/huffman/histogram.desc")? )) } @@ -110,7 +110,7 @@ fn histogram() -> Res { fn tree_reduce() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/tree_reduce.desc", None)? + descend::compile("examples/infer/tree_reduce.desc")? )) } @@ -118,24 +118,21 @@ fn tree_reduce() -> Res { fn vector_add() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/vec_add.desc", None)? + descend::compile("examples/infer/vec_add.desc")? )) } #[ignore] #[test] fn bfs() -> Res { - Ok(println!( - "{}", - descend::compile("examples/infer/bfs.desc", None)? - )) + Ok(println!("{}", descend::compile("examples/infer/bfs.desc")?)) } #[test] fn sgemm() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/sgemm.desc", None)? + descend::compile("examples/infer/sgemm.desc")? )) } @@ -143,7 +140,7 @@ fn sgemm() -> Res { fn shrd_mem_acc_equiv_exec() -> Res { Ok(println!( "{}", - descend::compile("examples/shrd_mem_acc_equiv_exec.desc", None)? + descend::compile("examples/shrd_mem_acc_equiv_exec.desc")? )) } @@ -151,7 +148,7 @@ fn shrd_mem_acc_equiv_exec() -> Res { fn sssp_ffi_unsafe() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/sssp-ffi.desc", None)? + descend::compile("examples/infer/sssp-ffi.desc")? )) } @@ -159,6 +156,6 @@ fn sssp_ffi_unsafe() -> Res { fn jacobisvd() -> Res { Ok(println!( "{}", - descend::compile("examples/infer/jacobisvd.desc", None)? + descend::compile("examples/infer/jacobisvd.desc")? )) } diff --git a/tests/rodinia.rs b/tests/rodinia.rs index 999be076..985991d3 100644 --- a/tests/rodinia.rs +++ b/tests/rodinia.rs @@ -9,6 +9,6 @@ type Res = Result<(), descend::error::ErrorReported>; fn gaussian() -> Res { Ok(println!( "{}", - descend::compile("examples/rodinia/gaussian.desc", None)? + descend::compile("examples/rodinia/gaussian.desc")? )) } From 00b231d9aebb9e76ca601322372bca0cb8823226 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 15 Apr 2025 10:45:20 +0200 Subject: [PATCH 10/57] refined logging and output saving logic of the cli --- src/main.rs | 111 +++++++++++++++++++++++++++++++++++----------- tests/cli_test.rs | 2 +- 2 files changed, 87 insertions(+), 26 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7f9a57ea..59336827 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,16 @@ use anyhow::{Context, Result}; use clap::{Args, Parser, Subcommand}; use descend::{compile, error::ErrorReported}; -use log::{debug, error, info, warn}; +use env_logger::Env; +use log::LevelFilter; +use log::{debug, error, info}; +use std::env; +use std::fs; use std::fs::write; +use std::path::PathBuf; +use std::process; use std::process::{exit, Command}; +use std::time::{SystemTime, UNIX_EPOCH}; use which::which; #[derive(Parser, Debug)] @@ -13,10 +20,6 @@ struct Cli { #[arg(short, long)] debug: bool, - /// Enable verbose output. - #[arg(short, long)] - verbose: bool, - /// Suppress warning if nvcc (CUDA Toolkit) is not installed. #[arg(long)] suppress_cuda_warning: bool, @@ -73,6 +76,40 @@ struct BuildRunArgs { /// Additional flags to pass directly to nvcc #[arg(long, default_value = "")] nvcc_flags: String, + + /// Only save the generated CUDA file if explicitly requested. + #[arg(long)] + save_cuda: bool, +} + +/// RAII wrapper for a temporary file. +struct TempFile { + path: PathBuf, +} + +impl TempFile { + fn new(path: PathBuf) -> Self { + TempFile { path } + } + + /// Returns the file path as a string. + fn path_string(&self) -> String { + self.path.to_string_lossy().into_owned() + } +} + +impl Drop for TempFile { + fn drop(&mut self) { + // Attempt to delete the file; report error if it fails. + if let Err(e) = fs::remove_file(&self.path) { + error!( + "Warning: failed to remove temporary file {:?}: {}", + self.path, e + ); + } else { + debug!("Temporary file {:?} deleted.", self.path); + } + } } /// Checks if a command exists using the which crate @@ -124,11 +161,11 @@ fn run_executable(executable: &str) -> Result<()> { let output = Command::new(format!("./{}", executable)) .output() .with_context(|| "Failed to run the executable")?; - println!( + info!( "Program output:\n{}", String::from_utf8_lossy(&output.stdout) ); - eprintln!( + error!( "Program errors:\n{}", String::from_utf8_lossy(&output.stderr) ); @@ -139,9 +176,9 @@ fn handle_emit(common: CommonArgs) -> Result<()> { let cuda_code = generate_cuda(&common.input)?; if let Some(file) = common.output { write_cuda_file(&cuda_code, &file)?; - println!("CUDA code written to {}", file); + info!("CUDA code written to {}", file); } else { - println!("Generated CUDA Code:\n{}", cuda_code); + info!("Generated CUDA Code:\n{}", cuda_code); } Ok(()) } @@ -154,18 +191,37 @@ fn handle_build_run( ) -> Result<()> { if !command_exists("nvcc") { if suppress_cuda_warning { - eprintln!("Warning: 'nvcc' not found, but warnings are suppressed. Compilation will likely fail."); + info!("Warning: 'nvcc' not found, but warnings are suppressed. Compilation will likely fail."); } else { return Err(anyhow::anyhow!("Error: 'nvcc' is not installed. Please install the CUDA Toolkit to compile the code.")); } } let cuda_code = generate_cuda(&common.input)?; - let cuda_file = common - .output - .unwrap_or_else(|| common.input.replace(".desc", ".cu")); - let executable = cuda_file.replace(".cu", ""); + + // Determine the file name based on the --save-cuda flag. If save_cuda is false, generate a temporary file path. + let (cuda_file, _temp_guard): (String, Option) = if build_run.save_cuda { + ( + common + .output + .unwrap_or_else(|| common.input.replace(".desc", ".cu")), + None, + ) + } else { + let temp_dir = env::temp_dir(); + let timestamp = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_millis(); + let temp_filename = format!("descendc-{}-{}.cu", process::id(), timestamp); + let temp_path = temp_dir.join(temp_filename); + let file_str = temp_path.to_string_lossy().into_owned(); + (file_str, Some(TempFile::new(temp_path))) + }; + write_cuda_file(&cuda_code, &cuda_file)?; - println!("CUDA code written to {}", cuda_file); + debug!("CUDA code written to {}", cuda_file); + + let executable = cuda_file.replace(".cu", ""); build_cuda( &cuda_file, &executable, @@ -173,28 +229,33 @@ fn handle_build_run( &build_run.arch, &build_run.nvcc_flags, )?; - println!("Compilation successful: {}", executable); + debug!("Compilation successful: {}", executable); + if run_after { run_executable(&executable)?; } + Ok(()) } fn main() { - env_logger::init(); let cli = Cli::parse(); + let default_log_level = if cli.debug { + LevelFilter::Debug + } else { + LevelFilter::Info + }; + + env_logger::Builder::from_env(Env::default().default_filter_or(default_log_level.to_string())) + .init(); + if cli.debug { - println!("Debug mode enabled."); - } - if cli.verbose { - println!("Verbose output enabled."); + info!("Debug mode enabled."); } if !command_exists("clang-format") { - eprintln!( - "Error: 'clang-format' is not installed. Please install clang-format to proceed." - ); + error!("Error: 'clang-format' is not installed. Please install clang-format to proceed."); exit(1); } @@ -209,7 +270,7 @@ fn main() { }; if let Err(e) = result { - eprintln!("{:#}", e); + error!("{:#}", e); exit(1); } } diff --git a/tests/cli_test.rs b/tests/cli_test.rs index 680ab3ff..ee702360 100644 --- a/tests/cli_test.rs +++ b/tests/cli_test.rs @@ -9,5 +9,5 @@ fn test_emit_cuda_on_transpose_desc() { cmd.assert() .success() - .stdout(predicate::str::contains("Generated CUDA Code")); + .stderr(predicate::str::contains("Generated CUDA Code")); } From 08c37f4ba98d1c77825becef7979e25fc8f03552 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 15 Apr 2025 16:35:31 +0200 Subject: [PATCH 11/57] refined error handling --- src/error.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 35 +++++++++++-------- tests/cli_test.rs | 2 +- 3 files changed, 109 insertions(+), 16 deletions(-) diff --git a/src/error.rs b/src/error.rs index 64fe3ff0..a46b5ecf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -94,3 +94,91 @@ impl std::fmt::Debug for ErrorReported { write!(f, "Aborting due to previous error.") } } + +impl std::fmt::Display for ErrorReported { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Aborting due to a previous error.") + } +} + +#[derive(Debug)] +pub struct NVCCError { + message: String, +} + +impl NVCCError { + pub fn new>(message: S) -> Self { + NVCCError { + message: message.into(), + } + } + + pub fn emit(&self) -> ErrorReported { + println!("{}", self.to_string()); + ErrorReported + } + + fn to_string(&self) -> String { + let label = format!("{}", self.message); + let snippet = Snippet { + title: Some(Annotation { + id: None, + label: Some(&label), + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![], + opt: default_format(), + }; + DisplayList::from(snippet).to_string() + } +} + +impl std::fmt::Display for NVCCError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "NVCC Error: {}", self.message) + } +} + +impl std::error::Error for NVCCError {} + +#[derive(Debug)] +pub struct ExecutableError { + message: String, +} + +impl ExecutableError { + pub fn new>(message: S) -> Self { + ExecutableError { + message: message.into(), + } + } + + pub fn emit(&self) -> ErrorReported { + println!("{}", self.to_string()); + ErrorReported + } + + fn to_string(&self) -> String { + let label = format!("{}", self.message); + let snippet = Snippet { + title: Some(Annotation { + id: None, + label: Some(&label), + annotation_type: AnnotationType::Error, + }), + footer: vec![], + slices: vec![], + opt: default_format(), + }; + DisplayList::from(snippet).to_string() + } +} + +impl std::fmt::Display for ExecutableError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Executable Error: {}", self.message) + } +} + +impl std::error::Error for ExecutableError {} diff --git a/src/main.rs b/src/main.rs index 59336827..5eef6abf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ -use anyhow::{Context, Result}; use clap::{Args, Parser, Subcommand}; -use descend::{compile, error::ErrorReported}; +use descend::error::NVCCError; +use descend::{compile, error::ErrorReported, error::ExecutableError, error::FileIOError}; use env_logger::Env; use log::LevelFilter; use log::{debug, error, info}; @@ -117,12 +117,12 @@ fn command_exists(cmd: &str) -> bool { which(cmd).is_ok() } -fn generate_cuda(input: &str) -> Result { - compile(input).map_err(|_| anyhow::anyhow!("Descend compilation failed for input '{}'", input)) +fn generate_cuda(input: &str) -> Result { + compile(input) } -fn write_cuda_file(cuda_code: &str, filename: &str) -> Result<()> { - write(filename, cuda_code).with_context(|| format!("Error writing CUDA file {}", filename)) +fn write_cuda_file(cuda_code: &str, filename: &str) -> Result<(), ErrorReported> { + write(filename, cuda_code).map_err(|e| FileIOError::new(filename, e).emit()) } fn build_cuda( @@ -131,7 +131,7 @@ fn build_cuda( optimize: u8, arch: &str, nvcc_flags: &str, -) -> Result<()> { +) -> Result<(), ErrorReported> { let mut nvcc_cmd = Command::new("nvcc"); nvcc_cmd .arg(cuda_file) @@ -147,20 +147,22 @@ fn build_cuda( debug!("Running NVCC command: {:?}", nvcc_cmd); let output = nvcc_cmd .output() - .with_context(|| "Failed to run nvcc command")?; + .map_err(|_e| NVCCError::new("Failed to run nvcc command").emit())?; if !output.status.success() { - return Err(anyhow::anyhow!( + return Err(NVCCError::new(format!( "nvcc compilation failed:\n{}", String::from_utf8_lossy(&output.stderr) - )); + )) + .emit()); } Ok(()) } -fn run_executable(executable: &str) -> Result<()> { +fn run_executable(executable: &str) -> Result<(), ErrorReported> { let output = Command::new(format!("./{}", executable)) .output() - .with_context(|| "Failed to run the executable")?; + .map_err(|_e| ExecutableError::new("Failed to run the executable").emit())?; + info!( "Program output:\n{}", String::from_utf8_lossy(&output.stdout) @@ -172,7 +174,7 @@ fn run_executable(executable: &str) -> Result<()> { Ok(()) } -fn handle_emit(common: CommonArgs) -> Result<()> { +fn handle_emit(common: CommonArgs) -> Result<(), ErrorReported> { let cuda_code = generate_cuda(&common.input)?; if let Some(file) = common.output { write_cuda_file(&cuda_code, &file)?; @@ -188,12 +190,15 @@ fn handle_build_run( build_run: BuildRunArgs, run_after: bool, suppress_cuda_warning: bool, -) -> Result<()> { +) -> Result<(), ErrorReported> { if !command_exists("nvcc") { if suppress_cuda_warning { info!("Warning: 'nvcc' not found, but warnings are suppressed. Compilation will likely fail."); } else { - return Err(anyhow::anyhow!("Error: 'nvcc' is not installed. Please install the CUDA Toolkit to compile the code.")); + return Err( + NVCCError::new("Error: 'nvcc' is not installed. Please install the CUDA Toolkit to compile the code.") + .emit() + ); } } let cuda_code = generate_cuda(&common.input)?; diff --git a/tests/cli_test.rs b/tests/cli_test.rs index ee702360..680ab3ff 100644 --- a/tests/cli_test.rs +++ b/tests/cli_test.rs @@ -9,5 +9,5 @@ fn test_emit_cuda_on_transpose_desc() { cmd.assert() .success() - .stderr(predicate::str::contains("Generated CUDA Code")); + .stdout(predicate::str::contains("Generated CUDA Code")); } From 74763cc2e500a302e2c8c532989731d4cda33928 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 15 Apr 2025 16:42:57 +0200 Subject: [PATCH 12/57] missing newline --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index cc67017f..e3d49422 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,4 +43,4 @@ version= "3.1.3" version = "2.0.16" [workspace] -members = ["descend_derive"] \ No newline at end of file +members = ["descend_derive"] From 16032dd7f46c1f77ce7b475a8bc5edf783601d7f Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 15 Apr 2025 16:43:32 +0200 Subject: [PATCH 13/57] removed anyhow dependency --- Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e3d49422..dd9ffffe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,9 +24,6 @@ path = "./descend_derive" version = "4.3" features = ["derive"] -[dependencies.anyhow] -version = "1.0" - [dependencies.which] version = "7.0.2" From 8ea0882935d0a497c8283b8b1e34f1ae335f423b Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 15 Apr 2025 16:44:56 +0200 Subject: [PATCH 14/57] changed test output source stderr --- tests/cli_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cli_test.rs b/tests/cli_test.rs index 680ab3ff..ee702360 100644 --- a/tests/cli_test.rs +++ b/tests/cli_test.rs @@ -9,5 +9,5 @@ fn test_emit_cuda_on_transpose_desc() { cmd.assert() .success() - .stdout(predicate::str::contains("Generated CUDA Code")); + .stderr(predicate::str::contains("Generated CUDA Code")); } From 9c3e639b8a8b97153e0be04fedcba84eec48ec06 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 21 May 2025 16:39:29 +0200 Subject: [PATCH 15/57] WIP: integrating arena in ast --- Cargo.toml | 8 + profile.json | 1 + profile_memory.sh | 6 + src/ast/internal.rs | 227 +++++++------- src/ast/mod.rs | 701 ++++++++++++++++++++++++-------------------- src/ast/utils.rs | 4 +- src/ty_check/mod.rs | 202 +++++++------ 7 files changed, 619 insertions(+), 530 deletions(-) create mode 100644 profile.json create mode 100755 profile_memory.sh diff --git a/Cargo.toml b/Cargo.toml index dd9ffffe..357fe30a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[profile.samply] +inherits = "release" +debug = true + [[bin]] name = "descendc" path = "src/main.rs" @@ -13,6 +17,10 @@ path = "src/main.rs" [dependencies.peg] version = "0.8.0" +[dependencies.bumpalo] +version="3.17.0" +features=["collections"] + [dependencies.annotate-snippets] version = "0.9.0" features = ["color"] diff --git a/profile.json b/profile.json new file mode 100644 index 00000000..983c9824 --- /dev/null +++ b/profile.json @@ -0,0 +1 @@ +{"meta":{"categories":[{"name":"Other","color":"grey","subcategories":["Other"]},{"name":"JIT app cache","color":"green","subcategories":["Other"]},{"name":"User","color":"yellow","subcategories":["Other"]},{"name":"Kernel","color":"orange","subcategories":["Other"]}],"debug":false,"extensions":{"baseURL":[],"id":[],"length":0,"name":[]},"interval":1.0,"preprocessedProfileVersion":55,"processType":0,"product":"descend","oscpu":"Ubuntu 20.04.6 LTS","sampleUnits":{"eventDelay":"ms","threadCPUDelta":"µs","time":"ms"},"startTime":1746530540509.1873,"symbolicated":false,"pausedRanges":[],"version":24,"usesOnlyOneStackType":true,"sourceCodeIsNotOnSearchfox":true,"markerSchema":[{"name":"mmap","display":["marker-chart","marker-table"],"fields":[{"key":"name","label":"Details","format":"unique-string","searchable":true}]}]},"libs":[{"name":"ld-2.31.so","path":"/usr/lib/x86_64-linux-gnu/ld-2.31.so","debugName":"ld-2.31.so","debugPath":"/usr/lib/x86_64-linux-gnu/ld-2.31.so","breakpadId":"674590CBB2E160A4B6FC20817776AD590","codeId":"cb904567e1b2a460b6fc20817776ad590d265686","arch":null},{"name":"libLLVM-10.so.1","path":"/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1","debugName":"libLLVM-10.so.1","debugPath":"/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1","breakpadId":"622F33C0FCBE7FD43E14942B0D1A046E0","codeId":"c0332f62befcd47f3e14942b0d1a046e204b9659","arch":null},{"name":"libclang-cpp.so.10","path":"/usr/lib/llvm-10/lib/libclang-cpp.so.10","debugName":"libclang-cpp.so.10","debugPath":"/usr/lib/llvm-10/lib/libclang-cpp.so.10","breakpadId":"9ED8032B401835C949890C1BEDE6D54C0","codeId":"2b03d89e1840c93549890c1bede6d54c8ea1ac9a","arch":null},{"name":"clang-format","path":"/usr/lib/llvm-10/bin/clang-format","debugName":"clang-format","debugPath":"/usr/lib/llvm-10/bin/clang-format","breakpadId":"122CEB0CB6A67554027E02B1169552930","codeId":"0ceb2c12a6b65475027e02b116955293a19ffd16","arch":null},{"name":"libc-2.31.so","path":"/usr/lib/x86_64-linux-gnu/libc-2.31.so","debugName":"libc-2.31.so","debugPath":"/usr/lib/x86_64-linux-gnu/libc-2.31.so","breakpadId":"48AB2303BE06F8E646D9AD4BCCFC29AF0","codeId":"0323ab4806bee6f846d9ad4bccfc29afdca49a58","arch":null},{"name":"descend","path":"/home/dominic/descend/target/release/descend","debugName":"descend","debugPath":"/home/dominic/descend/target/release/descend","breakpadId":"57CF708544F3088F8E9BEFD82437E7E20","codeId":"8570cf57f3448f088e9befd82437e7e28de71895","arch":null},{"name":"libpthread-2.31.so","path":"/usr/lib/x86_64-linux-gnu/libpthread-2.31.so","debugName":"libpthread-2.31.so","debugPath":"/usr/lib/x86_64-linux-gnu/libpthread-2.31.so","breakpadId":"6D89FB5C0FD4AA908C6C8BB856004D1F0","codeId":"5cfb896dd40f90aa8c6c8bb856004d1f5cfe293c","arch":null}],"threads":[{"frameTable":{"length":0,"address":[],"inlineDepth":[],"category":[],"subcategory":[],"func":[],"nativeSymbol":[],"innerWindowID":[],"line":[],"column":[]},"funcTable":{"length":0,"name":[],"isJS":[],"relevantForJS":[],"resource":[],"fileName":[],"lineNumber":[],"columnNumber":[]},"markers":{"length":0,"category":[],"data":[],"endTime":[],"name":[],"phase":[],"startTime":[]},"name":"samply","isMainThread":true,"nativeSymbols":{"length":0,"address":[],"functionSize":[],"libIndex":[],"name":[]},"pausedRanges":[],"pid":"54509","processName":"samply","processShutdownTime":7962895.391907,"processStartupTime":0.0,"processType":"default","registerTime":0.0,"resourceTable":{"length":0,"lib":[],"name":[],"host":[],"type":[]},"samples":{"length":0,"weightType":"samples","stack":[],"timeDeltas":[],"weight":[],"threadCPUDelta":[]},"stackTable":{"length":0,"prefix":[],"frame":[]},"stringArray":[],"tid":"54509","unregisterTime":7962895.391907,"showMarkersInTimeline":false},{"frameTable":{"length":834,"address":[411517,147586,455812,3019686,492760,497010,432303,1507765,1699476,3024850,3040958,78738,1507887,2086590,2089170,2091389,2091905,2126075,2475118,2400677,632543,2091309,2136220,2092356,2113865,2095565,2093697,2097026,2115302,2093017,2122833,2092440,2145816,2462355,2465317,2467211,2464852,2470944,2028663,2028056,2055233,2017918,2057260,2463207,2025269,2025002,2023767,2024017,1942400,1986795,1986873,1986672,3184878,2127330,2122799,2467178,2488966,2490709,2492477,2495967,2097039,2148050,2464146,2466606,2055132,2471409,1902552,2095932,2286540,1586007,1536790,2053155,2052791,2465283,2459189,1954552,1986801,2471054,2027587,1986626,2465011,2145897,2083140,2083731,616661,2116106,2027531,3184869,631284,2093789,2370625,1925539,2464525,2288545,2288171,2288037,2285827,631093,2465519,2027792,1688068,380972,634805,626270,621698,612957,2146341,1690803,1696466,1536820,2054678,2018576,622600,1986846,631123,623292,2370519,1697025,381915,2052877,2052992,2016696,2062924,2018411,2370434,2378787,2378591,2377888,1986879,1925507,1926684,1904099,1900236,1900708,2459233,2495961,2495760,3184816,2488879,2488034,2488118,621872,622591,2288299,2334928,2335378,2337604,2057548,2065214,631181,2117435,1627225,1664469,1666301,1669083,1668960,1537086,2055032,2057725,2065163,2065024,1941840,624074,2463356,2289928,2289382,2289892,1942380,1984428,631066,2471297,1902529,1900556,617242,2144858,1627543,1629590,1647416,1634206,1689517,626465,618323,612779,621712,2464593,2454031,2453921,2455971,2456668,2450803,2449356,2449688,616668,2028126,381001,631287,2488176,1985003,1984362,622369,1926723,616521,631087,616621,2017870,2378678,2379989,2381740,2384847,622331,2117431,1942024,612946,1647519,2016806,2064223,2064298,2018378,1942044,616616,2464994,2061835,2018597,612842,2025188,2065267,2057708,2065040,3058828,2017980,2377746,2378133,2378983,616835,2370735,2400215,2390214,2390154,2396384,2389620,2386465,2386860,616657,2054281,2064148,1986631,1900221,3058849,381023,2064152,2370268,2055063,2057763,1942049,2054337,2064275,2018469,2455984,2452532,2449281,508672,622021,612900,1911071,3058853,2467295,1670186,2064180,2018352,2453854,2454954,2465660,2456116,2449341,2449598,2471402,624070,616746,1902485,616757,2054435,2064357,616636,2017947,624114,612622,2335294,2337260,2340433,631140,612967,2377721,2018357,2287952,621491,2467303,2453126,2453066,2452860,616684,612987,612537,2065137,622378,3184835,612816,616638,622429,2061767,508656,617208,624191,1954700,1914153,2384878,631271,2466686,2487920,2057685,631297,632564,2463381,2364496,2383899,2382420,2384801,1696803,1678146,1678077,1678128,1676130,1676019,1671629,1671945,632536,2285777,631174,1585792,2052604,2052446,2053696,631071,2018751,2289821,631144,2023958,621927,2064281,1536802,621910,2490730,2492437,621955,1690857,2454945,1900568,2054379,2064345,2018517,2018810,2334718,2337420,2340336,2370382,3184885,2380175,2358526,2381580,2384911,1900537,2381757,1696628,2052693,2053930,2063696,2054915,623284,2488421,2489238,2122736,2023720,2018452,2384905,2384704,3184870,2017847,621967,2024078,2018524,612904,2147693,2145795,2458318,2490827,2285754,616847,2449274,2065247,1986770,2453850,2023749,2064994,623276,2383872,1629872,1611840,1984317,1664543,1935667,631080,1925520,1911860,1900161,3058852,2064308,2289880,2459509,2379875,621907,2145422,2322827,2328100,2041677,2038662,1986769,622519,632528,2016720,2018767,2055223,2053038,2018438,2286612,2054028,2064100,2449657,2144785,1664655,1617272,2289491,2334697,621288,623288,2464329,2028277,1687920,2052886,2024100,3184913,612822,2028590,2378950,2378874,2064181,2063712,2145214,2417961,2418539,3186023,2018664,1910977,2396417,2064112,2289496,623683,2097942,2079244,2073694,2289956,2024060,1942150,621940,2027810,2334903,1536832,1555027,2115546,2364390,1900109,2018821,2340272,616549,621950,2386452,2065241,2065479,2018603,1677868,1682595,2370546,1682625,632579,1986884,631119,2057768,2465349,612897,2389948,2395345,2287978,621265,2396371,2396860,2387987,2386540,616855,1900464,2285712,2055116,621168,2028192,623322,2289372,622619,2449352,612565,2027605,1930432,1984402,2471458,618463,616677,1987106,632555,2023928,622132,2052862,3058848,616749,616653,612992,2053985,2063794,2063860,1986114,2028031,1986076,2065169,2052836,2018631,2018568,2065026,2337235,612557,623272,1914178,616845,622464,1910032,2017396,616708,1910075,2290065,2465605,2053049,2027483,1910080,2052978,2018499,2057523,2053630,2054368,2018544,1900478,631304,2018684,2064205,2488096,616694,623223,2456003,616769,622549,622298,2053610,2054643,2018488,1910078,624128,2065045,2016784,2018611,622409,1910998,1910963,631175,3184899,1620396,2028198,1986811,2054221,2018742,1935789,2016752,2018491,622864,1941996,623185,2495889,2389941,2064212,2018722,612838,1926696,1951379,2052181,1593464,632590,2017953,622560,2039028,2404794,2018442,1900580,2463239,2018552,1942097,2390189,616571,2290082,2465396,2287223,1620392,2018530,2018753,2290017,3058752,2492460,2495883,612834,1942085,1986899,623482,621193,623173,1911781,2378902,1902576,1913424,2340510,622109,2288274,622868,383005,631053,2286558,2061668,2060834,2060787,2418650,3186074,3217202,3187554,409094,409168,2117679,2073727,2018660,2054270,2018565,2117490,2068523,2083692,2066029,2066286,612828,2052219,2019075,2063914,623309,631188,631280,1986608,2017808,2063702,2028062,2019337,2064093,623256,2145817,1536932,1541378,1986796,1628941,1611884,1605940,1605442,2024284,2396872,1951292,622281,631025,624292,381662,2449612,1633493,1668388,2470608,2064976,2018477,613034,621278,1668371,1666893,624235,1677830,1902462,2380010,1620240,2358578,2116734,2365665,616846,616671,2018692,1914157,2386525,2386872,2054181,2018607,2052897,2018513,622611,2334580,621876,1954339,381120,1676202,1671644,616594,2027550,2065204,2147434,2068419,2066376,2387996,2395377,2148026,2490895,2457787,2457882,2027630,2453101,2467195,2288749,2027456,1910128,2095709,2117458,1627319,1629808,612912,631178,1671964,621445,612917,2027815,2018512,2382773,1620351,616821,2057287,2495857,2337220,2466760,1696532,2116080,1620410,621751,2028308,2053127,1910045,2016640,1536980,616851,617217,1942391,2454892,2378880,623477,2455995,632615,2053148,622569,2418676,624110,622574,1555033,2379340,2064165,2061443,2018732,623056,631019,612909,613027,1605382,1605350,2465318,2452445,2495781,2028433,624123,622624,2378566,631022,623248,622228,2018587,1620348,616795,626236,2028563,2203455,2228859,2203550,1963503,2204090,2212390,2214294,2231566,2239002,2237693,2238276,1437693,1507961,2198493,1542519,3053232,3084832,1100270,1102346,1100659,1176389],"inlineDepth":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"category":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],"subcategory":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"func":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833],"nativeSymbol":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"innerWindowID":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"line":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"column":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"funcTable":{"length":834,"name":[4,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839],"isJS":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"relevantForJS":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"resource":[0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,1,0,1,0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,0,1,0,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],"fileName":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"lineNumber":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"columnNumber":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"markers":{"length":4,"category":[0,0,0,0],"data":[{"type":"mmap","name":1},{"type":"mmap","name":1},{"type":"mmap","name":1},{"type":"mmap","name":2}],"endTime":[0.0,0.0,0.0,0.0],"name":[0,0,0,0],"phase":[0,0,0,0],"startTime":[7962903.442004,7962903.858355,7963005.962321,7963550.437747]},"name":"descend","isMainThread":true,"nativeSymbols":{"length":0,"address":[],"functionSize":[],"libIndex":[],"name":[]},"pausedRanges":[],"pid":"54509.1","processName":"descend","processShutdownTime":7963631.330803,"processStartupTime":7962895.391907,"processType":"default","registerTime":7962895.391907,"resourceTable":{"length":3,"lib":[5,4,6],"name":[3,5,16],"host":[null,null,null],"type":[1,1,1]},"samples":{"length":649,"weightType":"samples","stack":[11,20,59,70,103,134,166,187,222,238,239,247,285,290,309,326,334,350,354,366,374,388,399,408,409,415,455,464,468,506,518,530,534,544,587,602,611,619,622,625,628,632,636,638,641,645,648,649,651,653,657,663,669,674,684,706,714,724,736,742,743,752,754,763,768,773,779,784,789,790,794,799,807,808,811,823,829,835,836,839,841,843,851,852,876,882,883,885,889,893,894,901,908,910,916,918,919,920,924,925,929,940,943,944,951,952,958,960,962,966,967,973,982,993,1001,1007,1009,1021,1026,1034,1039,1048,1054,1056,326,1060,1063,1074,1085,1092,1093,1096,1102,1108,1112,1117,1120,1127,1128,1133,1139,1144,1148,1153,1156,1158,1163,1167,1171,1172,1176,1179,1180,1184,1188,1217,1220,1224,1230,1233,1237,1242,1245,1248,1249,1252,1258,653,1262,1265,1271,1274,1278,1284,1287,1293,1296,1303,1311,1313,1316,1323,1326,1327,1331,1337,1347,1351,1353,1355,1356,1359,1362,1367,1370,1373,1376,1382,1383,1388,1391,1394,1398,1399,1400,1403,1409,1410,1415,1421,1422,1425,1428,1430,1432,1434,1439,1443,1444,1447,1448,1455,1456,1461,1464,1471,1472,1478,1484,1487,1495,1497,1498,1500,1501,1508,1515,1521,1410,1524,1526,1527,1532,1535,1539,1547,1549,1551,1552,326,1556,1558,1562,1564,1569,1572,1579,1580,1593,1595,1596,1602,1605,1611,1616,1617,1623,1628,1633,1637,1642,1649,1650,1651,1654,1656,1657,1658,1661,1663,1665,1668,1669,1670,1673,1676,1677,1678,1681,1684,1685,1688,1689,1696,1699,1702,1707,1714,1718,1722,1724,1726,1727,1731,1734,1738,1744,1748,1750,1751,1787,1791,1792,1793,1797,1800,1802,1803,1808,1809,1811,1816,1818,1820,1822,1824,1828,1832,1833,1835,1839,1842,1851,1854,1856,1860,1862,1866,1867,1872,1875,1877,1878,1883,1884,1887,1894,1896,1900,1901,1907,1908,1913,1915,1921,1923,1926,1929,1932,1933,1936,1938,1941,1950,1952,1954,1957,1960,1961,1962,1964,1966,1969,1975,1991,1994,1997,1998,1999,2000,2001,2004,2005,2011,2015,2018,2021,2024,2029,2032,2033,2036,2042,2046,2050,2076,2079,2080,2082,2084,910,2086,2088,2092,2095,2097,2099,2106,2107,2108,2112,2115,2116,2122,2125,2132,2140,2144,2149,2151,2153,2154,2160,2161,2163,2164,2166,2169,2176,2178,2196,2198,2203,1497,2207,2213,2215,2217,2219,2224,2225,2229,2234,2236,2239,2242,2246,2250,2257,2258,2262,2266,2267,2271,2275,2280,2282,2292,2297,2298,789,2299,2301,1933,2302,1933,2306,2315,2318,2321,2323,2327,2333,2337,2341,2348,2351,2352,2356,2363,2364,2366,2367,2370,2371,2380,2381,2389,2392,2397,2398,2399,2404,2410,2416,2418,2421,2426,2429,2432,2445,2446,2450,2453,2454,2457,2458,2462,2466,2469,2470,2472,2478,2483,2486,2487,2490,1444,2491,2495,2497,2529,2530,2531,2534,2536,2537,2539,2543,2545,2546,2548,2554,2557,2561,2562,2564,2566,2571,2572,2574,2577,2578,2581,2536,2585,2588,2592,1249,2593,2595,2597,2603,2609,2610,2612,2614,2620,2628,2629,2632,2638,2640,2648,2649,2651,2656,2664,2667,2668,2674,2675,2677,2680,2683,2685,2691,2696,2698,2699,2703,2704,2705,2706,2707,2709,2712,2713,2716,2718,2719,2720,2160,2722,2723,2724,2725,2726,2729,2731,2736,2740,2743,2744,2747,2749,2750,2751,2752,2755,2760,2764,2772,2774,2780,2781,2782,2302,2786,2794,2796,2797,2800,2804,2807,2810,2812,2818,2823,2825,2829,2832,2837,2838,2839,1410,2842,1128,2843,2846,2851,2855,2857,1933,2862,2863,2865,2892,2901],"timeDeltas":[7962900.856904,2.588686,0.999565,0.999758,1.000926,0.998966,0.999808,1.000042,1.000264,0.999625,1.000043,0.999992,1.000056,0.999918,0.999891,1.000093,1.000103,1.000176,1.001414,0.998606,0.999984,0.999711,1.00004,1.000157,0.999911,1.000061,0.999845,1.000009,1.000071,1.000029,0.999865,1.000018,1.000034,0.999951,1.0001,0.999874,1.000089,0.999751,1.000304,0.99999,0.999918,1.00019,0.999842,1.000078,0.999847,1.000086,1.000012,0.999935,1.000081,0.999907,0.999996,1.000066,1.000088,1.000022,0.999794,0.999994,1.00005,1.00008,0.999959,0.999845,1.000017,1.000187,1.000009,1.000028,0.999925,0.999979,1.000044,1.000012,1.000039,0.999819,1.000133,0.999887,1.000132,0.999924,0.999914,1.000103,0.999923,1.000138,0.999961,0.999873,1.000177,0.999915,1.000032,1.000002,0.99989,1.000157,0.999994,1.057135,0.943075,0.999619,1.000276,0.999873,1.000113,0.999787,0.999974,1.000128,0.999936,0.999992,1.000018,1.000081,0.999966,1.003755,0.996202,1.006338,0.993613,1.000178,0.999897,1.000158,1.0022,0.998023,0.999849,0.999688,1.000051,0.999989,1.172362,0.827964,0.999774,1.000058,0.999903,0.999901,1.0,1.000125,0.999778,1.000103,1.092511,0.911464,1.017639,0.980872,0.998274,1.002348,0.997563,1.00087,0.998671,1.000058,1.000279,1.00087,1.000532,0.998338,0.999856,1.000077,1.402158,0.597895,1.000381,0.999648,1.791202,0.208814,1.000377,0.999645,1.000231,0.999519,1.000001,0.999976,1.000016,0.999966,1.000118,0.999914,1.00013,1.000061,0.999952,0.999886,1.000207,0.999856,0.999853,1.000062,1.000285,1.003101,0.99688,0.99979,0.999839,1.000049,0.99997,1.000083,0.999966,1.000001,1.000006,1.000003,0.999869,1.000058,1.0001,0.9999,1.000182,0.999852,1.000002,1.000054,0.99994,0.999938,1.060128,0.940432,0.999547,1.000058,0.999818,1.000406,0.999814,0.999905,1.000049,0.999923,1.000053,1.000235,0.999778,1.000171,0.999693,0.999972,0.999875,1.000292,0.999929,1.000106,1.000079,0.999841,0.999931,1.000145,1.000067,0.99975,1.000056,1.000332,0.99984,0.999932,1.010016,0.990558,0.999666,0.999946,0.999931,0.999844,1.000167,0.999833,0.999949,0.999866,1.000301,0.999674,1.000069,1.000191,0.999803,1.000014,1.000255,0.999938,0.999752,1.000295,0.999748,1.000028,0.999988,1.000063,1.000027,1.000083,0.99998,0.999837,1.000056,1.00025,0.999717,1.000102,1.000038,0.999961,0.999966,1.000013,0.99998,0.999988,1.000123,0.999952,0.999846,1.000149,1.000075,0.999911,0.999882,1.000139,0.999868,1.0001,1.066274,0.934043,0.999944,0.99986,0.999947,1.000008,0.999937,1.000058,1.055203,0.945013,0.999846,0.999818,1.000183,0.99995,0.999994,1.000035,0.999775,1.000169,0.999892,1.000104,0.999936,1.0001,0.999813,1.000062,1.000034,0.999957,1.000104,0.999916,1.00002,0.99991,1.000129,0.999922,0.999989,0.999887,1.000165,0.999906,0.999935,1.000231,0.999721,1.000247,0.999968,1.000583,0.99942,1.000037,0.99997,0.999958,0.999904,1.000194,0.99973,1.000196,0.999907,1.000078,1.000105,1.000002,0.999799,0.999992,1.000017,1.000129,1.000031,0.999864,1.00002,1.000208,0.99972,1.000241,0.999868,0.9999,1.000055,0.999998,1.000128,0.999754,1.000189,0.999913,0.999981,1.000005,1.000127,0.99998,0.99996,1.000062,0.999887,1.000131,0.999892,1.000114,1.00284,0.997531,1.000031,0.999659,1.000075,1.001041,0.998769,1.000112,1.042977,0.957069,1.000002,0.999927,0.999979,0.999755,1.000274,1.000041,0.99983,1.000066,0.999943,1.000193,0.999838,1.000171,1.000178,0.999626,0.999902,1.007329,0.992761,1.000051,0.999904,1.000167,0.999914,0.999866,1.000229,0.999773,1.000144,0.999892,1.000147,0.999982,0.999881,1.000139,0.999845,1.000048,1.000048,1.000004,0.999966,1.00208,0.998212,0.999842,1.029876,0.999745,1.000066,0.999913,1.000061,1.000098,0.999704,1.000134,1.012705,0.998026,0.989654,0.999818,0.999953,0.999949,1.009993,1.023716,1.033929,0.965713,0.999858,0.999724,1.000151,1.058474,0.941614,0.999796,1.000133,0.999933,1.000078,0.999776,1.000065,1.000189,0.999879,0.999846,1.000368,0.999774,1.00059,0.999374,0.999976,1.000185,0.999884,0.999891,1.00001,1.000074,1.000645,0.999468,1.000414,0.999484,0.999922,1.000174,0.999922,1.000015,0.999844,1.000125,0.999996,1.000702,0.999892,0.99979,0.999987,1.000001,1.000206,0.999769,1.000124,0.99994,1.00015,0.99983,1.000185,0.999928,0.999895,1.000152,0.999417,1.003983,0.99651,0.999505,1.000128,0.999968,1.000425,0.999586,0.999751,1.000218,0.999888,1.000029,1.000073,1.0,1.000028,0.999976,1.058438,0.946799,0.995046,0.999681,0.999884,1.000077,1.000037,0.999842,1.004977,0.995308,0.999964,1.00008,0.999843,1.000062,0.999769,1.000215,1.000133,0.999907,0.999875,1.000162,1.000013,0.999878,0.999939,1.000156,0.999666,1.000357,0.999743,1.000122,1.000193,0.999909,0.99991,0.999921,1.000419,0.999709,1.000035,0.9998,1.000163,1.000034,0.999911,0.999994,0.999963,1.000058,0.999903,1.000099,1.000129,0.999898,0.999975,0.999842,1.000377,0.99987,0.99988,1.000109,0.999771,1.000264,0.999903,0.999853,1.000111,0.99983,1.000194,0.999999,0.999963,1.000036,0.999943,0.999988,1.000018,0.999968,0.999926,1.000069,1.000051,1.000019,0.999849,1.000035,1.000183,0.999964,0.999872,1.000096,0.999874,1.00012,1.002205,0.998135,0.999611,1.000157,0.9999,1.000039,0.999965,1.00004,0.999968,1.000078,0.999898,0.999998,1.000019,0.999865,1.00019,0.999851,1.000157,1.273838,0.727995,0.998297,0.999937,0.999954,0.999959,0.999885,0.999952,1.000085,0.999966,1.00009,0.999914,1.000111,0.999964,0.999899,1.00014,0.999861,1.000188,0.999854,1.000011,0.999981,0.999948,1.000108,1.000034,0.999822,1.000482,0.999648,0.999978,1.00004,0.999789,1.000148,0.999932,1.00013,1.000051,0.99996,0.999835,1.000223,0.999935,0.999989,1.000012,0.999996,0.999875,1.000024,0.999998,0.999999,1.00006,1.000085,1.000005,0.999925,1.000155,0.999799,1.000083,0.999802,1.000256,0.999911,1.000031,0.999941,0.999904,1.000117,1.00011,0.999953,0.999933,1.000155,0.999707,1.000283,0.999878,1.000255,0.999761,0.999988,1.000067,0.999921,0.999813,1.000007,1.000229,1.000217,1.004043],"weight":[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],"threadCPUDelta":[939,989,999,999,1000,998,999,1000,1000,999,1000,999,1000,999,999,1000,1000,1000,1001,998,999,999,1000,1000,999,1000,999,1000,1000,1000,999,1000,1000,999,1000,999,1000,999,1000,999,999,1000,999,1000,999,1000,1000,999,1000,999,999,1000,1000,1000,999,999,1000,1000,999,999,1000,1000,1000,1000,999,999,1000,1000,1000,999,1000,999,1000,999,999,1000,999,1000,999,999,1000,999,1000,1000,999,1000,999,1057,943,999,1000,999,1000,999,999,1000,999,999,1000,1000,999,1003,996,1006,993,1000,999,1000,1002,998,999,999,1000,999,1172,827,999,1000,999,999,1000,1000,999,1000,1092,911,1017,980,998,1002,997,1000,998,1000,1000,1000,1000,998,999,1000,1402,597,1000,999,1791,208,1000,999,1000,999,1000,999,1000,999,1000,999,1000,1000,999,999,1000,999,999,1000,1000,1003,996,999,999,1000,999,1000,999,1000,1000,1000,999,1000,1000,999,1000,999,1000,1000,999,999,1060,940,999,1000,999,1000,999,999,1000,999,1000,1000,999,1000,999,999,999,1000,999,1000,1000,999,999,1000,1000,999,1000,1000,999,999,1010,990,999,999,999,999,1000,999,999,999,1000,999,1000,1000,999,1000,1000,999,999,1000,999,1000,999,1000,1000,1000,999,999,1000,1000,999,1000,1000,999,999,1000,999,999,1000,999,999,1000,1000,999,999,1000,999,1000,1066,934,999,999,999,1000,999,1000,1055,945,999,999,1000,999,999,1000,999,1000,999,1000,999,1000,999,1000,1000,999,1000,999,1000,999,1000,999,999,999,1000,999,999,1000,999,1000,999,1000,999,1000,999,999,999,1000,999,1000,999,1000,1000,1000,999,999,1000,1000,1000,999,1000,1000,999,1000,999,999,1000,999,1000,999,1000,999,999,1000,1000,999,999,1000,999,1000,999,1000,1002,997,1000,999,1000,1001,998,1000,1042,957,1000,999,999,999,1000,1000,999,1000,999,1000,999,1000,1000,999,999,1007,992,1000,999,1000,999,999,1000,999,1000,999,1000,999,999,1000,999,1000,1000,1000,999,1002,998,999,996,999,1000,999,1000,1000,999,1000,1012,998,989,999,999,999,1009,987,1033,965,999,999,1000,1058,941,999,1000,999,1000,999,1000,1000,999,999,1000,999,1000,999,999,1000,999,999,1000,1000,1000,999,1000,999,999,1000,999,1000,999,1000,999,1000,999,999,999,1000,1000,999,1000,999,1000,999,1000,999,999,1000,999,1003,996,999,1000,999,1000,999,999,1000,999,1000,1000,1000,1000,999,1058,946,995,999,999,1000,1000,999,1004,995,999,1000,999,1000,999,1000,1000,999,999,1000,1000,999,999,1000,999,1000,999,1000,1000,999,999,999,1000,999,1000,999,1000,1000,999,999,999,1000,999,1000,1000,999,999,999,1000,999,999,1000,999,1000,999,999,1000,999,1000,999,999,1000,999,999,1000,999,999,1000,1000,1000,999,1000,1000,999,999,1000,999,1000,1002,998,999,1000,999,1000,999,1000,999,1000,999,999,1000,999,1000,999,1000,1273,727,998,999,999,999,999,999,1000,999,1000,999,1000,999,999,1000,999,1000,999,1000,999,999,1000,1000,999,1000,999,999,1000,999,1000,999,1000,1000,999,999,1000,999,999,1000,999,999,1000,999,999,1000,1000,1000,999,1000,999,1000,999,1000,999,1000,999,999,1000,1000,999,999,1000,999,1000,999,1000,999,999,1000,999,999,1000,1000,1000,1004]},"stackTable":{"length":2902,"prefix":[null,0,1,2,3,4,5,6,7,8,9,10,6,12,13,14,15,16,17,18,19,null,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,47,60,61,62,63,64,65,66,67,68,69,null,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,21,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,null,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,16,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,null,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,40,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,163,124,240,241,242,243,244,245,246,null,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,181,286,287,288,289,208,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,294,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,241,327,328,329,330,331,332,333,212,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,304,351,352,353,287,355,356,357,358,359,360,361,362,363,364,365,287,367,368,369,370,371,372,373,156,375,376,377,378,379,380,381,382,383,384,385,386,387,93,389,390,391,392,393,394,395,396,397,398,379,400,401,402,403,404,405,406,407,324,381,410,411,412,413,414,null,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,286,456,457,458,459,460,461,462,463,243,465,466,467,null,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,230,507,508,509,510,511,512,513,514,515,516,517,229,519,520,521,522,523,524,525,526,527,528,529,382,531,532,533,42,535,536,537,538,539,540,541,542,543,null,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,91,588,589,590,591,592,593,594,595,596,597,598,599,600,601,381,603,604,605,606,607,608,609,610,457,612,613,614,615,616,617,618,403,620,621,402,623,624,526,626,627,614,629,630,631,524,633,634,635,605,637,615,639,640,369,642,643,644,373,646,647,457,282,650,349,652,95,654,655,656,186,658,659,660,661,662,297,664,665,666,667,668,97,670,671,672,673,381,675,676,677,678,679,680,681,682,683,154,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,229,707,708,709,710,711,712,713,160,715,716,717,718,719,720,721,722,723,378,725,726,727,728,729,730,731,732,733,734,735,370,737,738,739,740,741,289,287,744,745,746,747,748,749,750,751,358,753,378,755,756,757,758,759,760,761,762,165,764,765,766,767,449,769,770,771,772,658,774,775,776,777,778,287,780,781,782,783,772,785,786,787,788,620,185,791,792,793,605,795,796,797,798,232,800,801,802,803,804,805,806,788,288,809,810,379,812,813,814,815,816,817,818,819,820,821,822,163,824,825,826,827,828,392,830,831,832,833,834,614,633,837,838,383,840,629,842,392,844,845,846,847,848,849,850,629,563,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,300,877,878,879,880,881,705,370,884,360,886,887,888,670,890,891,892,704,301,895,896,897,898,899,900,98,902,903,904,905,906,907,705,909,513,911,912,913,914,915,372,917,788,796,392,921,922,923,349,186,926,927,928,212,930,931,932,933,934,935,936,937,938,939,766,941,942,704,97,945,946,947,948,949,950,531,708,953,954,955,956,957,644,959,613,961,758,963,964,965,950,392,968,969,970,971,972,330,974,975,976,977,978,979,980,981,932,983,984,985,986,987,988,989,990,991,992,183,994,995,996,997,998,999,1000,867,1002,1003,1004,1005,1006,850,1008,47,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,64,1022,1023,1024,1025,163,1027,1028,1029,1030,1031,1032,1033,184,1035,1036,1037,1038,596,1040,1041,1042,1043,1044,1045,1046,1047,844,1049,1050,1051,1052,1053,465,1055,905,1057,1058,1059,658,1061,1062,48,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,355,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,985,1086,1087,1088,1089,1090,1091,287,990,1094,1095,510,1097,1098,1099,1100,1101,404,1103,1104,1105,1106,1107,642,1109,1110,1111,671,1113,1114,1115,1116,828,1118,1119,164,1121,1122,1123,1124,1125,1126,705,368,1129,1130,1131,1132,781,1134,1135,1136,1137,1138,330,1140,1141,1142,1143,52,1145,1146,1147,404,1149,1150,1151,1152,457,1154,1155,218,1157,926,1159,1160,1161,1162,1130,1164,1165,1166,133,1168,1169,1170,759,1077,1173,1174,1175,1076,1177,1178,705,710,1181,1182,1183,634,1185,1186,1187,null,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,328,1218,1219,895,1221,1222,1223,844,1225,1226,1227,1228,1229,904,1231,1232,665,1234,1235,1236,234,1238,1239,1240,1241,637,1243,1244,717,1246,1247,652,58,1250,1251,1065,1253,1254,1255,1256,1257,163,1259,1260,1261,672,1263,1264,210,1266,1267,1268,1269,1270,525,1272,1273,1235,1275,1276,1277,826,1279,1280,1281,1282,1283,459,1285,1286,130,1288,1289,1290,1291,1292,1078,1294,1295,932,1297,1298,1299,1300,1301,1302,578,1304,1305,1306,1307,1308,1309,1310,328,1312,1129,1314,1315,95,1317,1318,1319,1320,1321,1322,898,1324,1325,840,986,1328,1329,1330,1288,1332,1333,1334,1335,1336,98,1338,1339,1340,1341,1342,1343,1344,1345,1346,297,1348,1349,1350,630,1352,467,1354,1162,54,1357,1358,955,1360,1361,383,1363,1364,1365,1366,182,1368,1369,608,1371,1372,328,1374,1375,1298,1377,1378,1379,1380,1381,627,381,1384,1385,1386,1387,670,1389,1390,332,1392,1393,373,1395,1396,1397,658,1247,1350,1401,1402,727,1404,1405,1406,1407,1408,325,932,1411,1412,1413,1414,1411,1416,1417,1418,1419,1420,65,741,1423,1424,367,1426,1427,1076,1429,1000,1431,629,1433,328,1435,1436,1437,1438,680,1440,1441,1442,705,988,1445,1446,1433,466,1449,1450,1451,1452,1453,1454,746,1079,1457,1458,1459,1460,381,1462,1463,1068,1465,1466,1467,1468,1469,1470,325,501,1473,1474,1475,1476,1477,439,1479,1480,1481,1482,1483,392,1485,1486,570,1488,1489,1490,1491,1492,1493,1494,1138,1496,650,383,1499,1047,1040,1502,1503,1504,1505,1506,1507,1385,1509,1510,1511,1512,1513,1514,297,1516,1517,1518,1519,1520,331,1522,1523,457,1525,765,1031,1528,1529,1530,1531,412,1533,1534,1342,1536,1537,1538,508,1540,1541,1542,1543,1544,1545,1546,607,1548,1020,1550,749,1417,1553,1554,1555,1342,1557,976,1559,1560,1561,287,1563,1451,1565,1566,1567,1568,737,1570,1571,664,1573,1574,1575,1576,1577,1578,936,44,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1312,1594,788,747,1597,1598,1599,1600,1601,709,1603,1604,411,1606,1607,1608,1609,1610,747,1612,1613,1614,1615,652,922,1618,1619,1620,1621,1622,1517,1624,1625,1626,1627,1553,1629,1630,1631,1632,56,1634,1635,1636,1412,1638,1639,1640,1641,1304,1643,1644,1645,1646,1647,1648,1463,787,281,1652,1653,949,1655,909,759,282,1659,1660,371,1662,1288,1664,670,1666,1667,630,1104,165,1671,1672,64,1674,1675,1078,1621,1566,1679,1680,1433,1682,1683,788,1368,1686,1687,705,987,1690,1691,1692,1693,1694,1695,1236,1697,1698,53,1700,1701,729,1703,1704,1705,1706,160,1708,1709,1710,1711,1712,1713,342,1715,1716,1717,1354,1719,1720,1721,1081,1723,922,1725,956,879,1728,1729,1730,236,1732,1733,580,1735,1736,1737,393,1739,1740,1741,1742,1743,912,1745,1746,1747,531,1749,324,null,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1736,1788,1789,1790,1433,360,328,1794,1795,1796,62,1798,1799,1598,1801,324,280,1804,1805,1806,1807,705,97,1810,97,1812,1813,1814,1815,382,1817,1121,1819,658,1821,1076,1823,318,1825,1826,1827,782,1829,1830,1831,994,185,1834,1509,1836,1837,1838,671,1840,1841,161,1843,1844,1845,1846,1847,1848,1849,1850,886,1852,1853,776,1855,819,1857,1858,1859,404,1861,975,1863,1864,1865,601,297,1868,1869,1870,1871,935,1873,1874,604,1876,349,579,1879,1880,1881,1882,995,288,1885,1886,317,1888,1889,1890,1891,1892,1893,776,1895,849,1897,1898,1899,809,1692,1902,1903,1904,1905,1906,809,233,1909,1910,1911,1912,886,1914,1226,1916,1917,1918,1919,1920,1241,1922,911,1924,1925,1559,1927,1928,1005,1930,1931,652,1825,1934,1935,844,1937,1115,1939,1940,163,1942,1943,1944,1945,1946,1947,1948,1949,978,1951,164,1953,344,1955,1956,849,1958,1959,1352,1285,1335,1963,1457,1965,359,1967,1968,1392,1970,1971,1972,1973,1974,44,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,629,1992,1993,1844,1995,1996,787,1621,102,1597,677,2002,2003,325,730,2006,2007,2008,2009,2010,1416,2012,2013,2014,531,2016,2017,665,2019,2020,1142,2022,2023,2016,2025,2026,2027,2028,1705,2030,2031,324,1603,2034,2035,390,2037,2038,2039,2040,2041,1720,2043,2044,2045,1597,2047,2048,2049,189,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,661,2077,2078,1604,661,2081,809,2083,746,2085,1016,2087,392,2089,2090,2091,1392,2093,2094,332,2096,1485,2098,1843,2100,2101,2102,2103,2104,2105,652,371,911,2109,2110,2111,738,2113,2114,289,1742,2117,2118,2119,2120,2121,1071,2123,2124,163,2126,2127,2128,2129,2130,2131,279,2133,2134,2135,2136,2137,2138,2139,185,2141,2142,2143,1703,2145,2146,2147,2148,1339,2150,383,2152,349,447,2155,2156,2157,2158,2159,1992,1081,2162,367,1121,2165,1043,2167,2168,1624,2170,2171,2172,2173,2174,2175,1943,2177,226,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,356,2197,1066,2199,2200,2201,2202,182,2204,2205,2206,1436,2208,2209,2210,2211,2212,457,2214,186,2216,1030,2218,457,2220,2221,2222,2223,705,358,2226,2227,2228,1000,2230,2231,2232,2233,1035,2235,911,2237,2238,1275,2240,2241,728,2243,2244,2245,1465,2247,2248,2249,1136,2251,2252,2253,2254,2255,2256,1496,615,2259,2260,2261,997,2263,2264,2265,131,2022,2268,2269,2270,235,2272,2273,2274,303,2276,2277,2278,2279,1082,2281,294,2283,2284,2285,2286,2287,2288,2289,2290,2291,361,2293,2294,2295,2296,2226,243,357,2300,788,1505,2303,2304,2305,224,2307,2308,2309,2310,2311,2312,2313,2314,1587,2316,2317,1795,2319,2320,1612,2322,1735,2324,2325,2326,1041,2328,2329,2330,2331,2332,1909,2334,2335,2336,1886,2338,2339,2340,800,2342,2343,2344,2345,2346,2347,675,2349,2350,942,2130,2353,2354,2355,565,2357,2358,2359,2360,2361,2362,921,1817,2365,1081,185,2368,2369,705,522,2372,2373,2374,2375,2376,2377,2378,2379,2320,854,2382,2383,2384,2385,2386,2387,2388,373,2390,2391,921,2393,2394,2395,2396,1450,671,1129,2400,2401,2402,2403,1109,2405,2406,2407,2408,2409,710,2411,2412,2413,2414,2415,457,2417,1350,2419,2420,903,2422,2423,2424,2425,746,2427,2428,411,2430,2431,161,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,2444,1121,2428,2447,2448,2449,880,2451,2452,1719,1473,2455,2456,1834,658,2459,2460,2461,236,2463,2464,2465,1377,2467,2468,705,946,2471,711,2473,2474,2475,2476,2477,1711,2479,2480,2481,2482,1452,2484,2485,1659,1035,2488,2489,2412,1134,2492,2493,2494,1627,2496,null,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,1173,1613,132,2532,2533,1247,2535,2216,1597,2538,2523,2540,2541,2542,100,2544,1466,1227,2547,445,2549,2550,2551,2552,2553,98,2555,2556,890,2558,2559,2560,1433,181,2563,1615,2565,497,2567,2568,2569,2570,746,778,2573,1958,2575,2576,705,1607,2579,2580,1864,2582,2583,2584,917,2586,2587,1804,2589,2590,2591,788,770,2594,2295,2596,594,2598,2599,2600,2601,2602,1869,2604,2605,2606,2607,2608,764,639,2611,1463,2613,400,2615,2616,2617,2618,2619,1002,2621,2622,2623,2624,2625,2626,2627,2172,1554,2630,2631,50,2633,2634,2635,2636,2637,613,2639,457,2641,2642,2643,2644,2645,2646,2647,787,2047,2650,2493,2652,2653,2654,2655,446,2657,2658,2659,2660,2661,2662,2663,1145,2665,2666,1134,718,2669,2670,2671,2672,2673,332,1288,2676,1529,2678,2679,392,2681,2682,614,2684,769,2686,2687,2688,2689,2690,1571,2692,2693,2694,2695,629,2697,897,1574,2700,2701,2702,907,2576,652,367,1289,2708,1560,2710,2711,165,1462,2714,2715,739,2717,825,788,2025,2721,1574,1334,661,678,1607,2727,2728,1436,2730,1357,2732,2733,2734,2735,515,2737,2738,2739,1033,2741,2742,1565,2375,2745,2746,1075,2748,739,1852,2204,887,2753,2754,1604,2756,2757,2758,2759,1626,2761,2762,2763,2372,2765,2766,2767,2768,2769,2770,2771,947,2773,1067,2775,2776,2777,2778,2779,325,652,774,2783,2784,2785,292,2787,2788,2789,2790,2791,2792,2793,383,2795,1594,2191,2798,2799,2559,2801,2802,2803,947,2805,2806,101,2808,2809,2113,2811,1004,2813,2814,2815,2816,2817,1003,2819,2820,2821,2822,368,2824,511,2826,2827,2828,637,2830,2831,877,2833,2834,2835,2836,2799,2393,1070,2840,2841,1465,906,2844,2845,1958,2847,2848,2849,2850,2277,2852,2853,2854,1352,2856,1502,2858,2859,2860,2861,131,667,2864,null,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,6,2893,2894,2895,2896,2897,2898,2899,2900],"frame":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,30,31,32,33,34,35,33,36,37,38,38,38,38,38,38,39,40,41,42,43,44,45,45,46,47,48,49,50,51,52,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,54,31,32,33,34,55,56,57,58,59,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,54,60,61,33,62,63,37,38,39,64,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,30,31,32,33,34,35,33,36,65,66,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,67,68,69,70,71,72,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,30,31,32,33,73,74,75,45,45,46,47,48,49,76,54,31,32,33,34,35,33,36,77,38,38,38,78,48,50,79,80,30,29,30,31,81,82,83,84,3,4,5,6,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,85,62,63,37,38,38,38,38,86,87,88,25,89,90,91,84,54,31,32,33,34,35,33,92,93,94,94,95,96,48,49,50,51,87,97,98,37,38,38,38,38,38,38,38,38,99,100,101,102,103,104,105,54,31,106,107,108,109,110,111,98,37,38,38,38,38,38,38,38,38,99,100,101,102,103,112,50,113,114,115,116,117,118,109,71,71,119,119,120,121,122,123,124,125,126,126,127,48,50,128,54,31,32,33,34,35,33,36,65,129,130,131,132,133,30,31,32,33,73,134,57,58,135,136,137,55,138,138,139,139,140,87,114,141,142,92,93,143,144,145,146,6,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,85,62,63,37,38,38,38,38,38,38,39,40,41,147,148,149,26,27,150,151,152,153,154,155,137,106,107,108,156,1,2,3,4,5,6,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,85,62,63,37,39,157,158,159,160,37,38,38,38,38,38,38,38,78,161,114,162,163,164,165,165,166,96,167,168,49,51,87,169,170,171,172,173,174,175,176,177,178,179,101,102,180,181,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,30,31,32,33,34,35,33,36,37,38,38,38,38,38,38,38,38,99,100,101,102,103,104,182,54,60,61,33,62,63,37,38,38,78,48,51,87,114,183,184,185,186,187,188,189,190,191,192,85,62,63,37,193,100,194,195,196,167,197,196,167,198,113,114,199,65,129,200,201,48,49,113,202,186,203,39,40,204,205,206,207,208,113,114,209,210,78,211,104,212,174,175,176,213,119,120,214,215,216,217,36,37,38,38,78,218,98,65,171,172,219,220,108,109,71,71,120,121,221,122,222,54,60,61,33,62,63,37,38,38,38,38,38,38,38,38,99,100,101,102,103,104,223,43,44,45,224,40,41,147,225,73,74,75,224,157,226,159,227,87,228,98,37,38,38,38,39,40,229,226,227,87,228,230,230,230,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,73,74,75,45,45,47,48,49,245,129,130,131,246,247,38,38,99,100,248,71,119,119,243,215,249,250,38,39,251,252,101,102,103,104,105,253,254,215,255,256,257,258,259,191,260,39,40,229,147,227,87,114,261,262,171,263,264,265,266,107,108,109,71,71,119,120,214,267,268,184,185,186,186,269,270,271,272,188,189,273,274,275,113,114,276,171,277,278,279,34,265,266,107,108,109,280,281,282,54,31,32,33,34,35,33,36,37,38,38,38,38,38,38,39,40,283,158,227,87,114,284,285,143,144,286,287,288,289,290,291,202,120,121,255,292,37,39,157,252,142,293,95,96,48,113,114,294,295,296,297,297,298,298,299,300,301,39,157,226,302,114,303,51,304,305,306,98,65,278,203,307,120,121,221,308,34,35,33,43,44,224,251,158,227,87,309,132,172,310,311,73,74,312,187,188,273,279,313,224,157,158,159,227,137,314,315,316,317,224,251,318,319,320,321,322,323,324,325,228,326,327,328,329,330,331,332,333,334,92,93,94,94,293,293,293,95,335,87,336,337,338,338,339,338,339,339,340,38,38,38,78,161,341,216,342,163,164,165,165,343,343,343,166,96,48,113,344,46,345,87,114,346,220,108,109,71,71,120,121,347,348,254,215,255,268,38,39,40,229,226,227,87,114,349,55,56,350,351,114,352,353,310,354,355,355,84,356,357,358,77,38,38,38,38,78,48,49,113,114,115,108,109,71,71,119,120,214,215,215,267,359,143,360,361,362,87,114,115,363,96,48,128,39,157,226,159,227,364,196,48,50,51,87,309,365,366,367,368,129,130,131,246,242,354,172,242,170,129,130,131,246,369,201,212,205,206,370,325,88,38,38,38,38,78,253,371,372,338,373,374,39,375,114,376,139,377,378,87,309,28,29,379,46,380,214,215,215,267,381,207,382,383,384,40,385,114,386,387,254,215,255,268,254,216,388,389,251,226,227,137,49,51,87,309,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,54,60,390,247,391,392,393,293,95,394,319,295,296,297,297,298,395,257,258,396,39,157,158,397,38,38,78,48,398,269,269,399,45,45,400,182,147,159,401,39,157,158,148,114,402,321,322,403,202,369,369,320,174,175,176,177,404,405,406,114,402,226,302,114,402,187,188,189,273,191,334,407,408,409,65,410,411,412,369,413,120,121,414,163,164,165,165,343,343,415,39,157,226,159,227,87,114,162,32,416,417,114,418,419,420,421,422,423,87,319,424,114,425,426,95,394,114,162,129,130,131,132,355,192,265,266,107,108,109,71,71,120,427,428,43,44,224,429,130,282,109,430,431,78,161,97,148,114,115,410,411,412,172,84,432,433,434,273,435,260,436,437,438,439,440,361,288,114,441,442,443,185,187,188,279,77,444,445,71,356,244,49,51,87,97,446,447,157,226,401,39,157,158,159,227,448,449,36,77,38,38,450,37,39,40,385,114,115,253,451,87,309,452,383,304,356,453,433,454,171,84,455,456,457,458,169,214,215,267,459,449,95,96,253,460,326,327,328,329,330,332,84,461,119,119,120,214,462,163,164,463,38,38,78,48,113,114,464,389,38,39,157,158,302,228,28,29,30,465,466,467,163,468,309,43,44,45,45,46,46,46,469,48,128,470,278,219,471,38,38,38,38,38,38,472,186,187,188,189,273,435,306,163,164,439,473,114,402,474,475,217,476,477,478,119,119,120,427,479,440,361,480,254,215,255,268,39,157,158,159,227,87,114,115,190,481,114,482,483,157,226,484,485,110,486,328,487,488,233,489,334,328,487,490,172,491,127,48,492,77,38,39,157,226,302,493,494,73,74,75,45,45,46,46,47,48,49,51,87,309,33,495,496,237,497,497,498,172,84,45,47,253,94,94,293,499,114,500,501,502,503,504,505,105,129,130,131,132,369,506,165,165,343,166,507,158,484,227,87,289,508,408,114,509,510,227,87,114,402,40,283,158,227,87,114,511,512,513,78,48,76,189,514,515,400,38,516,517,167,518,91,426,519,520,449,521,522,410,412,523,524,114,525,526,527,487,490,528,369,369,529,530,531,532,533,182,95,96,48,51,87,114,276,148,114,376,78,167,534,38,38,38,535,319,98,37,38,38,78,167,536,39,157,226,537,71,71,538,539,267,540,171,299,541,542,114,284,543,113,114,544,38,78,161,319,74,312,186,186,354,133,158,148,114,115,545,546,547,5,6,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,85,62,63,37,38,38,78,167,168,49,128,48,424,114,115,548,549,81,82,83,550,224,157,252,498,551,513,78,167,406,114,525,305,163,552,553,108,109,554,268,77,555,171,556,557,558,243,462,78,167,406,149,40,229,559,309,560,561,562,186,354,355,563,410,246,279,55,138,56,57,58,135,136,87,564,214,255,268,538,565,119,120,214,566,567,202,329,330,332,568,471,321,322,403,114,569,157,318,319,570,571,572,78,167,406,114,573,574,129,130,395,39,157,226,159,227,87,319,575,359,243,215,255,576,577,49,49,51,87,114,578,84,39,157,158,484,579,580,581,187,188,189,273,191,282,50,79,375,114,582,490,583,584,48,424,585,449,48,49,128,35,416,132,369,571,92,93,94,94,293,95,335,586,587,332,334,77,588,78,48,589,71,590,591,84,592,369,506,120,593,254,267,594,71,119,119,119,538,581,98,37,38,38,38,38,38,38,38,38,38,78,48,113,114,595,410,246,279,138,196,596,597,563,598,599,243,600,601,602,251,158,227,87,114,349,38,39,375,97,129,603,604,535,114,500,338,605,606,130,131,246,172,607,39,40,608,609,46,46,469,419,420,421,422,610,611,120,214,255,612,498,369,369,613,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,54,60,61,33,614,215,255,615,616,255,217,369,84,617,618,343,619,620,621,586,622,254,267,623,561,624,625,626,56,57,627,628,136,87,169,629,630,251,226,227,137,127,48,631,334,269,269,269,354,355,563,424,114,632,443,185,186,187,188,273,274,39,157,226,159,227,87,114,633,243,215,267,222,78,167,406,114,386,353,320,91,242,634,99,100,101,102,103,307,635,216,594,636,637,638,158,227,364,439,144,286,287,639,114,640,641,88,98,37,38,38,38,38,38,38,38,38,38,78,48,49,51,87,114,642,643,306,39,40,229,318,644,645,646,647,648,649,650,651,652,653,654,655,656,538,657,658,659,660,661,662,663,664,665,254,215,216,292,338,339,666,667,668,575,359,40,385,149,148,114,669,78,48,51,137,78,48,424,670,78,48,49,50,51,87,671,672,38,39,40,673,339,666,667,674,675,666,676,532,677,167,168,113,309,167,168,424,114,678,267,268,73,74,75,45,45,46,46,47,161,409,120,214,215,255,594,347,679,680,681,449,78,48,49,682,174,175,176,177,683,404,684,685,686,46,46,687,662,663,529,688,689,86,87,114,690,157,226,484,227,87,691,40,385,114,402,131,132,172,550,157,226,159,227,87,114,692,117,693,319,260,189,273,435,694,174,175,176,177,683,695,696,697,510,698,249,280,357,699,700,343,166,96,48,50,51,87,114,701,664,174,175,176,177,683,695,702,703,424,114,704,37,39,157,158,537,705,706,707,207,383,586,708,709,370,383,87,114,642,157,226,484,227,87,409,710,711,40,385,319,187,188,189,190,712,501,502,713,641,114,442,265,266,107,108,109,71,71,119,119,119,119,538,714,715,503,716,717,282,639,114,162,718,38,38,675,719,119,119,720,721,49,424,114,722,723,114,724,629,725,726,283,226,227,87,114,162,38,38,38,38,675,727,728,729,730,280,267,268,731,39,40,385,319,394,670,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,54,60,732,662,733,663,734,664,462,735,38,78,253,47,211,459,736,618,737,392,738,739,738,740,741,742,84,78,167,168,49,113,319,743,93,744,38,38,38,745,746,747,260,717,571,748,749,175,750,564,84,267,699,254,267,123,751,95,394,752,331,728,753,260,87,114,754,48,50,49,79,755,38,756,216,757,39,157,158,148,114,386,323,758,382,383,586,759,760,157,761,165,463,56,57,58,762,114,294,78,48,49,50,51,87,114,183,763,148,114,402,39,157,226,302,114,294,764,765,766,392,57,627,628,136,87,691,294,355,242,229,226,227,586,767,39,40,229,158,227,87,114,768,251,226,541,769,251,226,227,87,114,482,770,171,771,119,120,772,553,108,773,519,774,78,48,49,113,114,386,49,51,87,114,701,91,775,776,38,535,114,573,777,217,602,778,246,264,487,488,84,313,468,114,779,291,97,780,629,132,523,675,781,244,782,499,114,783,784,729,48,51,87,114,678,48,424,114,785,215,255,601,705,424,114,786,474,787,788,789,790,215,267,791,48,50,113,114,792,343,166,394,793,343,166,96,48,49,51,87,169,257,84,78,167,168,49,50,79,794,795,120,121,267,558,174,175,176,177,404,684,796,797,637,638,798,113,114,786,86,87,114,349,186,257,799,627,628,800,161,88,38,38,801,87,114,802,78,48,424,114,803,804,805,78,161,114,806,354,355,563,440,361,288,114,402,500,675,424,114,807,741,354,355,760,71,120,214,267,808,50,51,586,809,246,810,99,100,101,102,811,812,38,675,813,814,813,814,813,814,813,814,815,816,817,818,819,820,821,821,821,821,821,821,821,821,821,821,822,823,824,825,826,827,828,829,830,831,832,833]},"stringArray":["mmap","[heap]","//anon","descend","0x6477d","libc-2.31.so","0x24082","0x6f484","0x2e13a6","0x784d8","0x79572","0x698af","0x1701b5","0x19ee94","0x2e27d2","0x2e66be","libpthread-2.31.so","0x13392","0x17022f","0x1fd6be","0x1fe0d2","0x1fe97d","0x1feb81","0x2070fb","0x25c46e","0x24a1a5","0x9a6df","0x1fe92d","0x20989c","0x1fed44","0x204149","0x1ff9cd","0x1ff281","0x1fff82","0x2046e6","0x1fefd9","0x206451","0x1fed98","0x20be18","0x259293","0x259e25","0x25a58b","0x259c54","0x25b420","0x1ef477","0x1ef218","0x1f5c41","0x1eca7e","0x1f642c","0x2595e7","0x1ee735","0x1ee62a","0x1ee157","0x1ee251","0x1da380","0x1e50eb","0x1e5139","0x1e5070","0x3098ee","0x2075e2","0x20642f","0x25a56a","0x25fa86","0x260155","0x26083d","0x2615df","0x1fff8f","0x20c6d2","0x259992","0x25a32e","0x1f5bdc","0x25b5f1","0x1d07d8","0x1ffb3c","0x22e3cc","0x183357","0x177316","0x1f5423","0x1f52b7","0x259e03","0x258635","0x1dd2f8","0x1e50f1","0x25b48e","0x1ef043","0x1e5042","0x259cf3","0x20be69","0x1fc944","0x1fcb93","0x968d5","0x204a0a","0x1ef00b","0x3098e5","0x9a1f4","0x1ff2dd","0x242c41","0x1d61a3","0x259b0d","0x22eba1","0x22ea2b","0x22e9a5","0x22e103","0x9a135","0x259eef","0x1ef110","0x19c204","0x5d02c","0x9afb5","0x98e5e","0x97c82","0x95a5d","0x20c025","0x19ccb3","0x19e2d2","0x177334","0x1f5a16","0x1ecd10","0x98008","0x1e511e","0x9a153","0x982bc","0x242bd7","0x19e501","0x5d3db","0x1f530d","0x1f5380","0x1ec5b8","0x1f7a4c","0x1ecc6b","0x242b82","0x244c23","0x244b5f","0x2448a0","0x1e513f","0x1d6183","0x1d661c","0x1d0de3","0x1cfecc","0x1d00a4","0x258661","0x2615d9","0x261510","0x3098b0","0x25fa2f","0x25f6e2","0x25f736","0x97d30","0x97fff","0x22eaab","0x23a0d0","0x23a292","0x23ab44","0x1f654c","0x1f833e","0x9a18d","0x204f3b","0x18d459","0x1965d5","0x196cfd","0x1977db","0x197760","0x17743e","0x1f5b78","0x1f65fd","0x1f830b","0x1f8280","0x1da150","0x985ca","0x25967c","0x22f108","0x22eee6","0x22f0e4","0x1da36c","0x1e47ac","0x9a11a","0x25b581","0x1d07c1","0x1d000c","0x96b1a","0x20ba5a","0x18d597","0x18dd96","0x192338","0x18ef9e","0x19c7ad","0x98f21","0x96f53","0x959ab","0x97c90","0x259b51","0x25720f","0x2571a1","0x2579a3","0x257c5c","0x256573","0x255fcc","0x256118","0x968dc","0x1ef25e","0x5d049","0x9a1f7","0x25f770","0x1e49eb","0x1e476a","0x97f21","0x1d6643","0x96849","0x9a12f","0x968ad","0x1eca4e","0x244bb6","0x2450d5","0x2457ac","0x2463cf","0x97efb","0x204f37","0x1da208","0x95a52","0x19239f","0x1ec626","0x1f7f5f","0x1f7faa","0x1ecc4a","0x1da21c","0x968a8","0x259ce2","0x1f760b","0x1ecd25","0x959ea","0x1ee6e4","0x1f8373","0x1f65ec","0x1f8290","0x2eac8c","0x1ecabc","0x244812","0x244995","0x244ce7","0x96983","0x242caf","0x249fd7","0x2478c6","0x24788a","0x2490e0","0x247674","0x246a21","0x246bac","0x968d1","0x1f5889","0x1f7f14","0x1e5047","0x1cfebd","0x2eaca1","0x5d05f","0x1f7f18","0x242adc","0x1f5b97","0x1f6623","0x1da221","0x1f58c1","0x1f7f93","0x1ecca5","0x2579b0","0x256c34","0x255f81","0x7c300","0x97dc5","0x95a24","0x1d291f","0x2eaca5","0x25a5df","0x197c2a","0x1f7f34","0x1ecc30","0x25715e","0x2575aa","0x259f7c","0x257a34","0x255fbd","0x2560be","0x25b5ea","0x985c6","0x9692a","0x1d0795","0x96935","0x1f5923","0x1f7fe5","0x968bc","0x1eca9b","0x985f2","0x9590e","0x23a23e","0x23a9ec","0x23b651","0x9a164","0x95a67","0x2447f9","0x1ecc35","0x22e950","0x97bb3","0x25a5e7","0x256e86","0x256e4a","0x256d7c","0x968ec","0x95a7b","0x958b9","0x1f82f1","0x97f2a","0x3098c3","0x959d0","0x968be","0x97f5d","0x1f75c7","0x7c2f0","0x96af8","0x9863f","0x1dd38c","0x1d3529","0x2463ee","0x9a1e7","0x25a37e","0x25f670","0x1f65d5","0x9a201","0x9a6f4","0x259695","0x241450","0x24601b","0x245a54","0x2463a1","0x19e423","0x199b42","0x199afd","0x199b30","0x199362","0x1992f3","0x1981cd","0x198309","0x9a6d8","0x22e0d1","0x9a186","0x183280","0x1f51fc","0x1f515e","0x1f5640","0x9a11f","0x1ecdbf","0x22f09d","0x9a168","0x1ee216","0x97d67","0x1f7f99","0x177322","0x97d56","0x26016a","0x260815","0x97d83","0x19cce9","0x2575a1","0x1d0018","0x1f58eb","0x1f7fd9","0x1eccd5","0x1ecdfa","0x239ffe","0x23aa8c","0x23b5f0","0x242b4e","0x3098f5","0x24518f","0x23fcfe","0x24570c","0x24640f","0x1cfff9","0x2457bd","0x19e374","0x1f5255","0x1f572a","0x1f7d50","0x1f5b03","0x982b4","0x25f865","0x25fb96","0x2063f0","0x1ee128","0x1ecc94","0x246409","0x246340","0x3098e6","0x1eca37","0x97d8f","0x1ee28e","0x1eccdc","0x95a28","0x20c56d","0x20be03","0x2582ce","0x2601cb","0x22e0ba","0x9698f","0x255f7a","0x1f835f","0x1e50d2","0x25715a","0x1ee145","0x1f8262","0x982ac","0x246000","0x18deb0","0x189840","0x1e473d","0x19661f","0x1d8933","0x9a128","0x1d6190","0x1d2c34","0x1cfe81","0x2eaca4","0x1f7fb4","0x22f0d8","0x258775","0x245063","0x97d53","0x20bc8e","0x23718b","0x238624","0x1f274d","0x1f1b86","0x1e50d1","0x97fb7","0x9a6d0","0x1ec5d0","0x1ecdcf","0x1f5c37","0x1f53ae","0x1ecc86","0x22e414","0x1f578c","0x1f7ee4","0x2560f9","0x20ba11","0x19668f","0x18ad78","0x22ef53","0x239fe9","0x97ae8","0x982b8","0x259a49","0x1ef2f5","0x19c170","0x1f5316","0x1ee2a4","0x309911","0x959d6","0x1ef42e","0x244cc6","0x244c7a","0x1f7f35","0x1f7d60","0x20bbbe","0x24e529","0x24e76b","0x309d67","0x1ecd68","0x1d28c1","0x249101","0x1f7ef0","0x22ef58","0x98443","0x200316","0x1fba0c","0x1fa45e","0x22f124","0x1ee27c","0x1da286","0x97d74","0x1ef122","0x23a0b7","0x177340","0x17ba53","0x2047da","0x2413e6","0x1cfe4d","0x1ece05","0x23b5b0","0x96865","0x97d7e","0x246a14","0x1f8359","0x1f8447","0x1ecd2b","0x199a2c","0x19aca3","0x242bf2","0x19acc1","0x9a703","0x1e5144","0x9a14f","0x1f6628","0x259e45","0x95a21","0x2477bc","0x248cd1","0x22e96a","0x97ad1","0x2490d3","0x2492bc","0x247013","0x246a6c","0x96997","0x1cffb0","0x22e090","0x1f5bcc","0x97a70","0x1ef2a0","0x982da","0x22eedc","0x9801b","0x255fc8","0x958d5","0x1ef055","0x1d74c0","0x1e4792","0x25b622","0x96fdf","0x968e5","0x1e5222","0x9a6eb","0x1ee1f8","0x97e34","0x1f52fe","0x2eaca0","0x9692d","0x968cd","0x95a80","0x1f5761","0x1f7db2","0x1f7df4","0x1e4e42","0x1ef1ff","0x1e4e1c","0x1f8311","0x1f52e4","0x1ecd47","0x1ecd08","0x1f8282","0x23a9d3","0x958cd","0x982a8","0x1d3542","0x9698d","0x97f80","0x1d2510","0x1ec874","0x96904","0x1d253b","0x22f191","0x259f45","0x1f53b9","0x1eefdb","0x1d2540","0x1f5372","0x1eccc3","0x1f6533","0x1f55fe","0x1f58e0","0x1eccf0","0x1cffbe","0x9a208","0x1ecd7c","0x1f7f4d","0x25f720","0x968f6","0x98277","0x2579c3","0x96941","0x97fd5","0x97eda","0x1f55ea","0x1f59f3","0x1eccb8","0x1d253e","0x98600","0x1f8295","0x1ec610","0x1ecd33","0x97f49","0x1d28d6","0x1d28b3","0x9a187","0x309903","0x18b9ac","0x1ef2a6","0x1e50fb","0x1f584d","0x1ecdb6","0x1d89ad","0x1ec5f0","0x1eccbb","0x98110","0x1da1ec","0x98251","0x261591","0x2477b5","0x1f7f54","0x1ecda2","0x959e6","0x1d6628","0x1dc693","0x1f5055","0x185078","0x9a70e","0x1ecaa1","0x97fe0","0x1f1cf4","0x24b1ba","0x1ecc8a","0x1d0024","0x259607","0x1eccf8","0x1da251","0x2478ad","0x9687b","0x22f1a2","0x259e74","0x22e677","0x18b9a8","0x1ecce2","0x1ecdc1","0x22f161","0x2eac40","0x26082c","0x26158b","0x959e2","0x1da245","0x1e5153","0x9837a","0x97a89","0x98245","0x1d2be5","0x244c96","0x1d07f0","0x1d3250","0x23b69e","0x97e1d","0x22ea92","0x98114","0x5d81d","0x9a10d","0x22e3de","0x1f7564","0x1f7222","0x1f71f3","0x24e7da","0x309d9a","0x311732","0x30a362","0x63e06","0x63e50","0x20502f","0x1fa47f","0x1ecd64","0x1f587e","0x1ecd05","0x204f72","0x1f902b","0x1fcb6c","0x1f866d","0x1f876e","0x959dc","0x1f507b","0x1ecf03","0x1f7e2a","0x982cd","0x9a194","0x9a1f0","0x1e5030","0x1eca10","0x1f7d56","0x1ef21e","0x1ed009","0x1f7edd","0x98298","0x20be19","0x1773a4","0x178502","0x1e50ec","0x18db0d","0x18986c","0x188134","0x187f42","0x1ee35c","0x2492c8","0x1dc63c","0x97ec9","0x9a0f1","0x986a4","0x5d2de","0x2560cc","0x18ecd5","0x197524","0x25b2d0","0x1f8250","0x1eccad","0x95aaa","0x97ade","0x197513","0x196f4d","0x9866b","0x199a06","0x1d077e","0x2450ea","0x18b910","0x23fd32","0x204c7e","0x2418e1","0x9698e","0x968df","0x1ecd84","0x1d352d","0x246a5d","0x246bb8","0x1f5825","0x1ecd2f","0x1f5321","0x1eccd1","0x98013","0x239f74","0x97d34","0x1dd223","0x5d0c0","0x1993aa","0x1981dc","0x96892","0x1ef01e","0x1f8334","0x20c46a","0x1f8fc3","0x1f87c8","0x24701c","0x248cf1","0x20c6ba","0x26020f","0x2580bb","0x25811a","0x1ef06e","0x256e6d","0x25a57b","0x22ec6d","0x1eefc0","0x1d2570","0x1ffa5d","0x204f52","0x18d4b7","0x18de70","0x95a30","0x9a18a","0x19831c","0x97b85","0x95a35","0x1ef127","0x1eccd0","0x245bb5","0x18b97f","0x96975","0x1f6447","0x261571","0x23a9c4","0x25a3c8","0x19e314","0x2049f0","0x18b9ba","0x97cb7","0x1ef314","0x1f5407","0x1d251d","0x1ec580","0x1773d4","0x96993","0x96b01","0x1da377","0x25756c","0x244c80","0x98375","0x2579bb","0x9a727","0x1f541c","0x97fe9","0x24e7f4","0x985ee","0x97fee","0x17ba59","0x244e4c","0x1f7f25","0x1f7483","0x1ecdac","0x981d0","0x9a0eb","0x95a2d","0x95aa3","0x187f06","0x187ee6","0x259e26","0x256bdd","0x261525","0x1ef391","0x985fb","0x98020","0x244b46","0x9a0ee","0x98290","0x97e94","0x1ecd1b","0x18b97c","0x9695b","0x98e3c","0x1ef413","0x219f3f","0x22027b","0x219f9e","0x1df5ef","0x21a1ba","0x21c226","0x21c996","0x220d0e","0x222a1a","0x2224fd","0x222744","0x15effd","0x170279","0x218bdd","0x178977","0x2e96b0","0x2f1220","0x10c9ee","0x10d20a","0x10cb73","0x11f345"],"tid":"54509.1","unregisterTime":7963631.330803,"showMarkersInTimeline":false},{"frameTable":{"length":0,"address":[],"inlineDepth":[],"category":[],"subcategory":[],"func":[],"nativeSymbol":[],"innerWindowID":[],"line":[],"column":[]},"funcTable":{"length":0,"name":[],"isJS":[],"relevantForJS":[],"resource":[],"fileName":[],"lineNumber":[],"columnNumber":[]},"markers":{"length":0,"category":[],"data":[],"endTime":[],"name":[],"phase":[],"startTime":[]},"name":"descend","isMainThread":true,"nativeSymbols":{"length":0,"address":[],"functionSize":[],"libIndex":[],"name":[]},"pausedRanges":[],"pid":"54517","processName":"descend","processShutdownTime":7963560.174892,"processStartupTime":7963550.576536,"processType":"default","registerTime":7963550.576536,"resourceTable":{"length":0,"lib":[],"name":[],"host":[],"type":[]},"samples":{"length":0,"weightType":"samples","stack":[],"timeDeltas":[],"weight":[],"threadCPUDelta":[]},"stackTable":{"length":0,"prefix":[],"frame":[]},"stringArray":[],"tid":"54517","unregisterTime":7963560.174892,"showMarkersInTimeline":false},{"frameTable":{"length":46,"address":[4359,8267,117834,17721,58132,58121,56820,57123,49452,4409,72864,72601,8520934,22837024,7618726,35103250,25901,147586,27703,30981,34850002,34849704,34966105,34925279,34925556,7806218,631123,624444,31375,34846898,34845077,34898983,34928293,9708086,34966536,34900977,35023342,35034334,35036380,147593,289375,288934,73578,8783414,290781,20954560],"inlineDepth":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"category":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],"subcategory":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"func":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"nativeSymbol":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"innerWindowID":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"line":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"column":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"funcTable":{"length":46,"name":[24,25,26,27,28,29,30,31,32,33,34,35,37,38,40,41,43,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73],"isJS":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"relevantForJS":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"resource":[0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,4,3,3,2,2,2,2,2,2,4,4,3,2,2,2,2,1,2,2,2,2,2,4,4,4,0,1,4,1],"fileName":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"lineNumber":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"columnNumber":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"markers":{"length":120,"category":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"data":[{"type":"mmap","name":1},{"type":"mmap","name":2},{"type":"mmap","name":2},{"type":"mmap","name":3},{"type":"mmap","name":4},{"type":"mmap","name":4},{"type":"mmap","name":4},{"type":"mmap","name":4},{"type":"mmap","name":3},{"type":"mmap","name":5},{"type":"mmap","name":6},{"type":"mmap","name":7},{"type":"mmap","name":3},{"type":"mmap","name":8},{"type":"mmap","name":8},{"type":"mmap","name":8},{"type":"mmap","name":8},{"type":"mmap","name":3},{"type":"mmap","name":9},{"type":"mmap","name":9},{"type":"mmap","name":9},{"type":"mmap","name":3},{"type":"mmap","name":10},{"type":"mmap","name":10},{"type":"mmap","name":3},{"type":"mmap","name":11},{"type":"mmap","name":11},{"type":"mmap","name":11},{"type":"mmap","name":11},{"type":"mmap","name":11},{"type":"mmap","name":3},{"type":"mmap","name":12},{"type":"mmap","name":12},{"type":"mmap","name":12},{"type":"mmap","name":12},{"type":"mmap","name":13},{"type":"mmap","name":13},{"type":"mmap","name":13},{"type":"mmap","name":13},{"type":"mmap","name":3},{"type":"mmap","name":14},{"type":"mmap","name":14},{"type":"mmap","name":14},{"type":"mmap","name":14},{"type":"mmap","name":3},{"type":"mmap","name":15},{"type":"mmap","name":15},{"type":"mmap","name":15},{"type":"mmap","name":15},{"type":"mmap","name":15},{"type":"mmap","name":16},{"type":"mmap","name":16},{"type":"mmap","name":16},{"type":"mmap","name":16},{"type":"mmap","name":3},{"type":"mmap","name":17},{"type":"mmap","name":17},{"type":"mmap","name":17},{"type":"mmap","name":17},{"type":"mmap","name":17},{"type":"mmap","name":18},{"type":"mmap","name":18},{"type":"mmap","name":18},{"type":"mmap","name":18},{"type":"mmap","name":19},{"type":"mmap","name":19},{"type":"mmap","name":19},{"type":"mmap","name":19},{"type":"mmap","name":3},{"type":"mmap","name":20},{"type":"mmap","name":20},{"type":"mmap","name":20},{"type":"mmap","name":20},{"type":"mmap","name":21},{"type":"mmap","name":21},{"type":"mmap","name":21},{"type":"mmap","name":21},{"type":"mmap","name":21},{"type":"mmap","name":3},{"type":"mmap","name":3},{"type":"mmap","name":3},{"type":"mmap","name":14},{"type":"mmap","name":21},{"type":"mmap","name":20},{"type":"mmap","name":19},{"type":"mmap","name":8},{"type":"mmap","name":18},{"type":"mmap","name":17},{"type":"mmap","name":16},{"type":"mmap","name":15},{"type":"mmap","name":13},{"type":"mmap","name":12},{"type":"mmap","name":11},{"type":"mmap","name":10},{"type":"mmap","name":9},{"type":"mmap","name":2},{"type":"mmap","name":4},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":3},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22}],"endTime":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"name":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"phase":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"startTime":[7963560.181201,7963560.183927,7963560.184846,7963560.185427,7963561.358189,7963561.362989,7963561.363897,7963561.365211,7963561.369329,7963561.371785,7963561.372205,7963561.436776,7963561.445769,7963561.449388,7963561.452749,7963561.45478,7963561.456387,7963561.459413,7963562.469263,7963562.471928,7963562.475042,7963563.575385,7963564.948793,7963564.95206,7963565.230608,7963565.872104,7963565.875103,7963565.877545,7963565.878745,7963565.879975,7963566.482538,7963566.503013,7963566.506771,7963566.509096,7963566.510444,7963566.522441,7963566.524888,7963566.526417,7963566.527574,7963566.537271,7963566.54078,7963566.543165,7963566.544668,7963566.546066,7963566.548342,7963567.442548,7963567.445196,7963567.447185,7963567.448299,7963567.449559,7963567.841714,7963567.844173,7963567.845438,7963567.846579,7963568.501945,7963568.513324,7963568.516166,7963568.518563,7963568.520509,7963568.52198,7963568.532649,7963568.535068,7963568.536892,7963568.537864,7963568.548797,7963568.55154,7963568.553954,7963568.555063,7963568.56538,7963568.567627,7963568.570461,7963568.571592,7963568.572506,7963568.748703,7963568.750083,7963568.752016,7963568.752844,7963568.75363,7963568.944028,7963569.418963,7963569.426668,7963570.261029,7963570.295066,7963570.31885,7963570.323081,7963570.32776,7963570.331128,7963570.333882,7963570.699851,7963570.703105,7963570.706627,7963570.717334,7963570.961962,7963591.492694,7963598.194983,7963598.206955,7963598.216356,7963598.314626,7963604.836583,7963608.687613,7963618.686049,7963620.903363,7963621.895996,7963621.998489,7963622.855637,7963624.011497,7963624.06866,7963624.193627,7963624.249902,7963624.302778,7963624.360985,7963624.411345,7963624.468227,7963624.519425,7963624.573801,7963624.63815,7963624.697822,7963624.757443,7963624.821874,7963624.88266]},"name":"clang-format","isMainThread":true,"nativeSymbols":{"length":0,"address":[],"functionSize":[],"libIndex":[],"name":[]},"pausedRanges":[],"pid":"54517.1","processName":"clang-format","processShutdownTime":7963630.944621,"processStartupTime":7963560.174892,"processType":"default","registerTime":7963560.174892,"resourceTable":{"length":5,"lib":[0,1,2,3,4],"name":[23,36,39,42,44],"host":[null,null,null,null,null],"type":[1,1,1,1,1]},"samples":{"length":14,"weightType":"samples","stack":[4,5,4,6,8,5,4,8,13,15,27,35,40,47],"timeDeltas":[7963570.337436,6.376416,2.547194,2.914668,6.893937,3.061123,2.871855,3.150672,8.388519,8.479917,6.937153,1.496905,1.136598,2.9944],"weight":[1,1,1,1,1,1,1,1,1,1,1,1,1,1],"threadCPUDelta":[823,990,970,981,959,985,975,985,958,957,964,997,997,989]},"stackTable":{"length":48,"prefix":[null,0,1,2,3,3,3,3,7,null,9,10,11,12,11,14,null,16,17,18,19,20,21,22,23,24,25,26,18,28,29,30,31,32,33,34,31,36,37,38,39,16,41,42,43,44,45,46],"frame":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,22,23,32,33,34,35,36,37,38,39,40,41,42,43,44,45]},"stringArray":["mmap","[stack]","/usr/lib/llvm-10/bin/clang-format","//anon","/usr/lib/x86_64-linux-gnu/ld-2.31.so","[vdso]","[vvar]","/etc/ld.so.cache","/usr/lib/x86_64-linux-gnu/libpthread-2.31.so","/usr/lib/llvm-10/lib/libclang-cpp.so.10","/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1","/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28","/usr/lib/x86_64-linux-gnu/libm-2.31.so","/usr/lib/x86_64-linux-gnu/libgcc_s.so.1","/usr/lib/x86_64-linux-gnu/libc-2.31.so","/usr/lib/x86_64-linux-gnu/libffi.so.7.1.0","/usr/lib/x86_64-linux-gnu/libedit.so.2.0.63","/usr/lib/x86_64-linux-gnu/libz.so.1.2.11","/usr/lib/x86_64-linux-gnu/librt-2.31.so","/usr/lib/x86_64-linux-gnu/libdl-2.31.so","/usr/lib/x86_64-linux-gnu/libtinfo.so.6.2","/usr/lib/x86_64-linux-gnu/libbsd.so.0.10.0","[heap]","ld-2.31.so","0x1107","0x204b","0x1cc4a","0x4539","0xe314","0xe309","0xddf4","0xdf23","0xc12c","0x1139","0x11ca0","0x11b99","libLLVM-10.so.1","0x8204e6","0x15c7720","libclang-cpp.so.10","0x7440a6","0x217a212","clang-format","0x652d","libc-2.31.so","0x24082","0x6c37","0x7905","0x213c4d2","0x213c3a8","0x2158a59","0x214eadf","0x214ebf4","0x771d0a","0x9a153","0x9873c","0x7a8f","0x213b8b2","0x213b195","0x2148427","0x214f6a5","0x942236","0x2158c08","0x2148bf1","0x21669ee","0x21694de","0x2169cdc","0x24089","0x46a5f","0x468a6","0x11f6a","0x860636","0x46fdd","0x13fbdc0"],"tid":"54517.1","unregisterTime":7963630.944621,"showMarkersInTimeline":false}],"pages":[],"profilerOverhead":[],"counters":[]} \ No newline at end of file diff --git a/profile_memory.sh b/profile_memory.sh new file mode 100755 index 00000000..40c44ae7 --- /dev/null +++ b/profile_memory.sh @@ -0,0 +1,6 @@ +#!/bin/bash +INPUT="examples/infer/matmul.desc" + +cargo build --profile samply + +samply record -- ./target/samply/descendc emit "$INPUT" \ No newline at end of file diff --git a/src/ast/internal.rs b/src/ast/internal.rs index 38db945f..7f5fdab1 100644 --- a/src/ast/internal.rs +++ b/src/ast/internal.rs @@ -5,48 +5,58 @@ use super::{Ident, Ownership, PlaceExpr, Ty}; use crate::ast::{ExecExpr, Mutability, Nat, PlaceExprKind, View}; +use bumpalo::collections::Vec as BumpVec; use std::collections::HashSet; -#[derive(Default, Clone, Debug, PartialEq, Eq)] -pub struct Frame { - pub bindings: Vec, +// TODO: Removed the Default trait here, see what kind of consequences has this later +// Otherwise implement the trait +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Frame<'a> { + pub bindings: BumpVec<'a, FrameEntry<'a>>, } -impl Frame { - pub fn new() -> Self { - Self::default() +impl<'a> Frame<'a> { + pub fn new_in(bump: &'a bumpalo::Bump) -> Self { + Self { + bindings: BumpVec::new_in(bump), + } } - pub fn append_idents_typed(&mut self, idents_typed: Vec) -> &mut Frame { - self.bindings.append( - &mut idents_typed - .into_iter() - .map(FrameEntry::Var) - .collect::>(), - ); - self + pub fn append_idents_typed(&mut self, idents_typed: I) + where + I: IntoIterator>, + { + for ident in idents_typed { + self.bindings.push(FrameEntry::Var(ident)); + } } } #[derive(PartialEq, Eq, Debug, Clone)] -pub enum FrameEntry { - Var(IdentTyped), - ExecMapping(ExecMapping), - PrvMapping(PrvMapping), +pub enum FrameEntry<'a> { + Var(IdentTyped<'a>), + ExecMapping(ExecMapping<'a>), + PrvMapping(PrvMapping<'a>), } #[derive(PartialEq, Eq, Debug, Clone)] -pub struct IdentTyped { - pub ident: Ident, - pub ty: Ty, +pub struct IdentTyped<'a> { + pub ident: Ident<'a>, + pub ty: Ty<'a>, pub mutbl: Mutability, - pub exec: ExecExpr, + pub exec: ExecExpr<'a>, } -impl IdentTyped { - pub fn new(ident: Ident, ty: Ty, mutbl: Mutability, exec: ExecExpr) -> Self { +impl<'a> IdentTyped<'a> { + pub fn new_in( + bump: &'a bumpalo::Bump, + ident: &str, + ty: Ty<'a>, + mutbl: Mutability, + exec: ExecExpr, + ) -> Self { IdentTyped { - ident, + ident: Ident::new(bump, ident), ty, mutbl, exec, @@ -55,24 +65,25 @@ impl IdentTyped { } #[derive(PartialEq, Eq, Debug, Clone)] -pub struct ExecMapping { - pub ident: Ident, - pub exec_expr: ExecExpr, +pub struct ExecMapping<'a> { + pub ident: Ident<'a>, + pub exec_expr: ExecExpr<'a>, } -impl ExecMapping { - pub fn new(ident: Ident, exec_expr: ExecExpr) -> Self { +impl<'a> ExecMapping<'a> { + pub fn new(ident: Ident<'a>, exec_expr: ExecExpr) -> Self { ExecMapping { ident, exec_expr } } } +// TODO: Problems with HashSet and String in the Arena implementation --> Find a work #[derive(PartialEq, Eq, Debug, Clone)] -pub struct PrvMapping { +pub struct PrvMapping<'a> { pub prv: String, - pub loans: HashSet, + pub loans: HashSet>, } -impl PrvMapping { +impl<'a> PrvMapping<'a> { pub fn new(name: &str) -> Self { PrvMapping { prv: name.to_string(), @@ -82,129 +93,127 @@ impl PrvMapping { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Loan { - pub place_expr: PlaceExpr, +pub struct Loan<'a> { + pub place_expr: PlaceExpr<'a>, pub own: Ownership, } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum PathElem { +pub enum PathElem<'a> { Proj(usize), - FieldProj(Box), + FieldProj(&'a Ident<'a>), } -pub type Path = Vec; +pub type Path<'a> = BumpVec<'a, PathElem<'a>>; + #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Place { - pub ident: Ident, - pub path: Path, +pub struct Place<'a> { + pub ident: Ident<'a>, + pub path: Path<'a>, } -impl Place { - pub fn new(ident: Ident, path: Path) -> Self { +impl<'a> Place<'a> { + pub fn new(ident: Ident<'a>, path: Path<'a>) -> Self { Place { ident, path } } - pub fn to_place_expr(&self) -> PlaceExpr { + pub fn to_place_expr(&self, bump: &'a bumpalo::Bump) -> PlaceExpr { self.path.iter().fold( PlaceExpr::new(PlaceExprKind::Ident(self.ident.clone())), |pl_expr, path_entry| match path_entry { - PathElem::Proj(n) => PlaceExpr::new(PlaceExprKind::Proj(Box::new(pl_expr), *n)), + PathElem::Proj(n) => PlaceExpr::new(PlaceExprKind::Proj(bump.alloc(pl_expr), *n)), PathElem::FieldProj(field) => { - PlaceExpr::new(PlaceExprKind::FieldProj(Box::new(pl_expr), field.clone())) + PlaceExpr::new(PlaceExprKind::FieldProj(bump.alloc(pl_expr), field)) } }, ) } + /** pub fn prefix_of(&self, other: &Self) -> bool { if self.path.len() > other.path.len() { return false; } self.ident == other.ident && &self.path == &other.path[..self.path.len()] + }*/ + + pub fn prefix_of(&self, other: &Self) -> bool { + if self.ident != other.ident || self.path.len() > other.path.len() { + return false; + } + + other.path.iter().zip(&self.path).all(|(a, b)| a == b) } } -pub enum PlaceCtx { - Proj(Box, usize), - FieldProj(Box, Box), - Deref(Box), - Select(Box, Box), - View(Box, Box), - Idx(Box, Box), +pub enum PlaceCtx<'a> { + Proj(&'a PlaceCtx<'a>, usize), + FieldProj(&'a PlaceCtx<'a>, Ident<'a>), + Deref(&'a PlaceCtx<'a>), + Select(&'a PlaceCtx<'a>, &'a ExecExpr<'a>), + View(&'a PlaceCtx<'a>, &'a View<'a>), + Idx(&'a PlaceCtx<'a>, &'a Nat<'a>), Hole, } -impl PlaceCtx { - pub fn insert_pl_expr(&self, pl_expr: PlaceExpr) -> PlaceExpr { +impl<'a> PlaceCtx<'a> { + pub fn insert_pl_expr( + &'a self, + bump: &'a bumpalo::Bump, + pl_expr: PlaceExpr<'a>, + ) -> PlaceExpr<'a> { match self { Self::Hole => pl_expr, Self::Proj(pl_ctx, n) => PlaceExpr::new(PlaceExprKind::Proj( - Box::new(pl_ctx.insert_pl_expr(pl_expr)), - n.clone(), + bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + *n, )), - Self::FieldProj(pl_ctx, field_name) => PlaceExpr::new(PlaceExprKind::FieldProj( - Box::new(pl_ctx.insert_pl_expr(pl_expr)), - field_name.clone(), + Self::FieldProj(pl_ctx, field) => PlaceExpr::new(PlaceExprKind::FieldProj( + bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + field, + )), + Self::Deref(pl_ctx) => PlaceExpr::new(PlaceExprKind::Deref( + bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), )), - Self::Deref(pl_ctx) => PlaceExpr::new(PlaceExprKind::Deref(Box::new( - pl_ctx.insert_pl_expr(pl_expr), - ))), Self::Select(pl_ctx, exec) => PlaceExpr::new(PlaceExprKind::Select( - Box::new(pl_ctx.insert_pl_expr(pl_expr)), + bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), exec.clone(), )), - Self::Idx(pl_ctx, idx) => PlaceExpr::new(PlaceExprKind::Idx( - Box::new(pl_ctx.insert_pl_expr(pl_expr)), - idx.clone(), - )), Self::View(pl_ctx, view) => PlaceExpr::new(PlaceExprKind::View( - Box::new(pl_ctx.insert_pl_expr(pl_expr)), + bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), view.clone(), )), + Self::Idx(pl_ctx, idx) => PlaceExpr::new(PlaceExprKind::Idx( + bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + idx.clone(), + )), } } - // Assumes the PlaceCtx HAS an innermost deref, meaning the Hole is wrapped by a Deref. - // This is always true for PlaceCtxs created by PlaceExpr.to_pl_ctx_and_most_specif_pl - pub fn without_innermost_deref(&self) -> Self { + pub fn without_innermost_deref(&'a self, bump: &'a bumpalo::Bump) -> &'a PlaceCtx<'a> { match self { - PlaceCtx::Hole => PlaceCtx::Hole, - PlaceCtx::Proj(pl_ctx, i) => { - if let PlaceCtx::Hole = **pl_ctx { - panic!("There must be an innermost deref context as created by PlaceExpr.to_pl_ctx_and_most_specif_pl.") - } else { - let inner_ctx = pl_ctx.without_innermost_deref(); - PlaceCtx::Proj(Box::new(inner_ctx), *i) - } - } - PlaceCtx::FieldProj(pl_ctx, field_name) => { - if let PlaceCtx::Hole = **pl_ctx { - panic!("There must be an innermost deref context as created by PlaceExpr.to_pl_ctx_and_most_specif_pl.") - } else { - let inner_ctx = pl_ctx.without_innermost_deref(); - PlaceCtx::FieldProj(Box::new(inner_ctx), field_name.clone()) - } - } - PlaceCtx::Deref(pl_ctx) => { - if let PlaceCtx::Hole = **pl_ctx { - PlaceCtx::Hole - } else { - let inner_ctx = pl_ctx.without_innermost_deref(); - PlaceCtx::Deref(Box::new(inner_ctx)) - } - } - PlaceCtx::Select(pl_ctx, exec_idents) => { - let inner_ctx = pl_ctx.without_innermost_deref(); - PlaceCtx::Select(Box::new(inner_ctx), exec_idents.clone()) - } - PlaceCtx::View(pl_ctx, view) => { - let inner_ctx = pl_ctx.without_innermost_deref(); - PlaceCtx::View(Box::new(inner_ctx), view.clone()) - } - - PlaceCtx::Idx(pl_ctx, idx) => { - let inner_ctx = pl_ctx.without_innermost_deref(); - PlaceCtx::Idx(Box::new(inner_ctx), idx.clone()) + PlaceCtx::Hole => self, + PlaceCtx::Proj(pl_ctx, idx) => { + bump.alloc(PlaceCtx::Proj(pl_ctx.without_innermost_deref(bump), *idx)) } + PlaceCtx::FieldProj(pl_ctx, ident) => bump.alloc(PlaceCtx::FieldProj( + pl_ctx.without_innermost_deref(bump), + ident.clone(), + )), + PlaceCtx::Deref(pl_ctx) => match **pl_ctx { + PlaceCtx::Hole => bump.alloc(PlaceCtx::Hole), + _ => bump.alloc(PlaceCtx::Deref(pl_ctx.without_innermost_deref(bump))), + }, + PlaceCtx::Select(pl_ctx, exec) => bump.alloc(PlaceCtx::Select( + pl_ctx.without_innermost_deref(bump), + exec.clone(), + )), + PlaceCtx::View(pl_ctx, view) => bump.alloc(PlaceCtx::View( + pl_ctx.without_innermost_deref(bump), + view.clone(), + )), + PlaceCtx::Idx(pl_ctx, idx) => bump.alloc(PlaceCtx::Idx( + pl_ctx.without_innermost_deref(bump), + idx.clone(), + )), } } } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 0d095fab..eefeb58d 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1,6 +1,7 @@ use std::fmt; use crate::ast::internal::PathElem; +use bumpalo::{collections::Vec as BumpVec, Bump}; use descend_derive::span_derive; pub use span::*; @@ -16,136 +17,147 @@ pub mod visit_mut; #[derive(Clone, Debug)] pub struct CompilUnit<'a> { - pub items: Vec, + pub items: Vec>, pub source: &'a SourceCode<'a>, } impl<'a> CompilUnit<'a> { - pub fn new(items: Vec, source: &'a SourceCode<'a>) -> Self { + pub fn new(items: Vec>, source: &'a SourceCode<'a>) -> Self { CompilUnit { items, source } } } #[derive(Debug, Clone)] -pub enum Item { - FunDef(Box), - FunDecl(Box), - StructDecl(Box), +pub enum Item<'a> { + FunDef(&'a FunDef<'a>), + FunDecl(&'a FunDecl<'a>), + StructDecl(&'a StructDecl<'a>), } #[derive(Debug, Clone, PartialEq)] -pub struct FunDecl { - pub ident: Ident, - pub generic_params: Vec, - pub generic_exec: Option, - pub param_decls: Vec, - pub ret_dty: Box, - pub exec: ExecExpr, - pub prv_rels: Vec, -} +pub struct FunDecl<'a> { + pub ident: Ident<'a>, + pub generic_params: BumpVec<'a, IdentKinded<'a>>, + pub generic_exec: Option>, + pub param_decls: BumpVec<'a, ParamDecl<'a>>, + pub ret_dty: &'a DataTy<'a>, + pub exec: ExecExpr<'a>, + pub prv_rels: BumpVec<'a, PrvRel<'a>>, +} + +impl<'a> FunDecl<'a> { + pub fn fn_ty(&self, bump: &'a Bump) -> FnTy<'a> { + let mut param_sigs = BumpVec::new_in(bump); + for p_decl in &self.param_decls { + let exec_expr = p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(); + let ty = p_decl.ty.as_ref().unwrap().clone(); // This may need arena allocation too + param_sigs.push(ParamSig::new(exec_expr, ty)); + } -impl FunDecl { - pub fn fn_ty(&self) -> FnTy { - let param_sigs: Vec<_> = self - .param_decls - .iter() - .map(|p_decl| { - ParamSig::new( - p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(), - p_decl.ty.as_ref().unwrap().clone(), - ) - }) - .collect(); - FnTy { - generics: self.generic_params.clone(), - generic_exec: self.generic_exec.clone(), + let mut generics = BumpVec::new_in(bump); + generics.extend(self.generic_params.iter().cloned()); + + FnTy::new( + bump, + generics, + self.generic_exec.clone(), param_sigs, - exec: self.exec.clone(), - ret_ty: Box::new(Ty::new(TyKind::Data(self.ret_dty.clone()))), - nat_constrs: vec![], - } + self.exec.clone(), + bump.alloc(Ty { + ty: TyKind::Data(self.ret_dty), + span: None, + }), + [], + ) } } #[derive(Debug, Clone, Eq, Hash, PartialEq)] -pub struct StructDecl { - pub ident: Ident, - pub generic_params: Vec, - pub fields: Vec<(Ident, DataTy)>, +pub struct StructDecl<'a> { + pub ident: Ident<'a>, + pub generic_params: BumpVec<'a, IdentKinded<'a>>, + pub fields: BumpVec<'a, (Ident<'a>, DataTy<'a>)>, } // TODO refactor to make use of FunDecl #[derive(Debug, Clone, PartialEq)] -pub struct FunDef { - pub ident: Ident, - pub generic_params: Vec, - pub generic_exec: Option, - pub param_decls: Vec, - pub ret_dty: Box, - pub exec: ExecExpr, - pub prv_rels: Vec, - pub body: Box, -} +pub struct FunDef<'a> { + pub ident: Ident<'a>, + pub generic_params: BumpVec<'a, IdentKinded<'a>>, + pub generic_exec: Option>, + pub param_decls: BumpVec<'a, ParamDecl<'a>>, + pub ret_dty: &'a DataTy<'a>, + pub exec: ExecExpr<'a>, + pub prv_rels: BumpVec<'a, PrvRel<'a>>, + pub body: &'a Block<'a>, +} + +impl<'a> FunDef<'a> { + pub fn fn_ty(&self, bump: &'a Bump) -> FnTy<'a> { + let mut param_sigs = BumpVec::new_in(bump); + for p_decl in &self.param_decls { + let exec_expr = p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(); + let ty = p_decl.ty.expect("Missing parameter type"); + let ty_ref = bump.alloc(ty.clone()); + param_sigs.push(ParamSig::new(exec_expr, ty_ref)); + } -impl FunDef { - pub fn fn_ty(&self) -> FnTy { - let param_sigs: Vec<_> = self - .param_decls - .iter() - .map(|p_decl| { - ParamSig::new( - p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(), - p_decl.ty.as_ref().unwrap().clone(), - ) - }) - .collect(); - FnTy { - generics: self.generic_params.clone(), - generic_exec: self.generic_exec.clone(), + let mut generics = BumpVec::new_in(bump); + generics.extend(self.generic_params.iter().cloned()); + + let ret_ty = bump.alloc(Ty { + ty: TyKind::Data(self.ret_dty), + span: None, + }); + + FnTy::new( + bump, + generics, + self.generic_exec.clone(), param_sigs, - exec: self.exec.clone(), - ret_ty: Box::new(Ty::new(TyKind::Data(self.ret_dty.clone()))), - nat_constrs: vec![], - } + self.exec.clone(), + ret_ty, + [], + ) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct IdentExec { - pub ident: Ident, - pub ty: Box, +pub struct IdentExec<'a> { + pub ident: Ident<'a>, + pub ty: &'a ExecTy, } -impl IdentExec { - pub fn new(ident: Ident, exec_ty: ExecTy) -> Self { +impl<'a> IdentExec<'a> { + pub fn new_in(bump: &'a bumpalo::Bump, ident: Ident<'a>, exec_ty: ExecTy) -> Self { IdentExec { ident, - ty: Box::new(exec_ty), + ty: bump.alloc(exec_ty), } } } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct ParamDecl { - pub ident: Ident, - pub ty: Option, +pub struct ParamDecl<'a> { + pub ident: Ident<'a>, + pub ty: Option<&'a Ty<'a>>, pub mutbl: Mutability, - pub exec_expr: Option, + pub exec_expr: Option>, } #[span_derive(PartialEq)] #[derive(Debug, Clone)] -pub struct Expr { - pub expr: ExprKind, +pub struct Expr<'a> { + pub expr: ExprKind<'a>, // FIXME misusing span_derive_ignore to ignore type on equality checks #[span_derive_ignore] - pub ty: Option>, + pub ty: Option<&'a Ty<'a>>, #[span_derive_ignore] pub span: Option, } -impl Expr { - pub fn new(expr: ExprKind) -> Expr { +impl<'a> Expr<'a> { + pub fn new(expr: ExprKind<'a>) -> Self { Expr { expr, ty: None, @@ -153,7 +165,7 @@ impl Expr { } } - pub fn with_span(expr: ExprKind, span: Span) -> Expr { + pub fn with_span(expr: ExprKind<'a>, span: Span) -> Self { Expr { expr, ty: None, @@ -161,10 +173,10 @@ impl Expr { } } - pub fn with_type(expr: ExprKind, ty: Ty) -> Expr { + pub fn with_type(expr: ExprKind<'a>, ty: &'a Ty<'a>) -> Self { Expr { expr, - ty: Some(Box::new(ty)), + ty: Some(ty), span: None, } } @@ -252,178 +264,197 @@ impl Expr { } #[derive(PartialEq, Debug, Clone)] -pub struct Sched { +pub struct Sched<'a> { pub dim: DimCompo, - pub inner_exec_ident: Option, - pub sched_exec: Box, - pub body: Box, + pub inner_exec_ident: Option>, + pub sched_exec: &'a ExecExpr<'a>, + pub body: &'a Block<'a>, } -impl Sched { - pub fn new( +impl<'a> Sched<'a> { + pub fn new_in( + bump: &'a bumpalo::Bump, dim: DimCompo, - inner_exec_ident: Option, + inner_exec_ident: Option>, sched_exec: ExecExpr, - body: Block, + body: Block<'a>, ) -> Self { Sched { dim, inner_exec_ident, - sched_exec: Box::new(sched_exec), - body: Box::new(body), + sched_exec: bump.alloc(sched_exec), + body: bump.alloc(body), } } } #[derive(PartialEq, Debug, Clone)] -pub struct Split { +pub struct Split<'a> { pub dim_compo: DimCompo, - pub pos: Nat, - pub split_exec: Box, - pub branch_idents: Vec, - pub branch_bodies: Vec, + pub pos: Nat<'a>, + pub split_exec: &'a ExecExpr<'a>, + pub branch_idents: BumpVec<'a, Ident<'a>>, + pub branch_bodies: BumpVec<'a, Expr<'a>>, } -impl Split { +impl<'a> Split<'a> { pub fn new( + bump: &'a bumpalo::Bump, dim_compo: DimCompo, - pos: Nat, + pos: Nat<'a>, split_exec: ExecExpr, - branch_idents: Vec, - branch_bodies: Vec, + branch_idents: impl IntoIterator>, + branch_bodies: impl IntoIterator>, ) -> Self { + let split_exec = bump.alloc(split_exec); + + let mut idents = BumpVec::new_in(bump); + idents.extend(branch_idents); + + let mut bodies = BumpVec::new_in(bump); + bodies.extend(branch_bodies); + Split { dim_compo, pos, - split_exec: Box::new(split_exec), - branch_idents, - branch_bodies, + split_exec, + branch_idents: idents, + branch_bodies: bodies, } } } #[derive(PartialEq, Debug, Clone)] -pub struct Block { - pub prvs: Vec, - pub body: Box, +pub struct Block<'a> { + pub prvs: BumpVec<'a, String>, + pub body: &'a Expr<'a>, } -impl Block { - pub fn new(body: Expr) -> Self { +impl<'a> Block<'a> { + pub fn new(bump: &'a bumpalo::Bump, body: Expr<'a>) -> Self { Block { - prvs: vec![], - body: Box::new(body), + prvs: BumpVec::new_in(bump), + body: bump.alloc(body), } } - pub fn with_prvs(prvs: Vec, body: Expr) -> Self { + pub fn with_prvs( + bump: &'a bumpalo::Bump, + prvs: impl IntoIterator, + body: Expr<'a>, + ) -> Self { + let mut prvs_vec = BumpVec::new_in(bump); + prvs_vec.extend(prvs); Block { - prvs, - body: Box::new(body), + prvs: prvs_vec, + body: bump.alloc(body), } } } #[derive(PartialEq, Debug, Clone)] -pub struct AppKernel { - pub grid_dim: Dim, - pub block_dim: Dim, - pub shared_mem_dtys: Vec, - pub shared_mem_prvs: Vec, - pub fun_ident: Box, - pub gen_args: Vec, - pub args: Vec, +pub struct AppKernel<'a> { + pub grid_dim: Dim<'a>, + pub block_dim: Dim<'a>, + pub shared_mem_dtys: BumpVec<'a, DataTy<'a>>, + pub shared_mem_prvs: BumpVec<'a, String>, + pub fun_ident: &'a Ident<'a>, + pub gen_args: BumpVec<'a, ArgKinded<'a>>, + pub args: BumpVec<'a, Expr<'a>>, } #[derive(PartialEq, Debug, Clone)] -pub enum ExprKind { +pub enum ExprKind<'a> { Hole, Lit(Lit), // An l-value equivalent: *p, p.n, x - PlaceExpr(Box), + PlaceExpr(&'a PlaceExpr<'a>), // e.g., [1, 2 + 3, 4] - Array(Vec), - Tuple(Vec), + Array(BumpVec<'a, Expr<'a>>), + Tuple(BumpVec<'a, Expr<'a>>), // Borrow Expressions - Ref(Option, Ownership, Box), - Block(Block), + Ref(Option, Ownership, &'a PlaceExpr<'a>), + Block(&'a Block<'a>), // Variable declaration // let mut x: ty; - LetUninit(Option>, Ident, Box), - // Variable declaration, assignment and sequencing + LetUninit(Option<&'a ExecExpr<'a>>, Ident<'a>, &'a Ty<'a>), // let w x: ty = e1 - Let(Pattern, Option>, Box), + Let(Pattern<'a>, Option<&'a Ty<'a>>, &'a Expr<'a>), // Assignment to existing place [expression] - Assign(Box, Box), + Assign(&'a PlaceExpr<'a>, &'a Expr<'a>), // e1[i] = e2 - IdxAssign(Box, Nat, Box), + IdxAssign(&'a PlaceExpr<'a>, Nat<'a>, &'a Expr<'a>), // e1 ; e2 - Seq(Vec), + Seq(BumpVec<'a, Expr<'a>>), // Anonymous function which can capture its surrounding context // | x_n: d_1, ..., x_n: d_n | [exec]-> d_r { e } // TODO body expression should always be block?! No but treated like one. - //Lambda(Vec, IdentExec, Box, Box), + //Lambda(Vec, Ident<'a>Exec, Box, Box), // Function application // e_f(e_1, ..., e_n) - App(Box, Vec, Vec), - DepApp(Ident, Vec), - AppKernel(Box), + App( + &'a Ident<'a>, + BumpVec<'a, ArgKinded<'a>>, + BumpVec<'a, Expr<'a>>, + ), + DepApp(Ident<'a>, BumpVec<'a, ArgKinded<'a>>), + AppKernel(&'a AppKernel<'a>), // TODO branches must be blocks - IfElse(Box, Box, Box), + IfElse(&'a Expr<'a>, &'a Expr<'a>, &'a Expr<'a>), // TODO branch must be block - If(Box, Box), + If(&'a Expr<'a>, &'a Expr<'a>), // For-each loop. // for x in e_1 { e_2 } // TODO body must be block - For(Ident, Box, Box), + For(Ident<'a>, &'a Expr<'a>, &'a Expr<'a>), // for n in range(..) { e } // TODO body must be block - ForNat(Ident, Box, Box), + ForNat(Ident<'a>, &'a NatRange<'a>, &'a Expr<'a>), // while( e_1 ) { e_2 } // TODO body must be block - While(Box, Box), - BinOp(BinOp, Box, Box), - UnOp(UnOp, Box), - Cast(Box, Box), + While(&'a Expr<'a>, &'a Expr<'a>), + BinOp(BinOp, &'a Expr<'a>, &'a Expr<'a>), + UnOp(UnOp, &'a Expr<'a>), + Cast(&'a Expr<'a>, &'a DataTy<'a>), // TODO branches must be blocks or treated like blocks - Split(Box), - Sched(Box), - Sync(Option), - Unsafe(Box), - Range(Box, Box), + Split(&'a Split<'a>), + Sched(&'a Sched<'a>), + Sync(Option>), + Unsafe(&'a Expr<'a>), + Range(&'a Expr<'a>, &'a Expr<'a>), } #[span_derive(PartialEq, Eq, Hash)] #[derive(Clone, Debug)] -pub struct Ident { +pub struct Ident<'a> { // Identifier names never change. Instead a new identifier is created. Therefore it is not // necessary to keep the capacity that is stored in a String for efficient appending. - pub name: Box, + pub name: &'a str, #[span_derive_ignore] pub span: Option, pub is_implicit: bool, } - -impl Ident { - pub fn new(name: &str) -> Self { +// TODO: Arena String Interna nachschauen +impl<'a> Ident<'a> { + pub fn new(bump: &'a bumpalo::Bump, name: &str) -> Self { Self { - name: Box::from(name), + name: bump.alloc_str(name), span: None, is_implicit: false, } } - pub fn new_impli(name: &str) -> Self { + pub fn new_impli(bump: &'a bumpalo::Bump, name: &str) -> Self { Self { - name: Box::from(name), + name: bump.alloc_str(name), span: None, is_implicit: true, } } - pub fn with_span(name: &str, span: Span) -> Self { + pub fn with_span(bump: &'a bumpalo::Bump, name: &str, span: Span) -> Self { Self { - name: Box::from(name), + name: bump.alloc_str(name), span: Some(span), is_implicit: false, } @@ -431,9 +462,9 @@ impl Ident { } #[derive(Debug, Clone, PartialEq)] -pub enum Pattern { - Ident(Mutability, Ident), - Tuple(Vec), +pub enum Pattern<'a> { + Ident(Mutability, Ident<'a>), + Tuple(BumpVec<'a, Pattern<'a>>), Wildcard, } @@ -570,15 +601,15 @@ pub enum Kind { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ArgKinded { - Ident(Ident), - Nat(Nat), - Memory(Memory), - DataTy(DataTy), - Provenance(Provenance), +pub enum ArgKinded<'a> { + Ident(Ident<'a>), + Nat(Nat<'a>), + Memory(Memory<'a>), + DataTy(DataTy<'a>), + Provenance(Provenance<'a>), } -impl ArgKinded { +impl<'a> ArgKinded<'a> { pub fn kind(&self) -> Kind { match self { ArgKinded::Ident(_) => { @@ -605,43 +636,48 @@ impl ArgKinded { #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct PlaceExpr { - pub pl_expr: PlaceExprKind, +pub struct PlaceExpr<'a> { + pub pl_expr: PlaceExprKind<'a>, // FIXME misusing span_derive_ignore to ignore type on equality checks #[span_derive_ignore] - pub ty: Option>, + pub ty: Option<&'a Ty<'a>>, #[span_derive_ignore] pub span: Option, } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct View { - pub name: Ident, - pub gen_args: Vec, - pub args: Vec, +pub struct View<'a> { + pub name: Ident<'a>, + pub gen_args: BumpVec<'a, ArgKinded<'a>>, + pub args: BumpVec<'a, View<'a>>, } -impl View { - pub fn equal(&self, nat_ctx: &NatCtx, other: &View) -> NatEvalResult { +impl<'a> View<'a> { + pub fn equal(&self, nat_ctx: &NatCtx, other: &View<'a>) -> NatEvalResult { if self.name.name != other.name.name { return Ok(false); } + if self.gen_args.len() != other.gen_args.len() { return Ok(false); } - for (ga, go) in self.gen_args.iter().zip(&other.gen_args) { + + for (ga, go) in self.gen_args.iter().zip(other.gen_args.iter()) { if !ga.equal(nat_ctx, go)? { return Ok(false); } } + if self.args.len() != other.args.len() { return Ok(false); } - for (v, vo) in self.args.iter().zip(&other.args) { + + for (v, vo) in self.args.iter().zip(other.args.iter()) { if !v.equal(nat_ctx, vo)? { return Ok(false); } } + Ok(true) } } @@ -659,36 +695,36 @@ impl View { // } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum PlaceExprKind { - View(Box, Box), +pub enum PlaceExprKind<'a> { + View(&'a PlaceExpr<'a>, &'a View<'a>), // similar to a projection, but it projects an element for each provided execution resource // (similar to indexing) // p[[x]] - Select(Box, Box), + Select(&'a PlaceExpr<'a>, &'a ExecExpr<'a>), // p.0 | p.1 - Proj(Box, usize), - FieldProj(Box, Box), + Proj(&'a PlaceExpr<'a>, usize), + FieldProj(&'a PlaceExpr<'a>, &'a Ident<'a>), // *p - Deref(Box), + Deref(&'a PlaceExpr<'a>), // Index into array, e.g., arr[i] - Idx(Box, Box), + Idx(&'a PlaceExpr<'a>, &'a Nat<'a>), // x - Ident(Ident), + Ident(Ident<'a>), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum PlExprPathElem { - View(View), - Select(Box), +pub enum PlExprPathElem<'a> { + View(View<'a>), + Select(Box>), Proj(usize), - FieldProj(Ident), + FieldProj(Ident<'a>), Deref, - Idx(Box), - RangeSelec(Box, Box), + Idx(Box>), + RangeSelec(Box>, Box>), } -impl PlaceExpr { - pub fn new(pl_expr: PlaceExprKind) -> Self { +impl<'a> PlaceExpr<'a> { + pub fn new(pl_expr: PlaceExprKind<'a>) -> Self { PlaceExpr { pl_expr, ty: None, @@ -696,7 +732,7 @@ impl PlaceExpr { } } - pub fn with_span(pl_expr: PlaceExprKind, span: Span) -> Self { + pub fn with_span(pl_expr: PlaceExprKind<'a>, span: Span) -> Self { PlaceExpr { pl_expr, ty: None, @@ -784,11 +820,11 @@ impl PlaceExpr { } } - pub fn as_ident_and_path(&self) -> (Ident, Vec) { + pub fn as_ident_and_path(&self) -> (Ident<'a>, Vec>) { fn as_ident_and_path_rec( pl_expr: &PlaceExpr, mut path: Vec, - ) -> (Ident, Vec) { + ) -> (Ident<'a>, Vec>) { match &pl_expr.pl_expr { PlaceExprKind::Ident(i) => { path.reverse(); @@ -826,8 +862,8 @@ impl PlaceExpr { #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct ExecExpr { - pub exec: Box, +pub struct ExecExpr<'a> { + pub exec: Box>, // FIXME misusing span_derive_ignore to ignore type on equality checks #[span_derive_ignore] pub ty: Option>, @@ -835,7 +871,7 @@ pub struct ExecExpr { pub span: Option, } -impl ExecExpr { +impl<'a> ExecExpr<'a> { pub fn new(exec: ExecExprKind) -> Self { ExecExpr { exec: Box::new(exec), @@ -946,14 +982,14 @@ impl fmt::Display for LeftOrRight { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct TakeRange { +pub struct TakeRange<'a> { pub split_dim: DimCompo, - pub pos: Nat, + pub pos: Nat<'a>, pub left_or_right: LeftOrRight, } -impl TakeRange { - pub fn new(split_dim: DimCompo, pos: Nat, proj: LeftOrRight) -> Self { +impl<'a> TakeRange<'a> { + pub fn new(split_dim: DimCompo, pos: Nat<'a>, proj: LeftOrRight) -> Self { TakeRange { split_dim, pos, @@ -963,9 +999,9 @@ impl TakeRange { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct ExecExprKind { - pub base: BaseExec, - pub path: Vec, +pub struct ExecExprKind<'a> { + pub base: BaseExec<'a>, + pub path: Vec>, } impl ExecExprKind { @@ -1001,15 +1037,15 @@ impl ExecExprKind { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum BaseExec { - Ident(Ident), +pub enum BaseExec<'a> { + Ident(Ident<'a>), CpuThread, - GpuGrid(Dim, Dim), + GpuGrid(Dim<'a>, Dim<'a>), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum ExecPathElem { - TakeRange(Box), +pub enum ExecPathElem<'a> { + TakeRange(Box>), ForAll(DimCompo), ToWarps, ToThreads(DimCompo), @@ -1037,83 +1073,93 @@ impl ExecTy { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum ExecTyKind { +pub enum ExecTyKind<'a> { CpuThread, GpuThread, GpuWarp, - GpuBlock(Dim), - GpuGrid(Dim, Dim), - GpuToThreads(Dim, Box), - GpuThreadGrp(Dim), - GpuWarpGrp(Nat), - GpuBlockGrp(Dim, Dim), + GpuBlock(Dim<'a>), + GpuGrid(Dim<'a>, Dim<'a>), + GpuToThreads(Dim<'a>, Box>), + GpuThreadGrp(Dim<'a>), + GpuWarpGrp(Nat<'a>), + GpuBlockGrp(Dim<'a>, Dim<'a>), Any, } #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct Ty { - pub ty: TyKind, +pub struct Ty<'a> { + pub ty: TyKind<'a>, #[span_derive_ignore] pub span: Option, } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct ParamSig { +pub struct ParamSig<'a> { pub exec_expr: ExecExpr, - pub ty: Ty, + pub ty: &'a Ty<'a>, } -impl ParamSig { - pub fn new(exec_expr: ExecExpr, ty: Ty) -> Self { +impl<'a> ParamSig<'a> { + pub fn new(exec_expr: ExecExpr, ty: &'a Ty<'a>) -> Self { ParamSig { exec_expr, ty } } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct FnTy { - pub generics: Vec, - pub generic_exec: Option, - pub param_sigs: Vec, +pub struct FnTy<'a> { + pub generics: BumpVec<'a, IdentKinded<'a>>, + pub generic_exec: Option>, + pub param_sigs: BumpVec<'a, ParamSig<'a>>, pub exec: ExecExpr, - pub ret_ty: Box, - pub nat_constrs: Vec, + pub ret_ty: &'a Ty<'a>, + pub nat_constrs: BumpVec<'a, NatConstr<'a>>, } -impl FnTy { +impl<'a> FnTy<'a> { pub fn new( - generics: Vec, + bump: &'a Bump, + generics: impl IntoIterator>, generic_exec: Option, - param_sigs: Vec, + param_sigs: impl IntoIterator>, exec: ExecExpr, - ret_ty: Ty, - nat_constrs: Vec, + ret_ty: &'a Ty<'a>, + nat_constrs: impl IntoIterator>, ) -> Self { + let mut generics_vec = BumpVec::new_in(bump); + generics_vec.extend(generics); + + let mut param_vec = BumpVec::new_in(bump); + param_vec.extend(param_sigs); + + let mut nat_vec = BumpVec::new_in(bump); + nat_vec.extend(nat_constrs); + FnTy { - generics, + generics: generics_vec, generic_exec, - param_sigs, + param_sigs: param_vec, exec, - ret_ty: Box::new(ret_ty), - nat_constrs, + ret_ty: bump.alloc(ret_ty), + nat_constrs: nat_vec, } } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum NatConstr { +pub enum NatConstr<'a> { True, - Eq(Box, Box), - Lt(Box, Box), - And(Box, Box), - Or(Box, Box), + Eq(Box>, Box>), + Lt(Box>, Box>), + And(Box>, Box>), + Or(Box>, Box>), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum TyKind { - Data(Box), +pub enum TyKind<'a> { + Data(&'a DataTy<'a>), // (ty..) -[x:exec]-> ty - FnTy(Box), + FnTy(&'a FnTy<'a>), } // TODO remove @@ -1122,19 +1168,19 @@ pub enum Constraint { Copyable, } -impl Ty { - pub fn new(ty: TyKind) -> Self { +impl<'a> Ty<'a> { + pub fn new(ty: TyKind<'a>) -> Self { Ty { ty, span: None } } - pub fn with_span(ty: TyKind, span: Span) -> Ty { + pub fn with_span(ty: TyKind<'a>, span: Span) -> Ty<'a> { Ty { ty, span: Some(span), } } - pub fn dty(&self) -> &DataTy { + pub fn dty(&self) -> &'a DataTy<'a> { match &self.ty { TyKind::Data(dty) => dty, _ => panic!("Expected data type but found {:?}", self), @@ -1170,23 +1216,23 @@ impl Ty { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Dim1d(pub Nat); +pub struct Dim1d<'a>(pub Nat<'a>); #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Dim2d(pub Nat, pub Nat); +pub struct Dim2d<'a>(pub Nat<'a>, pub Nat<'a>); #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Dim3d(pub Nat, pub Nat, pub Nat); +pub struct Dim3d<'a>(pub Nat<'a>, pub Nat<'a>, pub Nat<'a>); #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum Dim { - XYZ(Box), - XY(Box), - XZ(Box), - YZ(Box), - X(Box), - Y(Box), - Z(Box), +pub enum Dim<'a> { + XYZ(Box>), + XY(Box>), + XZ(Box>), + YZ(Box>), + X(Box>), + Y(Box>), + Z(Box>), } -impl Dim { +impl<'a> Dim<'a> { pub fn new_3d(n1: Nat, n2: Nat, n3: Nat) -> Self { Dim::XYZ(Box::new(Dim3d(n1, n2, n3))) } @@ -1224,35 +1270,41 @@ pub enum DimCompo { #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct DataTy { - pub dty: DataTyKind, +pub struct DataTy<'a> { + pub dty: DataTyKind<'a>, // TODO remove with introduction of traits - pub constraints: Vec, + pub constraints: BumpVec<'a, Constraint>, #[span_derive_ignore] pub span: Option, } -impl DataTy { - pub fn new(dty: DataTyKind) -> Self { +impl<'a> DataTy<'a> { + pub fn new_in(bump: &'a bumpalo::Bump, dty: DataTyKind<'a>) -> Self { DataTy { dty, - constraints: vec![], + constraints: BumpVec::new_in(bump), span: None, } } - pub fn with_constr(dty: DataTyKind, constraints: Vec) -> Self { + pub fn with_constr( + bump: &'a bumpalo::Bump, + dty: DataTyKind<'a>, + constraints: impl IntoIterator, + ) -> Self { + let mut v = BumpVec::new_in(bump); + v.extend(constraints); DataTy { dty, - constraints, + constraints: v, span: None, } } - pub fn with_span(dty: DataTyKind, span: Span) -> Self { + pub fn with_span(bump: &'a bumpalo::Bump, dty: DataTyKind<'a>, span: Span) -> Self { DataTy { dty, - constraints: vec![], + constraints: BumpVec::new_in(bump), span: Some(span), } } @@ -1394,41 +1446,46 @@ impl DataTy { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct RefDty { - pub rgn: Provenance, +pub struct RefDty<'a> { + pub rgn: Provenance<'a>, pub own: Ownership, - pub mem: Memory, - pub dty: Box, + pub mem: Memory<'a>, + pub dty: &'a DataTy<'a>, } -impl RefDty { - pub fn new(rgn: Provenance, own: Ownership, mem: Memory, dty: DataTy) -> Self { +impl<'a> RefDty<'a> { + pub fn new( + bump: &'a Bump, + rgn: Provenance, + own: Ownership, + mem: Memory, + dty: DataTy<'a>, + ) -> Self { RefDty { rgn, own, mem, - dty: Box::new(dty), + dty: bump.alloc(dty), } } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum DataTyKind { - Ident(Ident), +pub enum DataTyKind<'a> { + Ident(Ident<'a>), Scalar(ScalarTy), Atomic(AtomicTy), - Array(Box, Nat), - // [[ dty; n ]] - ArrayShape(Box, Nat), - Tuple(Vec), - Struct(Box), - At(Box, Memory), - Ref(Box), - RawPtr(Box), + Array(&'a DataTy<'a>, Nat<'a>), + ArrayShape(&'a DataTy<'a>, Nat<'a>), + Tuple(BumpVec<'a, DataTy<'a>>), + Struct(&'a StructDecl<'a>), + At(&'a DataTy<'a>, Memory<'a>), + Ref(&'a RefDty<'a>), + RawPtr(&'a DataTy<'a>), //Range, // TODO remove. This is an attribute of a typing context entry, not the type. // Only for type checking purposes. - Dead(Box), + Dead(&'a DataTy<'a>), } #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] @@ -1452,33 +1509,33 @@ pub enum AtomicTy { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum Provenance { +pub enum Provenance<'a> { Value(String), - Ident(Ident), + Ident(Ident<'a>), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum Memory { +pub enum Memory<'a> { CpuMem, GpuGlobal, GpuShared, GpuLocal, - Ident(Ident), + Ident(Ident<'a>), } #[derive(PartialEq, Eq, Debug, Clone)] -pub struct PrvRel { - pub longer: Ident, - pub shorter: Ident, +pub struct PrvRel<'a> { + pub longer: Ident<'a>, + pub shorter: Ident<'a>, } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct IdentKinded { - pub ident: Ident, +pub struct IdentKinded<'a> { + pub ident: Ident<'a>, pub kind: Kind, } -impl IdentKinded { +impl<'a> IdentKinded<'a> { pub fn new(ident: &Ident, kind: Kind) -> Self { IdentKinded { ident: ident.clone(), @@ -1488,13 +1545,13 @@ impl IdentKinded { } #[derive(PartialEq, Eq, Debug, Clone)] -pub enum NatRange { - Simple { lower: Nat, upper: Nat }, - Halved { upper: Nat }, - Doubled { upper: Nat }, +pub enum NatRange<'a> { + Simple { lower: Nat<'a>, upper: Nat<'a> }, + Halved { upper: Nat<'a> }, + Doubled { upper: Nat<'a> }, } -impl NatRange { +impl<'a> NatRange<'a> { pub fn lift(&self, nat_ctx: &NatCtx) -> NatEvalResult { let range_iter = match self { NatRange::Simple { lower, upper } => { @@ -1552,8 +1609,8 @@ impl Iterator for NatRangeIter { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum Nat { - Ident(Ident), +pub enum Nat<'a> { + Ident(Ident<'a>), Lit(usize), ThreadIdx(DimCompo), BlockIdx(DimCompo), @@ -1563,9 +1620,9 @@ pub enum Nat { LaneIdx, // Dummy that is always 0, i.e. equivalent to Lit(0) GridIdx, - BinOp(BinOpNat, Box, Box), + BinOp(BinOpNat, Box>, Box>), // Use Box<[Nat]> to safe 8 bytes compared to Vec - App(Ident, Box<[Nat]>), + App(Ident<'a>, Box<[Nat<'a>]>), } pub struct NatCtx { @@ -1619,13 +1676,13 @@ impl NatCtx { } #[derive(Debug)] -pub struct NatEvalError { - unevaluable: Nat, +pub struct NatEvalError<'a> { + unevaluable: Nat<'a>, } -pub type NatEvalResult = Result; +pub type NatEvalResult<'a, T> = Result>; -impl Nat { +impl<'a> Nat<'a> { pub fn eval(&self, nat_ctx: &NatCtx) -> NatEvalResult { match self { Nat::GridIdx diff --git a/src/ast/utils.rs b/src/ast/utils.rs index e50614ba..e7f84af2 100644 --- a/src/ast/utils.rs +++ b/src/ast/utils.rs @@ -27,8 +27,8 @@ pub(crate) fn fresh_name(name: &str) -> String { format!("{}_{}", prefix, i) } -pub fn implicit_idents(f: &FunDef) -> Option> { - struct ImplicitIdents(HashSet); +pub fn implicit_idents(f: &FunDef) -> Option>> { + struct ImplicitIdents(HashSet>); impl Visit for ImplicitIdents { fn visit_ident(&mut self, ident: &Ident) { if ident.is_implicit { diff --git a/src/ty_check/mod.rs b/src/ty_check/mod.rs index 09511b08..c2a36e01 100644 --- a/src/ty_check/mod.rs +++ b/src/ty_check/mod.rs @@ -13,6 +13,7 @@ use crate::ast::internal::{Frame, IdentTyped, Loan, Place, PrvMapping}; use crate::ast::utils; use crate::ast::*; use crate::error::ErrorReported; +use bumpalo::Bump; use ctxs::{AccessCtx, GlobalCtx, KindCtx, TyCtx}; use error::*; use std::collections::HashSet; @@ -37,20 +38,23 @@ pub(crate) use matches_dty; // -------------- // ⊢ Σ pub fn ty_check(compil_unit: &mut CompilUnit) -> Result<(), ErrorReported> { + let ty_arena = Bump::new(); + let mut gl_ctx = GlobalCtx::new( compil_unit, pre_decl::fun_decls() .into_iter() - .map(|(fname, fty)| GlobalDecl::FnDecl(Box::from(fname), Box::new(fty))) + .map(|(fname, fty)| GlobalDecl::FnDecl(Box::from(fname), ty_arena.alloc(fty))) .collect(), ); let mut nat_ctx = NatCtx::new(); if let Some(mut main_fun) = gl_ctx.pop_fun_def("main") { - if let Err(err) = ty_check_global_fun_def(&mut gl_ctx, &mut nat_ctx, &mut main_fun) { + if let Err(err) = ty_check_global_fun_def(&mut gl_ctx, &mut nat_ctx, &mut main_fun, &arena) + { err.emit(compil_unit.source); Err(ErrorReported) } else { - gl_ctx.push_fun_checked_under_nats(main_fun, Box::from(vec![])); + gl_ctx.push_fun_checked_under_nats(main_fun, arena.alloc(vec![])); Ok(()) } } else { @@ -71,10 +75,11 @@ struct ExprTyCtx<'src, 'compil, 'ctxt> { } // Σ ⊢ fn f (x1: τ1, ..., xn: τn) → τr where List[ρ1:ρ2] { e } -fn ty_check_global_fun_def( - gl_ctx: &mut GlobalCtx, +fn ty_check_global_fun_def<'a>( + gl_ctx: &mut GlobalCtx<'a>, nat_ctx: &mut NatCtx, - gf: &mut FunDef, + gf: &mut FunDef<'a>, + arena: &'a Bump, ) -> TyResult<()> { // TODO check that every prv_rel only uses provenance variables bound in generic_params let mut kind_ctx = KindCtx::gl_fun_kind_ctx(gf.generic_params.clone(), gf.prv_rels.clone())?; @@ -162,7 +167,7 @@ fn ty_check_global_fun_def( // type τ is well-formed under well-formed GlFunCtxt, kinding ctx, output context Γ'. // Σ; Δ; Γ ⊢ e :^exec τ ⇒ Γ′, side conditions: ⊢ Σ;Δ;Γ and Σ;Δ;Γ′ ⊢ τ // This never returns a dead type, because typing an expression with a dead type is not possible. -fn ty_check_expr(ctx: &mut ExprTyCtx, expr: &mut Expr) -> TyResult<()> { +fn ty_check_expr(ctx: &mut ExprTyCtx, expr: &mut Expr, arena) -> TyResult<()> { let ty = match &mut expr.expr { ExprKind::PlaceExpr(pl_expr) => { if pl_expr.is_place() { @@ -182,9 +187,9 @@ fn ty_check_expr(ctx: &mut ExprTyCtx, expr: &mut Expr) -> TyResult<()> { ExprKind::Tuple(elems) => ty_check_tuple(ctx, elems)?, // ExprKind::Proj(e, i) => ty_check_proj(ctx, e, *i)?, ExprKind::App(fn_ident, gen_args, args) => ty_check_app(ctx, fn_ident, gen_args, args)?, - ExprKind::DepApp(fn_ident, gen_args) => Ty::new(TyKind::FnTy(Box::new(ty_check_dep_app( - ctx, fn_ident, gen_args, - )?))), + ExprKind::DepApp(fn_ident, gen_args) => Ty::new(TyKind::FnTy( + arena.alloc(ty_check_dep_app(ctx, fn_ident, gen_args)?), + )), ExprKind::AppKernel(app_kernel) => ty_check_app_kernel(ctx, app_kernel)?, ExprKind::Ref(prv, own, pl_expr) => ty_check_borrow(ctx, prv, *own, pl_expr)?, ExprKind::Assign(pl_expr, e) => { @@ -225,13 +230,13 @@ fn ty_check_expr(ctx: &mut ExprTyCtx, expr: &mut Expr) -> TyResult<()> { //if let Err(err) = self.ty_well_formed(kind_ctx, &res_ty_ctx, exec, &ty) { // panic!("{:?}", err); //} - expr.ty = Some(Box::new(ty)); + expr.ty = Some(arena.alloc(ty)); Ok(()) } fn ty_check_hole(ctx: &ExprTyCtx) -> TyResult { if ctx.unsafe_flag { - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( DataTyKind::Ident(Ident::new_impli(&utils::fresh_name("hole"))), ))))) } else { @@ -249,9 +254,9 @@ fn ty_check_sync(ctx: &mut ExprTyCtx, exec: &mut Option) -> TyResult unimplemented!(), DataTyKind::Ref(reff) => match &reff.dty.as_ref().dty { - DataTyKind::Array(elem_dty, _) => DataTyKind::Ref(Box::new(RefDty::new( + DataTyKind::Array(elem_dty, _) => DataTyKind::Ref(arena.alloc(RefDty::new( reff.rgn.clone(), reff.own, reff.mem.clone(), elem_dty.as_ref().clone(), ))), - DataTyKind::ArrayShape(elem_dty, _) => DataTyKind::Ref(Box::new(RefDty::new( + DataTyKind::ArrayShape(elem_dty, _) => DataTyKind::Ref(arena.alloc(RefDty::new( reff.rgn.clone(), reff.own, reff.mem.clone(), @@ -386,7 +391,7 @@ fn ty_check_for( let mut frame = Frame::new(); frame.append_idents_typed(vec![IdentTyped::new( ident.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(ident_dty)))), + Ty::new(TyKind::Data(arena.alloc(DataTy::new(ident_dty)))), Mutability::Const, ctx.exec.clone(), )]); @@ -398,9 +403,9 @@ fn ty_check_for( "Using a data type in loop that can only be used once.".to_string(), )); } - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } fn ty_check_while(ctx: &mut ExprTyCtx, cond: &mut Expr, body: &mut Expr) -> TyResult { @@ -452,9 +457,9 @@ fn ty_check_while(ctx: &mut ExprTyCtx, cond: &mut Expr, body: &mut Expr) -> TyRe body_ty ))); } - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } fn ty_check_if_else( @@ -523,9 +528,9 @@ fn ty_check_if_else( ))); } - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } fn ty_check_if(ctx: &mut ExprTyCtx, cond: &mut Expr, case_true: &mut Expr) -> TyResult { @@ -563,9 +568,9 @@ fn ty_check_if(ctx: &mut ExprTyCtx, cond: &mut Expr, case_true: &mut Expr) -> Ty ))); } - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } fn ty_check_split(ctx: &mut ExprTyCtx, indep: &mut Split) -> TyResult { @@ -627,7 +632,7 @@ fn ty_check_split(ctx: &mut ExprTyCtx, indep: &mut Split) -> TyResult { .append_exec_mapping(indep.branch_idents[i].clone(), branch_exec.clone()); ty_check_expr(&mut branch_expr_ty_ctx, &mut indep.branch_bodies[i])?; if indep.branch_bodies[i].ty.as_ref().unwrap().ty - != TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit)))) + != TyKind::Data(arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit)))) { return Err(TyError::String( "A par_branch branch must not return a value.".to_string(), @@ -635,9 +640,9 @@ fn ty_check_split(ctx: &mut ExprTyCtx, indep: &mut Split) -> TyResult { } branch_expr_ty_ctx.ty_ctx.pop_frame(); } - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } fn ty_check_sched(ctx: &mut ExprTyCtx, sched: &mut Sched) -> TyResult { @@ -674,9 +679,9 @@ fn ty_check_sched(ctx: &mut ExprTyCtx, sched: &mut Sched) -> TyResult { } ty_check_expr(&mut schedule_body_ctx, &mut sched.body.body)?; schedule_body_ctx.ty_ctx.pop_frame(); - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } fn ty_check_block(ctx: &mut ExprTyCtx, block: &mut Block) -> TyResult { @@ -731,7 +736,7 @@ fn ty_check_assign_place( if !matches!(&place_ty.dty, DataTyKind::Dead(_),) { borrow_check::borrow_check(&BorrowCheckCtx::new(ctx, vec![], Ownership::Uniq), pl_expr) .map_err(|err| { - TyError::ConflictingBorrow(Box::new(pl_expr.clone()), Ownership::Uniq, err) + TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Uniq, err) })?; } @@ -756,9 +761,9 @@ fn ty_check_assign_place( // removing this leads to problems in Codegen, because the pl_expr is not annotated with a // type which is required by gen_pl_expr pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr)?; - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } fn ty_check_assign_non_place( @@ -773,7 +778,7 @@ fn ty_check_assign_non_place( deref_expr, ) .map_err(|err| { - TyError::ConflictingBorrow(Box::new(deref_expr.clone()), Ownership::Uniq, err) + TyError::ConflictingBorrow(arena.alloc(deref_expr.clone()), Ownership::Uniq, err) })?; ctx.access_ctx.insert(potential_accesses); let deref_ty = deref_expr.ty.as_mut().unwrap(); @@ -790,9 +795,9 @@ fn ty_check_assign_non_place( } // FIXME needs subtyping check on p, e types if let TyKind::Data(_) = &deref_ty.ty { - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } else { Err(TyError::String( "Trying to dereference view type which is not allowed.".to_string(), @@ -869,12 +874,14 @@ fn ty_check_idx_assign( &BorrowCheckCtx::new(ctx, vec![], Ownership::Uniq), pl_expr, ) - .map_err(|err| TyError::ConflictingBorrow(Box::new(pl_expr.clone()), Ownership::Shrd, err))?; + .map_err(|err| { + TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Shrd, err) + })?; ctx.access_ctx.insert(potential_accesses); subty::check(ctx.kind_ctx, ctx.ty_ctx, e.ty.as_ref().unwrap().dty(), dty)?; - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } // FIXME currently assumes that binary operators exist only for f32 and i32 and that both @@ -908,9 +915,9 @@ fn ty_check_binary_op( | BinOp::Ge | BinOp::And | BinOp::Or - | BinOp::Neq => Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::Bool, - ))))), + | BinOp::Neq => Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Bool))), + )), }; match bin_op { // Shift operators only allow integer values (lhs_ty and rhs_ty can differ!) @@ -1019,7 +1026,7 @@ fn ty_check_cast(ctx: &mut ExprTyCtx, e: &mut Expr, dty: &DataTy) -> TyResult Ok(Ty::new(TyKind::Data(Box::new(dty.clone())))), + | DataTyKind::Scalar(ScalarTy::F64) => Ok(Ty::new(TyKind::Data(arena.alloc(dty.clone())))), _ => Err(TyError::String(format!( "Exected a number type (i.e. i32 or f32) to cast to from {:?}, but found {:?}", e_ty, dty @@ -1030,7 +1037,7 @@ fn ty_check_cast(ctx: &mut ExprTyCtx, e: &mut Expr, dty: &DataTy) -> TyResult Ok(Ty::new(TyKind::Data(Box::new(dty.clone())))), + | DataTyKind::Scalar(ScalarTy::U64) => Ok(Ty::new(TyKind::Data(arena.alloc(dty.clone())))), _ => Err(TyError::String(format!( "Exected an integer type (i.e. i32 or u32) to cast to from a bool, but found {:?}", dty @@ -1058,10 +1065,9 @@ fn ty_check_app( .iter() .map(|arg| ParamSig::new(ctx.exec.clone(), arg.ty.as_ref().unwrap().as_ref().clone())) .collect(); - let ret_dty_placeholder = Ty::new(TyKind::Data(Box::new(DataTy::new(utils::fresh_ident( - "ret_ty", - DataTyKind::Ident, - ))))); + let ret_dty_placeholder = Ty::new(TyKind::Data( + arena.alloc(DataTy::new(utils::fresh_ident("ret_ty", DataTyKind::Ident))), + )); let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_dep_fn_ty); unify::unify( &mut FnTy::new( @@ -1250,8 +1256,8 @@ fn ty_check_app_kernel(ctx: &mut ExprTyCtx, app_kernel: &mut AppKernel) -> TyRes .map(|dty| { IdentTyped::new( Ident::new_impli(&utils::fresh_name("shared_mem")), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::At( - Box::new(dty.clone()), + Ty::new(TyKind::Data(arena.alloc(DataTy::new(DataTyKind::At( + arena.alloc(dty.clone()), Memory::GpuShared, ))))), Mutability::Mut, @@ -1276,7 +1282,7 @@ fn ty_check_app_kernel(ctx: &mut ExprTyCtx, app_kernel: &mut AppKernel) -> TyRes Expr::new(ExprKind::Ref( prv, Ownership::Uniq, - Box::new(PlaceExpr::new(PlaceExprKind::Ident(idt.ident.clone()))), + arena.alloc(PlaceExpr::new(PlaceExprKind::Ident(idt.ident.clone()))), )) }) .collect::>(); @@ -1305,9 +1311,9 @@ fn ty_check_app_kernel(ctx: &mut ExprTyCtx, app_kernel: &mut AppKernel) -> TyRes &mut app_kernel.gen_args, )?; // build expected type to unify with - let unit_ty = Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::Unit, - ))))); + let unit_ty = Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + )); let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_dep_fn_ty); unify::unify( &mut FnTy::new( @@ -1382,9 +1388,9 @@ fn ty_check_tuple(ctx: &mut ExprTyCtx, elems: &mut [Expr]) -> TyResult { )), }) .collect(); - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Tuple(elem_tys?), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Tuple(elem_tys?))), + ))) } fn ty_check_proj(ctx: &mut ExprTyCtx, e: &mut Expr, i: usize) -> TyResult { @@ -1398,7 +1404,7 @@ fn ty_check_proj(ctx: &mut ExprTyCtx, e: &mut Expr, i: usize) -> TyResult { return Err(TyError::UnexpectedType); }; let elem_ty = proj_elem_dty(e_dty, i); - Ok(Ty::new(TyKind::Data(Box::new(elem_ty?)))) + Ok(Ty::new(TyKind::Data(arena.alloc(elem_ty?)))) } fn ty_check_array(ctx: &mut ExprTyCtx, elems: &mut Vec) -> TyResult { @@ -1417,9 +1423,9 @@ fn ty_check_array(ctx: &mut ExprTyCtx, elems: &mut Vec) -> TyResult { "Not all provided elements have the same type.".to_string(), )) } else { - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( DataTyKind::Array( - Box::new(ty.as_ref().unwrap().dty().clone()), + arena.alloc(ty.as_ref().unwrap().dty().clone()), Nat::Lit(elems.len()), ), ))))) @@ -1437,9 +1443,9 @@ fn ty_check_literal(l: &mut Lit) -> Ty { Lit::F32(_) => ScalarTy::F32, Lit::F64(_) => ScalarTy::F64, }; - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - scalar_data, - ))))) + Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(scalar_data))), + )) } fn infer_pattern_ident_tys( @@ -1456,7 +1462,7 @@ fn infer_pattern_ident_tys( (Pattern::Ident(mutbl, ident), _) => { let ident_with_annotated_ty = IdentTyped::new( ident.clone(), - Ty::new(TyKind::Data(Box::new(pattern_dty.clone()))), + Ty::new(TyKind::Data(arena.alloc(pattern_dty.clone()))), *mutbl, ctx.exec.clone(), ); @@ -1466,7 +1472,7 @@ fn infer_pattern_ident_tys( (Pattern::Wildcard, _) => Ok(()), (Pattern::Tuple(patterns), DataTyKind::Tuple(elem_tys)) => { for (p, tty) in patterns.iter().zip(elem_tys) { - infer_pattern_ident_tys(ctx, p, &Ty::new(TyKind::Data(Box::new(tty.clone()))))?; + infer_pattern_ident_tys(ctx, p, &Ty::new(TyKind::Data(arena.alloc(tty.clone()))))?; } Ok(()) } @@ -1498,9 +1504,9 @@ fn ty_check_let( ty_check_expr(ctx, expr)?; let e_ty = expr.ty.as_mut().unwrap(); infer_tys_and_append_idents(ctx, pattern, pattern_ty, e_ty)?; - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } // TODO respect exec? @@ -1520,16 +1526,16 @@ fn ty_check_let_uninit( exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, &mut exec_expr)?; let ident_with_ty = IdentTyped::new( ident.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Dead( - dty.clone(), - ))))), + Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Dead(dty.clone()))), + )), Mutability::Mut, exec_expr, ); ctx.ty_ctx.append_ident_typed(ident_with_ty); - Ok(Ty::new(TyKind::Data(Box::new(DataTy::new( - DataTyKind::Scalar(ScalarTy::Unit), - ))))) + Ok(Ty::new(TyKind::Data( + arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + ))) } else { Err(TyError::MutabilityNotAllowed(ty.clone())) } @@ -1553,7 +1559,7 @@ fn ty_check_non_place(ctx: &mut ExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult< } unify::unify( pl_expr.ty.as_mut().unwrap().as_mut(), - &mut Ty::new(TyKind::Data(Box::new(DataTy::with_constr( + &mut Ty::new(TyKind::Data(arena.alloc(DataTy::with_constr( utils::fresh_ident("pl_deref", DataTyKind::Ident), vec![Constraint::Copyable], )))), @@ -1562,7 +1568,9 @@ fn ty_check_non_place(ctx: &mut ExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult< &BorrowCheckCtx::new(ctx, vec![], Ownership::Shrd), pl_expr, ) - .map_err(|err| TyError::ConflictingBorrow(Box::new(pl_expr.clone()), Ownership::Shrd, err))?; + .map_err(|err| { + TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Shrd, err) + })?; ctx.access_ctx.insert(potential_accesses); if pl_expr.ty.as_ref().unwrap().copyable() { Ok(pl_expr.ty.as_ref().unwrap().as_ref().clone()) @@ -1588,7 +1596,7 @@ fn ty_check_place(ctx: &mut ExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult pl_expr, ) .map_err(|err| { - TyError::ConflictingBorrow(Box::new(pl_expr.clone()), Ownership::Shrd, err) + TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Shrd, err) })?; } else { borrow_check::access_safety_check( @@ -1596,11 +1604,11 @@ fn ty_check_place(ctx: &mut ExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult pl_expr, ) .map_err(|err| { - TyError::ConflictingBorrow(Box::new(pl_expr.clone()), Ownership::Uniq, err) + TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Uniq, err) })?; ctx.ty_ctx.kill_place(&place); }; - Ok(Ty::new(TyKind::Data(Box::new(pl_ty)))) + Ok(Ty::new(TyKind::Data(arena.alloc(pl_ty)))) } fn ty_check_borrow( @@ -1621,7 +1629,7 @@ fn ty_check_borrow( } let mems = pl_expr::ty_check_and_passed_mems(&PlExprTyCtx::new(ctx, own), pl_expr)?; let loans = borrow_check::access_safety_check(&BorrowCheckCtx::new(ctx, vec![], own), pl_expr) - .map_err(|err| TyError::ConflictingBorrow(Box::new(pl_expr.clone()), own, err))?; + .map_err(|err| TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), own, err))?; mems.iter() .try_for_each(|mem| accessible_memory(ctx.exec.ty.as_ref().unwrap().as_ref(), mem))?; let pl_expr_ty = pl_expr.ty.as_ref().unwrap(); @@ -1655,14 +1663,14 @@ fn ty_check_borrow( "Trying to take reference of unaddressable gpu.local memory.".to_string(), )); } - let res_dty = DataTy::new(DataTyKind::Ref(Box::new(RefDty::new( + let res_dty = DataTy::new(DataTyKind::Ref(arena.alloc(RefDty::new( Provenance::Value(prv_val_name.clone()), own, rmem, reffed_ty, )))); ctx.ty_ctx.extend_loans_for_prv(&prv_val_name, loans)?; - Ok(Ty::new(TyKind::Data(Box::new(res_dty)))) + Ok(Ty::new(TyKind::Data(arena.alloc(res_dty)))) } fn allowed_mem_for_exec(exec_ty: &ExecTyKind) -> Vec { @@ -1773,13 +1781,13 @@ fn ty_well_formed(kind_ctx: &KindCtx, ty_ctx: &TyCtx, exec_ty: &ExecTy, ty: &Ty) kind_ctx, ty_ctx, exec_ty, - &Ty::new(TyKind::Data(Box::new(elem_dty.clone()))), + &Ty::new(TyKind::Data(arena.alloc(elem_dty.clone()))), )?; } } DataTyKind::Struct(struct_decl) => { for (_, dty) in &struct_decl.fields { - ty_well_formed(kind_ctx, ty_ctx, exec_ty, &Ty::new(TyKind::Data(Box::new(dty.clone()))))?; + ty_well_formed(kind_ctx, ty_ctx, exec_ty, &Ty::new(TyKind::Data(arena.alloc(dty.clone()))))?; } } DataTyKind::Array(elem_dty, n) => { From bf6e6d4c2e65d16c902de58dc2da2a898c654842 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 28 May 2025 13:18:09 +0200 Subject: [PATCH 16/57] add lib.rs --- descend_derive/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/descend_derive/src/lib.rs b/descend_derive/src/lib.rs index 21fb372e..233e17c0 100644 --- a/descend_derive/src/lib.rs +++ b/descend_derive/src/lib.rs @@ -1,7 +1,6 @@ -use std::collections::HashSet; - use proc_macro::TokenStream; use quote::quote; +use std::collections::HashSet; use syn::{ parse::{Parse, ParseStream}, parse_macro_input, From 122677ab26a1d963a7979f0979ae4e37798698df Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 28 May 2025 14:52:13 +0200 Subject: [PATCH 17/57] updates --- src/ast/internal.rs | 54 ++++---- src/ast/mod.rs | 291 +++++++++++++++++++++++++++----------------- 2 files changed, 207 insertions(+), 138 deletions(-) diff --git a/src/ast/internal.rs b/src/ast/internal.rs index 7f5fdab1..3435b33d 100644 --- a/src/ast/internal.rs +++ b/src/ast/internal.rs @@ -49,14 +49,14 @@ pub struct IdentTyped<'a> { impl<'a> IdentTyped<'a> { pub fn new_in( - bump: &'a bumpalo::Bump, - ident: &str, + arena: &'a bumpalo::Bump, + ident: &'a str, ty: Ty<'a>, mutbl: Mutability, - exec: ExecExpr, + exec: ExecExpr<'a>, ) -> Self { IdentTyped { - ident: Ident::new(bump, ident), + ident: Ident::new(arena, ident), ty, mutbl, exec, @@ -71,7 +71,7 @@ pub struct ExecMapping<'a> { } impl<'a> ExecMapping<'a> { - pub fn new(ident: Ident<'a>, exec_expr: ExecExpr) -> Self { + pub fn new(ident: Ident<'a>, exec_expr: ExecExpr<'a>) -> Self { ExecMapping { ident, exec_expr } } } @@ -115,13 +115,13 @@ impl<'a> Place<'a> { Place { ident, path } } - pub fn to_place_expr(&self, bump: &'a bumpalo::Bump) -> PlaceExpr { + pub fn to_place_expr(&self, arena: &'a bumpalo::Bump) -> PlaceExpr { self.path.iter().fold( PlaceExpr::new(PlaceExprKind::Ident(self.ident.clone())), |pl_expr, path_entry| match path_entry { - PathElem::Proj(n) => PlaceExpr::new(PlaceExprKind::Proj(bump.alloc(pl_expr), *n)), + PathElem::Proj(n) => PlaceExpr::new(PlaceExprKind::Proj(arena.alloc(pl_expr), *n)), PathElem::FieldProj(field) => { - PlaceExpr::new(PlaceExprKind::FieldProj(bump.alloc(pl_expr), field)) + PlaceExpr::new(PlaceExprKind::FieldProj(arena.alloc(pl_expr), field)) } }, ) @@ -157,61 +157,61 @@ pub enum PlaceCtx<'a> { impl<'a> PlaceCtx<'a> { pub fn insert_pl_expr( &'a self, - bump: &'a bumpalo::Bump, + arena: &'a bumpalo::Bump, pl_expr: PlaceExpr<'a>, ) -> PlaceExpr<'a> { match self { Self::Hole => pl_expr, Self::Proj(pl_ctx, n) => PlaceExpr::new(PlaceExprKind::Proj( - bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), *n, )), Self::FieldProj(pl_ctx, field) => PlaceExpr::new(PlaceExprKind::FieldProj( - bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), field, )), Self::Deref(pl_ctx) => PlaceExpr::new(PlaceExprKind::Deref( - bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), )), Self::Select(pl_ctx, exec) => PlaceExpr::new(PlaceExprKind::Select( - bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), exec.clone(), )), Self::View(pl_ctx, view) => PlaceExpr::new(PlaceExprKind::View( - bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), view.clone(), )), Self::Idx(pl_ctx, idx) => PlaceExpr::new(PlaceExprKind::Idx( - bump.alloc(pl_ctx.insert_pl_expr(bump, pl_expr)), + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), idx.clone(), )), } } - pub fn without_innermost_deref(&'a self, bump: &'a bumpalo::Bump) -> &'a PlaceCtx<'a> { + pub fn without_innermost_deref(&'a self, arena: &'a bumpalo::Bump) -> &'a PlaceCtx<'a> { match self { PlaceCtx::Hole => self, PlaceCtx::Proj(pl_ctx, idx) => { - bump.alloc(PlaceCtx::Proj(pl_ctx.without_innermost_deref(bump), *idx)) + arena.alloc(PlaceCtx::Proj(pl_ctx.without_innermost_deref(arena), *idx)) } - PlaceCtx::FieldProj(pl_ctx, ident) => bump.alloc(PlaceCtx::FieldProj( - pl_ctx.without_innermost_deref(bump), + PlaceCtx::FieldProj(pl_ctx, ident) => arena.alloc(PlaceCtx::FieldProj( + pl_ctx.without_innermost_deref(arena), ident.clone(), )), PlaceCtx::Deref(pl_ctx) => match **pl_ctx { - PlaceCtx::Hole => bump.alloc(PlaceCtx::Hole), - _ => bump.alloc(PlaceCtx::Deref(pl_ctx.without_innermost_deref(bump))), + PlaceCtx::Hole => arena.alloc(PlaceCtx::Hole), + _ => arena.alloc(PlaceCtx::Deref(pl_ctx.without_innermost_deref(arena))), }, - PlaceCtx::Select(pl_ctx, exec) => bump.alloc(PlaceCtx::Select( - pl_ctx.without_innermost_deref(bump), + PlaceCtx::Select(pl_ctx, exec) => arena.alloc(PlaceCtx::Select( + pl_ctx.without_innermost_deref(arena), exec.clone(), )), - PlaceCtx::View(pl_ctx, view) => bump.alloc(PlaceCtx::View( - pl_ctx.without_innermost_deref(bump), + PlaceCtx::View(pl_ctx, view) => arena.alloc(PlaceCtx::View( + pl_ctx.without_innermost_deref(arena), view.clone(), )), - PlaceCtx::Idx(pl_ctx, idx) => bump.alloc(PlaceCtx::Idx( - pl_ctx.without_innermost_deref(bump), + PlaceCtx::Idx(pl_ctx, idx) => arena.alloc(PlaceCtx::Idx( + pl_ctx.without_innermost_deref(arena), idx.clone(), )), } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index eefeb58d..eda08f9e 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -125,11 +125,11 @@ impl<'a> FunDef<'a> { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IdentExec<'a> { pub ident: Ident<'a>, - pub ty: &'a ExecTy, + pub ty: &'a ExecTy<'a>, } impl<'a> IdentExec<'a> { - pub fn new_in(bump: &'a bumpalo::Bump, ident: Ident<'a>, exec_ty: ExecTy) -> Self { + pub fn new_in(bump: &'a bumpalo::Bump, ident: Ident<'a>, exec_ty: ExecTy<'a>) -> Self { IdentExec { ident, ty: bump.alloc(exec_ty), @@ -276,7 +276,7 @@ impl<'a> Sched<'a> { bump: &'a bumpalo::Bump, dim: DimCompo, inner_exec_ident: Option>, - sched_exec: ExecExpr, + sched_exec: ExecExpr<'a>, body: Block<'a>, ) -> Self { Sched { @@ -302,7 +302,7 @@ impl<'a> Split<'a> { bump: &'a bumpalo::Bump, dim_compo: DimCompo, pos: Nat<'a>, - split_exec: ExecExpr, + split_exec: ExecExpr<'a>, branch_idents: impl IntoIterator>, branch_bodies: impl IntoIterator>, ) -> Self { @@ -436,7 +436,7 @@ pub struct Ident<'a> { } // TODO: Arena String Interna nachschauen impl<'a> Ident<'a> { - pub fn new(bump: &'a bumpalo::Bump, name: &str) -> Self { + pub fn new(bump: &'a bumpalo::Bump, name: &'a str) -> Self { Self { name: bump.alloc_str(name), span: None, @@ -444,7 +444,7 @@ impl<'a> Ident<'a> { } } - pub fn new_impli(bump: &'a bumpalo::Bump, name: &str) -> Self { + pub fn new_impli(bump: &'a bumpalo::Bump, name: &'a str) -> Self { Self { name: bump.alloc_str(name), span: None, @@ -452,7 +452,7 @@ impl<'a> Ident<'a> { } } - pub fn with_span(bump: &'a bumpalo::Bump, name: &str, span: Span) -> Self { + pub fn with_span(bump: &'a bumpalo::Bump, name: &'a str, span: Span) -> Self { Self { name: bump.alloc_str(name), span: Some(span), @@ -715,12 +715,12 @@ pub enum PlaceExprKind<'a> { #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum PlExprPathElem<'a> { View(View<'a>), - Select(Box>), + Select(&'a ExecExpr<'a>), Proj(usize), FieldProj(Ident<'a>), Deref, - Idx(Box>), - RangeSelec(Box>, Box>), + Idx(&'a Nat<'a>), + RangeSelec(&'a Nat<'a>, &'a Nat<'a>), } impl<'a> PlaceExpr<'a> { @@ -752,68 +752,77 @@ impl<'a> PlaceExpr<'a> { } // TODO refactor. Places are only needed during typechecking and codegen - pub fn to_place(&self) -> Option { + pub fn to_place(&self, arena: &'a bumpalo::Bump) -> Option { if self.is_place() { - Some(self.to_pl_ctx_and_most_specif_pl().1) + Some(self.to_pl_ctx_and_most_specif_pl(arena).1) } else { None } } // TODO refactor see to_place - pub fn to_pl_ctx_and_most_specif_pl(&self) -> (internal::PlaceCtx, internal::Place) { + pub fn to_pl_ctx_and_most_specif_pl( + &'a self, + arena: &'a bumpalo::Bump, + ) -> (internal::PlaceCtx<'a>, internal::Place<'a>) { match &self.pl_expr { PlaceExprKind::Select(inner_ple, exec_idents) => { - let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); ( - internal::PlaceCtx::Select(Box::new(pl_ctx), exec_idents.clone()), + internal::PlaceCtx::Select(arena.alloc(pl_ctx), exec_idents.clone()), pl, ) } PlaceExprKind::Deref(inner_ple) => { - let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); - (internal::PlaceCtx::Deref(Box::new(pl_ctx)), pl) + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + (internal::PlaceCtx::Deref(arena.alloc(pl_ctx)), pl) } PlaceExprKind::View(inner_ple, view) => { - let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); - (internal::PlaceCtx::View(Box::new(pl_ctx), view.clone()), pl) + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + ( + internal::PlaceCtx::View(arena.alloc(pl_ctx), view.clone()), + pl, + ) } PlaceExprKind::Proj(inner_ple, n) => { - let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); + let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); match pl_ctx { internal::PlaceCtx::Hole => { pl.path.push(PathElem::Proj(*n)); (pl_ctx, internal::Place::new(pl.ident, pl.path)) } - _ => (internal::PlaceCtx::Proj(Box::new(pl_ctx), *n), pl), + _ => (internal::PlaceCtx::Proj(arena.alloc(pl_ctx), *n), pl), } } PlaceExprKind::FieldProj(inner_ple, field_name) => { - let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); + let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); match pl_ctx { internal::PlaceCtx::Hole => { pl.path.push(PathElem::FieldProj(field_name.clone())); (pl_ctx, internal::Place::new(pl.ident, pl.path)) } _ => ( - internal::PlaceCtx::FieldProj(Box::new(pl_ctx), field_name.clone()), + internal::PlaceCtx::FieldProj(arena.alloc(pl_ctx), **field_name), pl, ), } } PlaceExprKind::Idx(inner_ple, idx) => { - let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); - (internal::PlaceCtx::Idx(Box::new(pl_ctx), idx.clone()), pl) + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + ( + internal::PlaceCtx::Idx(arena.alloc(pl_ctx), idx.clone()), + pl, + ) } PlaceExprKind::Ident(ident) => ( internal::PlaceCtx::Hole, - internal::Place::new(ident.clone(), vec![]), + internal::Place::new(ident.clone(), vec![]), // create a BumpVec here ), } } - pub fn equiv(&'_ self, place: &'_ internal::Place) -> bool { - if let (internal::PlaceCtx::Hole, pl) = self.to_pl_ctx_and_most_specif_pl() { + pub fn equiv(&'_ self, arena: &'a bumpalo::Bump, place: &'_ internal::Place) -> bool { + if let (internal::PlaceCtx::Hole, pl) = self.to_pl_ctx_and_most_specif_pl(arena) { &pl == place } else { false @@ -823,8 +832,8 @@ impl<'a> PlaceExpr<'a> { pub fn as_ident_and_path(&self) -> (Ident<'a>, Vec>) { fn as_ident_and_path_rec( pl_expr: &PlaceExpr, - mut path: Vec, - ) -> (Ident<'a>, Vec>) { + mut path: BumpVec>, + ) -> (Ident<'a>, BumpVec>) { match &pl_expr.pl_expr { PlaceExprKind::Ident(i) => { path.reverse(); @@ -839,7 +848,7 @@ impl<'a> PlaceExpr<'a> { as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::View(inner_ple, view) => { - path.push(PlExprPathElem::View(view.as_ref().clone())); + path.push(PlExprPathElem::View(**view)); // formerly as_ref().clone() ? Can that just work with double dereferencing? as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::Proj(inner_ple, n) => { @@ -847,7 +856,7 @@ impl<'a> PlaceExpr<'a> { as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::FieldProj(inner_ple, ident) => { - path.push(PlExprPathElem::FieldProj(ident.as_ref().clone())); + path.push(PlExprPathElem::FieldProj(**ident)); // formerly as_ref().clone() ? Can that just work with double dereferencing? as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::Idx(inner_ple, idx) => { @@ -863,18 +872,16 @@ impl<'a> PlaceExpr<'a> { #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] pub struct ExecExpr<'a> { - pub exec: Box>, - // FIXME misusing span_derive_ignore to ignore type on equality checks + pub exec: &'a ExecExprKind<'a>, #[span_derive_ignore] - pub ty: Option>, + pub ty: Option<&'a ExecTy<'a>>, #[span_derive_ignore] pub span: Option, } - impl<'a> ExecExpr<'a> { - pub fn new(exec: ExecExprKind) -> Self { - ExecExpr { - exec: Box::new(exec), + pub fn new(arena: &'a bumpalo::Bump, exec: ExecExprKind<'a>) -> Self { + Self { + exec: arena.alloc(exec), ty: None, span: None, } @@ -883,27 +890,54 @@ impl<'a> ExecExpr<'a> { // TODO how does this relate to is_prefix_of. Refactor. pub fn is_sub_exec_of(&self, exec: &ExecExpr) -> bool { if self.exec.path.len() > exec.exec.path.len() { - return self.exec.path[..exec.exec.path.len()] == exec.exec.path; + return self.exec.path[..exec.exec.path.len()] == exec.exec.path[..]; } false } - pub fn remove_last_distrib(&self) -> ExecExpr { + pub fn remove_last_distrib(&self, arena: &'a bumpalo::Bump) -> ExecExpr { let last_distrib_pos = self .exec .path .iter() .rposition(|e| matches!(e, ExecPathElem::ForAll(_))); + + // What did i do here? let removed_distrib_path = if let Some(ldp) = last_distrib_pos { - self.exec.path[..ldp].to_vec() + let mut vec = BumpVec::new_in(arena); + // self.exec.path[..ldp].to_vec() --> changed this to BumpVec + vec.extend_from_slice(&self.exec.path[..ldp]); + vec } else { - vec![] + //vec![] --> changed this to BumpVec + BumpVec::new_in(arena) + }; + + ExecExpr::new(arena, + ExecExprKind::with_path( + self.exec.base.clone(), + removed_distrib_path, + ) + ) + } + + /** Kind of idea how to do it + pub fn remove_last_distrib(&self, arena: &'a Bump) -> ExecExpr<'a> { + let last_distrib_pos = self + .exec + .path + .iter() + .rposition(|e| matches!(e, ExecPathElem::ForAll(_))); + + let removed_path = match last_distrib_pos { + Some(pos) => &self.exec.path[..pos], + None => &[], }; - ExecExpr::new(ExecExprKind::with_path( - self.exec.base.clone(), - removed_distrib_path, - )) + + let exec_kind = ExecExprKind::with_path(self.exec.base.clone(), removed_path.iter().cloned(), arena); + ExecExpr::new(arena, exec_kind) } + */ pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { match (&self.exec.base, &other.exec.base) { @@ -953,17 +987,31 @@ impl<'a> ExecExpr<'a> { #[test] fn equal_exec_exprs() { - let exec1 = ExecExpr::new(ExecExprKind::with_path( - BaseExec::Ident(Ident::new("grid")), - vec![ExecPathElem::ForAll(DimCompo::X)], - )); - let exec2 = ExecExpr::new(ExecExprKind::with_path( - BaseExec::Ident(Ident::new("grid")), - vec![ExecPathElem::ForAll(DimCompo::X)], - )); - if exec1 != exec2 { - panic!("Unequal execs, that should be equal") - } + let arena = Bump::new(); + + let exec1 = ExecExpr::new( + &arena, + ExecExprKind::with_path( + BaseExec::Ident(Ident::new(&arena, "grid")), + bumpalo::collections::Vec::from_iter_in( + [ExecPathElem::ForAll(DimCompo::X)], + &arena + ) + ) + ); + + let exec2 = ExecExpr::new( + &arena, + ExecExprKind::with_path( + BaseExec::Ident(Ident::new(&arena, "grid")), + bumpalo::collections::Vec::from_iter_in( + [ExecPathElem::ForAll(DimCompo::X)], + &arena + ) + ) + ); + + assert_eq!(exec1, exec2, "Unequal execs that should be equal"); } #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] @@ -1001,23 +1049,39 @@ impl<'a> TakeRange<'a> { #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub struct ExecExprKind<'a> { pub base: BaseExec<'a>, - pub path: Vec>, + pub path: BumpVec<'a, ExecPathElem<'a>>, } -impl ExecExprKind { - pub fn new(base: BaseExec) -> Self { - ExecExprKind { base, path: vec![] } +impl<'a> ExecExprKind<'a> { + pub fn new(arena: &'a bumpalo::Bump, base: BaseExec<'a>) -> Self { + ExecExprKind { + base, + path: BumpVec::new_in(arena), + } } - pub fn with_path(base: BaseExec, path: Vec) -> Self { + pub fn with_path(base: BaseExec<'a>, path: BumpVec<'a, ExecPathElem<'a>>) -> Self { ExecExprKind { base, path } } - pub fn split_proj(mut self, dim_compo: DimCompo, pos: Nat, proj: LeftOrRight) -> Self { - self.path - .push(ExecPathElem::TakeRange(Box::new(TakeRange::new( - dim_compo, pos, proj, - )))); + /** + pub fn with_path(base: BaseExec, path: impl IntoIterator>, arena: &'a Bump) -> Self { + let mut bump_vec = BumpVec::new_in(arena); + bump_vec.extend(path); + Self { base, path: bump_vec } + }*/ + + + pub fn split_proj( + mut self, + arena: &'a bumpalo::Bump, + dim_compo: DimCompo, + pos: Nat, + proj: LeftOrRight, + ) -> Self { + self.path.push(ExecPathElem::TakeRange( + arena.alloc(TakeRange::new(dim_compo, pos<'a>, proj)), + )); self } @@ -1045,7 +1109,7 @@ pub enum BaseExec<'a> { #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum ExecPathElem<'a> { - TakeRange(Box>), + TakeRange(&'a TakeRange<'a>), ForAll(DimCompo), ToWarps, ToThreads(DimCompo), @@ -1057,14 +1121,14 @@ pub enum ExecPathElem<'a> { // fn elem_type(DimCompo) -> ExecTy #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct ExecTy { - pub ty: ExecTyKind, +pub struct ExecTy<'a> { + pub ty: ExecTyKind<'a>, #[span_derive_ignore] pub span: Option, } -impl ExecTy { - pub fn new(exec: ExecTyKind) -> Self { +impl<'a> ExecTy<'a> { + pub fn new(exec: ExecTyKind<'a>) -> Self { ExecTy { ty: exec, span: None, @@ -1079,7 +1143,7 @@ pub enum ExecTyKind<'a> { GpuWarp, GpuBlock(Dim<'a>), GpuGrid(Dim<'a>, Dim<'a>), - GpuToThreads(Dim<'a>, Box>), + GpuToThreads(Dim<'a>, &'a ExecTy<'a>), GpuThreadGrp(Dim<'a>), GpuWarpGrp(Nat<'a>), GpuBlockGrp(Dim<'a>, Dim<'a>), @@ -1096,12 +1160,12 @@ pub struct Ty<'a> { #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub struct ParamSig<'a> { - pub exec_expr: ExecExpr, + pub exec_expr: ExecExpr<'a>, pub ty: &'a Ty<'a>, } impl<'a> ParamSig<'a> { - pub fn new(exec_expr: ExecExpr, ty: &'a Ty<'a>) -> Self { + pub fn new(exec_expr: ExecExpr<'a>, ty: &'a Ty<'a>) -> Self { ParamSig { exec_expr, ty } } } @@ -1111,28 +1175,28 @@ pub struct FnTy<'a> { pub generics: BumpVec<'a, IdentKinded<'a>>, pub generic_exec: Option>, pub param_sigs: BumpVec<'a, ParamSig<'a>>, - pub exec: ExecExpr, + pub exec: ExecExpr<'a>, pub ret_ty: &'a Ty<'a>, pub nat_constrs: BumpVec<'a, NatConstr<'a>>, } impl<'a> FnTy<'a> { pub fn new( - bump: &'a Bump, + arena: &'a Bump, generics: impl IntoIterator>, - generic_exec: Option, + generic_exec: Option>, param_sigs: impl IntoIterator>, - exec: ExecExpr, + exec: ExecExpr<'a>, ret_ty: &'a Ty<'a>, nat_constrs: impl IntoIterator>, ) -> Self { - let mut generics_vec = BumpVec::new_in(bump); + let mut generics_vec = BumpVec::new_in(arena); generics_vec.extend(generics); - let mut param_vec = BumpVec::new_in(bump); + let mut param_vec = BumpVec::new_in(arena); param_vec.extend(param_sigs); - let mut nat_vec = BumpVec::new_in(bump); + let mut nat_vec = BumpVec::new_in(arena); nat_vec.extend(nat_constrs); FnTy { @@ -1140,7 +1204,7 @@ impl<'a> FnTy<'a> { generic_exec, param_sigs: param_vec, exec, - ret_ty: bump.alloc(ret_ty), + ret_ty: arena.alloc(ret_ty), nat_constrs: nat_vec, } } @@ -1223,25 +1287,26 @@ pub struct Dim2d<'a>(pub Nat<'a>, pub Nat<'a>); pub struct Dim3d<'a>(pub Nat<'a>, pub Nat<'a>, pub Nat<'a>); #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum Dim<'a> { - XYZ(Box>), - XY(Box>), - XZ(Box>), - YZ(Box>), - X(Box>), - Y(Box>), - Z(Box>), + XYZ(&'a Dim3d<'a>), + XY(&'a Dim2d<'a>), + XZ(&'a Dim2d<'a>), + YZ(&'a Dim2d<'a>), + X(&'a Dim1d<'a>), + Y(&'a Dim1d<'a>), + Z(&'a Dim1d<'a>), } impl<'a> Dim<'a> { - pub fn new_3d(n1: Nat, n2: Nat, n3: Nat) -> Self { - Dim::XYZ(Box::new(Dim3d(n1, n2, n3))) + pub fn new_3d(arena: &'a Bump, n1: Nat<'a>, n2: Nat<'a>, n3: Nat<'a>) -> Self { + Dim::XYZ(arena.alloc(Dim3d(n1, n2, n3))) } - pub fn new_2d) -> Self>(constr: F, n1: Nat, n2: Nat) -> Self { - constr(Box::new(Dim2d(n1, n2))) + pub fn new_2d Self>(arena: &'a Bump, constr: F, n1: Nat<'a>, n2: Nat<'a>) -> Self { + constr(arena.alloc(Dim2d(n1, n2))) } - pub fn new_1d) -> Self>(constr: F, n: Nat) -> Self { - constr(Box::new(Dim1d(n))) + + pub fn new_1d Self>(arena: &'a Bump, constr: F, n: Nat<'a>) -> Self { + constr(arena.alloc(Dim1d(n))) } pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { @@ -1456,9 +1521,9 @@ pub struct RefDty<'a> { impl<'a> RefDty<'a> { pub fn new( bump: &'a Bump, - rgn: Provenance, + rgn: Provenance<'a>, own: Ownership, - mem: Memory, + mem: Memory<'a>, dty: DataTy<'a>, ) -> Self { RefDty { @@ -1536,7 +1601,7 @@ pub struct IdentKinded<'a> { } impl<'a> IdentKinded<'a> { - pub fn new(ident: &Ident, kind: Kind) -> Self { + pub fn new(ident: &Ident<'a>, kind: Kind) -> Self { IdentKinded { ident: ident.clone(), kind, @@ -1552,39 +1617,43 @@ pub enum NatRange<'a> { } impl<'a> NatRange<'a> { - pub fn lift(&self, nat_ctx: &NatCtx) -> NatEvalResult { + pub fn lift(&self, arena: &'a Bump, nat_ctx: &NatCtx) -> NatEvalResult { let range_iter = match self { NatRange::Simple { lower, upper } => { let lower = lower.eval(nat_ctx)?; let upper = upper.eval(nat_ctx)?; - NatRangeIter::new(lower, Box::new(|x| x + 1), Box::new(move |c| c >= upper)) + NatRangeIter::new( + lower, + arena.alloc(|x| x + 1), + arena.alloc(move |c| c >= upper), + ) } NatRange::Halved { upper } => { let upper = upper.eval(nat_ctx)?; - NatRangeIter::new(upper, Box::new(|x| x / 2), Box::new(|c| c == 0)) + NatRangeIter::new(upper, arena.alloc(|x| x / 2), arena.alloc(|c| c == 0)) } NatRange::Doubled { upper } => { let upper = upper.eval(nat_ctx)?; - NatRangeIter::new(1, Box::new(|x| x * 2), Box::new(move |c| c >= upper)) + NatRangeIter::new(1, arena.alloc(|x| x * 2), arena.alloc(move |c| c >= upper)) } }; Ok(range_iter) } } -pub struct NatRangeIter { +pub struct NatRangeIter<'a> { current: usize, // go from current to next value - step_fun: Box usize>, + step_fun: &'a dyn Fn(usize) -> usize, // determine whether the current value is still within range - end_cond: Box bool>, + end_cond: &'a dyn Fn(usize) -> bool, } -impl NatRangeIter { +impl<'a> NatRangeIter<'a> { fn new( start: usize, - step_fun: Box usize>, - end_cond: Box bool>, + step_fun: &'a dyn Fn(usize) -> usize, + end_cond: &'a dyn Fn(usize) -> bool, ) -> Self { NatRangeIter { current: start, @@ -1594,7 +1663,7 @@ impl NatRangeIter { } } -impl Iterator for NatRangeIter { +impl<'a> Iterator for NatRangeIter<'a> { type Item = usize; fn next(&mut self) -> Option { From 9f56d08193e69b1fea8fac9e096657eec1856299 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 3 Jun 2025 10:32:25 +0200 Subject: [PATCH 18/57] updates --- src/ast/mod.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index eda08f9e..15e788d9 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -424,8 +424,8 @@ pub enum ExprKind<'a> { Range(&'a Expr<'a>, &'a Expr<'a>), } -#[span_derive(PartialEq, Eq, Hash)] #[derive(Clone, Debug)] +#[span_derive(PartialEq, Eq, Hash)] pub struct Ident<'a> { // Identifier names never change. Instead a new identifier is created. Therefore it is not // necessary to keep the capacity that is stored in a String for efficient appending. @@ -434,7 +434,6 @@ pub struct Ident<'a> { pub span: Option, pub is_implicit: bool, } -// TODO: Arena String Interna nachschauen impl<'a> Ident<'a> { pub fn new(bump: &'a bumpalo::Bump, name: &'a str) -> Self { Self { @@ -802,7 +801,7 @@ impl<'a> PlaceExpr<'a> { (pl_ctx, internal::Place::new(pl.ident, pl.path)) } _ => ( - internal::PlaceCtx::FieldProj(arena.alloc(pl_ctx), **field_name), + internal::PlaceCtx::FieldProj(arena.alloc(pl_ctx), field_name), pl, ), } @@ -816,7 +815,7 @@ impl<'a> PlaceExpr<'a> { } PlaceExprKind::Ident(ident) => ( internal::PlaceCtx::Hole, - internal::Place::new(ident.clone(), vec![]), // create a BumpVec here + internal::Place::new(ident.clone(), BumpVec::new_in(arena)), ), } } @@ -1809,22 +1808,22 @@ mod size_asserts { }; } static_assert_size!(Dim, 16); - static_assert_size!(DataTy, 104); + static_assert_size!(DataTy, 112); static_assert_size!(DataTyKind, 64); static_assert_size!(ExecExpr, 32); - static_assert_size!(ExecExprKind, 64); + static_assert_size!(ExecExprKind, 72); static_assert_size!(ExecPathElem, 16); static_assert_size!(ExecTy, 64); static_assert_size!(ExecTyKind, 48); - static_assert_size!(Expr, 96); - static_assert_size!(ExprKind, 72); - static_assert_size!(FunDef, 192); + static_assert_size!(Expr, 104); + static_assert_size!(ExprKind, 80); + static_assert_size!(FunDef, 216); static_assert_size!(Ident, 32); // maybe too large? static_assert_size!(IdentExec, 40); static_assert_size!(Lit, 16); static_assert_size!(Memory, 32); static_assert_size!(Nat, 48); - static_assert_size!(ParamDecl, 104); + static_assert_size!(ParamDecl, 80); static_assert_size!(Pattern, 40); static_assert_size!(PlaceExpr, 56); static_assert_size!(PlaceExprKind, 32); From 984e5d3c86145fe461d215ef9436bcdaf3093981 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 3 Jun 2025 14:10:13 +0200 Subject: [PATCH 19/57] span_derive macro now works with lifetime generics --- descend_derive/src/lib.rs | 149 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/descend_derive/src/lib.rs b/descend_derive/src/lib.rs index 233e17c0..c4589d30 100644 --- a/descend_derive/src/lib.rs +++ b/descend_derive/src/lib.rs @@ -8,6 +8,154 @@ use syn::{ Fields, FieldsNamed, Ident, ItemStruct, Token, Type, TypeReference, }; +struct Args { + vars: HashSet, +} + +impl Parse for Args { + fn parse(input: ParseStream) -> syn::parse::Result { + let vars = Punctuated::::parse_terminated(input)?; + Ok(Args { + vars: vars.into_iter().collect(), + }) + } +} + +const IGNORE_ATTR_NAME: &str = "span_derive_ignore"; + +#[proc_macro_attribute] +pub fn span_derive(attr: TokenStream, input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as ItemStruct); + let args = parse_macro_input!(attr as Args); + if args.vars.is_empty() { + panic!("Need at least one attribute in span_derive!"); + } + + let original_name = &input.ident; + let original_generics = input.generics.clone(); + let (impl_generics, ty_generics, where_clause) = original_generics.split_for_impl(); + + let original_fields = match &input.fields { + syn::Fields::Named(fields) => fields, + _ => unreachable!(), + }; + + let mut new_fields = original_fields.clone(); + for field in new_fields.named.iter_mut() { + field + .attrs + .retain(|attr| !attr.path.is_ident(IGNORE_ATTR_NAME)); + } + + let mut original = input.clone(); + original.fields = Fields::Named(new_fields); + + let mut helper = input.clone(); + + let mut helper_generics = original_generics.clone(); + let mut new_params = Punctuated::new(); + new_params.push(syn::parse_quote!('helper)); + for param in original_generics.params.iter() { + new_params.push(param.clone()); + } + helper_generics.params = new_params; + helper.generics = helper_generics.clone(); + + let mut helper_fields = FieldsNamed { + brace_token: original_fields.brace_token.clone(), + named: Punctuated::new(), + }; + for mut field in original_fields.named.clone().into_iter() { + if field + .attrs + .iter() + .any(|attr| attr.path.is_ident(IGNORE_ATTR_NAME)) + { + continue; + } + let mut typ: TypeReference = syn::parse_str("&'helper i64").unwrap(); + typ.elem = Box::new(field.ty); + field.ty = Type::Reference(typ); + helper_fields.named.push(field); + } + helper.fields = Fields::Named(helper_fields); + + let helper_name = Ident::new( + &format!("__{}SpanHelper", original_name.to_string()), + input.ident.span(), + ); + helper.ident = helper_name.clone(); + helper.attrs.clear(); + + let into_fields = helper + .fields + .iter() + .map(|field| field.ident.as_ref().unwrap().clone()) + .collect::>(); + + let mut derive_args: Vec<_> = args.vars.iter().collect(); + derive_args.sort_by(|a, b| a.to_string().cmp(&b.to_string())); + + let (helper_impl_generics, helper_ty_generics, helper_where_clause) = + helper_generics.split_for_impl(); + + let mut output = quote! { + #original + + #[derive(#(#derive_args),*)] + #helper + + impl #helper_impl_generics From<&'helper #original_name #ty_generics> + for #helper_name #helper_ty_generics #helper_where_clause { + fn from(orig: &'helper #original_name #ty_generics) -> Self { + #helper_name { + #(#into_fields: &orig.#into_fields),* + } + } + } + }; + + for derive_arg in args.vars.iter() { + match &derive_arg.to_string() as &str { + "PartialEq" => { + output.extend(quote! { + impl #impl_generics ::core::cmp::PartialEq for #original_name #ty_generics #where_clause { + fn eq(&self, other: &Self) -> bool { + let helper = #helper_name::from(self); + let helper_other = #helper_name::from(other); + helper == helper_other + } + } + }); + } + "Eq" => { + output.extend(quote! { + impl #impl_generics ::core::cmp::Eq for #original_name #ty_generics #where_clause {} + }); + } + "Hash" => { + output.extend(quote! { + impl #impl_generics ::core::hash::Hash for #original_name #ty_generics #where_clause { + fn hash(&self, state: &mut H) { + let helper = #helper_name::from(self); + helper.hash(state); + } + } + }); + } + other => panic!("span_derive not implemented for {}", other), + } + } + + eprintln!( + "--- Generated code ---\n{}\n------------------------", + output + ); + + TokenStream::from(output) +} + +/*** OLD WAY // Copy paste from syn example struct Args { vars: HashSet, @@ -147,3 +295,4 @@ pub fn span_derive(attr: TokenStream, input: TokenStream) -> TokenStream { TokenStream::from(output) } +*/ From 02fe1ea5d6bdf4107a8dc8082f777ff50f2a451a Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 3 Jun 2025 14:46:57 +0200 Subject: [PATCH 20/57] fixed last ast errors --- src/ast/mod.rs | 92 ++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 15e788d9..ee4c773f 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -621,7 +621,7 @@ impl<'a> ArgKinded<'a> { } } - pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { + pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a Self) -> NatEvalResult<'a, bool> { match (self, other) { (ArgKinded::Ident(i), ArgKinded::Ident(o)) => Ok(i == o), (ArgKinded::Nat(n), ArgKinded::Nat(no)) => Ok(n.eval(nat_ctx)? == no.eval(nat_ctx)?), @@ -652,7 +652,7 @@ pub struct View<'a> { } impl<'a> View<'a> { - pub fn equal(&self, nat_ctx: &NatCtx, other: &View<'a>) -> NatEvalResult { + pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a View<'a>) -> NatEvalResult<'a, bool> { if self.name.name != other.name.name { return Ok(false); } @@ -801,7 +801,10 @@ impl<'a> PlaceExpr<'a> { (pl_ctx, internal::Place::new(pl.ident, pl.path)) } _ => ( - internal::PlaceCtx::FieldProj(arena.alloc(pl_ctx), field_name), + internal::PlaceCtx::FieldProj( + arena.alloc(pl_ctx), + field_name.clone().clone(), + ), pl, ), } @@ -820,7 +823,7 @@ impl<'a> PlaceExpr<'a> { } } - pub fn equiv(&'_ self, arena: &'a bumpalo::Bump, place: &'_ internal::Place) -> bool { + pub fn equiv(&'a self, arena: &'a bumpalo::Bump, place: &'a internal::Place) -> bool { if let (internal::PlaceCtx::Hole, pl) = self.to_pl_ctx_and_most_specif_pl(arena) { &pl == place } else { @@ -828,11 +831,14 @@ impl<'a> PlaceExpr<'a> { } } - pub fn as_ident_and_path(&self) -> (Ident<'a>, Vec>) { - fn as_ident_and_path_rec( - pl_expr: &PlaceExpr, - mut path: BumpVec>, - ) -> (Ident<'a>, BumpVec>) { + pub fn as_ident_and_path( + &'a self, + arena: &'a bumpalo::Bump, + ) -> (Ident<'a>, BumpVec<'a, PlExprPathElem<'a>>) { + fn as_ident_and_path_rec<'a>( + pl_expr: &'a PlaceExpr, + mut path: BumpVec<'a, PlExprPathElem<'a>>, + ) -> (Ident<'a>, BumpVec<'a, PlExprPathElem<'a>>) { match &pl_expr.pl_expr { PlaceExprKind::Ident(i) => { path.reverse(); @@ -847,7 +853,7 @@ impl<'a> PlaceExpr<'a> { as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::View(inner_ple, view) => { - path.push(PlExprPathElem::View(**view)); // formerly as_ref().clone() ? Can that just work with double dereferencing? + path.push(PlExprPathElem::View(view.clone().clone())); // formerly as_ref().clone() ? Can that just work with double cloning? as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::Proj(inner_ple, n) => { @@ -855,7 +861,7 @@ impl<'a> PlaceExpr<'a> { as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::FieldProj(inner_ple, ident) => { - path.push(PlExprPathElem::FieldProj(**ident)); // formerly as_ref().clone() ? Can that just work with double dereferencing? + path.push(PlExprPathElem::FieldProj(ident.clone().clone())); // formerly as_ref().clone() ? Can that just work with double cloning? as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::Idx(inner_ple, idx) => { @@ -864,7 +870,7 @@ impl<'a> PlaceExpr<'a> { } } } - as_ident_and_path_rec(self, vec![]) + as_ident_and_path_rec(self, BumpVec::new_in(arena)) // BumpVec Stuff into it } } @@ -900,7 +906,7 @@ impl<'a> ExecExpr<'a> { .path .iter() .rposition(|e| matches!(e, ExecPathElem::ForAll(_))); - + // What did i do here? let removed_distrib_path = if let Some(ldp) = last_distrib_pos { let mut vec = BumpVec::new_in(arena); @@ -911,16 +917,14 @@ impl<'a> ExecExpr<'a> { //vec![] --> changed this to BumpVec BumpVec::new_in(arena) }; - - ExecExpr::new(arena, - ExecExprKind::with_path( - self.exec.base.clone(), - removed_distrib_path, - ) + + ExecExpr::new( + arena, + ExecExprKind::with_path(self.exec.base.clone(), removed_distrib_path), ) } - /** Kind of idea how to do it + /** Kind of idea how to do it pub fn remove_last_distrib(&self, arena: &'a Bump) -> ExecExpr<'a> { let last_distrib_pos = self .exec @@ -992,22 +996,16 @@ fn equal_exec_exprs() { &arena, ExecExprKind::with_path( BaseExec::Ident(Ident::new(&arena, "grid")), - bumpalo::collections::Vec::from_iter_in( - [ExecPathElem::ForAll(DimCompo::X)], - &arena - ) - ) + bumpalo::collections::Vec::from_iter_in([ExecPathElem::ForAll(DimCompo::X)], &arena), + ), ); let exec2 = ExecExpr::new( &arena, ExecExprKind::with_path( BaseExec::Ident(Ident::new(&arena, "grid")), - bumpalo::collections::Vec::from_iter_in( - [ExecPathElem::ForAll(DimCompo::X)], - &arena - ) - ) + bumpalo::collections::Vec::from_iter_in([ExecPathElem::ForAll(DimCompo::X)], &arena), + ), ); assert_eq!(exec1, exec2, "Unequal execs that should be equal"); @@ -1063,23 +1061,22 @@ impl<'a> ExecExprKind<'a> { ExecExprKind { base, path } } - /** + /** pub fn with_path(base: BaseExec, path: impl IntoIterator>, arena: &'a Bump) -> Self { let mut bump_vec = BumpVec::new_in(arena); bump_vec.extend(path); Self { base, path: bump_vec } }*/ - pub fn split_proj( mut self, arena: &'a bumpalo::Bump, dim_compo: DimCompo, - pos: Nat, + pos: Nat<'a>, proj: LeftOrRight, ) -> Self { self.path.push(ExecPathElem::TakeRange( - arena.alloc(TakeRange::new(dim_compo, pos<'a>, proj)), + arena.alloc(TakeRange::new(dim_compo, pos, proj)), )); self } @@ -1296,15 +1293,20 @@ pub enum Dim<'a> { } impl<'a> Dim<'a> { - pub fn new_3d(arena: &'a Bump, n1: Nat<'a>, n2: Nat<'a>, n3: Nat<'a>) -> Self { + pub fn new_3d(arena: &'a Bump, n1: Nat<'a>, n2: Nat<'a>, n3: Nat<'a>) -> Self { Dim::XYZ(arena.alloc(Dim3d(n1, n2, n3))) } - pub fn new_2d Self>(arena: &'a Bump, constr: F, n1: Nat<'a>, n2: Nat<'a>) -> Self { + pub fn new_2d Self>( + arena: &'a Bump, + constr: F, + n1: Nat<'a>, + n2: Nat<'a>, + ) -> Self { constr(arena.alloc(Dim2d(n1, n2))) } - - pub fn new_1d Self>(arena: &'a Bump, constr: F, n: Nat<'a>) -> Self { + + pub fn new_1d Self>(arena: &'a Bump, constr: F, n: Nat<'a>) -> Self { constr(arena.alloc(Dim1d(n))) } @@ -1373,7 +1375,7 @@ impl<'a> DataTy<'a> { } } - pub fn non_copyable(&self) -> bool { + pub fn non_copyable(&'a self) -> bool { use DataTyKind::*; match &self.dty { @@ -1389,16 +1391,16 @@ impl<'a> DataTy<'a> { Range => true, Dead(_) => panic!( "This case is not expected to mean anything.\ - The type is dead. There is nothign we can do with it." + The type is dead. There is nothing we can do with it." ), } } - pub fn copyable(&self) -> bool { + pub fn copyable(&'a self) -> bool { !self.non_copyable() } - pub fn is_fully_alive(&self) -> bool { + pub fn is_fully_alive(&'a self) -> bool { use DataTyKind::*; match &self.dty { Scalar(_) @@ -1420,7 +1422,7 @@ impl<'a> DataTy<'a> { } } - pub fn occurs_in(&self, dty: &DataTy) -> bool { + pub fn occurs_in(&'a self, dty: &DataTy) -> bool { if self == dty { return true; } @@ -1450,7 +1452,7 @@ impl<'a> DataTy<'a> { } } - pub fn contains_ref_to_prv(&self, prv_val_name: &str) -> bool { + pub fn contains_ref_to_prv(&'a self, prv_val_name: &str) -> bool { use DataTyKind::*; match &self.dty { Scalar(_) | Atomic(_) | Ident(_) | Dead(_) => false, @@ -1476,7 +1478,7 @@ impl<'a> DataTy<'a> { } } - pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { + pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a Self) -> NatEvalResult<'a, bool> { match (&self.dty, &other.dty) { (DataTyKind::Ident(i), DataTyKind::Ident(o)) => Ok(i == o), (DataTyKind::Tuple(dtys), DataTyKind::Tuple(dtyos)) => { From a804ada6b0e91092a02ffebe3887a2e78ff628c6 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 10 Jun 2025 12:07:03 +0200 Subject: [PATCH 21/57] fixed vist_mut.rs --- src/ast/visit_mut.rs | 147 ++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 72 deletions(-) diff --git a/src/ast/visit_mut.rs b/src/ast/visit_mut.rs index cf35402d..46f9ddac 100644 --- a/src/ast/visit_mut.rs +++ b/src/ast/visit_mut.rs @@ -1,66 +1,66 @@ use crate::ast::*; #[rustfmt::skip] -pub trait VisitMut: Sized { +pub trait VisitMut<'a>: Sized { fn visit_binary_op_nat(&mut self, _op: &mut BinOpNat) {} - fn visit_nat(&mut self, n: &mut Nat) { walk_nat(self, n) } - fn visit_nat_range(&mut self, nr: &mut NatRange) { walk_nat_range(self, nr) } - fn visit_ident_kinded(&mut self, id_kind: &mut IdentKinded) { walk_ident_kinded(self, id_kind) } - fn visit_ident_exec(&mut self, id_exec: &mut IdentExec) { walk_ident_exec(self, id_exec) } - fn visit_prv_rel(&mut self, prv_rel: &mut PrvRel) { walk_prv_rel(self, prv_rel) } - fn visit_exec_ty(&mut self, _exec: &mut ExecTy) {} - fn visit_mem(&mut self, mem: &mut Memory) { walk_mem(self, mem) } - fn visit_prv(&mut self, prv: &mut Provenance) { walk_prv(self, prv) } + fn visit_nat(&mut self, n: &mut Nat<'a>) { walk_nat(self, n) } + fn visit_nat_range(&mut self, nr: &mut NatRange<'a>) { walk_nat_range(self, nr) } + fn visit_ident_kinded(&mut self, id_kind: &mut IdentKinded<'a>) { walk_ident_kinded(self, id_kind) } + fn visit_ident_exec(&mut self, id_exec: &mut IdentExec<'a>) { walk_ident_exec(self, id_exec) } + fn visit_prv_rel(&mut self, prv_rel: &mut PrvRel<'a>) { walk_prv_rel(self, prv_rel) } + fn visit_exec_ty(&mut self, _exec: &mut ExecTy<'a>) {} + fn visit_mem(&mut self, mem: &mut Memory<'a>) { walk_mem(self, mem) } + fn visit_prv(&mut self, prv: &mut Provenance<'a>) { walk_prv(self, prv) } fn visit_scalar_ty(&mut self, _sty: &mut ScalarTy) {} fn visit_atomic_ty(&mut self, _aty: &mut AtomicTy) {} fn visit_dim_compo(&mut self, _dim_compo: &mut DimCompo) {} - fn visit_dim(&mut self, dim: &mut Dim) { walk_dim(self, dim) } - fn visit_dim3d(&mut self, dim3d: &mut Dim3d) { walk_dim3d(self, dim3d) } - fn visit_dim2d(&mut self, dim2d: &mut Dim2d) { walk_dim2d(self, dim2d) } - fn visit_dim1d(&mut self, dim1d: &mut Dim1d) { walk_dim1d(self, dim1d) } - fn visit_ref(&mut self, reff: &mut RefDty) { walk_ref(self, reff) } - fn visit_dty(&mut self, dty: &mut DataTy) { walk_dty(self, dty) } - fn visit_fn_ty(&mut self, fn_ty: &mut FnTy) { walk_fn_ty(self, fn_ty) } - fn visit_nat_constr(&mut self, nat_constr: &mut NatConstr) { walk_nat_constr(self, nat_constr) } - fn visit_ty(&mut self, ty: &mut Ty) { walk_ty(self, ty) } - fn visit_view(&mut self, view: &mut View) { walk_view(self, view) } - fn visit_pl_expr(&mut self, pl_expr: &mut PlaceExpr) { walk_pl_expr(self, pl_expr) } - fn visit_arg_kinded(&mut self, arg_kinded: &mut ArgKinded) { walk_arg_kinded(self, arg_kinded) } + fn visit_dim(&mut self, dim: &mut Dim<'a>) { walk_dim(self, dim) } + fn visit_dim3d(&mut self, dim3d: &mut Dim3d<'a>) { walk_dim3d(self, dim3d) } + fn visit_dim2d(&mut self, dim2d: &mut Dim2d<'a>) { walk_dim2d(self, dim2d) } + fn visit_dim1d(&mut self, dim1d: &mut Dim1d<'a>) { walk_dim1d(self, dim1d) } + fn visit_ref(&mut self, reff: &mut RefDty<'a>) { walk_ref(self, reff) } + fn visit_dty(&mut self, dty: &mut DataTy<'a>) { walk_dty(self, dty) } + fn visit_fn_ty(&mut self, fn_ty: &mut FnTy<'a>) { walk_fn_ty(self, fn_ty) } + fn visit_nat_constr(&mut self, nat_constr: &mut NatConstr<'a>) { walk_nat_constr(self, nat_constr) } + fn visit_ty(&mut self, ty: &mut Ty<'a>) { walk_ty(self, ty) } + fn visit_view(&mut self, view: &mut View<'a>) { walk_view(self, view) } + fn visit_pl_expr(&mut self, pl_expr: &mut PlaceExpr<'a>) { walk_pl_expr(self, pl_expr) } + fn visit_arg_kinded(&mut self, arg_kinded: &mut ArgKinded<'a>) { walk_arg_kinded(self, arg_kinded) } fn visit_kind(&mut self, _kind: &mut Kind) {} fn visit_binary_op(&mut self, _op: &mut BinOp) {} fn visit_unary_op(&mut self, _op: &mut UnOp) {} fn visit_own(&mut self, _own: &mut Ownership) {} fn visit_mutability(&mut self, _mutbl: &mut Mutability) {} fn visit_lit(&mut self, _lit: &mut Lit) {} - fn visit_ident(&mut self, _ident: &mut Ident) {} - fn visit_pattern(&mut self, pattern: &mut Pattern) { walk_pattern(self, pattern) } - fn visit_split(&mut self, split: &mut Split) { walk_split(self, split) } - fn visit_sched(&mut self, sched: &mut Sched) { walk_sched(self, sched) } - fn visit_expr(&mut self, expr: &mut Expr) { walk_expr(self, expr) } - fn visit_app_kernel(&mut self, app_kernel: &mut AppKernel) { walk_app_kernel(self, app_kernel) } - fn visit_block(&mut self, block: &mut Block) { walk_block(self, block) } - fn visit_split_proj(&mut self, exec_split: &mut TakeRange) { walk_split_proj(self, exec_split) } - fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr) { walk_exec_expr(self, exec_expr) } - fn visit_exec(&mut self, exec: &mut ExecExprKind) { walk_exec(self, exec) } - fn visit_exec_path_elem(&mut self, exec_path_elem: &mut ExecPathElem) { walk_exec_path_elem(self, exec_path_elem) } - fn visit_param_decl(&mut self, param_decl: &mut ParamDecl) { walk_param_decl(self, param_decl) } - fn visit_fun_def(&mut self, fun_def: &mut FunDef) { walk_fun_def(self, fun_def) } - fn visit_fun_decl(&mut self, fun_decl: &mut FunDecl) { walk_fun_decl(self, fun_decl) } - fn visit_param_sig(&mut self, param_sig: &mut ParamSig) { walk_param_sig(self, param_sig) } - fn visit_field(&mut self, field: &mut (Ident, DataTy)) { walk_field(self, field) } + fn visit_ident(&mut self, _ident: &mut Ident<'a>) {} + fn visit_pattern(&mut self, pattern: &mut Pattern<'a>) { walk_pattern(self, pattern) } + fn visit_split(&mut self, split: &mut Split<'a>) { walk_split(self, split) } + fn visit_sched(&mut self, sched: &mut Sched<'a>) { walk_sched(self, sched) } + fn visit_expr(&mut self, expr: &mut Expr<'a>) { walk_expr(self, expr) } + fn visit_app_kernel(&mut self, app_kernel: &mut AppKernel<'a>) { walk_app_kernel(self, app_kernel) } + fn visit_block(&mut self, block: &mut Block<'a>) { walk_block(self, block) } + fn visit_split_proj(&mut self, exec_split: &mut TakeRange<'a>) { walk_split_proj(self, exec_split) } + fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr<'a>) { walk_exec_expr(self, exec_expr) } + fn visit_exec(&mut self, exec: &mut ExecExprKind<'a>) { walk_exec(self, exec) } + fn visit_exec_path_elem(&mut self, exec_path_elem: &mut ExecPathElem<'a>) { walk_exec_path_elem(self, exec_path_elem) } + fn visit_param_decl(&mut self, param_decl: &mut ParamDecl<'a>) { walk_param_decl(self, param_decl) } + fn visit_fun_def(&mut self, fun_def: &mut FunDef<'a>) { walk_fun_def(self, fun_def) } + fn visit_fun_decl(&mut self, fun_decl: &mut FunDecl<'a>) { walk_fun_decl(self, fun_decl) } + fn visit_param_sig(&mut self, param_sig: &mut ParamSig<'a>) { walk_param_sig(self, param_sig) } + fn visit_field(&mut self, field: &mut (Ident<'a>, DataTy<'a>)) { walk_field(self, field) } } // Taken from the Rust compiler macro_rules! walk_list { ($visitor: expr, $method: ident, $list: expr) => { - for elem in $list { + for elem in $list.iter_mut() { $visitor.$method(elem) } }; } pub(crate) use walk_list; -pub fn walk_nat(visitor: &mut V, n: &mut Nat) { +pub fn walk_nat<'a, V: VisitMut<'a>>(visitor: &mut V, n: &mut Nat<'a>) { match n { Nat::Ident(ident) => visitor.visit_ident(ident), Nat::BinOp(op, l, r) => { @@ -83,7 +83,7 @@ pub fn walk_nat(visitor: &mut V, n: &mut Nat) { } } -pub fn walk_nat_range(visitor: &mut V, nr: &mut NatRange) { +pub fn walk_nat_range<'a, V: VisitMut<'a>>(visitor: &mut V, nr: &mut NatRange<'a>) { match nr { NatRange::Simple { lower, upper } => { visitor.visit_nat(lower); @@ -93,56 +93,56 @@ pub fn walk_nat_range(visitor: &mut V, nr: &mut NatRange) { } } -pub fn walk_ident_kinded(visitor: &mut V, id_kind: &mut IdentKinded) { +pub fn walk_ident_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, id_kind: &mut IdentKinded<'a>) { let IdentKinded { ident, kind } = id_kind; visitor.visit_ident(ident); visitor.visit_kind(kind) } -pub fn walk_ident_exec(visitor: &mut V, id_exec: &mut IdentExec) { +pub fn walk_ident_exec<'a, V: VisitMut<'a>>(visitor: &mut V, id_exec: &mut IdentExec<'a>) { let IdentExec { ident, ty } = id_exec; visitor.visit_ident(ident); visitor.visit_exec_ty(ty) } -pub fn walk_prv_rel(visitor: &mut V, prv_rel: &mut PrvRel) { +pub fn walk_prv_rel<'a, V: VisitMut<'a>>(visitor: &mut V, prv_rel: &mut PrvRel<'a>) { let PrvRel { longer, shorter } = prv_rel; visitor.visit_ident(longer); visitor.visit_ident(shorter) } -pub fn walk_mem(visitor: &mut V, mem: &mut Memory) { +pub fn walk_mem<'a, V: VisitMut<'a>>(visitor: &mut V, mem: &mut Memory<'a>) { if let Memory::Ident(ident) = mem { visitor.visit_ident(ident) } } -pub fn walk_prv(visitor: &mut V, prv: &mut Provenance) { +pub fn walk_prv<'a, V: VisitMut<'a>>(visitor: &mut V, prv: &mut Provenance<'a>) { match prv { Provenance::Ident(ident) => visitor.visit_ident(ident), Provenance::Value(_) => {} } } -pub fn walk_dim3d(visitor: &mut V, dim3d: &mut Dim3d) { +pub fn walk_dim3d<'a, V: VisitMut<'a>>(visitor: &mut V, dim3d: &mut Dim3d<'a>) { let Dim3d(n1, n2, n3) = dim3d; visitor.visit_nat(n1); visitor.visit_nat(n2); visitor.visit_nat(n3); } -pub fn walk_dim2d(visitor: &mut V, dim2d: &mut Dim2d) { +pub fn walk_dim2d<'a, V: VisitMut<'a>>(visitor: &mut V, dim2d: &mut Dim2d<'a>) { let Dim2d(n1, n2) = dim2d; visitor.visit_nat(n1); visitor.visit_nat(n2); } -pub fn walk_dim1d(visitor: &mut V, dim1d: &mut Dim1d) { +pub fn walk_dim1d<'a, V: VisitMut<'a>>(visitor: &mut V, dim1d: &mut Dim1d<'a>) { let Dim1d(n) = dim1d; visitor.visit_nat(n); } -pub fn walk_dim(visitor: &mut V, dim: &mut Dim) { +pub fn walk_dim<'a, V: VisitMut<'a>>(visitor: &mut V, dim: &mut Dim<'a>) { match dim { Dim::XYZ(dim3d) => { visitor.visit_dim3d(dim3d); @@ -154,7 +154,7 @@ pub fn walk_dim(visitor: &mut V, dim: &mut Dim) { } } -pub fn walk_ref(visitor: &mut V, reff: &mut RefDty) { +pub fn walk_ref<'a, V: VisitMut<'a>>(visitor: &mut V, reff: &mut RefDty<'a>) { let RefDty { rgn, own, mem, dty } = reff; visitor.visit_prv(rgn); visitor.visit_own(own); @@ -162,7 +162,7 @@ pub fn walk_ref(visitor: &mut V, reff: &mut RefDty) { visitor.visit_dty(dty); } -pub fn walk_dty(visitor: &mut V, dty: &mut DataTy) { +pub fn walk_dty<'a, V: VisitMut<'a>>(visitor: &mut V, dty: &mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) => visitor.visit_ident(ident), DataTyKind::Scalar(sty) => visitor.visit_scalar_ty(sty), @@ -192,7 +192,7 @@ pub fn walk_dty(visitor: &mut V, dty: &mut DataTy) { } } -pub fn walk_fn_ty(visitor: &mut V, fn_ty: &mut FnTy) { +pub fn walk_fn_ty<'a, V: VisitMut<'a>>(visitor: &mut V, fn_ty: &mut FnTy<'a>) { let FnTy { generics, generic_exec, @@ -211,7 +211,7 @@ pub fn walk_fn_ty(visitor: &mut V, fn_ty: &mut FnTy) { walk_list!(visitor, visit_nat_constr, nat_constrs); } -pub fn walk_nat_constr(visitor: &mut V, nat_constr: &mut NatConstr) { +pub fn walk_nat_constr<'a, V: VisitMut<'a>>(visitor: &mut V, nat_constr: &mut NatConstr<'a>) { match nat_constr { NatConstr::True => {} NatConstr::Eq(l, r) => { @@ -233,7 +233,7 @@ pub fn walk_nat_constr(visitor: &mut V, nat_constr: &mut NatConstr) } } -pub fn walk_ty(visitor: &mut V, ty: &mut Ty) { +pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, ty: &mut Ty<'a>) { match &mut ty.ty { TyKind::Data(dty) => visitor.visit_dty(dty), TyKind::FnTy(fn_ty) => { @@ -242,7 +242,7 @@ pub fn walk_ty(visitor: &mut V, ty: &mut Ty) { } } -pub fn walk_view(visitor: &mut V, view: &mut View) { +pub fn walk_view<'a, V: VisitMut<'a>>(visitor: &mut V, view: &mut View<'a>) { visitor.visit_ident(&mut view.name); walk_list!(visitor, visit_arg_kinded, &mut view.gen_args); for v in &mut view.args { @@ -250,7 +250,7 @@ pub fn walk_view(visitor: &mut V, view: &mut View) { } } -pub fn walk_pl_expr(visitor: &mut V, pl_expr: &mut PlaceExpr) { +pub fn walk_pl_expr<'a, V: VisitMut<'a>>(visitor: &mut V, pl_expr: &mut PlaceExpr<'a>) { match &mut pl_expr.pl_expr { PlaceExprKind::Ident(ident) => visitor.visit_ident(ident), PlaceExprKind::Deref(pl_expr) => visitor.visit_pl_expr(pl_expr), @@ -276,7 +276,7 @@ pub fn walk_pl_expr(visitor: &mut V, pl_expr: &mut PlaceExpr) { } } -pub fn walk_arg_kinded(visitor: &mut V, arg_kinded: &mut ArgKinded) { +pub fn walk_arg_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, arg_kinded: &mut ArgKinded<'a>) { match arg_kinded { ArgKinded::Ident(ident) => visitor.visit_ident(ident), ArgKinded::Nat(n) => visitor.visit_nat(n), @@ -286,7 +286,7 @@ pub fn walk_arg_kinded(visitor: &mut V, arg_kinded: &mut ArgKinded) } } -pub fn walk_pattern(visitor: &mut V, pattern: &mut Pattern) { +pub fn walk_pattern<'a, V: VisitMut<'a>>(visitor: &mut V, pattern: &mut Pattern<'a>) { match pattern { Pattern::Ident(mutab, ident) => { visitor.visit_mutability(mutab); @@ -299,7 +299,7 @@ pub fn walk_pattern(visitor: &mut V, pattern: &mut Pattern) { } } -pub fn walk_split(visitor: &mut V, indep: &mut Split) { +pub fn walk_split<'a, V: VisitMut<'a>>(visitor: &mut V, indep: &mut Split<'a>) { let Split { dim_compo, pos, @@ -314,7 +314,7 @@ pub fn walk_split(visitor: &mut V, indep: &mut Split) { walk_list!(visitor, visit_expr, branch_bodies); } -pub fn walk_sched(visitor: &mut V, sched: &mut Sched) { +pub fn walk_sched<'a, V: VisitMut<'a>>(visitor: &mut V, sched: &mut Sched<'a>) { let Sched { dim, inner_exec_ident, @@ -329,7 +329,7 @@ pub fn walk_sched(visitor: &mut V, sched: &mut Sched) { visitor.visit_block(body); } -pub fn walk_expr(visitor: &mut V, expr: &mut Expr) { +pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, expr: &mut Expr<'a>) { // For now, only visit ExprKind match &mut expr.expr { ExprKind::Lit(l) => visitor.visit_lit(l), @@ -442,7 +442,7 @@ pub fn walk_expr(visitor: &mut V, expr: &mut Expr) { } } -pub fn walk_app_kernel(visitor: &mut V, app_kernel: &mut AppKernel) { +pub fn walk_app_kernel<'a, V: VisitMut<'a>>(visitor: &mut V, app_kernel: &mut AppKernel<'a>) { let AppKernel { grid_dim, block_dim, @@ -466,12 +466,12 @@ pub fn walk_app_kernel(visitor: &mut V, app_kernel: &mut AppKernel) } } -pub fn walk_block(visitor: &mut V, block: &mut Block) { +pub fn walk_block<'a, V: VisitMut<'a>>(visitor: &mut V, block: &mut Block<'a>) { let Block { body, .. } = block; visitor.visit_expr(body); } -pub fn walk_split_proj(visitor: &mut V, split_proj: &mut TakeRange) { +pub fn walk_split_proj<'a, V: VisitMut<'a>>(visitor: &mut V, split_proj: &mut TakeRange<'a>) { let TakeRange { split_dim, pos, @@ -481,14 +481,14 @@ pub fn walk_split_proj(visitor: &mut V, split_proj: &mut TakeRange) visitor.visit_nat(pos); } -pub fn walk_exec_expr(visitor: &mut V, exec_expr: &mut ExecExpr) { +pub fn walk_exec_expr<'a, V: VisitMut<'a>>(visitor: &mut V, exec_expr: &mut ExecExpr<'a>) { visitor.visit_exec(&mut exec_expr.exec); for t in &mut exec_expr.ty { visitor.visit_exec_ty(t); } } -pub fn walk_exec(visitor: &mut V, exec: &mut ExecExprKind) { +pub fn walk_exec<'a, V: VisitMut<'a>>(visitor: &mut V, exec: &mut ExecExprKind<'a>) { let ExecExprKind { base, path } = exec; match base { BaseExec::CpuThread => (), @@ -503,7 +503,10 @@ pub fn walk_exec(visitor: &mut V, exec: &mut ExecExprKind) { } } -pub fn walk_exec_path_elem(visitor: &mut V, exec_path_elem: &mut ExecPathElem) { +pub fn walk_exec_path_elem<'a, V: VisitMut<'a>>( + visitor: &mut V, + exec_path_elem: &mut ExecPathElem<'a>, +) { match exec_path_elem { ExecPathElem::TakeRange(split_proj) => visitor.visit_split_proj(split_proj), ExecPathElem::ForAll(dim_compo) => visitor.visit_dim_compo(dim_compo), @@ -512,7 +515,7 @@ pub fn walk_exec_path_elem(visitor: &mut V, exec_path_elem: &mut Ex } } -pub fn walk_param_decl(visitor: &mut V, param_decl: &mut ParamDecl) { +pub fn walk_param_decl<'a, V: VisitMut<'a>>(visitor: &mut V, param_decl: &mut ParamDecl<'a>) { let ParamDecl { ident, ty, @@ -529,7 +532,7 @@ pub fn walk_param_decl(visitor: &mut V, param_decl: &mut ParamDecl) } } -pub fn walk_fun_def(visitor: &mut V, fun_def: &mut FunDef) { +pub fn walk_fun_def<'a, V: VisitMut<'a>>(visitor: &mut V, fun_def: &mut FunDef<'a>) { let FunDef { ident: _, generic_params, @@ -551,7 +554,7 @@ pub fn walk_fun_def(visitor: &mut V, fun_def: &mut FunDef) { visitor.visit_block(body) } -pub fn walk_fun_decl(visitor: &mut V, fun_decl: &mut FunDecl) { +pub fn walk_fun_decl<'a, V: VisitMut<'a>>(visitor: &mut V, fun_decl: &mut FunDecl<'a>) { let FunDecl { ident: _, generic_params, @@ -571,13 +574,13 @@ pub fn walk_fun_decl(visitor: &mut V, fun_decl: &mut FunDecl) { walk_list!(visitor, visit_prv_rel, prv_rels); } -pub fn walk_param_sig(visitor: &mut V, param_sig: &mut ParamSig) { +pub fn walk_param_sig<'a, V: VisitMut<'a>>(visitor: &mut V, param_sig: &mut ParamSig<'a>) { let ParamSig { exec_expr, ty } = param_sig; visitor.visit_exec_expr(exec_expr); visitor.visit_ty(ty); } -pub fn walk_field(visitor: &mut V, field: &mut (Ident, DataTy)) { +pub fn walk_field<'a, V: VisitMut<'a>>(visitor: &mut V, field: &mut (Ident<'a>, DataTy<'a>)) { let (ident, dty) = field; visitor.visit_ident(ident); visitor.visit_dty(dty); From c8d28f754705496891e53ac622480db7c4fe42a2 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 10 Jun 2025 16:25:54 +0200 Subject: [PATCH 22/57] progress --- Cargo.toml | 2 +- src/ast/utils.rs | 146 +++++++++++++++++++++++++++----------------- src/ast/visit.rs | 140 +++++++++++++++++++++--------------------- src/parser/utils.rs | 12 ++-- 4 files changed, 166 insertions(+), 134 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 357fe30a..cbb69d56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ version = "0.8.0" [dependencies.bumpalo] version="3.17.0" -features=["collections"] +features=["collections", "boxed"] [dependencies.annotate-snippets] version = "0.9.0" diff --git a/src/ast/utils.rs b/src/ast/utils.rs index e7f84af2..7474c653 100644 --- a/src/ast/utils.rs +++ b/src/ast/utils.rs @@ -2,20 +2,20 @@ use crate::ast::visit::walk_list; use crate::ast::visit::Visit; use crate::ast::visit_mut::VisitMut; use crate::ast::{ - visit, visit_mut, ArgKinded, BaseExec, DataTy, DataTyKind, Dim, ExecExpr, ExecTy, Expr, - ExprKind, FnTy, FunDef, Ident, IdentExec, IdentKinded, Kind, Memory, Nat, ParamSig, Provenance, - Ty, TyKind, + visit, visit_mut, ArgKinded, BaseExec, DataTy, DataTyKind, Dim, ExecExpr, ExecExprKind, ExecTy, + Expr, ExprKind, FnTy, FunDef, Ident, IdentExec, IdentKinded, Kind, Memory, Nat, ParamSig, + Provenance, Ty, TyKind, }; use std::collections::{HashMap, HashSet}; use std::sync::atomic::{AtomicI32, Ordering}; static mut COUNTER: AtomicI32 = AtomicI32::new(0); -pub(crate) fn fresh_ident(name: &str, ident_constr: F) -> R +pub(crate) fn fresh_ident<'a, F, R>(arena: &'a bumpalo::Bump, name: &str, ident_constr: F) -> R where F: Fn(Ident) -> R, { - ident_constr(Ident::new_impli(&fresh_name(name))) + ident_constr(Ident::new_impli(&arena, &fresh_name(name))) } pub(crate) fn fresh_name(name: &str) -> String { @@ -27,10 +27,10 @@ pub(crate) fn fresh_name(name: &str) -> String { format!("{}_{}", prefix, i) } -pub fn implicit_idents(f: &FunDef) -> Option>> { - struct ImplicitIdents(HashSet>); - impl Visit for ImplicitIdents { - fn visit_ident(&mut self, ident: &Ident) { +pub fn implicit_idents<'a>(f: &FunDef<'a>) -> Option>> { + struct ImplicitIdents<'b>(HashSet>); + impl<'b> Visit<'b> for ImplicitIdents<'b> { + fn visit_ident(&mut self, ident: &Ident<'b>) { if ident.is_implicit { self.0.insert(ident.clone()); } @@ -46,13 +46,13 @@ pub fn implicit_idents(f: &FunDef) -> Option>> { } } -pub trait VisitableMut { - fn visit_mut(&mut self, visitor: &mut V); +pub trait VisitableMut<'a> { + fn visit_mut>(&mut self, visitor: &mut V); } macro_rules! visitable_mut { ($t:ident, $f:ident) => { - impl VisitableMut for $t { - fn visit_mut(&mut self, visitor: &mut V) { + impl<'a> VisitableMut<'a> for $t<'a> { + fn visit_mut>(&mut self, visitor: &mut V) { visitor.$f(self); } } @@ -71,10 +71,10 @@ visitable_mut!(FnTy, visit_fn_ty); * gen_args: the kinded expressions that are substituting the generic identifiers * t: the term to substitute in */ -pub fn subst_idents_kinded<'a, I, J, T: VisitableMut>(gen_idents: I, gen_args: J, t: &mut T) +pub fn subst_idents_kinded<'a, I, J, T: VisitableMut<'a>>(gen_idents: I, gen_args: J, t: &mut T) where - I: IntoIterator, - J: IntoIterator, + I: IntoIterator>, + J: IntoIterator>, { let subst_map = HashMap::from_iter( gen_idents @@ -82,15 +82,18 @@ where .map(|p| p.ident.name.as_ref()) .zip(gen_args), ); - let mut subst_idents_kinded = SubstIdentsKinded::new(&subst_map); + let mut subst_idents_kinded = SubstIdentsKinded::new(subst_map); t.visit_mut(&mut subst_idents_kinded); } -pub fn subst_ident_exec<'a, T: VisitableMut>(ident: &Ident, exec: &ExecExpr, t: &mut T) { +pub fn subst_ident_exec<'a, T: VisitableMut<'a>>( + ident: &'a Ident<'a>, + exec: &'a ExecExpr<'a>, + t: &mut T, +) { let mut subst_ident_exec = SubstIdentExec::new(ident, exec); t.visit_mut(&mut subst_ident_exec); } - /* * substitute kinded arguments for free identifiers * @@ -99,12 +102,12 @@ pub fn subst_ident_exec<'a, T: VisitableMut>(ident: &Ident, exec: &ExecExpr, t: * identifiers must be removed from the list, first. */ struct SubstIdentsKinded<'a> { - pub subst_map: &'a HashMap<&'a str, &'a ArgKinded>, - pub bound_idents: HashSet, + pub subst_map: &'a HashMap<&'a str, &'a ArgKinded<'a>>, + pub bound_idents: HashSet>, } impl<'a> SubstIdentsKinded<'a> { - fn new(subst_map: &'a HashMap<&'a str, &'a ArgKinded>) -> Self { + fn new(subst_map: &'a HashMap<&'a str, &'a ArgKinded<'a>>) -> Self { SubstIdentsKinded { subst_map, bound_idents: HashSet::new(), @@ -112,8 +115,8 @@ impl<'a> SubstIdentsKinded<'a> { } fn with_bound_idents( - subst_map: &'a HashMap<&'a str, &'a ArgKinded>, - bound_idents: HashSet, + subst_map: &'a HashMap<&'a str, &'a ArgKinded<'a>>, + bound_idents: HashSet>, ) -> Self { SubstIdentsKinded { subst_map, @@ -122,8 +125,8 @@ impl<'a> SubstIdentsKinded<'a> { } } -impl VisitMut for SubstIdentsKinded<'_> { - fn visit_nat(&mut self, nat: &mut Nat) { +impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { + fn visit_nat(&mut self, nat: &mut Nat<'a>) { match nat { Nat::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Nat); @@ -139,7 +142,7 @@ impl VisitMut for SubstIdentsKinded<'_> { } } - fn visit_mem(&mut self, mem: &mut Memory) { + fn visit_mem(&mut self, mem: &mut Memory<'a>) { match mem { Memory::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Memory); @@ -155,7 +158,7 @@ impl VisitMut for SubstIdentsKinded<'_> { } } - fn visit_prv(&mut self, prv: &mut Provenance) { + fn visit_prv(&mut self, prv: &mut Provenance<'a>) { match prv { Provenance::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Provenance); @@ -171,7 +174,7 @@ impl VisitMut for SubstIdentsKinded<'_> { } } - fn visit_dty(&mut self, dty: &mut DataTy) { + fn visit_dty(&mut self, dty: &mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::DataTy); @@ -188,7 +191,7 @@ impl VisitMut for SubstIdentsKinded<'_> { } // add generic paramters to list of bound identifiers - fn visit_fn_ty(&mut self, fn_ty: &mut FnTy) { + fn visit_fn_ty(&mut self, fn_ty: &mut FnTy<'a>) { let fun_bound_idents = fn_ty.generics.clone(); let mut all_bound_idents = self.bound_idents.clone(); all_bound_idents.extend(fun_bound_idents); @@ -207,7 +210,7 @@ impl VisitMut for SubstIdentsKinded<'_> { } // only required to introduce a new scope of bound identifiers - fn visit_expr(&mut self, expr: &mut Expr) { + fn visit_expr(&mut self, expr: &mut Expr<'a>) { match &mut expr.expr { ExprKind::ForNat(ident, collec, body) => { self.visit_nat_range(collec); @@ -222,7 +225,7 @@ impl VisitMut for SubstIdentsKinded<'_> { } // add generic paramters to list of bound identifiers - fn visit_fun_def(&mut self, fun_def: &mut FunDef) { + fn visit_fun_def(&mut self, fun_def: &mut FunDef<'a>) { let fun_bound_idents = fun_def.generic_params.clone(); let mut all_bound_idents = self.bound_idents.clone(); all_bound_idents.extend(fun_bound_idents); @@ -252,22 +255,23 @@ impl VisitMut for SubstIdentsKinded<'_> { * This substitution ignores whehter an execution identifier is bound by a function type. */ struct SubstIdentExec<'a> { - pub ident: &'a Ident, - pub exec: &'a ExecExpr, + pub ident: &'a Ident<'a>, + pub exec: &'a ExecExpr<'a>, } impl<'a> SubstIdentExec<'a> { - fn new(ident: &'a Ident, exec: &'a ExecExpr) -> Self { + fn new(ident: &'a Ident<'a>, exec: &'a ExecExpr<'a>) -> Self { SubstIdentExec { ident, exec } } } -impl VisitMut for SubstIdentExec<'_> { - fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr) { - insert_for_ident(self.exec, &self.ident, exec_expr) +impl<'a> VisitMut<'a> for SubstIdentExec<'a> { + fn visit_exec_expr(&mut self, bump: &'a bumpalo::Bump, exec_expr: &mut ExecExpr<'a>) { + insert_for_ident(bump, self.exec, &self.ident, exec_expr) } } -fn insert_for_ident(exec: &ExecExpr, ident: &Ident, in_exec: &mut ExecExpr) { +/** +fn insert_for_ident<'a>(exec: &ExecExpr<'a>, ident: &Ident<'a>, in_exec: &mut ExecExpr<'a>) { if let BaseExec::Ident(i) = &mut in_exec.exec.base { if i == ident { let mut subst_exec = exec.clone(); @@ -276,14 +280,42 @@ fn insert_for_ident(exec: &ExecExpr, ident: &Ident, in_exec: &mut ExecExpr) { } } } +*/ + +fn insert_for_ident<'a>( + bump: &'a bumpalo::Bump, + exec: &ExecExpr<'a>, + ident: &Ident<'a>, + in_exec: &mut ExecExpr<'a>, +) { + if let BaseExec::Ident(i) = &in_exec.exec.base { + if i == ident { + let mut merged_path = exec.exec.path.clone(); + merged_path.extend(in_exec.exec.path.iter().cloned()); + + let new_exec = bump.alloc(ExecExprKind { + base: exec.exec.base.clone(), + path: merged_path, + }); + + let new_exec_expr = ExecExpr { + exec: new_exec, + ty: in_exec.ty, + span: in_exec.span, + }; + + *in_exec = new_exec_expr; + } + } +} -pub trait Visitable { - fn visit(&self, visitor: &mut V); +pub trait Visitable<'a> { + fn visit>(&self, visitor: &mut V); } macro_rules! visitable { ($t:ident, $f:ident) => { - impl Visitable for $t { - fn visit(&self, visitor: &mut V) { + impl<'a> Visitable<'a> for $t<'a> { + fn visit>(&self, visitor: &mut V) { visitor.$f(self); } } @@ -301,18 +333,18 @@ visitable!(Dim, visit_dim); visitable!(Expr, visit_expr); visitable!(Nat, visit_nat); -pub fn free_kinded_idents(t: &T) -> HashSet { +pub fn free_kinded_idents<'a, T: Visitable<'a>>(t: &T) -> HashSet> { let mut free_kinded_idents = FreeKindedIdents::new(); t.visit(&mut free_kinded_idents); free_kinded_idents.set } -pub struct FreeKindedIdents { - pub set: HashSet, - pub bound_idents: HashSet, +pub struct FreeKindedIdents<'a> { + pub set: HashSet>, + pub bound_idents: HashSet>, } -impl FreeKindedIdents { +impl<'a> FreeKindedIdents<'a> { fn new() -> Self { FreeKindedIdents { set: HashSet::new(), @@ -320,7 +352,7 @@ impl FreeKindedIdents { } } - fn with_bound_idents(idents: HashSet) -> Self { + fn with_bound_idents(idents: HashSet>) -> Self { FreeKindedIdents { set: HashSet::new(), bound_idents: idents, @@ -328,8 +360,8 @@ impl FreeKindedIdents { } } -impl Visit for FreeKindedIdents { - fn visit_nat(&mut self, nat: &Nat) { +impl<'a> Visit<'a> for FreeKindedIdents<'a> { + fn visit_nat(&mut self, nat: &Nat<'a>) { match nat { Nat::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Nat); @@ -341,7 +373,7 @@ impl Visit for FreeKindedIdents { } } - fn visit_mem(&mut self, mem: &Memory) { + fn visit_mem(&mut self, mem: &Memory<'a>) { match mem { Memory::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Memory); @@ -353,7 +385,7 @@ impl Visit for FreeKindedIdents { } } - fn visit_prv(&mut self, prv: &Provenance) { + fn visit_prv(&mut self, prv: &Provenance<'a>) { match prv { Provenance::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Provenance); @@ -365,7 +397,7 @@ impl Visit for FreeKindedIdents { } } - fn visit_dty(&mut self, dty: &DataTy) { + fn visit_dty(&mut self, dty: &DataTy<'a>) { match &dty.dty { DataTyKind::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::DataTy); @@ -377,7 +409,7 @@ impl Visit for FreeKindedIdents { } } - fn visit_ty(&mut self, ty: &Ty) { + fn visit_ty(&mut self, ty: &Ty<'a>) { match &ty.ty { TyKind::FnTy(fn_ty) => { if !fn_ty.generics.is_empty() { @@ -388,13 +420,13 @@ impl Visit for FreeKindedIdents { } walk_list!(self, visit_param_sig, &fn_ty.param_sigs); - self.visit_ty(fn_ty.ret_ty.as_ref()) + self.visit_ty(fn_ty.ret_ty) } _ => visit::walk_ty(self, ty), } } - fn visit_expr(&mut self, expr: &Expr) { + fn visit_expr(&mut self, expr: &Expr<'a>) { match &expr.expr { ExprKind::ForNat(ident, collec, body) => { self.visit_nat_range(collec); diff --git a/src/ast/visit.rs b/src/ast/visit.rs index e14556a7..5f47ab59 100644 --- a/src/ast/visit.rs +++ b/src/ast/visit.rs @@ -1,64 +1,64 @@ use crate::ast::*; #[rustfmt::skip] -pub trait Visit: Sized { +pub trait Visit<'a>: Sized { fn visit_binary_op_nat(&mut self, _op: &BinOpNat) {} - fn visit_nat(&mut self, n: &Nat) { walk_nat(self, n) } - fn visit_nat_range(&mut self, nr: &NatRange) { walk_nat_range(self, nr) } - fn visit_ident_kinded(&mut self, id_kind: &IdentKinded) { walk_ident_kinded(self, id_kind) } - fn visit_ident_exec(&mut self, ident_exec: &IdentExec) { walk_ident_exec(self, ident_exec) } - fn visit_prv_rel(&mut self, prv_rel: &PrvRel) { walk_prv_rel(self, prv_rel) } - fn visit_exec_ty(&mut self, _exec: &ExecTy) {} - fn visit_mem(&mut self, mem: &Memory) { walk_mem(self, mem) } - fn visit_prv(&mut self, prv: &Provenance) { walk_prv(self, prv) } + fn visit_nat(&mut self, n: &Nat<'a>) { walk_nat(self, n) } + fn visit_nat_range(&mut self, nr: &NatRange<'a>) { walk_nat_range(self, nr) } + fn visit_ident_kinded(&mut self, id_kind: &IdentKinded<'a>) { walk_ident_kinded(self, id_kind) } + fn visit_ident_exec(&mut self, ident_exec: &IdentExec<'a>) { walk_ident_exec(self, ident_exec) } + fn visit_prv_rel(&mut self, prv_rel: &PrvRel<'a>) { walk_prv_rel(self, prv_rel) } + fn visit_exec_ty(&mut self, _exec: &ExecTy<'a>) {} + fn visit_mem(&mut self, mem: &Memory<'a>) { walk_mem(self, mem) } + fn visit_prv(&mut self, prv: &Provenance<'a>) { walk_prv(self, prv) } fn visit_scalar_ty(&mut self, _sty: &ScalarTy) {} fn visit_atomic_ty(&mut self, _aty: &AtomicTy) {} fn visit_dim_compo(&mut self, _dim_compo: &DimCompo) { } - fn visit_dim(&mut self, dim: &Dim) { walk_dim(self, dim) } - fn visit_dim3d(&mut self, dim3d: &Dim3d) { walk_dim3d(self, dim3d) } - fn visit_dim2d(&mut self, dim2d: &Dim2d) { walk_dim2d(self, dim2d) } - fn visit_dim1d(&mut self, dim1d: &Dim1d) { walk_dim1d(self, dim1d) } - fn visit_ref(&mut self, reff: &RefDty) { walk_ref(self, reff) } - fn visit_dty(&mut self, dty: &DataTy) { walk_dty(self, dty) } - fn visit_fn_ty(&mut self, fn_ty: &FnTy) { walk_fn_ty(self, fn_ty) } - fn visit_nat_constr(&mut self, nat_constr: &NatConstr) { walk_nat_constr(self, nat_constr) } - fn visit_ty(&mut self, ty: &Ty) { walk_ty(self, ty) } - fn visit_view(&mut self, view: &View) { walk_view(self, view) } - fn visit_pl_expr(&mut self, pl_expr: &PlaceExpr) { walk_pl_expr(self, pl_expr) } - fn visit_arg_kinded(&mut self, arg_kinded: &ArgKinded) { walk_arg_kinded(self, arg_kinded) } + fn visit_dim(&mut self, dim: &Dim<'a>) { walk_dim(self, dim) } + fn visit_dim3d(&mut self, dim3d: &Dim3d<'a>) { walk_dim3d(self, dim3d) } + fn visit_dim2d(&mut self, dim2d: &Dim2d<'a>) { walk_dim2d(self, dim2d) } + fn visit_dim1d(&mut self, dim1d: &Dim1d<'a>) { walk_dim1d(self, dim1d) } + fn visit_ref(&mut self, reff: &RefDty<'a>) { walk_ref(self, reff) } + fn visit_dty(&mut self, dty: &DataTy<'a>) { walk_dty(self, dty) } + fn visit_fn_ty(&mut self, fn_ty: &FnTy<'a>) { walk_fn_ty(self, fn_ty) } + fn visit_nat_constr(&mut self, nat_constr: &NatConstr<'a>) { walk_nat_constr(self, nat_constr) } + fn visit_ty(&mut self, ty: &Ty<'a>) { walk_ty(self, ty) } + fn visit_view(&mut self, view: &View<'a>) { walk_view(self, view) } + fn visit_pl_expr(&mut self, pl_expr: &PlaceExpr<'a>) { walk_pl_expr(self, pl_expr) } + fn visit_arg_kinded(&mut self, arg_kinded: &ArgKinded<'a>) { walk_arg_kinded(self, arg_kinded) } fn visit_kind(&mut self, _kind: &Kind) {} fn visit_binary_op(&mut self, _op: &BinOp) {} fn visit_unary_op(&mut self, _op: &UnOp) {} fn visit_own(&mut self, _own: &Ownership) {} fn visit_mutability(&mut self, _mutbl: &Mutability) {} fn visit_lit(&mut self, _lit: &Lit) {} - fn visit_ident(&mut self, _ident: &Ident) {} - fn visit_pattern(&mut self, pattern: &Pattern) { walk_pattern(self, pattern) } - fn visit_split(&mut self, split: &Split) { walk_split(self, split) } - fn visit_sched(&mut self, par_for: &Sched) { walk_sched(self, par_for) } - fn visit_expr(&mut self, expr: &Expr) { walk_expr(self, expr) } - fn visit_app_kernel(&mut self, app_kernel: &AppKernel) { walk_app_kernel(self, app_kernel) } - fn visit_block(&mut self, block: &Block) { walk_block(self, block) } - fn visit_split_proj(&mut self, exec_split: &TakeRange) { walk_split_proj(self, exec_split) } - fn visit_exec_expr(&mut self, exec_expr: &ExecExpr) { walk_exec_expr(self, exec_expr) } - fn visit_exec(&mut self, exec: &ExecExprKind) { walk_exec(self, exec) } - fn visit_param_decl(&mut self, param_decl: &ParamDecl) { walk_param_decl(self, param_decl) } - fn visit_fun_def(&mut self, fun_def: &FunDef) { walk_fun_def(self, fun_def) } - fn visit_fun_decl(&mut self, fun_decl: &FunDecl) { walk_fun_decl(self, fun_decl) } - fn visit_param_sig(&mut self, param_sig: &ParamSig) { walk_param_sig(self, param_sig) } - fn visit_field(&mut self, field: &(Ident, DataTy)) { walk_field(self, field) } + fn visit_ident(&mut self, _ident: &Ident<'a>) {} + fn visit_pattern(&mut self, pattern: &Pattern<'a>) { walk_pattern(self, pattern) } + fn visit_split(&mut self, split: &Split<'a>) { walk_split(self, split) } + fn visit_sched(&mut self, par_for: &Sched<'a>) { walk_sched(self, par_for) } + fn visit_expr(&mut self, expr: &Expr<'a>) { walk_expr(self, expr) } + fn visit_app_kernel(&mut self, app_kernel: &AppKernel<'a>) { walk_app_kernel(self, app_kernel) } + fn visit_block(&mut self, block: &Block<'a>) { walk_block(self, block) } + fn visit_split_proj(&mut self, exec_split: &TakeRange<'a>) { walk_split_proj(self, exec_split) } + fn visit_exec_expr(&mut self, exec_expr: &ExecExpr<'a>) { walk_exec_expr(self, exec_expr) } + fn visit_exec(&mut self, exec: &ExecExprKind<'a>) { walk_exec(self, exec) } + fn visit_param_decl(&mut self, param_decl: &ParamDecl<'a>) { walk_param_decl(self, param_decl) } + fn visit_fun_def(&mut self, fun_def: &FunDef<'a>) { walk_fun_def(self, fun_def) } + fn visit_fun_decl(&mut self, fun_decl: &FunDecl<'a>) { walk_fun_decl(self, fun_decl) } + fn visit_param_sig(&mut self, param_sig: &ParamSig<'a>) { walk_param_sig(self, param_sig) } + fn visit_field(&mut self, field: &(Ident<'a>, DataTy<'a>)) { walk_field(self, field) } } macro_rules! walk_list { ($visitor: expr, $method: ident, $list: expr) => { - for elem in $list { + for elem in $list.iter_mut() { $visitor.$method(elem) } }; } pub(crate) use walk_list; -pub fn walk_nat(visitor: &mut V, n: &Nat) { +pub fn walk_nat<'a, V: Visit<'a>>(visitor: &mut V, n: &Nat<'a>) { match n { Nat::Ident(ident) => visitor.visit_ident(ident), Nat::BinOp(op, l, r) => { @@ -81,7 +81,7 @@ pub fn walk_nat(visitor: &mut V, n: &Nat) { } } -pub fn walk_nat_range(visitor: &mut V, nr: &NatRange) { +pub fn walk_nat_range<'a, V: Visit<'a>>(visitor: &mut V, nr: &NatRange<'a>) { match nr { NatRange::Simple { lower, upper } => { visitor.visit_nat(lower); @@ -91,56 +91,56 @@ pub fn walk_nat_range(visitor: &mut V, nr: &NatRange) { } } -pub fn walk_ident_kinded(visitor: &mut V, id_kind: &IdentKinded) { +pub fn walk_ident_kinded<'a, V: Visit<'a>>(visitor: &mut V, id_kind: &IdentKinded<'a>) { let IdentKinded { ident, kind } = id_kind; visitor.visit_ident(ident); visitor.visit_kind(kind) } -pub fn walk_ident_exec(visitor: &mut V, id_exec: &IdentExec) { +pub fn walk_ident_exec<'a, V: Visit<'a>>(visitor: &mut V, id_exec: &IdentExec<'a>) { let IdentExec { ident, ty } = id_exec; visitor.visit_ident(ident); visitor.visit_exec_ty(ty) } -pub fn walk_prv_rel(visitor: &mut V, prv_rel: &PrvRel) { +pub fn walk_prv_rel<'a, V: Visit<'a>>(visitor: &mut V, prv_rel: &PrvRel<'a>) { let PrvRel { longer, shorter } = prv_rel; visitor.visit_ident(longer); visitor.visit_ident(shorter) } -pub fn walk_mem(visitor: &mut V, mem: &Memory) { +pub fn walk_mem<'a, V: Visit<'a>>(visitor: &mut V, mem: &Memory<'a>) { if let Memory::Ident(ident) = mem { visitor.visit_ident(ident) } } -pub fn walk_prv(visitor: &mut V, prv: &Provenance) { +pub fn walk_prv<'a, V: Visit<'a>>(visitor: &mut V, prv: &Provenance<'a>) { match prv { Provenance::Ident(ident) => visitor.visit_ident(ident), Provenance::Value(_) => {} } } -pub fn walk_dim3d(visitor: &mut V, dim3d: &Dim3d) { +pub fn walk_dim3d<'a, V: Visit<'a>>(visitor: &mut V, dim3d: &Dim3d<'a>) { let Dim3d(n1, n2, n3) = dim3d; visitor.visit_nat(n1); visitor.visit_nat(n2); visitor.visit_nat(n3); } -pub fn walk_dim2d(visitor: &mut V, dim2d: &Dim2d) { +pub fn walk_dim2d<'a, V: Visit<'a>>(visitor: &mut V, dim2d: &Dim2d<'a>) { let Dim2d(n1, n2) = dim2d; visitor.visit_nat(n1); visitor.visit_nat(n2); } -pub fn walk_dim1d(visitor: &mut V, dim1d: &Dim1d) { +pub fn walk_dim1d<'a, V: Visit<'a>>(visitor: &mut V, dim1d: &Dim1d<'a>) { let Dim1d(n) = dim1d; visitor.visit_nat(n); } -pub fn walk_dim(visitor: &mut V, dim: &Dim) { +pub fn walk_dim<'a, V: Visit<'a>>(visitor: &mut V, dim: &Dim<'a>) { match dim { Dim::XYZ(dim3d) => { visitor.visit_dim3d(dim3d); @@ -152,7 +152,7 @@ pub fn walk_dim(visitor: &mut V, dim: &Dim) { } } -pub fn walk_ref(visitor: &mut V, reff: &RefDty) { +pub fn walk_ref<'a, V: Visit<'a>>(visitor: &mut V, reff: &RefDty<'a>) { let RefDty { rgn, own, mem, dty } = reff; visitor.visit_prv(rgn); visitor.visit_own(own); @@ -160,7 +160,7 @@ pub fn walk_ref(visitor: &mut V, reff: &RefDty) { visitor.visit_dty(dty); } -pub fn walk_dty(visitor: &mut V, dty: &DataTy) { +pub fn walk_dty<'a, V: Visit<'a>>(visitor: &mut V, dty: &DataTy<'a>) { match &dty.dty { DataTyKind::Ident(ident) => visitor.visit_ident(ident), DataTyKind::Scalar(sty) => visitor.visit_scalar_ty(sty), @@ -190,7 +190,7 @@ pub fn walk_dty(visitor: &mut V, dty: &DataTy) { } } -pub fn walk_fn_ty(visitor: &mut V, fn_ty: &FnTy) { +pub fn walk_fn_ty<'a, V: Visit<'a>>(visitor: &mut V, fn_ty: &FnTy<'a>) { let FnTy { generics, generic_exec, @@ -209,7 +209,7 @@ pub fn walk_fn_ty(visitor: &mut V, fn_ty: &FnTy) { walk_list!(visitor, visit_nat_constr, nat_constrs); } -pub fn walk_nat_constr(visitor: &mut V, nat_constr: &NatConstr) { +pub fn walk_nat_constr<'a, V: Visit<'a>>(visitor: &mut V, nat_constr: &NatConstr<'a>) { match nat_constr { NatConstr::True => {} NatConstr::Eq(l, r) => { @@ -231,7 +231,7 @@ pub fn walk_nat_constr(visitor: &mut V, nat_constr: &NatConstr) { } } -pub fn walk_ty(visitor: &mut V, ty: &Ty) { +pub fn walk_ty<'a, V: Visit<'a>>(visitor: &mut V, ty: &Ty<'a>) { match &ty.ty { TyKind::Data(dty) => visitor.visit_dty(dty), TyKind::FnTy(fn_ty) => { @@ -240,7 +240,7 @@ pub fn walk_ty(visitor: &mut V, ty: &Ty) { } } -pub fn walk_view(visitor: &mut V, view: &View) { +pub fn walk_view<'a, V: Visit<'a>>(visitor: &mut V, view: &View<'a>) { visitor.visit_ident(&view.name); walk_list!(visitor, visit_arg_kinded, &view.gen_args); for v in &view.args { @@ -248,7 +248,7 @@ pub fn walk_view(visitor: &mut V, view: &View) { } } -pub fn walk_pl_expr(visitor: &mut V, pl_expr: &PlaceExpr) { +pub fn walk_pl_expr<'a, V: Visit<'a>>(visitor: &mut V, pl_expr: &PlaceExpr<'a>) { match &pl_expr.pl_expr { PlaceExprKind::Ident(ident) => visitor.visit_ident(ident), PlaceExprKind::Deref(pl_expr) => visitor.visit_pl_expr(pl_expr), @@ -274,7 +274,7 @@ pub fn walk_pl_expr(visitor: &mut V, pl_expr: &PlaceExpr) { } } -pub fn walk_arg_kinded(visitor: &mut V, arg_kinded: &ArgKinded) { +pub fn walk_arg_kinded<'a, V: Visit<'a>>(visitor: &mut V, arg_kinded: &ArgKinded<'a>) { match arg_kinded { ArgKinded::Ident(ident) => visitor.visit_ident(ident), ArgKinded::Nat(n) => visitor.visit_nat(n), @@ -284,7 +284,7 @@ pub fn walk_arg_kinded(visitor: &mut V, arg_kinded: &ArgKinded) { } } -pub fn walk_pattern(visitor: &mut V, pattern: &Pattern) { +pub fn walk_pattern<'a, V: Visit<'a>>(visitor: &mut V, pattern: &Pattern<'a>) { match pattern { Pattern::Ident(mutab, ident) => { visitor.visit_mutability(mutab); @@ -297,7 +297,7 @@ pub fn walk_pattern(visitor: &mut V, pattern: &Pattern) { } } -pub fn walk_split(visitor: &mut V, indep: &Split) { +pub fn walk_split<'a, V: Visit<'a>>(visitor: &mut V, indep: &Split<'a>) { let Split { dim_compo, pos, @@ -312,7 +312,7 @@ pub fn walk_split(visitor: &mut V, indep: &Split) { walk_list!(visitor, visit_expr, branch_bodies); } -pub fn walk_sched(visitor: &mut V, sched: &Sched) { +pub fn walk_sched<'a, V: Visit<'a>>(visitor: &mut V, sched: &Sched<'a>) { let Sched { dim, inner_exec_ident, @@ -327,7 +327,7 @@ pub fn walk_sched(visitor: &mut V, sched: &Sched) { visitor.visit_block(body); } -pub fn walk_expr(visitor: &mut V, expr: &Expr) { +pub fn walk_expr<'a, V: Visit<'a>>(visitor: &mut V, expr: &Expr<'a>) { // For now, only visit ExprKind match &expr.expr { ExprKind::Lit(l) => visitor.visit_lit(l), @@ -442,7 +442,7 @@ pub fn walk_expr(visitor: &mut V, expr: &Expr) { } } -pub fn walk_app_kernel(visitor: &mut V, app_kernel: &AppKernel) { +pub fn walk_app_kernel<'a, V: Visit<'a>>(visitor: &mut V, app_kernel: &AppKernel<'a>) { let AppKernel { grid_dim, block_dim, @@ -466,12 +466,12 @@ pub fn walk_app_kernel(visitor: &mut V, app_kernel: &AppKernel) { } } -pub fn walk_block(visitor: &mut V, block: &Block) { +pub fn walk_block<'a, V: Visit<'a>>(visitor: &mut V, block: &Block<'a>) { let Block { body, .. } = block; visitor.visit_expr(body); } -pub fn walk_split_proj(visitor: &mut V, split_proj: &TakeRange) { +pub fn walk_split_proj<'a, V: Visit<'a>>(visitor: &mut V, split_proj: &TakeRange<'a>) { let TakeRange { split_dim, pos, @@ -481,14 +481,14 @@ pub fn walk_split_proj(visitor: &mut V, split_proj: &TakeRange) { visitor.visit_nat(pos); } -pub fn walk_exec_expr(visitor: &mut V, exec_expr: &ExecExpr) { +pub fn walk_exec_expr<'a, V: Visit<'a>>(visitor: &mut V, exec_expr: &ExecExpr<'a>) { visitor.visit_exec(&exec_expr.exec); for t in &exec_expr.ty { visitor.visit_exec_ty(t); } } -pub fn walk_exec(visitor: &mut V, exec: &ExecExprKind) { +pub fn walk_exec<'a, V: Visit<'a>>(visitor: &mut V, exec: &ExecExprKind<'a>) { let ExecExprKind { base, path } = exec; match base { BaseExec::CpuThread => (), @@ -508,7 +508,7 @@ pub fn walk_exec(visitor: &mut V, exec: &ExecExprKind) { } } -pub fn walk_param_decl(visitor: &mut V, param_decl: &ParamDecl) { +pub fn walk_param_decl<'a, V: Visit<'a>>(visitor: &mut V, param_decl: &ParamDecl<'a>) { let ParamDecl { ident, ty, @@ -525,7 +525,7 @@ pub fn walk_param_decl(visitor: &mut V, param_decl: &ParamDecl) { } } -pub fn walk_fun_def(visitor: &mut V, fun_def: &FunDef) { +pub fn walk_fun_def<'a, V: Visit<'a>>(visitor: &mut V, fun_def: &FunDef<'a>) { let FunDef { ident: _, generic_params, @@ -547,7 +547,7 @@ pub fn walk_fun_def(visitor: &mut V, fun_def: &FunDef) { visitor.visit_block(body) } -pub fn walk_fun_decl(visitor: &mut V, fun_decl: &FunDecl) { +pub fn walk_fun_decl<'a, V: Visit<'a>>(visitor: &mut V, fun_decl: &FunDecl<'a>) { let FunDecl { ident: _, generic_params, @@ -567,13 +567,13 @@ pub fn walk_fun_decl(visitor: &mut V, fun_decl: &FunDecl) { walk_list!(visitor, visit_prv_rel, prv_rels); } -pub fn walk_param_sig(visitor: &mut V, param_sig: &ParamSig) { +pub fn walk_param_sig<'a, V: Visit<'a>>(visitor: &mut V, param_sig: &ParamSig<'a>) { let ParamSig { exec_expr, ty } = param_sig; visitor.visit_exec_expr(exec_expr); visitor.visit_ty(ty); } -pub fn walk_field(visitor: &mut V, field: &(Ident, DataTy)) { +pub fn walk_field<'a, V: Visit<'a>>(visitor: &mut V, field: &(Ident<'a>, DataTy<'a>)) { let (ident, dty) = field; visitor.visit_ident(ident); visitor.visit_dty(dty); diff --git a/src/parser/utils.rs b/src/parser/utils.rs index b0f194c9..7e1f311e 100644 --- a/src/parser/utils.rs +++ b/src/parser/utils.rs @@ -1,6 +1,6 @@ //! Helper functions for parsing - use crate::ast::{BinOp, BinOpNat, DataTy, DataTyKind, Expr, ExprKind, Lit, Nat, ScalarTy, UnOp}; +use bumpalo::{boxed::Box as BumpBox, Bump}; pub fn type_from_lit(lit: &Lit) -> DataTy { DataTy::new(DataTyKind::Scalar(match lit { @@ -15,7 +15,7 @@ pub fn type_from_lit(lit: &Lit) -> DataTy { })) } -pub fn make_binary(op: BinOp, lhs: Expr, rhs: Expr) -> Expr { +pub fn make_binary<'a>(bump: &'a Bump, op: BinOp, lhs: Expr<'a>, rhs: Expr<'a>) -> Expr<'a> { // TODO make operators functions? How do we deal with execution resources? // Expr::new(ExprKind::App( // Box::new(Expr::new(ExprKind::PlaceExpr(PlaceExpr::new( @@ -25,17 +25,17 @@ pub fn make_binary(op: BinOp, lhs: Expr, rhs: Expr) -> Expr { // vec![lhs, rhs], // )) Expr { - expr: ExprKind::BinOp(op, Box::new(lhs), Box::new(rhs)), + expr: ExprKind::BinOp(op, BumpBox::new_in(lhs, bump), BumpBox::new_in(rhs, bump)), ty: None, span: None, } } -pub fn make_binary_nat(op: BinOpNat, lhs: Nat, rhs: Nat) -> Nat { +pub fn make_binary_nat<'a>(op: BinOpNat, lhs: Nat<'a>, rhs: Nat<'a>) -> Nat<'a> { Nat::BinOp(op, Box::new(lhs), Box::new(rhs)) } -pub fn make_unary(op: UnOp, rhs: Expr) -> Expr { +pub fn make_unary<'a>(bump: &'a Bump, op: UnOp, rhs: Expr<'a>) -> Expr<'a> { // TODO see above // Expr::new(ExprKind::App( // Box::new(Expr::new(ExprKind::PlaceExpr(PlaceExpr::new( @@ -45,7 +45,7 @@ pub fn make_unary(op: UnOp, rhs: Expr) -> Expr { // vec![rhs], // )) Expr { - expr: ExprKind::UnOp(op, Box::new(rhs)), + expr: ExprKind::UnOp(op, BumpBox::new_in(rhs, bump)), ty: None, span: None, } From 1600e8aacc95e247b786eb0eff3c8854e94838e6 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 11 Jun 2025 16:20:13 +0200 Subject: [PATCH 23/57] refined Hash Ownership in utils --- src/ast/utils.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ast/utils.rs b/src/ast/utils.rs index 7474c653..9ad2d457 100644 --- a/src/ast/utils.rs +++ b/src/ast/utils.rs @@ -102,12 +102,12 @@ pub fn subst_ident_exec<'a, T: VisitableMut<'a>>( * identifiers must be removed from the list, first. */ struct SubstIdentsKinded<'a> { - pub subst_map: &'a HashMap<&'a str, &'a ArgKinded<'a>>, + pub subst_map: HashMap<&'a str, &'a ArgKinded<'a>>, pub bound_idents: HashSet>, } impl<'a> SubstIdentsKinded<'a> { - fn new(subst_map: &'a HashMap<&'a str, &'a ArgKinded<'a>>) -> Self { + fn new(subst_map: HashMap<&'a str, &'a ArgKinded<'a>>) -> Self { SubstIdentsKinded { subst_map, bound_idents: HashSet::new(), @@ -115,7 +115,7 @@ impl<'a> SubstIdentsKinded<'a> { } fn with_bound_idents( - subst_map: &'a HashMap<&'a str, &'a ArgKinded<'a>>, + subst_map: HashMap<&'a str, &'a ArgKinded<'a>>, bound_idents: HashSet>, ) -> Self { SubstIdentsKinded { From ac91827a8b6d0da1a27fde97d67590682f22cc37 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 11 Jun 2025 16:30:11 +0200 Subject: [PATCH 24/57] correct profile file uploaded --- profile.json | 1 - profile.json.gz | Bin 0 -> 29595 bytes 2 files changed, 1 deletion(-) delete mode 100644 profile.json create mode 100644 profile.json.gz diff --git a/profile.json b/profile.json deleted file mode 100644 index 983c9824..00000000 --- a/profile.json +++ /dev/null @@ -1 +0,0 @@ -{"meta":{"categories":[{"name":"Other","color":"grey","subcategories":["Other"]},{"name":"JIT app cache","color":"green","subcategories":["Other"]},{"name":"User","color":"yellow","subcategories":["Other"]},{"name":"Kernel","color":"orange","subcategories":["Other"]}],"debug":false,"extensions":{"baseURL":[],"id":[],"length":0,"name":[]},"interval":1.0,"preprocessedProfileVersion":55,"processType":0,"product":"descend","oscpu":"Ubuntu 20.04.6 LTS","sampleUnits":{"eventDelay":"ms","threadCPUDelta":"µs","time":"ms"},"startTime":1746530540509.1873,"symbolicated":false,"pausedRanges":[],"version":24,"usesOnlyOneStackType":true,"sourceCodeIsNotOnSearchfox":true,"markerSchema":[{"name":"mmap","display":["marker-chart","marker-table"],"fields":[{"key":"name","label":"Details","format":"unique-string","searchable":true}]}]},"libs":[{"name":"ld-2.31.so","path":"/usr/lib/x86_64-linux-gnu/ld-2.31.so","debugName":"ld-2.31.so","debugPath":"/usr/lib/x86_64-linux-gnu/ld-2.31.so","breakpadId":"674590CBB2E160A4B6FC20817776AD590","codeId":"cb904567e1b2a460b6fc20817776ad590d265686","arch":null},{"name":"libLLVM-10.so.1","path":"/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1","debugName":"libLLVM-10.so.1","debugPath":"/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1","breakpadId":"622F33C0FCBE7FD43E14942B0D1A046E0","codeId":"c0332f62befcd47f3e14942b0d1a046e204b9659","arch":null},{"name":"libclang-cpp.so.10","path":"/usr/lib/llvm-10/lib/libclang-cpp.so.10","debugName":"libclang-cpp.so.10","debugPath":"/usr/lib/llvm-10/lib/libclang-cpp.so.10","breakpadId":"9ED8032B401835C949890C1BEDE6D54C0","codeId":"2b03d89e1840c93549890c1bede6d54c8ea1ac9a","arch":null},{"name":"clang-format","path":"/usr/lib/llvm-10/bin/clang-format","debugName":"clang-format","debugPath":"/usr/lib/llvm-10/bin/clang-format","breakpadId":"122CEB0CB6A67554027E02B1169552930","codeId":"0ceb2c12a6b65475027e02b116955293a19ffd16","arch":null},{"name":"libc-2.31.so","path":"/usr/lib/x86_64-linux-gnu/libc-2.31.so","debugName":"libc-2.31.so","debugPath":"/usr/lib/x86_64-linux-gnu/libc-2.31.so","breakpadId":"48AB2303BE06F8E646D9AD4BCCFC29AF0","codeId":"0323ab4806bee6f846d9ad4bccfc29afdca49a58","arch":null},{"name":"descend","path":"/home/dominic/descend/target/release/descend","debugName":"descend","debugPath":"/home/dominic/descend/target/release/descend","breakpadId":"57CF708544F3088F8E9BEFD82437E7E20","codeId":"8570cf57f3448f088e9befd82437e7e28de71895","arch":null},{"name":"libpthread-2.31.so","path":"/usr/lib/x86_64-linux-gnu/libpthread-2.31.so","debugName":"libpthread-2.31.so","debugPath":"/usr/lib/x86_64-linux-gnu/libpthread-2.31.so","breakpadId":"6D89FB5C0FD4AA908C6C8BB856004D1F0","codeId":"5cfb896dd40f90aa8c6c8bb856004d1f5cfe293c","arch":null}],"threads":[{"frameTable":{"length":0,"address":[],"inlineDepth":[],"category":[],"subcategory":[],"func":[],"nativeSymbol":[],"innerWindowID":[],"line":[],"column":[]},"funcTable":{"length":0,"name":[],"isJS":[],"relevantForJS":[],"resource":[],"fileName":[],"lineNumber":[],"columnNumber":[]},"markers":{"length":0,"category":[],"data":[],"endTime":[],"name":[],"phase":[],"startTime":[]},"name":"samply","isMainThread":true,"nativeSymbols":{"length":0,"address":[],"functionSize":[],"libIndex":[],"name":[]},"pausedRanges":[],"pid":"54509","processName":"samply","processShutdownTime":7962895.391907,"processStartupTime":0.0,"processType":"default","registerTime":0.0,"resourceTable":{"length":0,"lib":[],"name":[],"host":[],"type":[]},"samples":{"length":0,"weightType":"samples","stack":[],"timeDeltas":[],"weight":[],"threadCPUDelta":[]},"stackTable":{"length":0,"prefix":[],"frame":[]},"stringArray":[],"tid":"54509","unregisterTime":7962895.391907,"showMarkersInTimeline":false},{"frameTable":{"length":834,"address":[411517,147586,455812,3019686,492760,497010,432303,1507765,1699476,3024850,3040958,78738,1507887,2086590,2089170,2091389,2091905,2126075,2475118,2400677,632543,2091309,2136220,2092356,2113865,2095565,2093697,2097026,2115302,2093017,2122833,2092440,2145816,2462355,2465317,2467211,2464852,2470944,2028663,2028056,2055233,2017918,2057260,2463207,2025269,2025002,2023767,2024017,1942400,1986795,1986873,1986672,3184878,2127330,2122799,2467178,2488966,2490709,2492477,2495967,2097039,2148050,2464146,2466606,2055132,2471409,1902552,2095932,2286540,1586007,1536790,2053155,2052791,2465283,2459189,1954552,1986801,2471054,2027587,1986626,2465011,2145897,2083140,2083731,616661,2116106,2027531,3184869,631284,2093789,2370625,1925539,2464525,2288545,2288171,2288037,2285827,631093,2465519,2027792,1688068,380972,634805,626270,621698,612957,2146341,1690803,1696466,1536820,2054678,2018576,622600,1986846,631123,623292,2370519,1697025,381915,2052877,2052992,2016696,2062924,2018411,2370434,2378787,2378591,2377888,1986879,1925507,1926684,1904099,1900236,1900708,2459233,2495961,2495760,3184816,2488879,2488034,2488118,621872,622591,2288299,2334928,2335378,2337604,2057548,2065214,631181,2117435,1627225,1664469,1666301,1669083,1668960,1537086,2055032,2057725,2065163,2065024,1941840,624074,2463356,2289928,2289382,2289892,1942380,1984428,631066,2471297,1902529,1900556,617242,2144858,1627543,1629590,1647416,1634206,1689517,626465,618323,612779,621712,2464593,2454031,2453921,2455971,2456668,2450803,2449356,2449688,616668,2028126,381001,631287,2488176,1985003,1984362,622369,1926723,616521,631087,616621,2017870,2378678,2379989,2381740,2384847,622331,2117431,1942024,612946,1647519,2016806,2064223,2064298,2018378,1942044,616616,2464994,2061835,2018597,612842,2025188,2065267,2057708,2065040,3058828,2017980,2377746,2378133,2378983,616835,2370735,2400215,2390214,2390154,2396384,2389620,2386465,2386860,616657,2054281,2064148,1986631,1900221,3058849,381023,2064152,2370268,2055063,2057763,1942049,2054337,2064275,2018469,2455984,2452532,2449281,508672,622021,612900,1911071,3058853,2467295,1670186,2064180,2018352,2453854,2454954,2465660,2456116,2449341,2449598,2471402,624070,616746,1902485,616757,2054435,2064357,616636,2017947,624114,612622,2335294,2337260,2340433,631140,612967,2377721,2018357,2287952,621491,2467303,2453126,2453066,2452860,616684,612987,612537,2065137,622378,3184835,612816,616638,622429,2061767,508656,617208,624191,1954700,1914153,2384878,631271,2466686,2487920,2057685,631297,632564,2463381,2364496,2383899,2382420,2384801,1696803,1678146,1678077,1678128,1676130,1676019,1671629,1671945,632536,2285777,631174,1585792,2052604,2052446,2053696,631071,2018751,2289821,631144,2023958,621927,2064281,1536802,621910,2490730,2492437,621955,1690857,2454945,1900568,2054379,2064345,2018517,2018810,2334718,2337420,2340336,2370382,3184885,2380175,2358526,2381580,2384911,1900537,2381757,1696628,2052693,2053930,2063696,2054915,623284,2488421,2489238,2122736,2023720,2018452,2384905,2384704,3184870,2017847,621967,2024078,2018524,612904,2147693,2145795,2458318,2490827,2285754,616847,2449274,2065247,1986770,2453850,2023749,2064994,623276,2383872,1629872,1611840,1984317,1664543,1935667,631080,1925520,1911860,1900161,3058852,2064308,2289880,2459509,2379875,621907,2145422,2322827,2328100,2041677,2038662,1986769,622519,632528,2016720,2018767,2055223,2053038,2018438,2286612,2054028,2064100,2449657,2144785,1664655,1617272,2289491,2334697,621288,623288,2464329,2028277,1687920,2052886,2024100,3184913,612822,2028590,2378950,2378874,2064181,2063712,2145214,2417961,2418539,3186023,2018664,1910977,2396417,2064112,2289496,623683,2097942,2079244,2073694,2289956,2024060,1942150,621940,2027810,2334903,1536832,1555027,2115546,2364390,1900109,2018821,2340272,616549,621950,2386452,2065241,2065479,2018603,1677868,1682595,2370546,1682625,632579,1986884,631119,2057768,2465349,612897,2389948,2395345,2287978,621265,2396371,2396860,2387987,2386540,616855,1900464,2285712,2055116,621168,2028192,623322,2289372,622619,2449352,612565,2027605,1930432,1984402,2471458,618463,616677,1987106,632555,2023928,622132,2052862,3058848,616749,616653,612992,2053985,2063794,2063860,1986114,2028031,1986076,2065169,2052836,2018631,2018568,2065026,2337235,612557,623272,1914178,616845,622464,1910032,2017396,616708,1910075,2290065,2465605,2053049,2027483,1910080,2052978,2018499,2057523,2053630,2054368,2018544,1900478,631304,2018684,2064205,2488096,616694,623223,2456003,616769,622549,622298,2053610,2054643,2018488,1910078,624128,2065045,2016784,2018611,622409,1910998,1910963,631175,3184899,1620396,2028198,1986811,2054221,2018742,1935789,2016752,2018491,622864,1941996,623185,2495889,2389941,2064212,2018722,612838,1926696,1951379,2052181,1593464,632590,2017953,622560,2039028,2404794,2018442,1900580,2463239,2018552,1942097,2390189,616571,2290082,2465396,2287223,1620392,2018530,2018753,2290017,3058752,2492460,2495883,612834,1942085,1986899,623482,621193,623173,1911781,2378902,1902576,1913424,2340510,622109,2288274,622868,383005,631053,2286558,2061668,2060834,2060787,2418650,3186074,3217202,3187554,409094,409168,2117679,2073727,2018660,2054270,2018565,2117490,2068523,2083692,2066029,2066286,612828,2052219,2019075,2063914,623309,631188,631280,1986608,2017808,2063702,2028062,2019337,2064093,623256,2145817,1536932,1541378,1986796,1628941,1611884,1605940,1605442,2024284,2396872,1951292,622281,631025,624292,381662,2449612,1633493,1668388,2470608,2064976,2018477,613034,621278,1668371,1666893,624235,1677830,1902462,2380010,1620240,2358578,2116734,2365665,616846,616671,2018692,1914157,2386525,2386872,2054181,2018607,2052897,2018513,622611,2334580,621876,1954339,381120,1676202,1671644,616594,2027550,2065204,2147434,2068419,2066376,2387996,2395377,2148026,2490895,2457787,2457882,2027630,2453101,2467195,2288749,2027456,1910128,2095709,2117458,1627319,1629808,612912,631178,1671964,621445,612917,2027815,2018512,2382773,1620351,616821,2057287,2495857,2337220,2466760,1696532,2116080,1620410,621751,2028308,2053127,1910045,2016640,1536980,616851,617217,1942391,2454892,2378880,623477,2455995,632615,2053148,622569,2418676,624110,622574,1555033,2379340,2064165,2061443,2018732,623056,631019,612909,613027,1605382,1605350,2465318,2452445,2495781,2028433,624123,622624,2378566,631022,623248,622228,2018587,1620348,616795,626236,2028563,2203455,2228859,2203550,1963503,2204090,2212390,2214294,2231566,2239002,2237693,2238276,1437693,1507961,2198493,1542519,3053232,3084832,1100270,1102346,1100659,1176389],"inlineDepth":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"category":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],"subcategory":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"func":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833],"nativeSymbol":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"innerWindowID":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"line":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"column":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"funcTable":{"length":834,"name":[4,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839],"isJS":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"relevantForJS":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"resource":[0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,1,0,0,0,0,1,1,1,0,1,0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,1,1,0,0,0,1,0,1,0,1,0,1,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],"fileName":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"lineNumber":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"columnNumber":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"markers":{"length":4,"category":[0,0,0,0],"data":[{"type":"mmap","name":1},{"type":"mmap","name":1},{"type":"mmap","name":1},{"type":"mmap","name":2}],"endTime":[0.0,0.0,0.0,0.0],"name":[0,0,0,0],"phase":[0,0,0,0],"startTime":[7962903.442004,7962903.858355,7963005.962321,7963550.437747]},"name":"descend","isMainThread":true,"nativeSymbols":{"length":0,"address":[],"functionSize":[],"libIndex":[],"name":[]},"pausedRanges":[],"pid":"54509.1","processName":"descend","processShutdownTime":7963631.330803,"processStartupTime":7962895.391907,"processType":"default","registerTime":7962895.391907,"resourceTable":{"length":3,"lib":[5,4,6],"name":[3,5,16],"host":[null,null,null],"type":[1,1,1]},"samples":{"length":649,"weightType":"samples","stack":[11,20,59,70,103,134,166,187,222,238,239,247,285,290,309,326,334,350,354,366,374,388,399,408,409,415,455,464,468,506,518,530,534,544,587,602,611,619,622,625,628,632,636,638,641,645,648,649,651,653,657,663,669,674,684,706,714,724,736,742,743,752,754,763,768,773,779,784,789,790,794,799,807,808,811,823,829,835,836,839,841,843,851,852,876,882,883,885,889,893,894,901,908,910,916,918,919,920,924,925,929,940,943,944,951,952,958,960,962,966,967,973,982,993,1001,1007,1009,1021,1026,1034,1039,1048,1054,1056,326,1060,1063,1074,1085,1092,1093,1096,1102,1108,1112,1117,1120,1127,1128,1133,1139,1144,1148,1153,1156,1158,1163,1167,1171,1172,1176,1179,1180,1184,1188,1217,1220,1224,1230,1233,1237,1242,1245,1248,1249,1252,1258,653,1262,1265,1271,1274,1278,1284,1287,1293,1296,1303,1311,1313,1316,1323,1326,1327,1331,1337,1347,1351,1353,1355,1356,1359,1362,1367,1370,1373,1376,1382,1383,1388,1391,1394,1398,1399,1400,1403,1409,1410,1415,1421,1422,1425,1428,1430,1432,1434,1439,1443,1444,1447,1448,1455,1456,1461,1464,1471,1472,1478,1484,1487,1495,1497,1498,1500,1501,1508,1515,1521,1410,1524,1526,1527,1532,1535,1539,1547,1549,1551,1552,326,1556,1558,1562,1564,1569,1572,1579,1580,1593,1595,1596,1602,1605,1611,1616,1617,1623,1628,1633,1637,1642,1649,1650,1651,1654,1656,1657,1658,1661,1663,1665,1668,1669,1670,1673,1676,1677,1678,1681,1684,1685,1688,1689,1696,1699,1702,1707,1714,1718,1722,1724,1726,1727,1731,1734,1738,1744,1748,1750,1751,1787,1791,1792,1793,1797,1800,1802,1803,1808,1809,1811,1816,1818,1820,1822,1824,1828,1832,1833,1835,1839,1842,1851,1854,1856,1860,1862,1866,1867,1872,1875,1877,1878,1883,1884,1887,1894,1896,1900,1901,1907,1908,1913,1915,1921,1923,1926,1929,1932,1933,1936,1938,1941,1950,1952,1954,1957,1960,1961,1962,1964,1966,1969,1975,1991,1994,1997,1998,1999,2000,2001,2004,2005,2011,2015,2018,2021,2024,2029,2032,2033,2036,2042,2046,2050,2076,2079,2080,2082,2084,910,2086,2088,2092,2095,2097,2099,2106,2107,2108,2112,2115,2116,2122,2125,2132,2140,2144,2149,2151,2153,2154,2160,2161,2163,2164,2166,2169,2176,2178,2196,2198,2203,1497,2207,2213,2215,2217,2219,2224,2225,2229,2234,2236,2239,2242,2246,2250,2257,2258,2262,2266,2267,2271,2275,2280,2282,2292,2297,2298,789,2299,2301,1933,2302,1933,2306,2315,2318,2321,2323,2327,2333,2337,2341,2348,2351,2352,2356,2363,2364,2366,2367,2370,2371,2380,2381,2389,2392,2397,2398,2399,2404,2410,2416,2418,2421,2426,2429,2432,2445,2446,2450,2453,2454,2457,2458,2462,2466,2469,2470,2472,2478,2483,2486,2487,2490,1444,2491,2495,2497,2529,2530,2531,2534,2536,2537,2539,2543,2545,2546,2548,2554,2557,2561,2562,2564,2566,2571,2572,2574,2577,2578,2581,2536,2585,2588,2592,1249,2593,2595,2597,2603,2609,2610,2612,2614,2620,2628,2629,2632,2638,2640,2648,2649,2651,2656,2664,2667,2668,2674,2675,2677,2680,2683,2685,2691,2696,2698,2699,2703,2704,2705,2706,2707,2709,2712,2713,2716,2718,2719,2720,2160,2722,2723,2724,2725,2726,2729,2731,2736,2740,2743,2744,2747,2749,2750,2751,2752,2755,2760,2764,2772,2774,2780,2781,2782,2302,2786,2794,2796,2797,2800,2804,2807,2810,2812,2818,2823,2825,2829,2832,2837,2838,2839,1410,2842,1128,2843,2846,2851,2855,2857,1933,2862,2863,2865,2892,2901],"timeDeltas":[7962900.856904,2.588686,0.999565,0.999758,1.000926,0.998966,0.999808,1.000042,1.000264,0.999625,1.000043,0.999992,1.000056,0.999918,0.999891,1.000093,1.000103,1.000176,1.001414,0.998606,0.999984,0.999711,1.00004,1.000157,0.999911,1.000061,0.999845,1.000009,1.000071,1.000029,0.999865,1.000018,1.000034,0.999951,1.0001,0.999874,1.000089,0.999751,1.000304,0.99999,0.999918,1.00019,0.999842,1.000078,0.999847,1.000086,1.000012,0.999935,1.000081,0.999907,0.999996,1.000066,1.000088,1.000022,0.999794,0.999994,1.00005,1.00008,0.999959,0.999845,1.000017,1.000187,1.000009,1.000028,0.999925,0.999979,1.000044,1.000012,1.000039,0.999819,1.000133,0.999887,1.000132,0.999924,0.999914,1.000103,0.999923,1.000138,0.999961,0.999873,1.000177,0.999915,1.000032,1.000002,0.99989,1.000157,0.999994,1.057135,0.943075,0.999619,1.000276,0.999873,1.000113,0.999787,0.999974,1.000128,0.999936,0.999992,1.000018,1.000081,0.999966,1.003755,0.996202,1.006338,0.993613,1.000178,0.999897,1.000158,1.0022,0.998023,0.999849,0.999688,1.000051,0.999989,1.172362,0.827964,0.999774,1.000058,0.999903,0.999901,1.0,1.000125,0.999778,1.000103,1.092511,0.911464,1.017639,0.980872,0.998274,1.002348,0.997563,1.00087,0.998671,1.000058,1.000279,1.00087,1.000532,0.998338,0.999856,1.000077,1.402158,0.597895,1.000381,0.999648,1.791202,0.208814,1.000377,0.999645,1.000231,0.999519,1.000001,0.999976,1.000016,0.999966,1.000118,0.999914,1.00013,1.000061,0.999952,0.999886,1.000207,0.999856,0.999853,1.000062,1.000285,1.003101,0.99688,0.99979,0.999839,1.000049,0.99997,1.000083,0.999966,1.000001,1.000006,1.000003,0.999869,1.000058,1.0001,0.9999,1.000182,0.999852,1.000002,1.000054,0.99994,0.999938,1.060128,0.940432,0.999547,1.000058,0.999818,1.000406,0.999814,0.999905,1.000049,0.999923,1.000053,1.000235,0.999778,1.000171,0.999693,0.999972,0.999875,1.000292,0.999929,1.000106,1.000079,0.999841,0.999931,1.000145,1.000067,0.99975,1.000056,1.000332,0.99984,0.999932,1.010016,0.990558,0.999666,0.999946,0.999931,0.999844,1.000167,0.999833,0.999949,0.999866,1.000301,0.999674,1.000069,1.000191,0.999803,1.000014,1.000255,0.999938,0.999752,1.000295,0.999748,1.000028,0.999988,1.000063,1.000027,1.000083,0.99998,0.999837,1.000056,1.00025,0.999717,1.000102,1.000038,0.999961,0.999966,1.000013,0.99998,0.999988,1.000123,0.999952,0.999846,1.000149,1.000075,0.999911,0.999882,1.000139,0.999868,1.0001,1.066274,0.934043,0.999944,0.99986,0.999947,1.000008,0.999937,1.000058,1.055203,0.945013,0.999846,0.999818,1.000183,0.99995,0.999994,1.000035,0.999775,1.000169,0.999892,1.000104,0.999936,1.0001,0.999813,1.000062,1.000034,0.999957,1.000104,0.999916,1.00002,0.99991,1.000129,0.999922,0.999989,0.999887,1.000165,0.999906,0.999935,1.000231,0.999721,1.000247,0.999968,1.000583,0.99942,1.000037,0.99997,0.999958,0.999904,1.000194,0.99973,1.000196,0.999907,1.000078,1.000105,1.000002,0.999799,0.999992,1.000017,1.000129,1.000031,0.999864,1.00002,1.000208,0.99972,1.000241,0.999868,0.9999,1.000055,0.999998,1.000128,0.999754,1.000189,0.999913,0.999981,1.000005,1.000127,0.99998,0.99996,1.000062,0.999887,1.000131,0.999892,1.000114,1.00284,0.997531,1.000031,0.999659,1.000075,1.001041,0.998769,1.000112,1.042977,0.957069,1.000002,0.999927,0.999979,0.999755,1.000274,1.000041,0.99983,1.000066,0.999943,1.000193,0.999838,1.000171,1.000178,0.999626,0.999902,1.007329,0.992761,1.000051,0.999904,1.000167,0.999914,0.999866,1.000229,0.999773,1.000144,0.999892,1.000147,0.999982,0.999881,1.000139,0.999845,1.000048,1.000048,1.000004,0.999966,1.00208,0.998212,0.999842,1.029876,0.999745,1.000066,0.999913,1.000061,1.000098,0.999704,1.000134,1.012705,0.998026,0.989654,0.999818,0.999953,0.999949,1.009993,1.023716,1.033929,0.965713,0.999858,0.999724,1.000151,1.058474,0.941614,0.999796,1.000133,0.999933,1.000078,0.999776,1.000065,1.000189,0.999879,0.999846,1.000368,0.999774,1.00059,0.999374,0.999976,1.000185,0.999884,0.999891,1.00001,1.000074,1.000645,0.999468,1.000414,0.999484,0.999922,1.000174,0.999922,1.000015,0.999844,1.000125,0.999996,1.000702,0.999892,0.99979,0.999987,1.000001,1.000206,0.999769,1.000124,0.99994,1.00015,0.99983,1.000185,0.999928,0.999895,1.000152,0.999417,1.003983,0.99651,0.999505,1.000128,0.999968,1.000425,0.999586,0.999751,1.000218,0.999888,1.000029,1.000073,1.0,1.000028,0.999976,1.058438,0.946799,0.995046,0.999681,0.999884,1.000077,1.000037,0.999842,1.004977,0.995308,0.999964,1.00008,0.999843,1.000062,0.999769,1.000215,1.000133,0.999907,0.999875,1.000162,1.000013,0.999878,0.999939,1.000156,0.999666,1.000357,0.999743,1.000122,1.000193,0.999909,0.99991,0.999921,1.000419,0.999709,1.000035,0.9998,1.000163,1.000034,0.999911,0.999994,0.999963,1.000058,0.999903,1.000099,1.000129,0.999898,0.999975,0.999842,1.000377,0.99987,0.99988,1.000109,0.999771,1.000264,0.999903,0.999853,1.000111,0.99983,1.000194,0.999999,0.999963,1.000036,0.999943,0.999988,1.000018,0.999968,0.999926,1.000069,1.000051,1.000019,0.999849,1.000035,1.000183,0.999964,0.999872,1.000096,0.999874,1.00012,1.002205,0.998135,0.999611,1.000157,0.9999,1.000039,0.999965,1.00004,0.999968,1.000078,0.999898,0.999998,1.000019,0.999865,1.00019,0.999851,1.000157,1.273838,0.727995,0.998297,0.999937,0.999954,0.999959,0.999885,0.999952,1.000085,0.999966,1.00009,0.999914,1.000111,0.999964,0.999899,1.00014,0.999861,1.000188,0.999854,1.000011,0.999981,0.999948,1.000108,1.000034,0.999822,1.000482,0.999648,0.999978,1.00004,0.999789,1.000148,0.999932,1.00013,1.000051,0.99996,0.999835,1.000223,0.999935,0.999989,1.000012,0.999996,0.999875,1.000024,0.999998,0.999999,1.00006,1.000085,1.000005,0.999925,1.000155,0.999799,1.000083,0.999802,1.000256,0.999911,1.000031,0.999941,0.999904,1.000117,1.00011,0.999953,0.999933,1.000155,0.999707,1.000283,0.999878,1.000255,0.999761,0.999988,1.000067,0.999921,0.999813,1.000007,1.000229,1.000217,1.004043],"weight":[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],"threadCPUDelta":[939,989,999,999,1000,998,999,1000,1000,999,1000,999,1000,999,999,1000,1000,1000,1001,998,999,999,1000,1000,999,1000,999,1000,1000,1000,999,1000,1000,999,1000,999,1000,999,1000,999,999,1000,999,1000,999,1000,1000,999,1000,999,999,1000,1000,1000,999,999,1000,1000,999,999,1000,1000,1000,1000,999,999,1000,1000,1000,999,1000,999,1000,999,999,1000,999,1000,999,999,1000,999,1000,1000,999,1000,999,1057,943,999,1000,999,1000,999,999,1000,999,999,1000,1000,999,1003,996,1006,993,1000,999,1000,1002,998,999,999,1000,999,1172,827,999,1000,999,999,1000,1000,999,1000,1092,911,1017,980,998,1002,997,1000,998,1000,1000,1000,1000,998,999,1000,1402,597,1000,999,1791,208,1000,999,1000,999,1000,999,1000,999,1000,999,1000,1000,999,999,1000,999,999,1000,1000,1003,996,999,999,1000,999,1000,999,1000,1000,1000,999,1000,1000,999,1000,999,1000,1000,999,999,1060,940,999,1000,999,1000,999,999,1000,999,1000,1000,999,1000,999,999,999,1000,999,1000,1000,999,999,1000,1000,999,1000,1000,999,999,1010,990,999,999,999,999,1000,999,999,999,1000,999,1000,1000,999,1000,1000,999,999,1000,999,1000,999,1000,1000,1000,999,999,1000,1000,999,1000,1000,999,999,1000,999,999,1000,999,999,1000,1000,999,999,1000,999,1000,1066,934,999,999,999,1000,999,1000,1055,945,999,999,1000,999,999,1000,999,1000,999,1000,999,1000,999,1000,1000,999,1000,999,1000,999,1000,999,999,999,1000,999,999,1000,999,1000,999,1000,999,1000,999,999,999,1000,999,1000,999,1000,1000,1000,999,999,1000,1000,1000,999,1000,1000,999,1000,999,999,1000,999,1000,999,1000,999,999,1000,1000,999,999,1000,999,1000,999,1000,1002,997,1000,999,1000,1001,998,1000,1042,957,1000,999,999,999,1000,1000,999,1000,999,1000,999,1000,1000,999,999,1007,992,1000,999,1000,999,999,1000,999,1000,999,1000,999,999,1000,999,1000,1000,1000,999,1002,998,999,996,999,1000,999,1000,1000,999,1000,1012,998,989,999,999,999,1009,987,1033,965,999,999,1000,1058,941,999,1000,999,1000,999,1000,1000,999,999,1000,999,1000,999,999,1000,999,999,1000,1000,1000,999,1000,999,999,1000,999,1000,999,1000,999,1000,999,999,999,1000,1000,999,1000,999,1000,999,1000,999,999,1000,999,1003,996,999,1000,999,1000,999,999,1000,999,1000,1000,1000,1000,999,1058,946,995,999,999,1000,1000,999,1004,995,999,1000,999,1000,999,1000,1000,999,999,1000,1000,999,999,1000,999,1000,999,1000,1000,999,999,999,1000,999,1000,999,1000,1000,999,999,999,1000,999,1000,1000,999,999,999,1000,999,999,1000,999,1000,999,999,1000,999,1000,999,999,1000,999,999,1000,999,999,1000,1000,1000,999,1000,1000,999,999,1000,999,1000,1002,998,999,1000,999,1000,999,1000,999,1000,999,999,1000,999,1000,999,1000,1273,727,998,999,999,999,999,999,1000,999,1000,999,1000,999,999,1000,999,1000,999,1000,999,999,1000,1000,999,1000,999,999,1000,999,1000,999,1000,1000,999,999,1000,999,999,1000,999,999,1000,999,999,1000,1000,1000,999,1000,999,1000,999,1000,999,1000,999,999,1000,1000,999,999,1000,999,1000,999,1000,999,999,1000,999,999,1000,1000,1000,1004]},"stackTable":{"length":2902,"prefix":[null,0,1,2,3,4,5,6,7,8,9,10,6,12,13,14,15,16,17,18,19,null,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,47,60,61,62,63,64,65,66,67,68,69,null,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,21,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,null,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,16,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,null,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,40,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,163,124,240,241,242,243,244,245,246,null,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,181,286,287,288,289,208,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,294,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,241,327,328,329,330,331,332,333,212,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,304,351,352,353,287,355,356,357,358,359,360,361,362,363,364,365,287,367,368,369,370,371,372,373,156,375,376,377,378,379,380,381,382,383,384,385,386,387,93,389,390,391,392,393,394,395,396,397,398,379,400,401,402,403,404,405,406,407,324,381,410,411,412,413,414,null,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,286,456,457,458,459,460,461,462,463,243,465,466,467,null,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,230,507,508,509,510,511,512,513,514,515,516,517,229,519,520,521,522,523,524,525,526,527,528,529,382,531,532,533,42,535,536,537,538,539,540,541,542,543,null,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,91,588,589,590,591,592,593,594,595,596,597,598,599,600,601,381,603,604,605,606,607,608,609,610,457,612,613,614,615,616,617,618,403,620,621,402,623,624,526,626,627,614,629,630,631,524,633,634,635,605,637,615,639,640,369,642,643,644,373,646,647,457,282,650,349,652,95,654,655,656,186,658,659,660,661,662,297,664,665,666,667,668,97,670,671,672,673,381,675,676,677,678,679,680,681,682,683,154,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,229,707,708,709,710,711,712,713,160,715,716,717,718,719,720,721,722,723,378,725,726,727,728,729,730,731,732,733,734,735,370,737,738,739,740,741,289,287,744,745,746,747,748,749,750,751,358,753,378,755,756,757,758,759,760,761,762,165,764,765,766,767,449,769,770,771,772,658,774,775,776,777,778,287,780,781,782,783,772,785,786,787,788,620,185,791,792,793,605,795,796,797,798,232,800,801,802,803,804,805,806,788,288,809,810,379,812,813,814,815,816,817,818,819,820,821,822,163,824,825,826,827,828,392,830,831,832,833,834,614,633,837,838,383,840,629,842,392,844,845,846,847,848,849,850,629,563,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,300,877,878,879,880,881,705,370,884,360,886,887,888,670,890,891,892,704,301,895,896,897,898,899,900,98,902,903,904,905,906,907,705,909,513,911,912,913,914,915,372,917,788,796,392,921,922,923,349,186,926,927,928,212,930,931,932,933,934,935,936,937,938,939,766,941,942,704,97,945,946,947,948,949,950,531,708,953,954,955,956,957,644,959,613,961,758,963,964,965,950,392,968,969,970,971,972,330,974,975,976,977,978,979,980,981,932,983,984,985,986,987,988,989,990,991,992,183,994,995,996,997,998,999,1000,867,1002,1003,1004,1005,1006,850,1008,47,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,64,1022,1023,1024,1025,163,1027,1028,1029,1030,1031,1032,1033,184,1035,1036,1037,1038,596,1040,1041,1042,1043,1044,1045,1046,1047,844,1049,1050,1051,1052,1053,465,1055,905,1057,1058,1059,658,1061,1062,48,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,355,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,985,1086,1087,1088,1089,1090,1091,287,990,1094,1095,510,1097,1098,1099,1100,1101,404,1103,1104,1105,1106,1107,642,1109,1110,1111,671,1113,1114,1115,1116,828,1118,1119,164,1121,1122,1123,1124,1125,1126,705,368,1129,1130,1131,1132,781,1134,1135,1136,1137,1138,330,1140,1141,1142,1143,52,1145,1146,1147,404,1149,1150,1151,1152,457,1154,1155,218,1157,926,1159,1160,1161,1162,1130,1164,1165,1166,133,1168,1169,1170,759,1077,1173,1174,1175,1076,1177,1178,705,710,1181,1182,1183,634,1185,1186,1187,null,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,328,1218,1219,895,1221,1222,1223,844,1225,1226,1227,1228,1229,904,1231,1232,665,1234,1235,1236,234,1238,1239,1240,1241,637,1243,1244,717,1246,1247,652,58,1250,1251,1065,1253,1254,1255,1256,1257,163,1259,1260,1261,672,1263,1264,210,1266,1267,1268,1269,1270,525,1272,1273,1235,1275,1276,1277,826,1279,1280,1281,1282,1283,459,1285,1286,130,1288,1289,1290,1291,1292,1078,1294,1295,932,1297,1298,1299,1300,1301,1302,578,1304,1305,1306,1307,1308,1309,1310,328,1312,1129,1314,1315,95,1317,1318,1319,1320,1321,1322,898,1324,1325,840,986,1328,1329,1330,1288,1332,1333,1334,1335,1336,98,1338,1339,1340,1341,1342,1343,1344,1345,1346,297,1348,1349,1350,630,1352,467,1354,1162,54,1357,1358,955,1360,1361,383,1363,1364,1365,1366,182,1368,1369,608,1371,1372,328,1374,1375,1298,1377,1378,1379,1380,1381,627,381,1384,1385,1386,1387,670,1389,1390,332,1392,1393,373,1395,1396,1397,658,1247,1350,1401,1402,727,1404,1405,1406,1407,1408,325,932,1411,1412,1413,1414,1411,1416,1417,1418,1419,1420,65,741,1423,1424,367,1426,1427,1076,1429,1000,1431,629,1433,328,1435,1436,1437,1438,680,1440,1441,1442,705,988,1445,1446,1433,466,1449,1450,1451,1452,1453,1454,746,1079,1457,1458,1459,1460,381,1462,1463,1068,1465,1466,1467,1468,1469,1470,325,501,1473,1474,1475,1476,1477,439,1479,1480,1481,1482,1483,392,1485,1486,570,1488,1489,1490,1491,1492,1493,1494,1138,1496,650,383,1499,1047,1040,1502,1503,1504,1505,1506,1507,1385,1509,1510,1511,1512,1513,1514,297,1516,1517,1518,1519,1520,331,1522,1523,457,1525,765,1031,1528,1529,1530,1531,412,1533,1534,1342,1536,1537,1538,508,1540,1541,1542,1543,1544,1545,1546,607,1548,1020,1550,749,1417,1553,1554,1555,1342,1557,976,1559,1560,1561,287,1563,1451,1565,1566,1567,1568,737,1570,1571,664,1573,1574,1575,1576,1577,1578,936,44,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1312,1594,788,747,1597,1598,1599,1600,1601,709,1603,1604,411,1606,1607,1608,1609,1610,747,1612,1613,1614,1615,652,922,1618,1619,1620,1621,1622,1517,1624,1625,1626,1627,1553,1629,1630,1631,1632,56,1634,1635,1636,1412,1638,1639,1640,1641,1304,1643,1644,1645,1646,1647,1648,1463,787,281,1652,1653,949,1655,909,759,282,1659,1660,371,1662,1288,1664,670,1666,1667,630,1104,165,1671,1672,64,1674,1675,1078,1621,1566,1679,1680,1433,1682,1683,788,1368,1686,1687,705,987,1690,1691,1692,1693,1694,1695,1236,1697,1698,53,1700,1701,729,1703,1704,1705,1706,160,1708,1709,1710,1711,1712,1713,342,1715,1716,1717,1354,1719,1720,1721,1081,1723,922,1725,956,879,1728,1729,1730,236,1732,1733,580,1735,1736,1737,393,1739,1740,1741,1742,1743,912,1745,1746,1747,531,1749,324,null,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1736,1788,1789,1790,1433,360,328,1794,1795,1796,62,1798,1799,1598,1801,324,280,1804,1805,1806,1807,705,97,1810,97,1812,1813,1814,1815,382,1817,1121,1819,658,1821,1076,1823,318,1825,1826,1827,782,1829,1830,1831,994,185,1834,1509,1836,1837,1838,671,1840,1841,161,1843,1844,1845,1846,1847,1848,1849,1850,886,1852,1853,776,1855,819,1857,1858,1859,404,1861,975,1863,1864,1865,601,297,1868,1869,1870,1871,935,1873,1874,604,1876,349,579,1879,1880,1881,1882,995,288,1885,1886,317,1888,1889,1890,1891,1892,1893,776,1895,849,1897,1898,1899,809,1692,1902,1903,1904,1905,1906,809,233,1909,1910,1911,1912,886,1914,1226,1916,1917,1918,1919,1920,1241,1922,911,1924,1925,1559,1927,1928,1005,1930,1931,652,1825,1934,1935,844,1937,1115,1939,1940,163,1942,1943,1944,1945,1946,1947,1948,1949,978,1951,164,1953,344,1955,1956,849,1958,1959,1352,1285,1335,1963,1457,1965,359,1967,1968,1392,1970,1971,1972,1973,1974,44,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,629,1992,1993,1844,1995,1996,787,1621,102,1597,677,2002,2003,325,730,2006,2007,2008,2009,2010,1416,2012,2013,2014,531,2016,2017,665,2019,2020,1142,2022,2023,2016,2025,2026,2027,2028,1705,2030,2031,324,1603,2034,2035,390,2037,2038,2039,2040,2041,1720,2043,2044,2045,1597,2047,2048,2049,189,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,661,2077,2078,1604,661,2081,809,2083,746,2085,1016,2087,392,2089,2090,2091,1392,2093,2094,332,2096,1485,2098,1843,2100,2101,2102,2103,2104,2105,652,371,911,2109,2110,2111,738,2113,2114,289,1742,2117,2118,2119,2120,2121,1071,2123,2124,163,2126,2127,2128,2129,2130,2131,279,2133,2134,2135,2136,2137,2138,2139,185,2141,2142,2143,1703,2145,2146,2147,2148,1339,2150,383,2152,349,447,2155,2156,2157,2158,2159,1992,1081,2162,367,1121,2165,1043,2167,2168,1624,2170,2171,2172,2173,2174,2175,1943,2177,226,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,356,2197,1066,2199,2200,2201,2202,182,2204,2205,2206,1436,2208,2209,2210,2211,2212,457,2214,186,2216,1030,2218,457,2220,2221,2222,2223,705,358,2226,2227,2228,1000,2230,2231,2232,2233,1035,2235,911,2237,2238,1275,2240,2241,728,2243,2244,2245,1465,2247,2248,2249,1136,2251,2252,2253,2254,2255,2256,1496,615,2259,2260,2261,997,2263,2264,2265,131,2022,2268,2269,2270,235,2272,2273,2274,303,2276,2277,2278,2279,1082,2281,294,2283,2284,2285,2286,2287,2288,2289,2290,2291,361,2293,2294,2295,2296,2226,243,357,2300,788,1505,2303,2304,2305,224,2307,2308,2309,2310,2311,2312,2313,2314,1587,2316,2317,1795,2319,2320,1612,2322,1735,2324,2325,2326,1041,2328,2329,2330,2331,2332,1909,2334,2335,2336,1886,2338,2339,2340,800,2342,2343,2344,2345,2346,2347,675,2349,2350,942,2130,2353,2354,2355,565,2357,2358,2359,2360,2361,2362,921,1817,2365,1081,185,2368,2369,705,522,2372,2373,2374,2375,2376,2377,2378,2379,2320,854,2382,2383,2384,2385,2386,2387,2388,373,2390,2391,921,2393,2394,2395,2396,1450,671,1129,2400,2401,2402,2403,1109,2405,2406,2407,2408,2409,710,2411,2412,2413,2414,2415,457,2417,1350,2419,2420,903,2422,2423,2424,2425,746,2427,2428,411,2430,2431,161,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,2444,1121,2428,2447,2448,2449,880,2451,2452,1719,1473,2455,2456,1834,658,2459,2460,2461,236,2463,2464,2465,1377,2467,2468,705,946,2471,711,2473,2474,2475,2476,2477,1711,2479,2480,2481,2482,1452,2484,2485,1659,1035,2488,2489,2412,1134,2492,2493,2494,1627,2496,null,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,1173,1613,132,2532,2533,1247,2535,2216,1597,2538,2523,2540,2541,2542,100,2544,1466,1227,2547,445,2549,2550,2551,2552,2553,98,2555,2556,890,2558,2559,2560,1433,181,2563,1615,2565,497,2567,2568,2569,2570,746,778,2573,1958,2575,2576,705,1607,2579,2580,1864,2582,2583,2584,917,2586,2587,1804,2589,2590,2591,788,770,2594,2295,2596,594,2598,2599,2600,2601,2602,1869,2604,2605,2606,2607,2608,764,639,2611,1463,2613,400,2615,2616,2617,2618,2619,1002,2621,2622,2623,2624,2625,2626,2627,2172,1554,2630,2631,50,2633,2634,2635,2636,2637,613,2639,457,2641,2642,2643,2644,2645,2646,2647,787,2047,2650,2493,2652,2653,2654,2655,446,2657,2658,2659,2660,2661,2662,2663,1145,2665,2666,1134,718,2669,2670,2671,2672,2673,332,1288,2676,1529,2678,2679,392,2681,2682,614,2684,769,2686,2687,2688,2689,2690,1571,2692,2693,2694,2695,629,2697,897,1574,2700,2701,2702,907,2576,652,367,1289,2708,1560,2710,2711,165,1462,2714,2715,739,2717,825,788,2025,2721,1574,1334,661,678,1607,2727,2728,1436,2730,1357,2732,2733,2734,2735,515,2737,2738,2739,1033,2741,2742,1565,2375,2745,2746,1075,2748,739,1852,2204,887,2753,2754,1604,2756,2757,2758,2759,1626,2761,2762,2763,2372,2765,2766,2767,2768,2769,2770,2771,947,2773,1067,2775,2776,2777,2778,2779,325,652,774,2783,2784,2785,292,2787,2788,2789,2790,2791,2792,2793,383,2795,1594,2191,2798,2799,2559,2801,2802,2803,947,2805,2806,101,2808,2809,2113,2811,1004,2813,2814,2815,2816,2817,1003,2819,2820,2821,2822,368,2824,511,2826,2827,2828,637,2830,2831,877,2833,2834,2835,2836,2799,2393,1070,2840,2841,1465,906,2844,2845,1958,2847,2848,2849,2850,2277,2852,2853,2854,1352,2856,1502,2858,2859,2860,2861,131,667,2864,null,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,6,2893,2894,2895,2896,2897,2898,2899,2900],"frame":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,30,31,32,33,34,35,33,36,37,38,38,38,38,38,38,39,40,41,42,43,44,45,45,46,47,48,49,50,51,52,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,54,31,32,33,34,55,56,57,58,59,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,54,60,61,33,62,63,37,38,39,64,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,30,31,32,33,34,35,33,36,65,66,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,67,68,69,70,71,72,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,30,31,32,33,73,74,75,45,45,46,47,48,49,76,54,31,32,33,34,35,33,36,77,38,38,38,78,48,50,79,80,30,29,30,31,81,82,83,84,3,4,5,6,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,85,62,63,37,38,38,38,38,86,87,88,25,89,90,91,84,54,31,32,33,34,35,33,92,93,94,94,95,96,48,49,50,51,87,97,98,37,38,38,38,38,38,38,38,38,99,100,101,102,103,104,105,54,31,106,107,108,109,110,111,98,37,38,38,38,38,38,38,38,38,99,100,101,102,103,112,50,113,114,115,116,117,118,109,71,71,119,119,120,121,122,123,124,125,126,126,127,48,50,128,54,31,32,33,34,35,33,36,65,129,130,131,132,133,30,31,32,33,73,134,57,58,135,136,137,55,138,138,139,139,140,87,114,141,142,92,93,143,144,145,146,6,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,85,62,63,37,38,38,38,38,38,38,39,40,41,147,148,149,26,27,150,151,152,153,154,155,137,106,107,108,156,1,2,3,4,5,6,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,85,62,63,37,39,157,158,159,160,37,38,38,38,38,38,38,38,78,161,114,162,163,164,165,165,166,96,167,168,49,51,87,169,170,171,172,173,174,175,176,177,178,179,101,102,180,181,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,30,29,30,31,32,33,34,35,33,36,37,38,38,38,38,38,38,38,38,99,100,101,102,103,104,182,54,60,61,33,62,63,37,38,38,78,48,51,87,114,183,184,185,186,187,188,189,190,191,192,85,62,63,37,193,100,194,195,196,167,197,196,167,198,113,114,199,65,129,200,201,48,49,113,202,186,203,39,40,204,205,206,207,208,113,114,209,210,78,211,104,212,174,175,176,213,119,120,214,215,216,217,36,37,38,38,78,218,98,65,171,172,219,220,108,109,71,71,120,121,221,122,222,54,60,61,33,62,63,37,38,38,38,38,38,38,38,38,99,100,101,102,103,104,223,43,44,45,224,40,41,147,225,73,74,75,224,157,226,159,227,87,228,98,37,38,38,38,39,40,229,226,227,87,228,230,230,230,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,73,74,75,45,45,47,48,49,245,129,130,131,246,247,38,38,99,100,248,71,119,119,243,215,249,250,38,39,251,252,101,102,103,104,105,253,254,215,255,256,257,258,259,191,260,39,40,229,147,227,87,114,261,262,171,263,264,265,266,107,108,109,71,71,119,120,214,267,268,184,185,186,186,269,270,271,272,188,189,273,274,275,113,114,276,171,277,278,279,34,265,266,107,108,109,280,281,282,54,31,32,33,34,35,33,36,37,38,38,38,38,38,38,39,40,283,158,227,87,114,284,285,143,144,286,287,288,289,290,291,202,120,121,255,292,37,39,157,252,142,293,95,96,48,113,114,294,295,296,297,297,298,298,299,300,301,39,157,226,302,114,303,51,304,305,306,98,65,278,203,307,120,121,221,308,34,35,33,43,44,224,251,158,227,87,309,132,172,310,311,73,74,312,187,188,273,279,313,224,157,158,159,227,137,314,315,316,317,224,251,318,319,320,321,322,323,324,325,228,326,327,328,329,330,331,332,333,334,92,93,94,94,293,293,293,95,335,87,336,337,338,338,339,338,339,339,340,38,38,38,78,161,341,216,342,163,164,165,165,343,343,343,166,96,48,113,344,46,345,87,114,346,220,108,109,71,71,120,121,347,348,254,215,255,268,38,39,40,229,226,227,87,114,349,55,56,350,351,114,352,353,310,354,355,355,84,356,357,358,77,38,38,38,38,78,48,49,113,114,115,108,109,71,71,119,120,214,215,215,267,359,143,360,361,362,87,114,115,363,96,48,128,39,157,226,159,227,364,196,48,50,51,87,309,365,366,367,368,129,130,131,246,242,354,172,242,170,129,130,131,246,369,201,212,205,206,370,325,88,38,38,38,38,78,253,371,372,338,373,374,39,375,114,376,139,377,378,87,309,28,29,379,46,380,214,215,215,267,381,207,382,383,384,40,385,114,386,387,254,215,255,268,254,216,388,389,251,226,227,137,49,51,87,309,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,54,60,390,247,391,392,393,293,95,394,319,295,296,297,297,298,395,257,258,396,39,157,158,397,38,38,78,48,398,269,269,399,45,45,400,182,147,159,401,39,157,158,148,114,402,321,322,403,202,369,369,320,174,175,176,177,404,405,406,114,402,226,302,114,402,187,188,189,273,191,334,407,408,409,65,410,411,412,369,413,120,121,414,163,164,165,165,343,343,415,39,157,226,159,227,87,114,162,32,416,417,114,418,419,420,421,422,423,87,319,424,114,425,426,95,394,114,162,129,130,131,132,355,192,265,266,107,108,109,71,71,120,427,428,43,44,224,429,130,282,109,430,431,78,161,97,148,114,115,410,411,412,172,84,432,433,434,273,435,260,436,437,438,439,440,361,288,114,441,442,443,185,187,188,279,77,444,445,71,356,244,49,51,87,97,446,447,157,226,401,39,157,158,159,227,448,449,36,77,38,38,450,37,39,40,385,114,115,253,451,87,309,452,383,304,356,453,433,454,171,84,455,456,457,458,169,214,215,267,459,449,95,96,253,460,326,327,328,329,330,332,84,461,119,119,120,214,462,163,164,463,38,38,78,48,113,114,464,389,38,39,157,158,302,228,28,29,30,465,466,467,163,468,309,43,44,45,45,46,46,46,469,48,128,470,278,219,471,38,38,38,38,38,38,472,186,187,188,189,273,435,306,163,164,439,473,114,402,474,475,217,476,477,478,119,119,120,427,479,440,361,480,254,215,255,268,39,157,158,159,227,87,114,115,190,481,114,482,483,157,226,484,485,110,486,328,487,488,233,489,334,328,487,490,172,491,127,48,492,77,38,39,157,226,302,493,494,73,74,75,45,45,46,46,47,48,49,51,87,309,33,495,496,237,497,497,498,172,84,45,47,253,94,94,293,499,114,500,501,502,503,504,505,105,129,130,131,132,369,506,165,165,343,166,507,158,484,227,87,289,508,408,114,509,510,227,87,114,402,40,283,158,227,87,114,511,512,513,78,48,76,189,514,515,400,38,516,517,167,518,91,426,519,520,449,521,522,410,412,523,524,114,525,526,527,487,490,528,369,369,529,530,531,532,533,182,95,96,48,51,87,114,276,148,114,376,78,167,534,38,38,38,535,319,98,37,38,38,78,167,536,39,157,226,537,71,71,538,539,267,540,171,299,541,542,114,284,543,113,114,544,38,78,161,319,74,312,186,186,354,133,158,148,114,115,545,546,547,5,6,12,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,85,62,63,37,38,38,78,167,168,49,128,48,424,114,115,548,549,81,82,83,550,224,157,252,498,551,513,78,167,406,114,525,305,163,552,553,108,109,554,268,77,555,171,556,557,558,243,462,78,167,406,149,40,229,559,309,560,561,562,186,354,355,563,410,246,279,55,138,56,57,58,135,136,87,564,214,255,268,538,565,119,120,214,566,567,202,329,330,332,568,471,321,322,403,114,569,157,318,319,570,571,572,78,167,406,114,573,574,129,130,395,39,157,226,159,227,87,319,575,359,243,215,255,576,577,49,49,51,87,114,578,84,39,157,158,484,579,580,581,187,188,189,273,191,282,50,79,375,114,582,490,583,584,48,424,585,449,48,49,128,35,416,132,369,571,92,93,94,94,293,95,335,586,587,332,334,77,588,78,48,589,71,590,591,84,592,369,506,120,593,254,267,594,71,119,119,119,538,581,98,37,38,38,38,38,38,38,38,38,38,78,48,113,114,595,410,246,279,138,196,596,597,563,598,599,243,600,601,602,251,158,227,87,114,349,38,39,375,97,129,603,604,535,114,500,338,605,606,130,131,246,172,607,39,40,608,609,46,46,469,419,420,421,422,610,611,120,214,255,612,498,369,369,613,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,54,60,61,33,614,215,255,615,616,255,217,369,84,617,618,343,619,620,621,586,622,254,267,623,561,624,625,626,56,57,627,628,136,87,169,629,630,251,226,227,137,127,48,631,334,269,269,269,354,355,563,424,114,632,443,185,186,187,188,273,274,39,157,226,159,227,87,114,633,243,215,267,222,78,167,406,114,386,353,320,91,242,634,99,100,101,102,103,307,635,216,594,636,637,638,158,227,364,439,144,286,287,639,114,640,641,88,98,37,38,38,38,38,38,38,38,38,38,78,48,49,51,87,114,642,643,306,39,40,229,318,644,645,646,647,648,649,650,651,652,653,654,655,656,538,657,658,659,660,661,662,663,664,665,254,215,216,292,338,339,666,667,668,575,359,40,385,149,148,114,669,78,48,51,137,78,48,424,670,78,48,49,50,51,87,671,672,38,39,40,673,339,666,667,674,675,666,676,532,677,167,168,113,309,167,168,424,114,678,267,268,73,74,75,45,45,46,46,47,161,409,120,214,215,255,594,347,679,680,681,449,78,48,49,682,174,175,176,177,683,404,684,685,686,46,46,687,662,663,529,688,689,86,87,114,690,157,226,484,227,87,691,40,385,114,402,131,132,172,550,157,226,159,227,87,114,692,117,693,319,260,189,273,435,694,174,175,176,177,683,695,696,697,510,698,249,280,357,699,700,343,166,96,48,50,51,87,114,701,664,174,175,176,177,683,695,702,703,424,114,704,37,39,157,158,537,705,706,707,207,383,586,708,709,370,383,87,114,642,157,226,484,227,87,409,710,711,40,385,319,187,188,189,190,712,501,502,713,641,114,442,265,266,107,108,109,71,71,119,119,119,119,538,714,715,503,716,717,282,639,114,162,718,38,38,675,719,119,119,720,721,49,424,114,722,723,114,724,629,725,726,283,226,227,87,114,162,38,38,38,38,675,727,728,729,730,280,267,268,731,39,40,385,319,394,670,13,14,15,16,53,14,15,21,22,14,23,24,23,24,23,24,23,24,15,25,26,27,28,29,54,60,732,662,733,663,734,664,462,735,38,78,253,47,211,459,736,618,737,392,738,739,738,740,741,742,84,78,167,168,49,113,319,743,93,744,38,38,38,745,746,747,260,717,571,748,749,175,750,564,84,267,699,254,267,123,751,95,394,752,331,728,753,260,87,114,754,48,50,49,79,755,38,756,216,757,39,157,158,148,114,386,323,758,382,383,586,759,760,157,761,165,463,56,57,58,762,114,294,78,48,49,50,51,87,114,183,763,148,114,402,39,157,226,302,114,294,764,765,766,392,57,627,628,136,87,691,294,355,242,229,226,227,586,767,39,40,229,158,227,87,114,768,251,226,541,769,251,226,227,87,114,482,770,171,771,119,120,772,553,108,773,519,774,78,48,49,113,114,386,49,51,87,114,701,91,775,776,38,535,114,573,777,217,602,778,246,264,487,488,84,313,468,114,779,291,97,780,629,132,523,675,781,244,782,499,114,783,784,729,48,51,87,114,678,48,424,114,785,215,255,601,705,424,114,786,474,787,788,789,790,215,267,791,48,50,113,114,792,343,166,394,793,343,166,96,48,49,51,87,169,257,84,78,167,168,49,50,79,794,795,120,121,267,558,174,175,176,177,404,684,796,797,637,638,798,113,114,786,86,87,114,349,186,257,799,627,628,800,161,88,38,38,801,87,114,802,78,48,424,114,803,804,805,78,161,114,806,354,355,563,440,361,288,114,402,500,675,424,114,807,741,354,355,760,71,120,214,267,808,50,51,586,809,246,810,99,100,101,102,811,812,38,675,813,814,813,814,813,814,813,814,815,816,817,818,819,820,821,821,821,821,821,821,821,821,821,821,822,823,824,825,826,827,828,829,830,831,832,833]},"stringArray":["mmap","[heap]","//anon","descend","0x6477d","libc-2.31.so","0x24082","0x6f484","0x2e13a6","0x784d8","0x79572","0x698af","0x1701b5","0x19ee94","0x2e27d2","0x2e66be","libpthread-2.31.so","0x13392","0x17022f","0x1fd6be","0x1fe0d2","0x1fe97d","0x1feb81","0x2070fb","0x25c46e","0x24a1a5","0x9a6df","0x1fe92d","0x20989c","0x1fed44","0x204149","0x1ff9cd","0x1ff281","0x1fff82","0x2046e6","0x1fefd9","0x206451","0x1fed98","0x20be18","0x259293","0x259e25","0x25a58b","0x259c54","0x25b420","0x1ef477","0x1ef218","0x1f5c41","0x1eca7e","0x1f642c","0x2595e7","0x1ee735","0x1ee62a","0x1ee157","0x1ee251","0x1da380","0x1e50eb","0x1e5139","0x1e5070","0x3098ee","0x2075e2","0x20642f","0x25a56a","0x25fa86","0x260155","0x26083d","0x2615df","0x1fff8f","0x20c6d2","0x259992","0x25a32e","0x1f5bdc","0x25b5f1","0x1d07d8","0x1ffb3c","0x22e3cc","0x183357","0x177316","0x1f5423","0x1f52b7","0x259e03","0x258635","0x1dd2f8","0x1e50f1","0x25b48e","0x1ef043","0x1e5042","0x259cf3","0x20be69","0x1fc944","0x1fcb93","0x968d5","0x204a0a","0x1ef00b","0x3098e5","0x9a1f4","0x1ff2dd","0x242c41","0x1d61a3","0x259b0d","0x22eba1","0x22ea2b","0x22e9a5","0x22e103","0x9a135","0x259eef","0x1ef110","0x19c204","0x5d02c","0x9afb5","0x98e5e","0x97c82","0x95a5d","0x20c025","0x19ccb3","0x19e2d2","0x177334","0x1f5a16","0x1ecd10","0x98008","0x1e511e","0x9a153","0x982bc","0x242bd7","0x19e501","0x5d3db","0x1f530d","0x1f5380","0x1ec5b8","0x1f7a4c","0x1ecc6b","0x242b82","0x244c23","0x244b5f","0x2448a0","0x1e513f","0x1d6183","0x1d661c","0x1d0de3","0x1cfecc","0x1d00a4","0x258661","0x2615d9","0x261510","0x3098b0","0x25fa2f","0x25f6e2","0x25f736","0x97d30","0x97fff","0x22eaab","0x23a0d0","0x23a292","0x23ab44","0x1f654c","0x1f833e","0x9a18d","0x204f3b","0x18d459","0x1965d5","0x196cfd","0x1977db","0x197760","0x17743e","0x1f5b78","0x1f65fd","0x1f830b","0x1f8280","0x1da150","0x985ca","0x25967c","0x22f108","0x22eee6","0x22f0e4","0x1da36c","0x1e47ac","0x9a11a","0x25b581","0x1d07c1","0x1d000c","0x96b1a","0x20ba5a","0x18d597","0x18dd96","0x192338","0x18ef9e","0x19c7ad","0x98f21","0x96f53","0x959ab","0x97c90","0x259b51","0x25720f","0x2571a1","0x2579a3","0x257c5c","0x256573","0x255fcc","0x256118","0x968dc","0x1ef25e","0x5d049","0x9a1f7","0x25f770","0x1e49eb","0x1e476a","0x97f21","0x1d6643","0x96849","0x9a12f","0x968ad","0x1eca4e","0x244bb6","0x2450d5","0x2457ac","0x2463cf","0x97efb","0x204f37","0x1da208","0x95a52","0x19239f","0x1ec626","0x1f7f5f","0x1f7faa","0x1ecc4a","0x1da21c","0x968a8","0x259ce2","0x1f760b","0x1ecd25","0x959ea","0x1ee6e4","0x1f8373","0x1f65ec","0x1f8290","0x2eac8c","0x1ecabc","0x244812","0x244995","0x244ce7","0x96983","0x242caf","0x249fd7","0x2478c6","0x24788a","0x2490e0","0x247674","0x246a21","0x246bac","0x968d1","0x1f5889","0x1f7f14","0x1e5047","0x1cfebd","0x2eaca1","0x5d05f","0x1f7f18","0x242adc","0x1f5b97","0x1f6623","0x1da221","0x1f58c1","0x1f7f93","0x1ecca5","0x2579b0","0x256c34","0x255f81","0x7c300","0x97dc5","0x95a24","0x1d291f","0x2eaca5","0x25a5df","0x197c2a","0x1f7f34","0x1ecc30","0x25715e","0x2575aa","0x259f7c","0x257a34","0x255fbd","0x2560be","0x25b5ea","0x985c6","0x9692a","0x1d0795","0x96935","0x1f5923","0x1f7fe5","0x968bc","0x1eca9b","0x985f2","0x9590e","0x23a23e","0x23a9ec","0x23b651","0x9a164","0x95a67","0x2447f9","0x1ecc35","0x22e950","0x97bb3","0x25a5e7","0x256e86","0x256e4a","0x256d7c","0x968ec","0x95a7b","0x958b9","0x1f82f1","0x97f2a","0x3098c3","0x959d0","0x968be","0x97f5d","0x1f75c7","0x7c2f0","0x96af8","0x9863f","0x1dd38c","0x1d3529","0x2463ee","0x9a1e7","0x25a37e","0x25f670","0x1f65d5","0x9a201","0x9a6f4","0x259695","0x241450","0x24601b","0x245a54","0x2463a1","0x19e423","0x199b42","0x199afd","0x199b30","0x199362","0x1992f3","0x1981cd","0x198309","0x9a6d8","0x22e0d1","0x9a186","0x183280","0x1f51fc","0x1f515e","0x1f5640","0x9a11f","0x1ecdbf","0x22f09d","0x9a168","0x1ee216","0x97d67","0x1f7f99","0x177322","0x97d56","0x26016a","0x260815","0x97d83","0x19cce9","0x2575a1","0x1d0018","0x1f58eb","0x1f7fd9","0x1eccd5","0x1ecdfa","0x239ffe","0x23aa8c","0x23b5f0","0x242b4e","0x3098f5","0x24518f","0x23fcfe","0x24570c","0x24640f","0x1cfff9","0x2457bd","0x19e374","0x1f5255","0x1f572a","0x1f7d50","0x1f5b03","0x982b4","0x25f865","0x25fb96","0x2063f0","0x1ee128","0x1ecc94","0x246409","0x246340","0x3098e6","0x1eca37","0x97d8f","0x1ee28e","0x1eccdc","0x95a28","0x20c56d","0x20be03","0x2582ce","0x2601cb","0x22e0ba","0x9698f","0x255f7a","0x1f835f","0x1e50d2","0x25715a","0x1ee145","0x1f8262","0x982ac","0x246000","0x18deb0","0x189840","0x1e473d","0x19661f","0x1d8933","0x9a128","0x1d6190","0x1d2c34","0x1cfe81","0x2eaca4","0x1f7fb4","0x22f0d8","0x258775","0x245063","0x97d53","0x20bc8e","0x23718b","0x238624","0x1f274d","0x1f1b86","0x1e50d1","0x97fb7","0x9a6d0","0x1ec5d0","0x1ecdcf","0x1f5c37","0x1f53ae","0x1ecc86","0x22e414","0x1f578c","0x1f7ee4","0x2560f9","0x20ba11","0x19668f","0x18ad78","0x22ef53","0x239fe9","0x97ae8","0x982b8","0x259a49","0x1ef2f5","0x19c170","0x1f5316","0x1ee2a4","0x309911","0x959d6","0x1ef42e","0x244cc6","0x244c7a","0x1f7f35","0x1f7d60","0x20bbbe","0x24e529","0x24e76b","0x309d67","0x1ecd68","0x1d28c1","0x249101","0x1f7ef0","0x22ef58","0x98443","0x200316","0x1fba0c","0x1fa45e","0x22f124","0x1ee27c","0x1da286","0x97d74","0x1ef122","0x23a0b7","0x177340","0x17ba53","0x2047da","0x2413e6","0x1cfe4d","0x1ece05","0x23b5b0","0x96865","0x97d7e","0x246a14","0x1f8359","0x1f8447","0x1ecd2b","0x199a2c","0x19aca3","0x242bf2","0x19acc1","0x9a703","0x1e5144","0x9a14f","0x1f6628","0x259e45","0x95a21","0x2477bc","0x248cd1","0x22e96a","0x97ad1","0x2490d3","0x2492bc","0x247013","0x246a6c","0x96997","0x1cffb0","0x22e090","0x1f5bcc","0x97a70","0x1ef2a0","0x982da","0x22eedc","0x9801b","0x255fc8","0x958d5","0x1ef055","0x1d74c0","0x1e4792","0x25b622","0x96fdf","0x968e5","0x1e5222","0x9a6eb","0x1ee1f8","0x97e34","0x1f52fe","0x2eaca0","0x9692d","0x968cd","0x95a80","0x1f5761","0x1f7db2","0x1f7df4","0x1e4e42","0x1ef1ff","0x1e4e1c","0x1f8311","0x1f52e4","0x1ecd47","0x1ecd08","0x1f8282","0x23a9d3","0x958cd","0x982a8","0x1d3542","0x9698d","0x97f80","0x1d2510","0x1ec874","0x96904","0x1d253b","0x22f191","0x259f45","0x1f53b9","0x1eefdb","0x1d2540","0x1f5372","0x1eccc3","0x1f6533","0x1f55fe","0x1f58e0","0x1eccf0","0x1cffbe","0x9a208","0x1ecd7c","0x1f7f4d","0x25f720","0x968f6","0x98277","0x2579c3","0x96941","0x97fd5","0x97eda","0x1f55ea","0x1f59f3","0x1eccb8","0x1d253e","0x98600","0x1f8295","0x1ec610","0x1ecd33","0x97f49","0x1d28d6","0x1d28b3","0x9a187","0x309903","0x18b9ac","0x1ef2a6","0x1e50fb","0x1f584d","0x1ecdb6","0x1d89ad","0x1ec5f0","0x1eccbb","0x98110","0x1da1ec","0x98251","0x261591","0x2477b5","0x1f7f54","0x1ecda2","0x959e6","0x1d6628","0x1dc693","0x1f5055","0x185078","0x9a70e","0x1ecaa1","0x97fe0","0x1f1cf4","0x24b1ba","0x1ecc8a","0x1d0024","0x259607","0x1eccf8","0x1da251","0x2478ad","0x9687b","0x22f1a2","0x259e74","0x22e677","0x18b9a8","0x1ecce2","0x1ecdc1","0x22f161","0x2eac40","0x26082c","0x26158b","0x959e2","0x1da245","0x1e5153","0x9837a","0x97a89","0x98245","0x1d2be5","0x244c96","0x1d07f0","0x1d3250","0x23b69e","0x97e1d","0x22ea92","0x98114","0x5d81d","0x9a10d","0x22e3de","0x1f7564","0x1f7222","0x1f71f3","0x24e7da","0x309d9a","0x311732","0x30a362","0x63e06","0x63e50","0x20502f","0x1fa47f","0x1ecd64","0x1f587e","0x1ecd05","0x204f72","0x1f902b","0x1fcb6c","0x1f866d","0x1f876e","0x959dc","0x1f507b","0x1ecf03","0x1f7e2a","0x982cd","0x9a194","0x9a1f0","0x1e5030","0x1eca10","0x1f7d56","0x1ef21e","0x1ed009","0x1f7edd","0x98298","0x20be19","0x1773a4","0x178502","0x1e50ec","0x18db0d","0x18986c","0x188134","0x187f42","0x1ee35c","0x2492c8","0x1dc63c","0x97ec9","0x9a0f1","0x986a4","0x5d2de","0x2560cc","0x18ecd5","0x197524","0x25b2d0","0x1f8250","0x1eccad","0x95aaa","0x97ade","0x197513","0x196f4d","0x9866b","0x199a06","0x1d077e","0x2450ea","0x18b910","0x23fd32","0x204c7e","0x2418e1","0x9698e","0x968df","0x1ecd84","0x1d352d","0x246a5d","0x246bb8","0x1f5825","0x1ecd2f","0x1f5321","0x1eccd1","0x98013","0x239f74","0x97d34","0x1dd223","0x5d0c0","0x1993aa","0x1981dc","0x96892","0x1ef01e","0x1f8334","0x20c46a","0x1f8fc3","0x1f87c8","0x24701c","0x248cf1","0x20c6ba","0x26020f","0x2580bb","0x25811a","0x1ef06e","0x256e6d","0x25a57b","0x22ec6d","0x1eefc0","0x1d2570","0x1ffa5d","0x204f52","0x18d4b7","0x18de70","0x95a30","0x9a18a","0x19831c","0x97b85","0x95a35","0x1ef127","0x1eccd0","0x245bb5","0x18b97f","0x96975","0x1f6447","0x261571","0x23a9c4","0x25a3c8","0x19e314","0x2049f0","0x18b9ba","0x97cb7","0x1ef314","0x1f5407","0x1d251d","0x1ec580","0x1773d4","0x96993","0x96b01","0x1da377","0x25756c","0x244c80","0x98375","0x2579bb","0x9a727","0x1f541c","0x97fe9","0x24e7f4","0x985ee","0x97fee","0x17ba59","0x244e4c","0x1f7f25","0x1f7483","0x1ecdac","0x981d0","0x9a0eb","0x95a2d","0x95aa3","0x187f06","0x187ee6","0x259e26","0x256bdd","0x261525","0x1ef391","0x985fb","0x98020","0x244b46","0x9a0ee","0x98290","0x97e94","0x1ecd1b","0x18b97c","0x9695b","0x98e3c","0x1ef413","0x219f3f","0x22027b","0x219f9e","0x1df5ef","0x21a1ba","0x21c226","0x21c996","0x220d0e","0x222a1a","0x2224fd","0x222744","0x15effd","0x170279","0x218bdd","0x178977","0x2e96b0","0x2f1220","0x10c9ee","0x10d20a","0x10cb73","0x11f345"],"tid":"54509.1","unregisterTime":7963631.330803,"showMarkersInTimeline":false},{"frameTable":{"length":0,"address":[],"inlineDepth":[],"category":[],"subcategory":[],"func":[],"nativeSymbol":[],"innerWindowID":[],"line":[],"column":[]},"funcTable":{"length":0,"name":[],"isJS":[],"relevantForJS":[],"resource":[],"fileName":[],"lineNumber":[],"columnNumber":[]},"markers":{"length":0,"category":[],"data":[],"endTime":[],"name":[],"phase":[],"startTime":[]},"name":"descend","isMainThread":true,"nativeSymbols":{"length":0,"address":[],"functionSize":[],"libIndex":[],"name":[]},"pausedRanges":[],"pid":"54517","processName":"descend","processShutdownTime":7963560.174892,"processStartupTime":7963550.576536,"processType":"default","registerTime":7963550.576536,"resourceTable":{"length":0,"lib":[],"name":[],"host":[],"type":[]},"samples":{"length":0,"weightType":"samples","stack":[],"timeDeltas":[],"weight":[],"threadCPUDelta":[]},"stackTable":{"length":0,"prefix":[],"frame":[]},"stringArray":[],"tid":"54517","unregisterTime":7963560.174892,"showMarkersInTimeline":false},{"frameTable":{"length":46,"address":[4359,8267,117834,17721,58132,58121,56820,57123,49452,4409,72864,72601,8520934,22837024,7618726,35103250,25901,147586,27703,30981,34850002,34849704,34966105,34925279,34925556,7806218,631123,624444,31375,34846898,34845077,34898983,34928293,9708086,34966536,34900977,35023342,35034334,35036380,147593,289375,288934,73578,8783414,290781,20954560],"inlineDepth":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"category":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],"subcategory":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"func":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"nativeSymbol":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"innerWindowID":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"line":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"column":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"funcTable":{"length":46,"name":[24,25,26,27,28,29,30,31,32,33,34,35,37,38,40,41,43,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73],"isJS":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"relevantForJS":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false],"resource":[0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,4,3,3,2,2,2,2,2,2,4,4,3,2,2,2,2,1,2,2,2,2,2,4,4,4,0,1,4,1],"fileName":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"lineNumber":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"columnNumber":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]},"markers":{"length":120,"category":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"data":[{"type":"mmap","name":1},{"type":"mmap","name":2},{"type":"mmap","name":2},{"type":"mmap","name":3},{"type":"mmap","name":4},{"type":"mmap","name":4},{"type":"mmap","name":4},{"type":"mmap","name":4},{"type":"mmap","name":3},{"type":"mmap","name":5},{"type":"mmap","name":6},{"type":"mmap","name":7},{"type":"mmap","name":3},{"type":"mmap","name":8},{"type":"mmap","name":8},{"type":"mmap","name":8},{"type":"mmap","name":8},{"type":"mmap","name":3},{"type":"mmap","name":9},{"type":"mmap","name":9},{"type":"mmap","name":9},{"type":"mmap","name":3},{"type":"mmap","name":10},{"type":"mmap","name":10},{"type":"mmap","name":3},{"type":"mmap","name":11},{"type":"mmap","name":11},{"type":"mmap","name":11},{"type":"mmap","name":11},{"type":"mmap","name":11},{"type":"mmap","name":3},{"type":"mmap","name":12},{"type":"mmap","name":12},{"type":"mmap","name":12},{"type":"mmap","name":12},{"type":"mmap","name":13},{"type":"mmap","name":13},{"type":"mmap","name":13},{"type":"mmap","name":13},{"type":"mmap","name":3},{"type":"mmap","name":14},{"type":"mmap","name":14},{"type":"mmap","name":14},{"type":"mmap","name":14},{"type":"mmap","name":3},{"type":"mmap","name":15},{"type":"mmap","name":15},{"type":"mmap","name":15},{"type":"mmap","name":15},{"type":"mmap","name":15},{"type":"mmap","name":16},{"type":"mmap","name":16},{"type":"mmap","name":16},{"type":"mmap","name":16},{"type":"mmap","name":3},{"type":"mmap","name":17},{"type":"mmap","name":17},{"type":"mmap","name":17},{"type":"mmap","name":17},{"type":"mmap","name":17},{"type":"mmap","name":18},{"type":"mmap","name":18},{"type":"mmap","name":18},{"type":"mmap","name":18},{"type":"mmap","name":19},{"type":"mmap","name":19},{"type":"mmap","name":19},{"type":"mmap","name":19},{"type":"mmap","name":3},{"type":"mmap","name":20},{"type":"mmap","name":20},{"type":"mmap","name":20},{"type":"mmap","name":20},{"type":"mmap","name":21},{"type":"mmap","name":21},{"type":"mmap","name":21},{"type":"mmap","name":21},{"type":"mmap","name":21},{"type":"mmap","name":3},{"type":"mmap","name":3},{"type":"mmap","name":3},{"type":"mmap","name":14},{"type":"mmap","name":21},{"type":"mmap","name":20},{"type":"mmap","name":19},{"type":"mmap","name":8},{"type":"mmap","name":18},{"type":"mmap","name":17},{"type":"mmap","name":16},{"type":"mmap","name":15},{"type":"mmap","name":13},{"type":"mmap","name":12},{"type":"mmap","name":11},{"type":"mmap","name":10},{"type":"mmap","name":9},{"type":"mmap","name":2},{"type":"mmap","name":4},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":3},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22},{"type":"mmap","name":22}],"endTime":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"name":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"phase":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"startTime":[7963560.181201,7963560.183927,7963560.184846,7963560.185427,7963561.358189,7963561.362989,7963561.363897,7963561.365211,7963561.369329,7963561.371785,7963561.372205,7963561.436776,7963561.445769,7963561.449388,7963561.452749,7963561.45478,7963561.456387,7963561.459413,7963562.469263,7963562.471928,7963562.475042,7963563.575385,7963564.948793,7963564.95206,7963565.230608,7963565.872104,7963565.875103,7963565.877545,7963565.878745,7963565.879975,7963566.482538,7963566.503013,7963566.506771,7963566.509096,7963566.510444,7963566.522441,7963566.524888,7963566.526417,7963566.527574,7963566.537271,7963566.54078,7963566.543165,7963566.544668,7963566.546066,7963566.548342,7963567.442548,7963567.445196,7963567.447185,7963567.448299,7963567.449559,7963567.841714,7963567.844173,7963567.845438,7963567.846579,7963568.501945,7963568.513324,7963568.516166,7963568.518563,7963568.520509,7963568.52198,7963568.532649,7963568.535068,7963568.536892,7963568.537864,7963568.548797,7963568.55154,7963568.553954,7963568.555063,7963568.56538,7963568.567627,7963568.570461,7963568.571592,7963568.572506,7963568.748703,7963568.750083,7963568.752016,7963568.752844,7963568.75363,7963568.944028,7963569.418963,7963569.426668,7963570.261029,7963570.295066,7963570.31885,7963570.323081,7963570.32776,7963570.331128,7963570.333882,7963570.699851,7963570.703105,7963570.706627,7963570.717334,7963570.961962,7963591.492694,7963598.194983,7963598.206955,7963598.216356,7963598.314626,7963604.836583,7963608.687613,7963618.686049,7963620.903363,7963621.895996,7963621.998489,7963622.855637,7963624.011497,7963624.06866,7963624.193627,7963624.249902,7963624.302778,7963624.360985,7963624.411345,7963624.468227,7963624.519425,7963624.573801,7963624.63815,7963624.697822,7963624.757443,7963624.821874,7963624.88266]},"name":"clang-format","isMainThread":true,"nativeSymbols":{"length":0,"address":[],"functionSize":[],"libIndex":[],"name":[]},"pausedRanges":[],"pid":"54517.1","processName":"clang-format","processShutdownTime":7963630.944621,"processStartupTime":7963560.174892,"processType":"default","registerTime":7963560.174892,"resourceTable":{"length":5,"lib":[0,1,2,3,4],"name":[23,36,39,42,44],"host":[null,null,null,null,null],"type":[1,1,1,1,1]},"samples":{"length":14,"weightType":"samples","stack":[4,5,4,6,8,5,4,8,13,15,27,35,40,47],"timeDeltas":[7963570.337436,6.376416,2.547194,2.914668,6.893937,3.061123,2.871855,3.150672,8.388519,8.479917,6.937153,1.496905,1.136598,2.9944],"weight":[1,1,1,1,1,1,1,1,1,1,1,1,1,1],"threadCPUDelta":[823,990,970,981,959,985,975,985,958,957,964,997,997,989]},"stackTable":{"length":48,"prefix":[null,0,1,2,3,3,3,3,7,null,9,10,11,12,11,14,null,16,17,18,19,20,21,22,23,24,25,26,18,28,29,30,31,32,33,34,31,36,37,38,39,16,41,42,43,44,45,46],"frame":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,22,23,32,33,34,35,36,37,38,39,40,41,42,43,44,45]},"stringArray":["mmap","[stack]","/usr/lib/llvm-10/bin/clang-format","//anon","/usr/lib/x86_64-linux-gnu/ld-2.31.so","[vdso]","[vvar]","/etc/ld.so.cache","/usr/lib/x86_64-linux-gnu/libpthread-2.31.so","/usr/lib/llvm-10/lib/libclang-cpp.so.10","/usr/lib/x86_64-linux-gnu/libLLVM-10.so.1","/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28","/usr/lib/x86_64-linux-gnu/libm-2.31.so","/usr/lib/x86_64-linux-gnu/libgcc_s.so.1","/usr/lib/x86_64-linux-gnu/libc-2.31.so","/usr/lib/x86_64-linux-gnu/libffi.so.7.1.0","/usr/lib/x86_64-linux-gnu/libedit.so.2.0.63","/usr/lib/x86_64-linux-gnu/libz.so.1.2.11","/usr/lib/x86_64-linux-gnu/librt-2.31.so","/usr/lib/x86_64-linux-gnu/libdl-2.31.so","/usr/lib/x86_64-linux-gnu/libtinfo.so.6.2","/usr/lib/x86_64-linux-gnu/libbsd.so.0.10.0","[heap]","ld-2.31.so","0x1107","0x204b","0x1cc4a","0x4539","0xe314","0xe309","0xddf4","0xdf23","0xc12c","0x1139","0x11ca0","0x11b99","libLLVM-10.so.1","0x8204e6","0x15c7720","libclang-cpp.so.10","0x7440a6","0x217a212","clang-format","0x652d","libc-2.31.so","0x24082","0x6c37","0x7905","0x213c4d2","0x213c3a8","0x2158a59","0x214eadf","0x214ebf4","0x771d0a","0x9a153","0x9873c","0x7a8f","0x213b8b2","0x213b195","0x2148427","0x214f6a5","0x942236","0x2158c08","0x2148bf1","0x21669ee","0x21694de","0x2169cdc","0x24089","0x46a5f","0x468a6","0x11f6a","0x860636","0x46fdd","0x13fbdc0"],"tid":"54517.1","unregisterTime":7963630.944621,"showMarkersInTimeline":false}],"pages":[],"profilerOverhead":[],"counters":[]} \ No newline at end of file diff --git a/profile.json.gz b/profile.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..86077875f93739a39d3baea4d825e3961d9af4c3 GIT binary patch literal 29595 zcmagEbx<5Z*XX^lu-KwO7GE?#(8b-|B?Nbe0D%x(g9Hl;!3h@J0>KH+qQTvr;O@@N z^WM7m`{UO4zEe|OXJ)Fp&*^D7eSU{J8XX<*pXApb4E`)>H_~Plw?a9;o1H&$o{nYH4e9r-!{(w#_Qq~cywzq*^V3WuzA!+jl*HO z+~O@1jyS`m{)($!xhg6`lf9TxwAubVxJqpjaN{q~(v}^#N$}wUrIj)M9>*!f_lH0h%wzCxI7i{=dB+ zo`=s&sZ9bkwBy=^#r$sXZ@0Jq(-#fu5w8Cf+C1BSE(?5~t&DSl93x(y0{2cGvCkKa z5ZPVpdx+u9h}GRMbs`SGbRAg!hP`%NKfUa0XgFDEv6(yZ#BXiCyZzYmLLw8r;75(q zZYX*|fkU1BRsH4ibUW_l()IBgF}&tcb?5kW^rVf0%j5`r~oJ2JA zW%M;uo3=h6%!N0PhBsZ};#OCly!?FKe|~dWU1<>yMLZo8-Ry68E~be$Kb&o!A!y3u zsGXfxDR5UK5M{G{{5RSafxa?~TF0(l?(V*R?q1&iOkCf-B1bvjU*23Kr++zHzk0bl zyR9k0jjN;%kmz#w?p!?cwD%y+HQ{2iYNC?Dei=eY<}w*6?nx_?ydS z>vFeI9M#29vGrr9#_`IM$m3~E^UVnZ@$s{f@Jh?w@?y4rVquH-QyNy5;@?T({m`9| zyPAepyusV)Sy9Fp>#sA~cMegX}x>oD|`_9I^*6#Ub4F-+$_36 zec(Uf`Q&BE@430HY>_59SGbgd>h^HIzB8&OO475_cAtPJ=3W+kobm9k{oeXbxPa5=>!h-bz2FIr|1D~hul)H>6rQw3WE38qH5T^HD%Fm@&Rt2lm z_xpV93ueu3Ez zErCfc_eb33e(f8ndv2zpD=nhWHovz5h2y%Nk58!M)D1<>@7IS9A~t9HZf-4*6WN@f zHXlDmff|67Vq#0fl~m4REziqmhGC)?{Ra^do0~7s_v_EgCxK5_BHhC~&CQ-JVr~9w zPuU^I=S_vf#Rm9WlYuXvOm4mW+#i>R5fLscqFFe@yLMR;9Rffg`&Q)3?b*@M+1X=L z5nZ6cS)5d74dAMJ^M=1Wc^s@*b6-YL1(I!iu1`Y+cHvjbuJx-)@uil4 z+gOVsqLxhM6K`d95PEQ+*VFO(;_QpN?^4EWLwi7@__H~mOWm%z*O#5~ZC~WG&%X8o zt8DOsX_87*^+WL>LyRO!#>AB*Hv$`ot-h?B^$) zc<1%_ug!l3&zHn4Hu^j7{+n^FhZ+Kpx5s-3k!#6c?V-Y!cRREXPiI%S;sL2=7XeWg z*UhWW4PH;z#k&F8kKR4k%QdHgVhZ?ow%el*eVb*o8JD~RjgiFYD2R41KP%(lYQIMK zb6(~%=j%9K!%%p3_E>AJYa!RXh%8pJp)+y9yEjb{godMB zZjF~@ZY2eYaEo(3i~c<8GMbweWw2nuoMDy0MzNsRAIp4*h=+0$iaOo)M97XvdEA=d z!sCIM!|a)j-${wbv%zufW`RuQBr{RsIGcmm?26%ag!sad2TacH$~0gO*a($ zOdUS%c(Dx#1sbaP9j`2mtr|Ee@ELH>>0PC|$vP9$9S!Hn*I6c(USFkaxpH{u;2zg` z?YIx~EiNh-W=@x%HpJ?B_`kobx!L~waJ|i2B0l0C(G&0BdeUR@Z~3=Jxxp7D5^E3= z5QCl9FJ#cQFKEe8)fv=uoAUE#ri|wpxE~TboF{lZh<)@q?{e*pH{PgE*GO@mW&=4c zvjpzR4fAm5NAu*>OV!->$J)fo)Kuik$_BR5F&;FXH)UM39Dfi%951Id`iG_uiG=O* z{6vtm= zI}PUJyv%+vWNx+imc`6BdQw;WY!ih-KE>P1%|g!jPt3;*XR|y%{rE1K8UwLH2 z*1yW#_MirTU5DsAN|| z$D*&*9P?LWi53ZRg!+jDWvptEg38<$xt1T{ovPch82vJRcsE(`@)ZRZkkl$L z+HbNZN4AUYJbpqMDQDfLey&r}z1s1r-z!?PmyTHlnZt%Nsw|e{i|}992Cm4EqNyTc zgA0v~k8~9obzJYWooYS(LI}%T_~iMDd82)P7iL`OC~LbEWP5<+8u>?I`hse)`}&1W zGI3NQX;(J)!k9JlTJH{g%Jo}?yP9{@%9?isuEb)Gy(AABnLu<@Pk*(3i-Px5Iqg^Rx|}DmbLXZ_w)*QsW*f~(+2$auV_E$G3ltHB&o&cQ9#scxL1Y@_6l+Ha~%VRwmlidbxNQdrS;xLSN71(V%wbZV%_ z9oW=@XO+V-ruqbSATK#PT; zfzaWrE#PpC(xVm8D*;i10$fz}Lf0|Nl&ZlPeoVOvL-nCKAs?0)$FCxo8HIY&zpZJ3 z>T`<@(loHZUwzZBav5^-3O&9e_GXGFBDJc1)X&Wk~;`rI7AWGiic=4d@N3PRlDQaDryHDBWPe+~EwOST(wacvQ zdC0nm4&FB$V;UH+W_DD~s9cK1ImTe|mHmF>%!G>MV0U(OZpZrRlqQ{{yc7Q2R*>iu zv6Wp~^<`h}VE1ZNtC|Tx8`Ia|)?vE0!_bR@hPU6O(pk8_X%Y!_B=hTkdtf@RmRrAY+>BunT5UYU?ep@!!oY)P)#XH*eC5n$+r#G@xPCg{eYqzL{~}`6*1~UQ(&63h8i;q6<6DH+smQ zEEY>bhimm9kyq6QHkcR`J8FFqtR_R!WtB{G9ile0-f_d^p9O|&H5Oy_?Q^j8zNb4n zNQFCL;*_<-W^U)PqGJWI6x5UPn@<02Ug!vfdHMgwqIFD@#36A<4s^5x{6VK5r!64X zO=jJXkKJM2MHplRXXIe?{H-1pg>6H`Wx~%aGxK?I%A9TS!9T{(O3jo7PA~7tND-h$2$7b-d880-OT^szx(Ko?2_KexAVqdOh2}V*GdOGUgRT&+ zSrLm#lHlPvRDT9}`qlH4^2jCTE5g4c5te65KuTanjdP6 ze&KeJ0>I&sci7v=T6ASF+U=m*MtqcW5~%9>c6jS)>WnISoQ_giV;08Z9z~q28TZ&X zeB1fTX_&%z?RS5mV7hLLD1o(CwNwX!py-wK>u;~EE0}RD>RzJ`uu2j}ISjz{EQSC^ z;~HPVT3n+tuqGk1^c+|?!!IjsTstlWwDe^8gDzqpARcUqu^&wVLpPIZv^d{x9&6(D zP`#ZX7!O%WVNk!UM#0k9AY+Fe_m2hGl#?sc+@8sTjzXp-O67c4F?wg{@Rb$)=-PPQ zN6TpY74U8p1K)E}qkM-fWfW%gKwK);vOCuMy(fCG6X38{ZnNM1cRp8HNWUPYL-R(5qOoT zMz<&W{!AQm)M=>;8-CzWH@trQYhTmb?gNj-4tG^u5DPzBi15xJ#HOcwB1vGvOlQ-M zi4jYFzEKN}E~Ei^Sc?e?W}{KspE=jb5s}N~55xH56-*0DciY^3b5Vg$;aX{x;AfvH z7(C;=U+kg4hTMdn_qVh;V}=1?!*t>;Wji8YNT_U*pR*QehTs0KG(&2lyVNj>3Dt>} zAV_@AOf}6m*vGDfo1h`9Ui-(Oe>Cm5&DFnX4zfNYJ%ehClwR?kBW7HrLcO=*s@~g?@{9`E9F^AidXPR7oyREHUBZn6QG$lJ)aG9)7a^( z*Y(LWspBp3I}9TR*QAa>Bn%_B1QDYb-U&EkakSEVpjV$Byn2@;mG}w`k0Lm*JAk z2dgzgtm})p9)wB`lP*HDtJu7j)5lDhgok(ryO@VO#|b?|0oY!1^oJOAv5p`E^?fp} zpiIOe9@T_p9(b3Eki3-S;kA=q4KLU>YM7}$Vm==!FMPKrOC;m%;n!bms419oWaJA@ zPa&x_iXGbwzPpE6NS8Itf8;1LxSa5|l&hmVKJr|Jlzw-H`3_4}Fem>HiK}^flnAsRwq+6& zU>K5FThJhyWgOrcTUhQe;8zk(ic&uQB?lW!h#5qtMM2?stsHNbG%^4=DrW5({4LPhS5x_u2!0V)1jnwU4 zPFyS7TL>oK!lQM-hDXjzdVI--OU|oVlH?XZ>uG$^oJ#75WdtnMQ?WChgDD-Y-*h-x zzxskrgB}ZK?cXqKk5g6rWHcWY1VN!eRic_lJLJZ-@dIxaRdHiTM_~IhWi#v6pCVg5 z(NiH8c1po;ouqzIBd*`W`cc^6@krW9M|{Qbf%T{YI0fiE%^8D)Qb<-x6;CReQ*4YX zrqk~0Lu?RQ^ydLZx_k=hKg4t1Dx_tJz&=~7|>qxy7YMGzjHb_LBevDOh1JAQYnOqbdP+yE2rZf;P~Nvxh&W;*D@ zaG_O$M7YvEv&2aFhfE*rd~*pOMgLG9vo{6`2x&6r{CHq9LSu;rNAj!XBxDNVAbc|Pc(#w6uv? zm{A}c1{qM%QJM&0naD$zMn3)4D7WC#8@DR}8uu)P0)OzPJTYDe1bABv!1=BnrtDm(UU>}3fOynuok-C{0py2<9@dWYpk>8m$zKFf(}1)lJzS?J z;<#LafC=d{LIvhvas3vM8-CPH2bHZNSE3b?E=?0U!`}`YKSf>%00Sb(Dki}as*Hg{ z-27YPt-=?mZ1EOx4x~!m*md;QmV$@Mfctuh3rVdj!%Z2wDTJ^M{yq_K|z?jd~*_b?;>Bk)#r!5zmni$zDLAK$`M zLgBMBmsD6+Je$OFMVj902&E9rL?lSlsYi}@6)*NM@i|k>sFa2dGO5#84~vN01|#xo z+SgLAEnbJbmR0A4*U%EPwV3VZx;~^wENJ0r2Os(F)>WWZ1Lg+86Aft^rR74;k>4P- zsa7I|vy|`?u@JPZnIqxIQ8G)g5|JW5a~~4%y`aS#f;sgJFUKq}*|x_lFitI@BVF%8 z+s9+@Mv*Cas~6M%0=OV*!t;@M@#(P=AzJPhlDNa#c3ILF1UYQ{F1g;gRm28SNLu>J zD6!17iPFjpwK~$uY_(Is7!-vTHbc94=|Pzk!CE7!L0 zY2~039N(%WDutBKWyt*KA@o+<6AcCoCKbWu3QX){%w#ldTx^nTnr!B5A1aU+iF1&< z&O$U~`OFWfpzrIlqz@P*PJ@;}v8`A53Rv$E$WtABT0!l|Mc+`+8~5Q{3sBv!x$;<| zKD%6~#r*kQ@ptIMcuHzm@)o4TQh{N~9AFI4v9O&H(i}Ih%6&60*ldQH$Zr z%DX1gH^lwLpIgve$kjkPN_Ix@vVq@FEYxH+D@2yuu3&f;+vOorJ%p7CmYg#svAoxW zHfK)Xc5RVMg4>!e5d~?IY}K*$H_iX8J;`8X`V-c;-|0bSRP^5!kFjdNzn_hg_a4ez zpf7d&#g#YhN^2~^Whg%hZcU|;4U=XOgKr348pv#nfE@?@Mzerfd)G|R|8J2FnyS-l zk91EO@Gvkc>X{b)AKGVA|IG26RT+@>@xgn+uY$z=f4VPT+I_f!J#gEx<_FPRd&kP+ zJ+3ZS+eKR*kEe$-iYy!3{;%usUk=Cr^*sJx;RQx;D@H*T=km3^+57f%xVi6*npclP zB|+o=>4N`8xHZ*8?!w4k@%L-VyJc(dRqa{5yU#X#xDo%f+J4CLfHkuDeP^eFD)4^T zUGS0NNFdYQhyMhzGiX_)UgY`x;*K~VfM=xg(cM<0{p8|er*(#M)^tQDFfd^H@7bVw z(S?}jcgr17R&yBsE_i5Q2qoT&YM*e1vo;*BW>`{%j3;J&_KYsK+{CJeIn)!3>`+W7F z<;B9_O2v-WF`^;GwtV#B!04_zbMo@v4VVa&y`daq%; z=vl`YxH+@6&{h^@^7c{)`{(4^|5H4-r-L5JmKQVnR;j47aX4O%PPcDQ5fRk59EJi* z%YFjSr^jb;f4++hYTk)a9J`49!@dDGE)lqaet{w_A}#*D7teV0t3PYR!$t$wUyeE2 zyvhP!NS=#M5bL+DFB!8+g^?Tz7~o-ol=v9O>8xvEv!- z5U)mYv1Ll?;}e|6kG=oJFoxs)A;Aa4AZ{FW-1n>XtCO#*&;OW6Gd~F(C1QR1`T6Yj z@}t)sC8<0$^|4q>z|HB=!Hc44&r;LV72@d(_hRxI7$$P}G~8FT`PBXo)449O2fW-r zpPsLoEO?nmxO%#M{I( ztqSI_9On(@)$fOOdLA~*GU8msD2nlJ5eG%MeSI88*NqIIm+kHA;WMKv%AXTQ>wi6Y zx4yCGYqa4;P_K&m3lwqqQ`a+}QtlZ9Vn!5YG@PtLV<&Y=>%tHxag~9$XNZ|zj|85b zUuO5 z(TCmasH88*45D%iC=7n)CP54aa+8P+_Hw7G3~I&`Sd@$Z`jrF37CXWqEHBkJH z9a9Fk3ba2G_$cRkVzv72wuXyY>>{M7nJ>q?zA%7mILjl<>A*Lf31RWK8Hj$a7?Ca} zu9yw;L@GH_^C^hj6{iD6o<3w4vHQqj9s}uB=(KP%QL0LfO`&2<{-caVOm52am5cL( zjER8Dr5SN-N^i8-S2G)iRPU`G@Abv*zQhpwRNfI?0o}$JYX90l14-H}?|4?uTn|L@ z+^KN+shojty4*8&e#@E&Y%`?3cES`rFDDs!L-A&p%>QC|2<4(zIfcNdija;YGG#~^ zD>){PFNEQD5}uxtU$lo3lk)~?q;0;IS4qn*BxSro$G2)qfHWh;%X#1LaEWS<@jf{f z&;FE+cI4M-7Yf%7!&w)JbIWPP#b+rMYJ+5aZthOE?OqYCogroHWPC}v{iY9Yn|Zyd zGutCv=?U>3g`#QKTb=H3pIp%}T|zPq$mWKqo}yp03??qemo}>vA~iXj0=IHEsxGD^ zOYlc~3P(SyS}ZoE%(&VdPEJ%~Hl93a228F>$~0v+qKh& zEmkH1arkAmmBej1@kHyKcSXnVo*?#r4Rop}j8sD2f~shL|6$SvX@nI2tFmcgA{@qR zFs6~vi}*zzUeHjOCijkf*v?LUb3Jy4?_*(Zp&pTAjIOjwtURBMm1Qki>0&Asb}+Bi zG=wSUt4Dazrn|6q)nu|7w-D}$NcH5!i2EHE%jRrxIk!e;@V-dP7dwt#~$b&^sBnFg_P+~LK%b!vqQ2O1hELE=6nWWhud;8eb&WZfWh}91U{pgS2#f@ zC0Bdx1kk-B$wbo6w7k}_4m$HLDr`*zP)QIFZxt?q!V$~uEs>DEE|M^E!mmWm8cp^4 zltn!3j!U&4Og5vx9?g5;_2KJjNjK=iZelMx2?aii=JPv2$t|8=?EShA0VCDJSN{$ zx|IKhaj>3uktBPq8!n_kbYiM3Lq)j~2MkYTlwYx_M!tcYDj9`861-Q7`6QJfgPVm% z%N1Jmr>>uax6RD!RfRe_7guk|2Ou&5xaKu|r1`Z92`pjg*BLCt)*w650ERuvL-6V- zE!jp+XwnE=x6>`(oyL6v*&2e{8YF49t4zYuQ%Dz<8kKh_LxwZuCrVX5W8!N|u2+ql z!0mJG!*q${enaQF6f9eeFM>Pzu`EseP&gE-p#vfGzxGY+tRw@%xHxzk#+GPl_C*$q zSW?DaSz9f)DCyc;$Kpc1V?A{&`AVw)x--$3nJ_$!GJAtvSq$h*d$(YuiS#crXrnIs zJ&EsCvtVb&yM>T-Pp3A^z1AP)dOm#}hV!KOy3*z-WkUyB*ChNW>gnT|GTCV7C zvhcH_C5v^63CJsm9hlMx4*yP`w`%8}H;j$Xf0;ABB&Qrn(>kt25xPnK-D`q;K~ZO~ zVrmV$a|7H$WBfgsKRsIBl~%Qn%}e@Ag*)c^UOF%7_ls+Ug!$a7x4g0^>DHIUbQ>cv zU2nbQt0=9H(lv*|My&RW0a*xPSdY7a8bUZWk+RF(OTO?H>trZv1nSuxIq8aQ^t$Ux zjV{uil6u4VeJ5;9%rB=In1*8|gtsH{U8eo3a+3$qrlH@=e?wP%XjF9bIE&fX_;HP%h+kXFM;qr&vn|Y}KE~NpPNDiel zGT$#8y%5pDJCN!azV{gkmt2{*Fxtx~zEjYMW)33$i{%Wt5uJ+`+u~c4JPr#L)}+SL zBYvlDi|9i~LtG}q=nq{NWgaOCOSy}Gh1#`TbLspYbt%fSz4l1{ z?a)VJC6(m86~4m_*F7!9Jp@*KpY>Fa^wE;(^<{@`t7%h*_4yfZr}0BJNVsfxzN;n1 zd<(>-zgJjEe$QPS>P*2p}Bao!P(ZuKT_7< zGIs8bzs?{n?`Os_#I0%UH=gloV4s$D$y=P3iFfpdj=)DzbZ?}IVCG<}-r(D;9YNXt zem&1b{o+T~l>4gK+~l`H5}bwnZO+;=v9qo*syUk~gvyL%o0bD{(>sS?O>R${x10}6 zb#ZeFX!q&FB9c2o>-V^X9I4yR85B@^gwo6s z`MHi?S(AS-b(mP3>3Aw-X!||DxWilG$7{iCXK>+MQupg}?3F&2^0i8FT#fnQmQ zz@;i*S*G=D$&scE$%R;1rvX)oXT}^TsG|kL8_Ls-XmNuaNtc@{!|QmX&&k>fGDk`^UiY=0EWS0MJWHw^Jma~* zFXv^a=Ca=Pm`vkyYA(gARJ$veFIPnWp0_wBMsRUqW5PMK2uw*nWa%MOVbhCR)`#z* z59+QseJ=L;4&pK81Ip(!+UFKU>-C@aCPO-ZeC(dJyKXx~Dh9qTI+8HeB@Gl}sKwTa zaooQxj1>FVv$s4g?LSL%zz$)R-eoxCyEvZ5{z1R?tdOtfBd6Dm1NT;2Mq%du9#~0J z@4C{buKd+b7REpQ;sCl%bhjR4mri_weP|*pEGVP;C7L+*)kUj*y8UT5VNcAD)%PQB zfbX?H#opH9D_s}2#d2J`e!puN>w!gK&tv%8s?e6pgs{8Bd$LwG%rEu5HNZMooL>(u z!?0Ux42$*?0w%AZk!j@2vKz0#TeZ)7i}FX92Uzuthri?%2Nzd`kBLC#ct_2-#u?LHKWEdO%J7kGW9iRDUvkev>gKV34U8B6)hw11|C1ukQ z`swPVJE=jq3=7sr>c1voYbc=?;U82>mS@WuPxjHgM1+5j{F>gX$gbbeu2I$37oW#^ zLsd{K>bW7gTu_Pg3Nj*BZU=aqEuUN_AzEKn@1lEB)q0V!?5=uM*A_-9nn$%%dAof% zS@mAvrqhsbe=A@XeRw5#2!_|g&g!*8=ZV(djx;d&rBW|uHEtGPSl@Zi*x;xva<2p1 zP$}cfuRlI027DZ*2KCzOgNFZoac@0b+uAI4Cl~sD#rb|v)8oo&9!T@BulL-{6t@Oq0 zadNCmCoUhKtb8&g?r99)-kMKoI3=PvH2CxB8<~saIXbq@++1Bct}&wid;OYy>|u4r z+_U%baj7nK@<)Kc4znXOanS-yFy#+xWj$N+d$uhyNwT=1!$#MP5k@MPbT-uE!ST8} zfM5l`E=m{7({Xp^!|JA|nd6m%cbWg6%r=8>a*YjYD?;%dZ#{PG*9Mtn*;HdILhrCS z`ALEoMs!)-YZ<$r`?ag8hsN6gpyjN0mA}yVv*dN*1n*AUXQ1};`6@X}#L)@9$K_bK%Jp^16>UCqzE57gS$_Vh8&t4&E=pLt?0PsD z;*ZgIoOcAl?iOk~sy6BpI0;>-6Mwa&{H~@WlhPO>Z}6EYWg(lm@gbf_)kPC*EIwK3 zjd&7kMm53LF#wfU=zE2PB<~2xsx)KFH`jf?VV;U~1k6uJvK+dWlG-}98>^?ZyjxXw z_TqKAvmWQ=sdaxk0r60onkmcx)j(FV4+rc3O{2^PiMFZ}el!ck>LVN<(ggpg^7s{C zls{3KSoKk{`}Ni6S6x<0)OL;8xukz72G6XjW=ln!Mb%y=VpQ0h z3G6MmVSRilgzs;UWz@0whe^oAu;0ab1a>%JDGQ1I`-jN(eql-rhnCP!uYQOMs|GDM zs$)%&>#Hy0@`$} z9ffPdy;Yw_OxjQcJkpjiNe7dKn;C0Lgc%zzODeODql+nHIzJ7S@nJExh4|Dgp%kBs zSgYnYGSV+vT$HhWIV&jfzbSP}9CE)d7^m7}^MVh0j2z=^;w-S~AHH%YImW4Ab2KBT zO*4~qZLg1(FuWwVSy_KNCki?$!+T#!P~ptiP?c76{cE0!{5PRxxgL^5c-utVFZxD7 zh4PX&sUGzr*i!+7*Qn zgxK()y$3zpMZ`A`v9nsxVX?l^?Gdex6X3?R)IMo>c=0alr;zyFxt4!=CMPs)y08`F zq2M7tnm_x+3^Qde(G0a;kYtBc0biiwetTo_31PeNGJr}lyja=dRTHRD2H3o&BXMCD z`<~_h!Ry8KY)M`GJA1p=Zou8MP5Z~dn!uinC&XU(L+;b?Jx=UK0*BqS(0hlSfUA~m zDdSd9Jx`!PjrjZ1fUV1X@jUGZqU>55@v39gYzfuC8DZ|?7XK)R_Wh0F=k<*b6i=5K z(b_XLXDMnEaFU%HfF*pSF}I zPo~QJ*Vr#T1D8lvjHpaJrTyHeX14N-eHWh-_z!g53ACtY!doRCvDjuh0K=^&&%#graEj!gsczddxBL@d+VQ?;%_hGZ9T_jQz#dy+uP?)PVEgj z+70+uDvi*@M2|j}MSBXU+Fk7f^V)STy9l%5o}SATq>@jEK7-(2&XHhz2w2&`H7 zL#h7t94n>r+m5T>I=!>M_rufV^Y;0~(_~LU_S5MeF8wqQ`$p@dR9ZA zdqC1Roiir_7xm}Cq(ru?RMDVPzw^2103*LUn80N^rtj z!{;TDPUmNxn5S|E#S#r_=i`6}`%grS_ox42GW)z3)=KVMXw@R!aA^$Q+A$yq3ejgl zT4O|;LZ%7~It2kmzhqLbiF74lyM8j)1X0uUz**^WnZpvLS-3M`b#Naj8w!V$~#jX_Eg=3Yr) z=@qO2_WWA-kQ4|DgEjvrJV#0jv+4C#I^03Z0V9n8saiY{$6D!EMUTm_3LXtfC<5$y1u91Et|5FIQ6!NlNTH^7__kHudTI8>4y zWdJu{mFXo|2MtEq?*xrBR|;9?{Y%=h5%wxpE^mT+GiVDr0YiZf8XZKBJb|V_0_6tm zi~9wlKWW^ppCFbZvZ*PMc|`&h+Q-^@N^FxQVk4M1h($xai_fbz8ss|Bir!UK&~PKL z!iiPX(DuNb>59LC0h3A_~GKu+7OzdCKjI$Evb&g{0qyPl*Vl#b#^)CzLpEKPyrL(+HjT;%j;X$hpO4 zBsL79MBzG;YO*k_{I~G8@vLYBZ~Dv3sL^_fg}3Q->HDI*6tbkwDdy6ZOn@cC@CSl= zkmcvP_$I|*6ab8U4nV(${1eHW#Hu&m2Wgej`Y=I@Na_!7mH*&~!5_MO0$`K-$FwD| zXajs-AE@~8R8@;K*eOxH^V#|=@oj($ zG$G}72@w8%hBJSU%%f+=JOB`|Hm5`)s=ir8J)e61*!=5z0 zIQie;r}A!%`)fIS)Bp5;g`w1`&;vNg? zXZrRfAv(fH3u+6;zBO{_FF-B8o!BCi{z>e11$V^EFW-u?Euonub~~b(#aA$+2@H#o zu76e#qTk`ryq=LFNva#(|Ms4BHaU;KVmDOQplyZhQqejd=JaM2kH7uSR*O1uvXUyF9{z zjxa8`oAlg9!@&D|gB~)g(Sk}qW4@6@2z-!cSl7~qCKcur^cMz$jkR#C6q6}{cPR98 zi7_X`NTtvgG_CjjwdVYpRv94?y|SBmfAf`@8tor>zW$DpAjVlREJaKB(BDHtg!U7Q zfRRofL$J0$A4(p9GBn}F6l>Y&Pmu2m6_2>2sCNG^;z_?pNKoo6_gZXMat{juEJ;6| zGp9|72R5buKC#OMBV*7;LKIF)#(_yl4nx88YHk7pw=~~=^x`Y*l-uN{qX}s0MWijy z14|^VkmJ#HM8o&H8L9d)O0$4g)BC(|Af^W#oLjopr}ka*)r-5COJhQCmH||;wh*5M z6s__48=6|xHz2c&6<$1tfjcfd)FBdyg^mJBAfLpqq^*QqSF53nOCP68`}$b^Q07$T zGXFI4LSW@{wUWJ0jRZ*Reak44mfZVp{jFS=@Gsr@3v5-!Xu?(36b>9nv~-4}R{T?9 zQj}cqaLnd}W$RCQ0}2d*C0~j6cXM$<{wJzfg)_ZShL>KvN1xHM7EO zsQURkOA|Jy%0Uy~``tq1WOJszyN&_9sp-X-Pf8lbzQ2gVk!3^26HsBf=_2TX%65?` z55x+Q4)!P$HtQvIhq>0sDg-B_s|5YI)}pyv`p13uKfIuUQ5|1(46HTQCHAyQgRM$+ z+2F}QYeM8#tYAGhTCDL(A!H2Q&msZ1r#%bXqw7C@m8f06&tnHP>=7$;hbhXkvwtnT zBFmYF3nJwF$+;ws%=|%>G8?2*pkgFvl6n0vzxp6PwGuywn`F4(MYr=__TPwJ3Lx(p z?$ST}bmE%CfqY&Tn2~xH^cLuC45v{%3R#~B?rlXu@1XbY+z78xa^{o?%0i#g4jSzI z$;bR!v`%7yQ)M&DGN@2R34lR-i2e;nPVH63?wYE3aS|(U=>Q^z+e8SePk>F!Z>6A&OO2zN!Q7{Ir#Bs)m z*4+!inOm4!6RQ_+!^%fJqkLuFzn}*(tLg|5(gli0k-jUHcJ(bMB4XIZ zJ{CDk*<^$N0D5>-Z6TC`rRoXIt`KMp&ESa)0Dh2PRfO~6Di6ML{;Xq=6YvF>Ok@UE zmjH#@dx~Z$uI{GGbyNdLQ*7YtNXbF3YL^=+j3(T#K*xOsrF$bi*A04@k%@#>AQ*SM z?(y29@!lda66@1NQL^?{Fh$}WC2rWzma;H^c4F3+L&x|_oF-Pj(LF`e9HP*hcnVbP z4boFZQ8{(1RZoqJTx0m10y)6%%_Eq^Q0ftnWu@wo)nOs!{Ec*EkgtNl)tV)2s>f6F z1;v~H?|GyamgB073;s9W>f}%hyFW`b4a>9#iV5s7te(+xB8qXm1#|nXEbEneR{G3c zc}yJfNd*%IW^u1%GwhC)yy!Aeu(gkABG2Tmb0V2Y^sS_lxdcAYa!Q8qS3KxDI<8kH zwI@FtJk;E#OfvFG#4PS-|81XnK?W38hvYD#K*18wAWkkkq(T}53x$M45FC&L5D8Lc z4Vnw~XdVNs0aSis;Nn3!4F_&9UjYa;W)l5?u@1t_Dx?miZW>pK-Jmt3 zYJU|#aD3p8(7;T_oX=;d3{bgQxkQZDcp3mL&N%MhU6?4u=xhM?j=9v+5N~R^S!k5K z7b;m08Qw{T8E_qhjFb3MaxW5&E{P$5`z3!nhX6#@|LJp%29*}OwB3WYy5-X%X1c?nY7ZU$sn}Y>v z$>~hvEe^fmj0}c=W6YZ|a&S362XhxYpi6uX=7DH@4(5fJeGcY>xPBHq#SQv5Qi286 zT*3XF9Tea($={$|Gbzd`tRG&5LXDr1L?Hd2kwhVLpOM5MyFim63Z5@KvNItdfH@Qo zgkoNkO02DS=iY$_!pUW2`^y$A1JMW#mW7N=S=k5CeR;$d=>pKl7W@tp6c$VYfrka_Lvq4`4Iouv!G@_UvSXi0WfjbW*};cW zB}f9smJCtS{A*aic1{2o*vVO{K?(`4Zjr$S^>FHjy3=Y~cS*ov4*N)D-H<)A=)fNp zED5706hy&v*g57NqnK0*a{Dr)3^iY)0FC7)i0%tnVojNwQG({o|Ae6(r+x!=AS6V< z{gy%!61c!C37iR-8Ll?Vn~sQJzoAaR180vbzUayooW9eOkO1?ekO zk>(76S9gcJo+Rm2A2_r-NC6zv4NwFpb_Xefzjp(a!1>)lO5pNtfHLGYkWG{LN+y-m z2Ji~V#YKE67s*XGW#;Xi!w7P+AVg2|H%~=U18>Pty`A>zPy?S@saXw6IFAy7#JK>3 zKuInrAyAr2f)FSh?}94Ff5)11-5E zlJ^LcOpr$`0BlMVNcOo?R2=9Etr>Qr*cM-qjKJMtf8j_?kg&htu^tIy@SH588lahF z#9lW~N=K5biUjDVxz?G02r{)1D454U<_02jLYl0bFtE8fV}cPw58Pc)u7!l0pP8)j z7HmIJW5%amYljmxAoUFiqCqX8Fc7_E=?pqk9wojp3ajNB48)n&^%lx4cWZ6NEr;5A z)X4JTgBT)O2x$z09?Pr)%;WM_C?Et*+NsMiX90K_^TU1E8xsap z-SpZ>A(j#Xpzu6JoG*D}K*GMD z4`7NufLl2%jL0JBZ`G$1UpPU?cIpbV3Cb839;HzQ(jKG^6+sxOkRfsi@&d>70laGqVP;g?pHL;@f-h6SNfTB8UzJGy z4pGpGG^(1(oVi76QafPRGDi$#V!kHExE68#1$1c{L|*uVI!7GzXi2EX1AuB5wm_kn z%w$lw;_KjG6~#<|B#6LDLJ~6`n^WO;PPyzF6o{LyODUt!riP=Xt!rPNIGLvX%BUX& z%#5vCTHxeeaIf8^?D5h;3-+^fbpiY!C1BB%Pg4()f%O~E0bY?7DCvArEA9ThoXE%f zFMA)8J^Qq;7{eYQH@REvgUL9@L}(vn8610hr5%a%6}+VoPPyA({Mug0DXA4z40cL~ z%@0UW#0rLk!2>!%a^6jD>1zswwFYo{pb`xBsPcyVudv3CiNs*c94jRzfEMhn9Fh)9 zgJB+nK`r=AS`dQ_sM?AJ4^W?2PsavKg|*iJ{^ zweN*uV)GUx`XN7C{gKqBqQRSrSxn-<#kBtO0V%=)s(OWyI0PiLRtnZNhp^#TL816$ zVQ>}Z)IYZ0ULhyKG?=xIi2r&zwB|P9^6mC;6XaYVE^SI8dh$S-ZC&*hG%{}BM-(l$LFBjm26>}=jszMupmjigAQp)dl@UGb|5d~TOsIzR+gLgT2mxFh?@Geyv z1n+Y2E(h--YGMA1o&eb80=t+A4%nq~i-27Y*o6agz%B>ua=~eu!cp=BffSbC& zE)1Ki{0p1&q;3(xJ7AXsb~#{|3+z%MH}cV(HHL$BIW!lS#X^rgokJQTp@p2F^7w<*I=779h)E9(Lpy6|s2;Bnu3-O+-7Bf+{ z3-iM9I!o=1&B0!x*dQuesTWRwc>&VnEL0rKi_L#$z34z*PRU;f@^T=riBPGdn#*b} zBn&VwpO_Z|AYP2*2v{|R2{*)XPD=RIm`#%OTA;7>9!*xN24tYC4M*+`WT(;Te2_ zUXVA$pAmtEDT?oLQE0@WQ9)zo4y!RoPYIP>k_Rku&3+)S87ksaTx6QbromvV^e6$T zPezSyAcKuEOjeC(H3GfZO5}Db(6eYV8Dw2x1 z2BUJ(apsU>y99cvNTmWv7Lcm^C_Af4()dq^4GuHMfxWb)!?c*77d!yUB#?{ zMN}lm1$tpNz`PvH%OUQ#q{njBS!(*cB?|&nd)8BBB5PD(@VGPs4v%6y2lsMlJPz>X z0ADWPi#3)5d^yh3LB1S1kE>=jyZTIB^+$dQ!;>`J=M2l{f=_f~aHpf3mdBHNyK;50m0K0w%)D*6ih zlFwq>&RNhp*q4KSIoQ{fImN+UgADd1HG>W0R0(&mFNYB1U|&=J!M+${kO^l|>>ytb zFUWzu9O%n|z8r3lgMG1_aG);-`f@>EDn2aeOD+uP%YnWe=!@my)_p8C(3is$a;QQS zO`O32(3cY^xu7p%Sl7H_iR8k*rt}$Tz%Lj0C65hn$RQ3n=$8xqnuCUKhCSrqUkW<} zf2sH_o*DED@WBDU#ACw}Y!!D^dl%Klq!4Dy-$NvFurCMua$#T69-s>c`*N@^EwN~g z&UI^dT>Msk5)B7_2dIpCMGsHIvUFKkmo0A+vyzZ_bU6G!?q5===}JdP99 z(nKYh#N-0NpfS0u zvk)-Z1`sd@0h2M&+Rvdg(Q1AYMid^O9T6;|dtk94H8~KN1A$FH3IwKE0kO$}z#It7 z#cfiX8EOzP2LW^VO*77&5SXN_9Y-t=5SW9BI1ret62DwK5SRmj&5;8Fb3tHCMi!>B zZvwy+1pt7#I8OjzJX7!&Q=fIYgMK;amxF#e=$DK7M6gLW!Ms$gH0J*C{sTBCwXJ?6eWXw%{3FuDaYm!!#K6aT;^yZu*_9q zUs4LNFW0ga?90Kv9PCRL0_e-}RY=`Iz8vJsG0P6}wXonmAz5`1Nh~DUk=gA zL0BC0OI{N2%h{H3z%Ruqn)qN}4)*0Ru4W7e`sJWsE}IYfhQoZn=OF7O#sxyxUO`C-%9N1+~9nuj}jx+lYTYJBkDbB}kFIFmt3ndF31> zPLaiMmNtb;_{q#EB!v;$GO_-`XFbcek~aN&u4Vaf%Flvq{Ar37U@BQ!MAs`#3rg~{ zOfH@F+4QYFgX=%iyYm*V954u;=V@R7B%etJg8;a4&<5O6GRH(U{E5skB>I!joL$tf zvHa(W8k4c*w9U?3zOFPik`_p_`;RM&y0#1BCm;FcjJPd#j}36~zOb0ve>fumwGezr zCnBHlr>Dzvf#cx6s9#@dumr^30_-d{o<+U*d`h3Ti$zNMytWIw6v>Bu*qO`5e$$q| zHxms7wnJND~J|xgtSPiE{HZlWX&8{Ieq%wGEy@BUytLKSgC38*#yDo!y`iA zHbl=82hV!~#Go>}5BXeOb+=U47Uq(v~c$#=O(EDVW&j zr_DaH+C1cBu-c6?v1E2+F)QWVf!ySHC+e3-#RWF3GD5&X|Zf9 zOL$YIKgp6k-A7{F&lPuRR~9AHveF^+WUL5TiC76(iBOe-!{#%K3DC@o!C!f{yUEaY z0L&_4NnwbUd~p3p7@2M>lbi^Z@P5m~)z5nhZsJ*}_)_z!>TDQHdpvgy0DuH6?a8`( zDmi;R!h1whKPlNs!I+!Gz_=-;vR@?l{s#iMPr{AQWeLybYa<_Ef=y0PiJ3J_euk3e z&+~_8D7Qp>nN3Wj$=aR&Gpl%c&^eT`Ln=n}&$~+|P*g zg~wRlgK2iAzt5}@+b78XrxKa@o^>6|cK|wlK5NhU%wJi~^p9PYGriv)g*E>q|C!&3 z{Y(Nh`7|s7F?3YyP|<-IXX@wX#7iefdge!Cro=o(DC9D;an3D}EvHrJD`WiK!tSI5uZF-n&`f z%%pz*bXlQGrQ^;R5`wCq_Bv-Hs(Z|ts_SPaImy~kId=`Y=!VE6@SG;0ZO=J>{?z&N zf8?OgJaqB*$$cmNd4+rWZQ(63ecfQXa>)c!yv#A1+n1T^pL6=`3hB3s`K#ELJ+Wt1 zFX*e1M$c|Piy*AT_u2O^rN2+xvXbEWN#wIU_+4!03GuTohkiX7OqL;Jo}Yyc=c)2D zbP-n>)|f=C-%#XHTN*vrKNG-I?dK*Ab_>Du3@nv>&&(nkVv3VQc@}Fcm(TSZ&zgW| z$@#N-$=3HRQJ^E`c}aiD^vL~l9!7q0PKd)et@D9-ZvFTW-_+7xEX@mJ1*EZ}8K zwwWe1ixN6i08m!Uw!Hcz^5MDU{KE&hP;bIV%>`&CYyCt4fmu{wYwzmQW!S05u7xSX zzse8j3ra9hd0*-IW!hli>Mr^*LZ6cELbzq0_sGrgIRw367QoyrXOOoTgsGaP_i ziH@tuL_(Y0R_cIqNBD(txd82>X67x$7P@|Pd{x>|(HTvbPp1qUu2XafSy>0$08_Pq zjM~%agR!bs1Vt=J7~5_~aSM{O;Ma)szLk*KM+@PTl)Ht9r*-w*E#$eg&c!PCu>V~8 zQih+X`#@*KiXLYQxtr$Cy&?aB_HIQY*f2XU6akxK^E0P7kE{sx=GTN?l_ZvGVx(79 z3B_+qYbcVNcSmjY{!#fN9%ZDF>jfo#Xy&Yy z7d0TZq8jJpqJ8maW2F?4eeozFhDry0X>65EaxzFK+jq9^qkSw~gql#(Lp%fIbs(++aDv{% zMjJsb-kb_1XO&Mjj-6EZtOyD;$r+5ID$6*Xmqs~5v`FDuVZf@Evc`oromWm-aUsMo zq72ai!CcN(z-YOc#oMSuFg``ctKNzduBaojrrW6mnt<~QE%?L;uJ&zV0eInlSd)u&hH}t|(>91{6@`JOq5PyX7qAM%>`VAnDP|@t%}Oz( zD?!-+PJ$JFE7!zc$^NY2DB6SRj}c?b$C+6#wCIZtf4k#RQ{ zKIFL(#ld$0RZHvt4EE3<5|nUAXT4VT)7gT1tush_JT0o0+HTfbxxdN;qFNgT%I3Ot z6+i;)6RU`7YZR2*R*$URKeJM0_emCx`U~6gi;6-l(doq24(tyl*r+Nqiz?~I*jbD% z1bjom;UAOBb&6A2BkwkZvPf|K>Gs*e2|KUEDB*q2OsYTuEh|ahCy$Q!^Sre@b1D~% z&NB~0!6?CkP-Ru`iRwbCu(ozj*5XSn7u?B7*)zEtXQ3i27iIs>UT*?nwJY+~ej&ia zUPwypK{1GCS%tNZfDlk9y-Cfb8MZW4Y@xl&kg#>kpnAO_4aSs$ddRmM6E`>K&el!R^E z)=e{5n7}rJqfAQ_j<%@8*4h{q)#ej?=1XO^PTLflB&jQOw#Uudj*POislBZORiEqA z+FS}^nOdLQ574G^IOuTC zR0?&1ASY($ww(-DP7D@;7P0_28UuSMftb1bV~*7F*# zQsj#rP&n#q&Qc?cz}}%k%oP#5Jq|xBSq85f79qK-Gj(+V#!BJd>^Pi0@lZ8MadWe% z9V~R#Rd9B7bGCYbf957P$*=JLM3GXhGfrjan;Lu+lO#)#`ntpuBpYf>99%Gem{ zpAnQR(H8a~PX1(XxO}VFwht`EjY4iz#H3Q@>>zPC6vkE1jnrNEi>sg;X}cshK3sMq&NT{3zbDcMtPdnsT(>+S6N2Fxm;bRvdDri zxkQ)G(v{~$m{)wTsR@o`g+pX2V`lftcCZD(bLHk?Z;~|uos`<58{|k+u;3?cWZ6A4 zoVA6pMQBQQW>6`S$9e+eK-T;|ozUQA`;~e*S7J~^Nut_H>M1)K<_hK2sK9nvUGJIF zat8JG#2~+@xVcL5!YYNk46&5F66IA>v5;A~4cZ1IZ0MAjF|x1w)*30;3kD>#TDANX z*q%D6QK$N)3KeZ}?e6;lOrb#|Az}cCtg7v@#cP7r0i4eQPAIM@fTD|iJC2Z&qJfld zIU}_Qf18B_p}{IqT+G86QBN)i3IIP=so^^cLy8Nf2xrN`efcovxSx7BeT||pq8Cd3 zVLn&9#%>_-yS)EI*##fWxq+sTbN;F2CbCfK!Ipy^r-eCnK5Sw+Bn$iQU5pI|@AD1KUIk%!>;kco=BY~lOX zc2S1ULt84`&Rw^?I3qVDwVL{jm_NW4Er&@qK~v7lHZmyeZ4<@IG>9vuiff-Z+g0Lm zwMi!Mq}@ObXT=}awkL~SxiKCLCQ7iLi1N?&RaYOd(Pz%!Gr=b{DPTLV5qY*kSN{Jd zGvtW#{i(8(aG@zX2^IQT*~wX)|MB(155IVPy!qqd<#&g-Z*Sfo!r{9gk2mkXKZL{2 ze}41u?%@y)_s6HZZ|5y-B(prPN%yz)X1>j(x@~XUxE=Ft zDX+Y2M{m;2di$#1&IdR@E50ASJ#KBu_rs3c9a?!co8YA#)ArzUQ|{LzZpQug;A;Ig z&C6;kWp>u?@~eoL;vej;n6>Tg{r&yCuifQxzn^=&+s?g@-e%wIuK4Xb;bz3yGP^6I zPl4IJ_2X=g-Id}~;C7$x*B$De-);}CcjJC`lcFZCwnwzs<94%lcf6Usuy*wIh<3bL zE$d!yw>xx_Y}BC??{3#+{dTMek7Q{Zx4Sg%_NKpjwK`Pp@+L`dF>j*w5$`rhdcRvY zyDPWHCCOTC-S_6WDGr_AMSXXd=djq_-Q9j}Npb7jJ+%2bSbl#@>uJYvGX>@T%G0I~ ze(Yr%?qlVxHMQp8mlDpz`KXnPcBWC3c55S=BwwotCbbfU$!c&>C{|1s8MQTdH#$yk zHDNp!$+j^tE_;>1U)W`}gQrVNRWhxu17?nMUOeWsiu_vMgxsZ`j z6;rgWQhe8`<~^rf6dK+-y3BdcqsJVx2p&Jm# zMQpiPl7~uZqTM*{O8Q!xXf#__Rz+A_^g88~gUncMR0n%-C`I@@gPnlbz@FCI4 zZahv@Nwf}8S&LpRn~HRt!oQYX6cAC~_c2(ayeadQ;zbvw)v9u@vC46|ehxo}`joFYIE z*fF)_d}Dp@x~}6DXt>`ZQX*??rgpdmY}xnGLJ-SWSR2F%E+ns$-Q+| zTU48o_u{8q#XJn!L7@pBZdAl8vw15dJ*+hdcR~42GSfcQe6p%MIS1w1b!{Z9x>0m8 z1esd`r;;jzqb9Ul(0O>(g3pwwF?KtgGweHGC_aTVVC#t&{ z^yJ8@J~wCOtwd`ROGVCaVj?k3;${H|LewJ%HZtY3lN#2{K@DrIyo$KiM(T!D+SLcm zjhiZ&8j`Yb4Qh94^+~lvb*zm!D-JD(qMCNYxkb^{!D+K82Az>qHsM8Zvv@#ISu$Qu zZ5zWuThno+RjjdHsj2d)J8k;1#%gA3E8^kfr*@p#s<#SFsEQ!&qG;gjh$`fm^(h$N zK@Y&C=zDVvqKa*HwW^&9PW5^YK~xRkjnt{kw5d_e)XLD-9CIC=vDr-x7jqdi!l8&- z=VHbEf!C`%SxiwHCElH~r!Gr?uqDC*=1DwrNF}ukk!22H5 z*M~0DIWr!!1jP`lk&W;N3^MeFLNx>%C#)!@Vh$6`mjLaf3`#H;uqL?s6$Wl7=~a9ULz zhoY*8>n^OARuV_k=2orBPza(HaWxKFM;nT8MXg0yxwhE=hpJqSCC%h&^~zImn+z)l zGkv-(&lzk{-S%R1?QN?wvN*S?n5ovtWMRBaPH4!fY~vyvZ(Xqi;bIJdsCco_MBMf< z2O!+Bt*G))tP>_GrKyjdNoBM+QYPcIsvRmtXBLZIwUiuI@g(7~4SC{_r*f)IoDj>c zh>_qNR#AWJ+Kd{J+NNaeYM%3P(U)tQSJ&eLQZI52;w53}rP7jD;k%esEI6#917Y_h z1mVmU<_uQWkPKDz_rRFqYJgIrPMFm~*>#;u9L`zwC9h755sd%PfgFnXlbrUcV=0Qq z!PyFjLPJhZiG^a-vwEx9Os&46wW^NDWmCJHc`jfwR|$`CiJMsHjl8}$u0?5? zEX|IGC=&}Uq+yv<%qo7L^IH>}=7JZ-25yeHQk>K_5tSeUjdhcRx;U_E1PG>@$J*4V zqLpNA%`xwyM`D!s zW46jqafY)t3Nl}C5Oh6RTTv|ox{0NMMv|X3#OeN#kQmV+RkW$8l2|M0N;^j{_0XBe zMU9fRhNCmvG@c3dE?Nd!O1+A;QWPhArBy>PtEnWeWZEZT3{Ao`(gkmAMr0ZWR)mH_ z)u2LTasDuc!Xq5B@=z(OgaP6Ct0^l1sE1dRLQ_ zp)wf}MEHA3xa^8FhLxX2lQKE+H@HlXvy>UDfQnUysxv5Boze9`C{rsI(GQr|VWWv^ zQEOY9E_m%ms_Fq~tC0)_+U{_Oa;*}*gRvAZX5WK^tnI$o+#hOc0VkG?v zLAE$`758G)pl`GbOWU>j=_Q!WizKk!RU5W#m)I1iT^3hhGl@DvMM*e`C^zNVTH_4n zIWxx&h#zr`osn1rXZ=uuNt!_%OA-;bHF=>f-YcFG$1I|Tc(1C6oJ604%J$)o@Sdq9N(bRimMqtAx72FzTu8#!Yv82AnEo@m%462%|uC&dH;uN)k+=>)MSa zo(Tz_%QU~QA{LwTt1NzMiz-327BOXLOk1eUOj!s{mruD>RbyZvk--Y*v`+)aT^uUJ zfkg0aDOCfSnT*8#?dq!r`%2m7s$fl`ML6vm|4mJ3%Q1@xgDzw0!6s9L*v<)aMk2Cc z9_7i+Sy`z8(LRWf#Wm}yF6JOhXd7dbr8)RO{iL<2gtC%HK)x~P4BLg{d3Y)|pF}G?#ur$;uSyz!Ocw!>N@WgaQU1+Y&e3*fX z%37a_N^>z{`r%>E=tf!fyAc$z=zwHh6WbqyRb85j#QtG`q`JBpsoU@wYz!+Nzr$1? z)SmKoV&P76ngKM;9R#w4yYR8g{gSAcn%UW_xM$BCMs3W|-aqd8Skdr$!4 z1K_8AYl26l0?ti^i`mveZny@6#N7anpV0HraD-K5y+f6?(b|FrNTOOV zC_7n7BCsdl#Sn`cukXP!i8*j?O{@ey-N@D2(lNqg)pXDRmBaE0+h$kvYg6{S z43CKQ6A;m+`lz#@QiW+9D!zZ!Q(A8%%A9Cds@S|vpSHwl`N}3P8%LgB<0H={PSD^k z+%(}#E>^?|{)J9!DPF%yLrm{4)`>z1bwJCcugpq47?6p9(t#`i-B zSK_BQe9*q465-#^P)*d2Z&}?0$kXwY2dQ_lk$z=@uQR5DQxjppa!Qu>oHqT4TP`!!!OrT(&22X-LCs_dpxF{u-AdC;(N74Cbj5C)BmH>T z63KFsOxt8$2&tn6mjTFmNP~|>LQFog_*uBULUR~bZ zx7+V7fqG{tCO~~JNdDo|;o|P~%@2Ppw|{B3cfY^JJy)04?c&8=uI}28hrbWByzffA zY8Nm5esR^VU){gHcwr6~W!rAs-QC5D?_VA+F0b*}H|;GdabYd@?bXdK_Bg#fT--g> z#~1d8>vdFJm;1|i?c2Y;sW(^J)^)r6zsu|G=7-;ZGcJuj^>%Nr9^PEz>W_!s%2Qpt z9sqyn*WG`7JDRv{SM6Q7zW?`|+vBCXn}^%AjT`pMtM;e)Al~?=hc~s|j@t3wvAU@xVta6_j=EddeiAfu*u)drCNI3YtiQkB+WXN#?bDBki?`+Bu5JHau3t5o z-?z$E-9>tPd$YE?yFsnf4obzhuOIHWn;$wm3Cj`1#rq5Z;&~Uw`|$RJFNyq;l1Ca5 zz3IEZzHJwH$6g+;?k^4(Pq6dpW4AJ=PqD?-Wqmx_6j3^ z#P2_}%U7@Or9XPh0kgLLMVh#L)4pj}_eF>{o{+jeY5(?L|I=^4wIAi#r+WJKw(XZP zFA7&V9yr}Rcq;CFUY->8Q_BBy!k*%(wBr*Fc8!i?tvJV$aB?9eY_|1Si{SVoP8epu z_=SuUJf5*N+%vE-d_uYn&)9A2J<_>#?AJs%+m{jbjYv>!ERK>g`HbC{4D5C6*p3vC z(KovgJT`4dWOM>9Psk2nt<0(8<1!mUE|;8K>^LDAFv306H{O60*}X07RmFKApZWpH zG)@^Ife|6KW(KG$Gt%1P<*vi=QvyJ$Gk_m;J_m!WIL>F!IN;(u$B3LEE*O`AZ;C72 zPgo&@ilb^h;co=iJ&rYETQeSy9bVRFACUaT`OF!(rlUcek?~9cn~0rf*K@Jqhr_Y! zeh{u1BkTIBB;^6b6r=ysad&ad;nT3X11Aqm48b@!q`Z2Bo%=j+?gtRKkI>Z2Q|IkJ z0<-NWi4G}r!+x~J7cai=Ne{pLcl8UhfatX>~SA%5c{`mN8%=jwl- z*%?gwl%HYG{L#VobQEsZyMsGfb%X9-M~NKc!y(#p+)k^ee*OB}lD@#)m&_@s(yo zuOC;?KV0F?J>h?binA{d=UyJqRitwjXWx;}J@FYU&c2+_z5E}qIQtH3&b{P(&H2X8 z^4!l=bG~b5x&AZPobSPBtvTP=S(*I2HRn5URxW?GnzIVv^VXav!C6J~v(=o{PoKHw ztSb7vHD^gpXZ6=-t~smPey*CcB>2ZG&TE2a26L9s=V$t#VZ!sGb6%>?Yn-#Rc}DA> zo$2!y@vIb_wK`|DG@X6q^VXcD%;$a0m)0(RP8z&CoNOpEi#dGx_b*F><9@M!v6bzo zR_ZSgb9>w;@BLI;zpZ*~>NwdA*f(wVeOw_%pi^QKXD>$wtih8quXwNOi zMr3C^DQ9F2KbFa0uiQzQI`sa0o&r)YN!c$ZS~HogmpuT0PwFFpc2CL)NyJae>`&_h zS)@dt^#Rj$(q5o|+~z0s2?;f3IfV|dKDz6d6y0$yQH&k@^H`mGx|mr`#`MI%;62=* zIxO@oX5u3;{gQI%IIqY0jI4+!WkwpzW0~2Umb0+{cAoXw(ByRImuwthYme2I0KI-v z?l~^>?HRipAKjiiHvX}m9}N!M5|6Cp7iO|k?t8f>=FrEP1M=6Llq1qFN;xbx#SS4p z?hi|L5rECdvJcqVDdo6?$k-M+%h3d6em|BW_>amV0@Zu8AD8I(gfrq2z3Tv|ed;tk?oRsqkpT#8y0#@;{K867i+nY;^^`4PvpqHavGB$teXj0cgJmmo8Y>*;y z+>bKjpuw^1T|8>JloyU6B5i4JKfA><0}^(WIWC4h_UB4DFUccmgcNyU6CL*Q;&Erp zVw?xqvXt#Y-Wyd~&d}ncN6JsBrzN<+*oQlwrzJ+tIytyM`2=*>S)W}7;OZ>1b)-rg z_j69j03-EoF^PIkjM2VZtdD&!sg{Y{lq6@|;!K*u@8z8Gv43vyDNa#AeTZaKZJ`{! zcd;Y2j_~@$dR4ApeYM}*zA4y${;Sx7-;Z`Y-i7}`H_z|Hch)Q^n3U7pWdGDo{ExQl z|FoU>$H&g@#E%`v_Tt6qM$n^=+cP*Fg6kVG^C4k_tL)N$_R}0T!;dZeC!g2*p81b= z^OHY(YCHc(gPQvvve6u@m6Anfhy&7a2JArUxcNPyPC`Dq1o-T}G5_Q&KxbBRaiNd^ ze(e@Rwr4$A496}`OSII}7AzrnhQKY@dJg>Q#kqjQJ#Jy^dlIxIB!W(&#aJZxvWt&| zl(Tm6A@tm{OY8_ocomdiJcNZZ4x%0W!q#yAVQ}&|9sH7gLi&fWSa>w?;1=ft(udi_ zJDkBi*u`Yz8no~mdj6&*CKD{iI?p+rP=0Pp^R1haRaLxxtMwS#0jC#~zpB4PR(QFzADa!is$%||t5_0sS zbKB`&Wo*V6sp9?E&kD7LWW@*M#L&IUHXNXBk;3`_0`{G1_&*?oB_jTNz;E z=XWb3ZJusda|hY6hWuuliRr1`%1CyUk%9=>H;{g3?pB^#*RV7Db{u><9j+z<9=s2~ z`>EkV6p$obhWo+Byt#e*6Fc;t88!0#JvC}%y+9i8Ickr?3nyvOKG?8FbKqnCPY=@Q zchm3tVV(}d{cv~t_0?tl`s(W4o3E_-x?Wy?{eg;|P~G$9_c{JK`me4ouOHrj_3HZJ z>#OYqt^50T+uaQs|Nh;(a@*h1?$@ucw&m_-S>$1Kb;&RgFyj}a*`+QkP zSJ$_1(RM%1IPd(plb7`mfB4@&eq~L+`BR;^yWiH|{SLRr1>VZ1?tk-Ccc1FSt9AYJ z-B0SmDF*tpIi{{c7Z>@T!0cH4DJNYDv!9T4~wZRZmgd$~fx!F=LwdX)94MCGr}h zU>W7jZi1bYH=y&5wOj5aZ;t**ZAL zlj3FGC!d<&bYvX22IjyA8pFJgp&x{Q3ddjI2qFtcPF}eRP8p}bf&|CODKI3{UIcU_ zt^&7{SWq^|y4CA}V(V5Xlp-5)Q8)q{Cyo%=z^Nl)TwOjT;^uuR^$4D+;Nv+7NNZBO zFS4#?IaQ6{R`BA;`s@{17oAY_R_j|);B*^|lk@ZVT@|>(hP>)IXzOzoJRq_$PWUpw zT?zgXey;)pK$ZaL)ER;-)ol`jcB7zH6Yd$UuL?tLlWzjYh2Oidcj8rYL z`RuGnCsxtpbHswHcgM$l8vp=p+W;~4_(11#=eLh8{If?o5kW1-L%g>)*Z_L_pYPi3 c>wbiIoTz@dzHhhv%<7N-4`5oe*+%RE0KsZinE(I) literal 0 HcmV?d00001 From 5c74fd012a9723efad96ca11e50c48a984088232 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 17 Jun 2025 16:07:09 +0200 Subject: [PATCH 25/57] partial parser integration of arena --- src/ast/mod.rs | 31 +++---- src/parser/mod.rs | 195 ++++++++++++++++++++++++++------------------ src/parser/utils.rs | 31 +++---- 3 files changed, 150 insertions(+), 107 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index ee4c773f..28f2c933 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1,7 +1,7 @@ use std::fmt; use crate::ast::internal::PathElem; -use bumpalo::{collections::Vec as BumpVec, Bump}; +use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; use descend_derive::span_derive; pub use span::*; @@ -15,23 +15,23 @@ pub mod utils; pub mod visit; pub mod visit_mut; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct CompilUnit<'a> { - pub items: Vec>, + pub items: BumpVec<'a, Item<'a>>, pub source: &'a SourceCode<'a>, } impl<'a> CompilUnit<'a> { - pub fn new(items: Vec>, source: &'a SourceCode<'a>) -> Self { + pub fn new(items: BumpVec<'a, Item<'a>>, source: &'a SourceCode<'a>) -> Self { CompilUnit { items, source } } } -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum Item<'a> { - FunDef(&'a FunDef<'a>), - FunDecl(&'a FunDecl<'a>), - StructDecl(&'a StructDecl<'a>), + FunDef(BumpBox<'a, FunDef<'a>>), + FunDecl(BumpBox<'a, FunDecl<'a>>), + StructDecl(BumpBox<'a, StructDecl<'a>>), } #[derive(Debug, Clone, PartialEq)] @@ -146,7 +146,7 @@ pub struct ParamDecl<'a> { } #[span_derive(PartialEq)] -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Expr<'a> { pub expr: ExprKind<'a>, // FIXME misusing span_derive_ignore to ignore type on equality checks @@ -288,7 +288,7 @@ impl<'a> Sched<'a> { } } -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug)] pub struct Split<'a> { pub dim_compo: DimCompo, pub pos: Nat<'a>, @@ -352,18 +352,18 @@ impl<'a> Block<'a> { } } -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug)] pub struct AppKernel<'a> { pub grid_dim: Dim<'a>, pub block_dim: Dim<'a>, pub shared_mem_dtys: BumpVec<'a, DataTy<'a>>, pub shared_mem_prvs: BumpVec<'a, String>, - pub fun_ident: &'a Ident<'a>, + pub fun_ident: BumpBox<'a, Ident<'a>>, pub gen_args: BumpVec<'a, ArgKinded<'a>>, pub args: BumpVec<'a, Expr<'a>>, } -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug)] pub enum ExprKind<'a> { Hole, Lit(Lit), @@ -398,7 +398,8 @@ pub enum ExprKind<'a> { BumpVec<'a, Expr<'a>>, ), DepApp(Ident<'a>, BumpVec<'a, ArgKinded<'a>>), - AppKernel(&'a AppKernel<'a>), + //AppKernel(&'a AppKernel<'a>), + AppKernel(BumpBox<'a, AppKernel<'a>>), // TODO branches must be blocks IfElse(&'a Expr<'a>, &'a Expr<'a>, &'a Expr<'a>), // TODO branch must be block @@ -1345,7 +1346,7 @@ pub struct DataTy<'a> { } impl<'a> DataTy<'a> { - pub fn new_in(bump: &'a bumpalo::Bump, dty: DataTyKind<'a>) -> Self { + pub fn new(bump: &'a bumpalo::Bump, dty: DataTyKind<'a>) -> Self { DataTy { dty, constraints: BumpVec::new_in(bump), diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 935fef89..0149bc5b 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7,75 +7,99 @@ use core::iter; use error::ParseError; use std::collections::HashMap; +use crate::ast::visit_mut::VisitMut; use crate::error::ErrorReported; +use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; pub use source::*; -use crate::ast::visit_mut::VisitMut; +impl<'s> Item<'s> { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> Item<'a> { + match self { + Item::FunDef(boxed) => Item::FunDef(BumpBox::new_in(*boxed, arena)), + Item::FunDecl(boxed) => Item::FunDecl(BumpBox::new_in(*boxed, arena)), + Item::StructDecl(boxed) => Item::StructDecl(BumpBox::new_in(*boxed, arena)), + } + } +} -pub fn parse<'a>(source: &'a SourceCode<'a>) -> Result { - let parser = Parser::new(source); - let mut items = parser.parse().map_err(|err| err.emit())?; - // TODO refactor to not require unnecessary copying out of items - let struct_copies = items +pub fn parse<'a>( + arena: &'a bumpalo::Bump, + source: &'a SourceCode<'a>, +) -> Result, ErrorReported> { + let parser = Parser::new(arena, source); + let parsed_items = parser.parse().map_err(|err| err.emit())?; + + // Allocate Items into arena + let mut items = BumpVec::new_in(arena); + for item in parsed_items { + items.push(item.into_arena(arena)); + } + + // Collect StructDecls + let struct_copies: Vec<&'a StructDecl<'a>> = items .iter() - .filter_map(|i| { - if let Item::StructDecl(struct_dty) = i { - Some(struct_dty.as_ref()) - } else { - None - } + .filter_map(|item| match item { + Item::StructDecl(decl_box) => Some(&**decl_box), + _ => None, }) - .cloned() - .collect::>(); - for fun_def in &mut items.iter_mut().filter_map(|i| { - if let Item::FunDef(fun_def) = i { - Some(fun_def) - } else { - None + .collect(); + + // Mutate FunDefs + for item in items.iter_mut() { + if let Item::FunDef(fun_def) = item { + replace_arg_kinded_idents(fun_def.as_mut()); + replace_exec_idents_with_specific_execs(arena, fun_def.as_mut()); } - }) { - replace_arg_kinded_idents(fun_def); - replace_exec_idents_with_specific_execs(fun_def); } - for i in &mut items.iter_mut() { - replace_struct_idents_with_specific_struct_dtys(&struct_copies, i); + + // Apply struct replacements + for item in &mut items { + replace_struct_idents_with_specific_struct_dtys(&struct_copies, item); } + Ok(CompilUnit::new(items, source)) } #[derive(Debug)] struct Parser<'a> { + arena: &'a Bump, source: &'a SourceCode<'a>, } impl<'a> Parser<'a> { - fn new(source: &'a SourceCode<'a>) -> Self { - Parser { source } + fn new(arena: &'a Bump, source: &'a SourceCode<'a>) -> Self { + Parser { arena, source } } - fn parse(&self) -> Result, ParseError<'_>> { + fn parse(&self) -> Result>, ParseError<'_>> { descend::compil_unit(self.source.str()).map_err(|peg_err| ParseError::new(self, peg_err)) } } -fn replace_arg_kinded_idents(fun_def: &mut FunDef) { +fn replace_arg_kinded_idents<'a>(fun_def: &mut FunDef) { struct ReplaceArgKindedIdents { ident_names_to_kinds: HashMap, Kind>, } - impl ReplaceArgKindedIdents { - fn subst_in_gen_args(&self, gen_args: &mut [ArgKinded]) { + impl<'a> ReplaceArgKindedIdents { + fn subst_in_gen_args(&self, arena: &'a Bump, gen_args: &mut [ArgKinded<'a>]) { for gen_arg in gen_args { if let ArgKinded::Ident(ident) = gen_arg { let to_be_kinded = ident.clone(); - match self.ident_names_to_kinds.get(&ident.name).unwrap() { + match self + .ident_names_to_kinds + .get::(ident.name.as_ref()) + .unwrap() + { Kind::Provenance => { *gen_arg = ArgKinded::Provenance(Provenance::Ident(to_be_kinded)) } Kind::Memory => *gen_arg = ArgKinded::Memory(Memory::Ident(to_be_kinded)), Kind::Nat => *gen_arg = ArgKinded::Nat(Nat::Ident(to_be_kinded)), Kind::DataTy => { - *gen_arg = - ArgKinded::DataTy(DataTy::new(DataTyKind::Ident(to_be_kinded))) + *gen_arg = ArgKinded::DataTy(DataTy::new( + arena, + DataTyKind::Ident(to_be_kinded), + )) } } } @@ -83,8 +107,8 @@ fn replace_arg_kinded_idents(fun_def: &mut FunDef) { } } - impl VisitMut for ReplaceArgKindedIdents { - fn visit_expr(&mut self, expr: &mut Expr) { + impl<'a> VisitMut<'a> for ReplaceArgKindedIdents { + fn visit_expr(&mut self, arena: &'a Bump, expr: &mut Expr) { match &mut expr.expr { ExprKind::Block(block) => { self.ident_names_to_kinds.extend( @@ -97,7 +121,7 @@ fn replace_arg_kinded_idents(fun_def: &mut FunDef) { } ExprKind::DepApp(fun_ident, gen_args) => { self.visit_ident(fun_ident); - self.subst_in_gen_args(gen_args); + self.subst_in_gen_args(arena, gen_args); } ExprKind::AppKernel(app_kernel) => { let AppKernel { @@ -107,25 +131,27 @@ fn replace_arg_kinded_idents(fun_def: &mut FunDef) { .. } = app_kernel.as_mut(); self.visit_ident(fun_ident); - self.subst_in_gen_args(gen_args); + self.subst_in_gen_args(arena, gen_args); visit_mut::walk_list!(self, visit_expr, args) } ExprKind::App(fun_ident, gen_args, args) => { self.visit_ident(fun_ident); - self.subst_in_gen_args(gen_args); + self.subst_in_gen_args(arena, gen_args); visit_mut::walk_list!(self, visit_expr, args) } ExprKind::ForNat(ident, _, body) => { - self.ident_names_to_kinds - .extend(iter::once((ident.name.clone(), Kind::Nat))); + self.ident_names_to_kinds.extend(iter::once(( + ident.name.to_owned().into_boxed_str(), + Kind::Nat, + ))); self.visit_expr(body) } _ => visit_mut::walk_expr(self, expr), } } - fn visit_view(&mut self, view: &mut View) { - self.subst_in_gen_args(&mut view.gen_args); + fn visit_view(&mut self, arena: &'a Bump, view: &mut View) { + self.subst_in_gen_args(arena, &mut view.gen_args); for v in &mut view.args { self.visit_view(v) } @@ -135,7 +161,7 @@ fn replace_arg_kinded_idents(fun_def: &mut FunDef) { self.ident_names_to_kinds = fun_def .generic_params .iter() - .map(|IdentKinded { ident, kind }| (ident.name.clone(), *kind)) + .map(|IdentKinded { ident, kind }| (ident.name.to_owned().into_boxed_str(), *kind)) .collect(); visit_mut::walk_fun_def(self, fun_def) } @@ -146,12 +172,12 @@ fn replace_arg_kinded_idents(fun_def: &mut FunDef) { replace.visit_fun_def(fun_def); } -fn replace_exec_idents_with_specific_execs(fun_def: &mut FunDef) { - struct ReplaceExecIdents { - ident_names_to_exec_expr: Vec<(Box, ExecExpr)>, +fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut FunDef) { + struct ReplaceExecIdents<'a> { + ident_names_to_exec_expr: Vec<(Box, ExecExpr<'a>)>, } - impl VisitMut for ReplaceExecIdents { - fn visit_split(&mut self, indep: &mut Split) { + impl<'a> VisitMut<'a> for ReplaceExecIdents<'a> { + fn visit_split(&mut self, arena: &'a Bump, indep: &mut Split) { // manually expand to keep scopes for different branches of split expand_exec_expr(&self.ident_names_to_exec_expr, &mut indep.split_exec); for (i, (ident, branch)) in indep @@ -160,31 +186,35 @@ fn replace_exec_idents_with_specific_execs(fun_def: &mut FunDef) { .zip(&mut indep.branch_bodies) .enumerate() { - let branch_exec_expr = ExecExpr::new(indep.split_exec.exec.clone().split_proj( - indep.dim_compo, - indep.pos.clone(), - if i == 0 { - LeftOrRight::Left - } else if i == 1 { - LeftOrRight::Right - } else { - panic!("Unexpected projection.") - }, - )); + let branch_exec_expr = ExecExpr::new( + arena, + indep.split_exec.exec.clone().split_proj( + arena, + indep.dim_compo, + indep.pos.clone(), + if i == 0 { + LeftOrRight::Left + } else if i == 1 { + LeftOrRight::Right + } else { + panic!("Unexpected projection.") + }, + ), + ); self.ident_names_to_exec_expr - .push((ident.name.clone(), branch_exec_expr)); + .push((ident.name.to_owned().into_boxed_str(), branch_exec_expr)); self.visit_expr(branch); self.ident_names_to_exec_expr.pop(); } } - fn visit_sched(&mut self, sched: &mut Sched) { + fn visit_sched(&mut self, arena: &'a Bump, sched: &mut Sched) { // manually expand to map inner_exec_ident to expanded exec expand_exec_expr(&self.ident_names_to_exec_expr, &mut sched.sched_exec); - let body_exec = ExecExpr::new(sched.sched_exec.exec.clone().forall(sched.dim)); + let body_exec = ExecExpr::new(arena, sched.sched_exec.exec.clone().forall(sched.dim)); if let Some(ident) = &sched.inner_exec_ident { self.ident_names_to_exec_expr - .push((ident.name.clone(), body_exec)); + .push((ident.name.to_owned().into_boxed_str(), body_exec)); } visit_mut::walk_sched(self, sched); self.ident_names_to_exec_expr.pop(); @@ -206,23 +236,26 @@ fn replace_exec_idents_with_specific_execs(fun_def: &mut FunDef) { // } // } - fn visit_fun_def(&mut self, fun_def: &mut FunDef) { + fn visit_fun_def(&mut self, arena: &'a Bump, fun_def: &mut FunDef) { if let Some(ident_exec) = fun_def.generic_exec.as_ref() { match &ident_exec.ty.ty { ExecTyKind::CpuThread => { self.ident_names_to_exec_expr.push(( - ident_exec.ident.name.clone(), - ExecExpr::new(ExecExprKind::new(BaseExec::CpuThread)), + ident_exec.ident.name.to_owned().into_boxed_str(), + ExecExpr::new(arena, ExecExprKind::new(arena, BaseExec::CpuThread)), )); fun_def.generic_exec = None; } ExecTyKind::GpuGrid(gdim, bdim) => { self.ident_names_to_exec_expr.push(( - ident_exec.ident.name.clone(), - ExecExpr::new(ExecExprKind::new(BaseExec::GpuGrid( - gdim.clone(), - bdim.clone(), - ))), + ident_exec.ident.name.to_owned().into_boxed_str(), + ExecExpr::new( + arena, + ExecExprKind::new( + arena, + BaseExec::GpuGrid(gdim.clone(), bdim.clone()), + ), + ), )); fun_def.generic_exec = None; } @@ -233,7 +266,7 @@ fn replace_exec_idents_with_specific_execs(fun_def: &mut FunDef) { } } - fn expand_exec_expr(exec_mapping: &[(Box, ExecExpr)], exec_expr: &mut ExecExpr) { + fn expand_exec_expr<'a>(exec_mapping: &[(Box, ExecExpr)], exec_expr: &mut ExecExpr<'a>) { match &exec_expr.exec.base { BaseExec::CpuThread | BaseExec::GpuGrid(_, _) => {} BaseExec::Ident(ident) => { @@ -248,9 +281,12 @@ fn replace_exec_idents_with_specific_execs(fun_def: &mut FunDef) { } } - fn get_exec_expr(exec_mapping: &[(Box, ExecExpr)], ident: &Ident) -> Option { + fn get_exec_expr<'a>( + exec_mapping: &[(Box, ExecExpr)], + ident: &Ident, + ) -> Option> { for (i, exec) in exec_mapping.iter().rev() { - if i == &ident.name { + if i.as_ref() == ident.name { return Some(exec.clone()); } } @@ -263,15 +299,18 @@ fn replace_exec_idents_with_specific_execs(fun_def: &mut FunDef) { replace_exec_idents.visit_fun_def(fun_def); } -fn replace_struct_idents_with_specific_struct_dtys(struct_dtys: &[StructDecl], item: &mut Item) { +fn replace_struct_idents_with_specific_struct_dtys<'a>( + struct_dtys: &[&'a StructDecl<'a>], + item: &mut Item, +) { struct ReplaceStructIdents<'a> { - struct_dtys: &'a [StructDecl], + struct_dtys: &'a [&'a StructDecl<'a>], } - impl<'a> VisitMut for ReplaceStructIdents<'a> { + impl<'a> VisitMut<'a> for ReplaceStructIdents<'a> { fn visit_dty(&mut self, dty: &mut DataTy) { if let DataTyKind::Ident(ident) = &mut dty.dty { if let Some(struct_decl) = self.struct_dtys.iter().find(|s| &s.ident == ident) { - dty.dty = DataTyKind::Struct(Box::new(struct_decl.clone())) + dty.dty = DataTyKind::Struct(struct_decl) } } else { visit_mut::walk_dty(self, dty) diff --git a/src/parser/utils.rs b/src/parser/utils.rs index 7e1f311e..37d8e596 100644 --- a/src/parser/utils.rs +++ b/src/parser/utils.rs @@ -1,18 +1,21 @@ //! Helper functions for parsing use crate::ast::{BinOp, BinOpNat, DataTy, DataTyKind, Expr, ExprKind, Lit, Nat, ScalarTy, UnOp}; -use bumpalo::{boxed::Box as BumpBox, Bump}; +use bumpalo::Bump; -pub fn type_from_lit(lit: &Lit) -> DataTy { - DataTy::new(DataTyKind::Scalar(match lit { - Lit::Bool(_) => ScalarTy::Bool, - Lit::Unit => ScalarTy::Unit, - Lit::I32(_) => ScalarTy::I32, - Lit::U8(_) => ScalarTy::U8, - Lit::U32(_) => ScalarTy::U32, - Lit::U64(_) => ScalarTy::U64, - Lit::F32(_) => ScalarTy::F32, - Lit::F64(_) => ScalarTy::F64, - })) +pub fn type_from_lit<'a>(bump: &'a Bump, lit: &Lit) -> DataTy<'a> { + DataTy::new( + bump, + DataTyKind::Scalar(match lit { + Lit::Bool(_) => ScalarTy::Bool, + Lit::Unit => ScalarTy::Unit, + Lit::I32(_) => ScalarTy::I32, + Lit::U8(_) => ScalarTy::U8, + Lit::U32(_) => ScalarTy::U32, + Lit::U64(_) => ScalarTy::U64, + Lit::F32(_) => ScalarTy::F32, + Lit::F64(_) => ScalarTy::F64, + }), + ) } pub fn make_binary<'a>(bump: &'a Bump, op: BinOp, lhs: Expr<'a>, rhs: Expr<'a>) -> Expr<'a> { @@ -25,7 +28,7 @@ pub fn make_binary<'a>(bump: &'a Bump, op: BinOp, lhs: Expr<'a>, rhs: Expr<'a>) // vec![lhs, rhs], // )) Expr { - expr: ExprKind::BinOp(op, BumpBox::new_in(lhs, bump), BumpBox::new_in(rhs, bump)), + expr: ExprKind::BinOp(op, bump.alloc(lhs), bump.alloc(rhs)), ty: None, span: None, } @@ -45,7 +48,7 @@ pub fn make_unary<'a>(bump: &'a Bump, op: UnOp, rhs: Expr<'a>) -> Expr<'a> { // vec![rhs], // )) Expr { - expr: ExprKind::UnOp(op, BumpBox::new_in(rhs, bump)), + expr: ExprKind::UnOp(op, bump.alloc(rhs)), ty: None, span: None, } From 55f6d5d978d4ae1f2ac3bf7941a20921b820375e Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 1 Jul 2025 16:15:25 +0200 Subject: [PATCH 26/57] change the complete parser stuff again --- src/arena_ast/internal.rs | 219 ++++ src/arena_ast/mod.rs | 1848 +++++++++++++++++++++++++++++ src/arena_ast/printer.rs | 380 ++++++ src/arena_ast/span.rs | 21 + src/arena_ast/utils.rs | 443 +++++++ src/arena_ast/visit.rs | 580 +++++++++ src/arena_ast/visit_mut.rs | 587 +++++++++ src/ast/internal.rs | 227 ++-- src/ast/mod.rs | 1060 ++++++++--------- src/ast/utils.rs | 146 +-- src/ast/visit.rs | 140 +-- src/ast/visit_mut.rs | 147 ++- src/codegen/cu_ast.rs | 4 +- src/codegen/mod.rs | 8 +- src/codegen/printer.rs | 2 +- src/lib.rs | 1 + src/parser/mod.rs | 281 +++-- src/parser/utils.rs | 37 +- src/ty_check/borrow_check.rs | 4 +- src/ty_check/ctxs.rs | 4 +- src/ty_check/error.rs | 6 +- src/ty_check/exec.rs | 2 +- src/ty_check/infer_kinded_args.rs | 2 +- src/ty_check/mod.rs | 8 +- src/ty_check/pl_expr.rs | 2 +- src/ty_check/pre_decl.rs | 2 +- src/ty_check/subty.rs | 4 +- src/ty_check/unify.rs | 8 +- 28 files changed, 5099 insertions(+), 1074 deletions(-) create mode 100644 src/arena_ast/internal.rs create mode 100644 src/arena_ast/mod.rs create mode 100644 src/arena_ast/printer.rs create mode 100644 src/arena_ast/span.rs create mode 100644 src/arena_ast/utils.rs create mode 100644 src/arena_ast/visit.rs create mode 100644 src/arena_ast/visit_mut.rs diff --git a/src/arena_ast/internal.rs b/src/arena_ast/internal.rs new file mode 100644 index 00000000..e0aaa2e4 --- /dev/null +++ b/src/arena_ast/internal.rs @@ -0,0 +1,219 @@ +// Constructs in this module are part of the AST but not part of the user facing syntax. +// These are also used in typechecking and ty_check::ctxs + +// TODO specific access modifiers + +use super::{Ident, Ownership, PlaceExpr, Ty}; +use crate::arena_ast::{ExecExpr, Mutability, Nat, PlaceExprKind, View}; +use bumpalo::collections::Vec as BumpVec; +use std::collections::HashSet; + +// TODO: Removed the Default trait here, see what kind of consequences has this later +// Otherwise implement the trait +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Frame<'a> { + pub bindings: BumpVec<'a, FrameEntry<'a>>, +} + +impl<'a> Frame<'a> { + pub fn new_in(bump: &'a bumpalo::Bump) -> Self { + Self { + bindings: BumpVec::new_in(bump), + } + } + + pub fn append_idents_typed(&mut self, idents_typed: I) + where + I: IntoIterator>, + { + for ident in idents_typed { + self.bindings.push(FrameEntry::Var(ident)); + } + } +} + +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum FrameEntry<'a> { + Var(IdentTyped<'a>), + ExecMapping(ExecMapping<'a>), + PrvMapping(PrvMapping<'a>), +} + +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct IdentTyped<'a> { + pub ident: Ident<'a>, + pub ty: Ty<'a>, + pub mutbl: Mutability, + pub exec: ExecExpr<'a>, +} + +impl<'a> IdentTyped<'a> { + pub fn new_in( + arena: &'a bumpalo::Bump, + ident: &'a str, + ty: Ty<'a>, + mutbl: Mutability, + exec: ExecExpr<'a>, + ) -> Self { + IdentTyped { + ident: Ident::new(arena, ident), + ty, + mutbl, + exec, + } + } +} + +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct ExecMapping<'a> { + pub ident: Ident<'a>, + pub exec_expr: ExecExpr<'a>, +} + +impl<'a> ExecMapping<'a> { + pub fn new(ident: Ident<'a>, exec_expr: ExecExpr<'a>) -> Self { + ExecMapping { ident, exec_expr } + } +} + +// TODO: Problems with HashSet and String in the Arena implementation --> Find a work +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct PrvMapping<'a> { + pub prv: String, + pub loans: HashSet>, +} + +impl<'a> PrvMapping<'a> { + pub fn new(name: &str) -> Self { + PrvMapping { + prv: name.to_string(), + loans: HashSet::new(), + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct Loan<'a> { + pub place_expr: PlaceExpr<'a>, + pub own: Ownership, +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum PathElem<'a> { + Proj(usize), + FieldProj(&'a Ident<'a>), +} +pub type Path<'a> = BumpVec<'a, PathElem<'a>>; + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct Place<'a> { + pub ident: Ident<'a>, + pub path: Path<'a>, +} +impl<'a> Place<'a> { + pub fn new(ident: Ident<'a>, path: Path<'a>) -> Self { + Place { ident, path } + } + + pub fn to_place_expr(&self, arena: &'a bumpalo::Bump) -> PlaceExpr { + self.path.iter().fold( + PlaceExpr::new(PlaceExprKind::Ident(self.ident.clone())), + |pl_expr, path_entry| match path_entry { + PathElem::Proj(n) => PlaceExpr::new(PlaceExprKind::Proj(arena.alloc(pl_expr), *n)), + PathElem::FieldProj(field) => { + PlaceExpr::new(PlaceExprKind::FieldProj(arena.alloc(pl_expr), field)) + } + }, + ) + } + + /** + pub fn prefix_of(&self, other: &Self) -> bool { + if self.path.len() > other.path.len() { + return false; + } + self.ident == other.ident && &self.path == &other.path[..self.path.len()] + }*/ + + pub fn prefix_of(&self, other: &Self) -> bool { + if self.ident != other.ident || self.path.len() > other.path.len() { + return false; + } + + other.path.iter().zip(&self.path).all(|(a, b)| a == b) + } +} + +pub enum PlaceCtx<'a> { + Proj(&'a PlaceCtx<'a>, usize), + FieldProj(&'a PlaceCtx<'a>, Ident<'a>), + Deref(&'a PlaceCtx<'a>), + Select(&'a PlaceCtx<'a>, &'a ExecExpr<'a>), + View(&'a PlaceCtx<'a>, &'a View<'a>), + Idx(&'a PlaceCtx<'a>, &'a Nat<'a>), + Hole, +} + +impl<'a> PlaceCtx<'a> { + pub fn insert_pl_expr( + &'a self, + arena: &'a bumpalo::Bump, + pl_expr: PlaceExpr<'a>, + ) -> PlaceExpr<'a> { + match self { + Self::Hole => pl_expr, + Self::Proj(pl_ctx, n) => PlaceExpr::new(PlaceExprKind::Proj( + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + *n, + )), + Self::FieldProj(pl_ctx, field) => PlaceExpr::new(PlaceExprKind::FieldProj( + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + field, + )), + Self::Deref(pl_ctx) => PlaceExpr::new(PlaceExprKind::Deref( + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + )), + Self::Select(pl_ctx, exec) => PlaceExpr::new(PlaceExprKind::Select( + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + exec.clone(), + )), + Self::View(pl_ctx, view) => PlaceExpr::new(PlaceExprKind::View( + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + view.clone(), + )), + Self::Idx(pl_ctx, idx) => PlaceExpr::new(PlaceExprKind::Idx( + arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + idx.clone(), + )), + } + } + + pub fn without_innermost_deref(&'a self, arena: &'a bumpalo::Bump) -> &'a PlaceCtx<'a> { + match self { + PlaceCtx::Hole => self, + PlaceCtx::Proj(pl_ctx, idx) => { + arena.alloc(PlaceCtx::Proj(pl_ctx.without_innermost_deref(arena), *idx)) + } + PlaceCtx::FieldProj(pl_ctx, ident) => arena.alloc(PlaceCtx::FieldProj( + pl_ctx.without_innermost_deref(arena), + ident.clone(), + )), + PlaceCtx::Deref(pl_ctx) => match **pl_ctx { + PlaceCtx::Hole => arena.alloc(PlaceCtx::Hole), + _ => arena.alloc(PlaceCtx::Deref(pl_ctx.without_innermost_deref(arena))), + }, + PlaceCtx::Select(pl_ctx, exec) => arena.alloc(PlaceCtx::Select( + pl_ctx.without_innermost_deref(arena), + exec.clone(), + )), + PlaceCtx::View(pl_ctx, view) => arena.alloc(PlaceCtx::View( + pl_ctx.without_innermost_deref(arena), + view.clone(), + )), + PlaceCtx::Idx(pl_ctx, idx) => arena.alloc(PlaceCtx::Idx( + pl_ctx.without_innermost_deref(arena), + idx.clone(), + )), + } + } +} diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs new file mode 100644 index 00000000..96a8f0d1 --- /dev/null +++ b/src/arena_ast/mod.rs @@ -0,0 +1,1848 @@ +use std::fmt; + +use crate::arena_ast::internal::PathElem; +use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; +use descend_derive::span_derive; +pub use span::*; + +use crate::parser::SourceCode; + +pub mod internal; + +pub mod printer; +mod span; +pub mod utils; +pub mod visit; +pub mod visit_mut; + +#[derive(Debug)] +pub struct CompilUnit<'a> { + pub items: BumpVec<'a, Item<'a>>, + pub source: &'a SourceCode<'a>, +} + +impl<'a> CompilUnit<'a> { + pub fn new(items: BumpVec<'a, Item<'a>>, source: &'a SourceCode<'a>) -> Self { + CompilUnit { items, source } + } +} + +#[derive(Debug)] +pub enum Item<'a> { + FunDef(BumpBox<'a, FunDef<'a>>), + FunDecl(BumpBox<'a, FunDecl<'a>>), + StructDecl(BumpBox<'a, StructDecl<'a>>), +} + +#[derive(Debug, Clone, PartialEq)] +pub struct FunDecl<'a> { + pub ident: Ident<'a>, + pub generic_params: BumpVec<'a, IdentKinded<'a>>, + pub generic_exec: Option>, + pub param_decls: BumpVec<'a, ParamDecl<'a>>, + pub ret_dty: &'a DataTy<'a>, + pub exec: ExecExpr<'a>, + pub prv_rels: BumpVec<'a, PrvRel<'a>>, +} + +impl<'a> FunDecl<'a> { + pub fn fn_ty(&self, bump: &'a Bump) -> FnTy<'a> { + let mut param_sigs = BumpVec::new_in(bump); + for p_decl in &self.param_decls { + let exec_expr = p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(); + let ty = p_decl.ty.as_ref().unwrap().clone(); // This may need arena allocation too + param_sigs.push(ParamSig::new(exec_expr, ty)); + } + + let mut generics = BumpVec::new_in(bump); + generics.extend(self.generic_params.iter().cloned()); + + FnTy::new( + bump, + generics, + self.generic_exec.clone(), + param_sigs, + self.exec.clone(), + bump.alloc(Ty { + ty: TyKind::Data(self.ret_dty), + span: None, + }), + [], + ) + } +} + +#[derive(Debug, Clone, Eq, Hash, PartialEq)] +pub struct StructDecl<'a> { + pub ident: Ident<'a>, + pub generic_params: BumpVec<'a, IdentKinded<'a>>, + pub fields: BumpVec<'a, (Ident<'a>, DataTy<'a>)>, +} + +// TODO refactor to make use of FunDecl +#[derive(Debug, Clone, PartialEq)] +pub struct FunDef<'a> { + pub ident: Ident<'a>, + pub generic_params: BumpVec<'a, IdentKinded<'a>>, + pub generic_exec: Option>, + pub param_decls: BumpVec<'a, ParamDecl<'a>>, + pub ret_dty: &'a DataTy<'a>, + pub exec: ExecExpr<'a>, + pub prv_rels: BumpVec<'a, PrvRel<'a>>, + pub body: &'a Block<'a>, +} + +impl<'a> FunDef<'a> { + pub fn fn_ty(&self, bump: &'a Bump) -> FnTy<'a> { + let mut param_sigs = BumpVec::new_in(bump); + for p_decl in &self.param_decls { + let exec_expr = p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(); + let ty = p_decl.ty.expect("Missing parameter type"); + let ty_ref = bump.alloc(ty.clone()); + param_sigs.push(ParamSig::new(exec_expr, ty_ref)); + } + + let mut generics = BumpVec::new_in(bump); + generics.extend(self.generic_params.iter().cloned()); + + let ret_ty = bump.alloc(Ty { + ty: TyKind::Data(self.ret_dty), + span: None, + }); + + FnTy::new( + bump, + generics, + self.generic_exec.clone(), + param_sigs, + self.exec.clone(), + ret_ty, + [], + ) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct IdentExec<'a> { + pub ident: Ident<'a>, + pub ty: &'a ExecTy<'a>, +} + +impl<'a> IdentExec<'a> { + pub fn new_in(bump: &'a bumpalo::Bump, ident: Ident<'a>, exec_ty: ExecTy<'a>) -> Self { + IdentExec { + ident, + ty: bump.alloc(exec_ty), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParamDecl<'a> { + pub ident: Ident<'a>, + pub ty: Option<&'a Ty<'a>>, + pub mutbl: Mutability, + pub exec_expr: Option>, +} + +#[span_derive(PartialEq)] +#[derive(Debug)] +pub struct Expr<'a> { + pub expr: ExprKind<'a>, + // FIXME misusing span_derive_ignore to ignore type on equality checks + #[span_derive_ignore] + pub ty: Option<&'a Ty<'a>>, + #[span_derive_ignore] + pub span: Option, +} + +impl<'a> Expr<'a> { + pub fn new(expr: ExprKind<'a>) -> Self { + Expr { + expr, + ty: None, + span: None, + } + } + + pub fn with_span(expr: ExprKind<'a>, span: Span) -> Self { + Expr { + expr, + ty: None, + span: Some(span), + } + } + + pub fn with_type(expr: ExprKind<'a>, ty: &'a Ty<'a>) -> Self { + Expr { + expr, + ty: Some(ty), + span: None, + } + } + + // pub fn subst_idents(&mut self, subst_map: &HashMap<&str, &Expr>) { + // fn pl_expr_contains_name_in<'a, I>(pl_expr: &PlaceExpr, mut idents: I) -> bool + // where + // I: Iterator, + // { + // match &pl_expr.pl_expr { + // PlaceExprKind::Ident(ident) => idents.any(|name| ident.name.as_ref() == *name), + // PlaceExprKind::Proj(tuple, _) => pl_expr_contains_name_in(tuple, idents), + // PlaceExprKind::Deref(deref) => pl_expr_contains_name_in(deref, idents), + // PlaceExprKind::Select(pl_expr, _) => pl_expr_contains_name_in(pl_expr, idents), + // PlaceExprKind::SplitAt(_, pl_expr) => pl_expr_contains_name_in(pl_expr, idents), + // PlaceExprKind::View(pl_expr, _) => pl_expr_contains_name_in(pl_expr, idents), + // PlaceExprKind::Idx(pl_expr, _) => pl_expr_contains_name_in(pl_expr, idents), + // } + // } + // + // struct SubstIdents<'a> { + // subst_map: &'a HashMap<&'a str, &'a Expr>, + // } + // impl VisitMut for SubstIdents<'_> { + // fn visit_pl_expr(&mut self, pl_expr: &mut PlaceExpr) { + // if pl_expr_contains_name_in(pl_expr, self.subst_map.keys()) { + // match &pl_expr.pl_expr { + // PlaceExprKind::Ident(ident) => { + // let subst_expr = + // self.subst_map.get::(ident.name.as_ref()).unwrap(); + // if let ExprKind::PlaceExpr(pl_e) = &subst_expr.expr { + // *pl_expr = pl_e.as_ref().clone(); + // } else { + // // TODO can this happen? + // panic!("How did this happen?") + // } + // } + // _ => visit_mut::walk_pl_expr(self, pl_expr), + // } + // } + // } + // + // fn visit_expr(&mut self, expr: &mut Expr) { + // match &expr.expr { + // ExprKind::PlaceExpr(pl_expr) => { + // if pl_expr_contains_name_in(pl_expr, self.subst_map.keys()) { + // match &pl_expr.pl_expr { + // PlaceExprKind::Ident(ident) => { + // if let Some(&subst_expr) = + // self.subst_map.get::(ident.name.as_ref()) + // { + // *expr = subst_expr.clone(); + // } + // } + // PlaceExprKind::Proj(tuple, i) => { + // let mut tuple_expr = Expr::new(ExprKind::PlaceExpr(Box::new( + // tuple.as_ref().clone(), + // ))); + // self.visit_expr(&mut tuple_expr); + // *expr = Expr::new(ExprKind::Proj(Box::new(tuple_expr), *i)); + // } + // PlaceExprKind::Deref(deref_expr) => { + // let mut ref_expr = Expr::new(ExprKind::PlaceExpr(Box::new( + // deref_expr.as_ref().clone(), + // ))); + // self.visit_expr(&mut ref_expr); + // *expr = Expr::new(ExprKind::Deref(Box::new(ref_expr))); + // } + // PlaceExprKind::Select(_, _) + // | PlaceExprKind::SplitAt(_, _) + // | PlaceExprKind::Idx(_, _) + // | PlaceExprKind::View(_, _) => { + // unimplemented!() + // } + // } + // } + // } + // _ => visit_mut::walk_expr(self, expr), + // } + // } + // } + // let mut subst_idents = SubstIdents { subst_map }; + // subst_idents.visit_expr(self); + // } +} + +#[derive(PartialEq, Debug)] // Apparently you cannot clone BumpBoxes. If needed again, just make them mutable references? +pub struct Sched<'a> { + pub dim: DimCompo, + pub inner_exec_ident: Option>, + pub sched_exec: BumpBox<'a, ExecExpr<'a>>, + pub body: BumpBox<'a, Block<'a>>, +} + +impl<'a> Sched<'a> { + pub fn new_in( + bump: &'a bumpalo::Bump, + dim: DimCompo, + inner_exec_ident: Option>, + sched_exec: ExecExpr<'a>, + body: Block<'a>, + ) -> Self { + Sched { + dim, + inner_exec_ident, + sched_exec: BumpBox::new_in(sched_exec, bump), + body: BumpBox::new_in(body, bump), + } + } +} + +#[derive(PartialEq, Debug)] +pub struct Split<'a> { + pub dim_compo: DimCompo, + pub pos: Nat<'a>, + pub split_exec: &'a ExecExpr<'a>, + pub branch_idents: BumpVec<'a, Ident<'a>>, + pub branch_bodies: BumpVec<'a, Expr<'a>>, +} + +impl<'a> Split<'a> { + pub fn new( + bump: &'a bumpalo::Bump, + dim_compo: DimCompo, + pos: Nat<'a>, + split_exec: ExecExpr<'a>, + branch_idents: impl IntoIterator>, + branch_bodies: impl IntoIterator>, + ) -> Self { + let split_exec = bump.alloc(split_exec); + + let mut idents = BumpVec::new_in(bump); + idents.extend(branch_idents); + + let mut bodies = BumpVec::new_in(bump); + bodies.extend(branch_bodies); + + Split { + dim_compo, + pos, + split_exec, + branch_idents: idents, + branch_bodies: bodies, + } + } +} + +#[derive(PartialEq, Debug, Clone)] +pub struct Block<'a> { + pub prvs: BumpVec<'a, String>, + pub body: &'a Expr<'a>, +} + +impl<'a> Block<'a> { + pub fn new(bump: &'a bumpalo::Bump, body: Expr<'a>) -> Self { + Block { + prvs: BumpVec::new_in(bump), + body: bump.alloc(body), + } + } + + pub fn with_prvs( + bump: &'a bumpalo::Bump, + prvs: impl IntoIterator, + body: Expr<'a>, + ) -> Self { + let mut prvs_vec = BumpVec::new_in(bump); + prvs_vec.extend(prvs); + Block { + prvs: prvs_vec, + body: bump.alloc(body), + } + } +} + +#[derive(PartialEq, Debug)] +pub struct AppKernel<'a> { + pub grid_dim: Dim<'a>, + pub block_dim: Dim<'a>, + pub shared_mem_dtys: BumpVec<'a, DataTy<'a>>, + pub shared_mem_prvs: BumpVec<'a, String>, + pub fun_ident: BumpBox<'a, Ident<'a>>, + pub gen_args: BumpVec<'a, ArgKinded<'a>>, + pub args: BumpVec<'a, Expr<'a>>, +} + +#[derive(PartialEq, Debug)] +pub enum ExprKind<'a> { + Hole, + Lit(Lit), + // An l-value equivalent: *p, p.n, x + PlaceExpr(&'a PlaceExpr<'a>), + // e.g., [1, 2 + 3, 4] + Array(BumpVec<'a, Expr<'a>>), + Tuple(BumpVec<'a, Expr<'a>>), + // Borrow Expressions + Ref(Option, Ownership, &'a PlaceExpr<'a>), + Block(&'a Block<'a>), + // Variable declaration + // let mut x: ty; + LetUninit(Option<&'a ExecExpr<'a>>, Ident<'a>, &'a Ty<'a>), + // let w x: ty = e1 + Let(Pattern<'a>, Option<&'a Ty<'a>>, &'a Expr<'a>), + // Assignment to existing place [expression] + Assign(&'a PlaceExpr<'a>, &'a Expr<'a>), + // e1[i] = e2 + IdxAssign(&'a PlaceExpr<'a>, Nat<'a>, &'a Expr<'a>), + // e1 ; e2 + Seq(BumpVec<'a, Expr<'a>>), + // Anonymous function which can capture its surrounding context + // | x_n: d_1, ..., x_n: d_n | [exec]-> d_r { e } + // TODO body expression should always be block?! No but treated like one. + //Lambda(Vec, Ident<'a>Exec, Box, Box), + // Function application + // e_f(e_1, ..., e_n) + App( + &'a Ident<'a>, + BumpVec<'a, ArgKinded<'a>>, + BumpVec<'a, Expr<'a>>, + ), + DepApp(Ident<'a>, BumpVec<'a, ArgKinded<'a>>), + //AppKernel(&'a AppKernel<'a>), + AppKernel(BumpBox<'a, AppKernel<'a>>), + // TODO branches must be blocks + IfElse(&'a Expr<'a>, &'a Expr<'a>, &'a Expr<'a>), + // TODO branch must be block + If(&'a Expr<'a>, &'a Expr<'a>), + // For-each loop. + // for x in e_1 { e_2 } + // TODO body must be block + For(Ident<'a>, &'a Expr<'a>, &'a Expr<'a>), + // for n in range(..) { e } + // TODO body must be block + ForNat(Ident<'a>, &'a NatRange<'a>, &'a Expr<'a>), + // while( e_1 ) { e_2 } + // TODO body must be block + While(&'a Expr<'a>, &'a Expr<'a>), + BinOp(BinOp, &'a Expr<'a>, &'a Expr<'a>), + UnOp(UnOp, &'a Expr<'a>), + Cast(&'a Expr<'a>, &'a DataTy<'a>), + // TODO branches must be blocks or treated like blocks + Split(&'a Split<'a>), + Sched(&'a Sched<'a>), + Sync(Option>), + Unsafe(&'a Expr<'a>), + Range(&'a Expr<'a>, &'a Expr<'a>), +} + +#[derive(Clone, Debug)] +#[span_derive(PartialEq, Eq, Hash)] +pub struct Ident<'a> { + // Identifier names never change. Instead a new identifier is created. Therefore it is not + // necessary to keep the capacity that is stored in a String for efficient appending. + pub name: &'a str, + #[span_derive_ignore] + pub span: Option, + pub is_implicit: bool, +} +impl<'a> Ident<'a> { + pub fn new(bump: &'a bumpalo::Bump, name: &'a str) -> Self { + Self { + name: bump.alloc_str(name), + span: None, + is_implicit: false, + } + } + + pub fn new_impli(bump: &'a bumpalo::Bump, name: &'a str) -> Self { + Self { + name: bump.alloc_str(name), + span: None, + is_implicit: true, + } + } + + pub fn with_span(bump: &'a bumpalo::Bump, name: &'a str, span: Span) -> Self { + Self { + name: bump.alloc_str(name), + span: Some(span), + is_implicit: false, + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Pattern<'a> { + Ident(Mutability, Ident<'a>), + Tuple(BumpVec<'a, Pattern<'a>>), + Wildcard, +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum Lit { + Unit, + Bool(bool), + I32(i32), + U8(u8), + U32(u32), + U64(u64), + F32(f32), + F64(f64), +} + +// impl PartialEq for Lit{ +// fn eq(&self, other:&Self) -> bool { +// let b = match (self, other) { +// (Self::Unit, Self::Unit) => true, +// (Self::Bool(x), Self::Bool(y)) => if x == y {true} else {false}, +// (Self::Int(x), Self::Int(y)) => if x == y {true} else {false}, +// (Self::Float(x), Self::Float(y)) => if x == y {true} else {false}, +// _ => false +// }; +// b +// } +// } + +impl fmt::Display for Lit { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Unit => write!(f, "()"), + Self::Bool(b) => write!(f, "{}", b), + Self::I32(i) => write!(f, "{}", i), + Self::U8(uc) => write!(f, "{}", uc), + Self::U32(u) => write!(f, "{}", u), + Self::U64(ul) => write!(f, "{}", ul), + Self::F32(fl) => write!(f, "{}f", fl), + Self::F64(d) => write!(f, "{}", d), + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Mutability { + Const, + Mut, +} + +impl fmt::Display for Mutability { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match self { + Self::Const => "const", + Self::Mut => "mut", + }; + write!(f, "{}", str) + } +} + +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy, Clone)] +pub enum Ownership { + Shrd, + Uniq, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum UnOp { + Not, + Neg, +} + +impl fmt::Display for UnOp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match self { + Self::Not => "!", + Self::Neg => "-", + }; + write!(f, "{}", str) + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum BinOp { + Add, + Sub, + Mul, + Div, + Mod, + And, + Or, + Eq, + Lt, + Le, + Gt, + Ge, + Neq, + Shl, + Shr, + BitOr, + BitAnd, +} + +impl fmt::Display for BinOp { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match self { + Self::Add => "+", + Self::Sub => "-", + Self::Mul => "*", + Self::Div => "/", + Self::Mod => "%", + Self::And => "&&", + Self::Or => "||", + Self::Eq => "=", + Self::Lt => "<", + Self::Le => "<=", + Self::Gt => ">", + Self::Ge => ">=", + Self::Neq => "!=", + Self::Shl => "<<", + Self::Shr => ">>", + Self::BitOr => "|", + Self::BitAnd => "&", + }; + write!(f, "{}", str) + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] +pub enum Kind { + Nat, + Memory, + DataTy, + Provenance, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ArgKinded<'a> { + Ident(Ident<'a>), + Nat(Nat<'a>), + Memory(Memory<'a>), + DataTy(DataTy<'a>), + Provenance(Provenance<'a>), +} + +impl<'a> ArgKinded<'a> { + pub fn kind(&self) -> Kind { + match self { + ArgKinded::Ident(_) => { + panic!("Unexpected: unkinded identifier should have been removed after parsing") + } + ArgKinded::DataTy(_) => Kind::DataTy, + ArgKinded::Provenance(_) => Kind::Provenance, + ArgKinded::Memory(_) => Kind::Memory, + ArgKinded::Nat(_) => Kind::Nat, + } + } + + pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a Self) -> NatEvalResult<'a, bool> { + match (self, other) { + (ArgKinded::Ident(i), ArgKinded::Ident(o)) => Ok(i == o), + (ArgKinded::Nat(n), ArgKinded::Nat(no)) => Ok(n.eval(nat_ctx)? == no.eval(nat_ctx)?), + (ArgKinded::Provenance(r), ArgKinded::Provenance(ro)) => Ok(r == ro), + (ArgKinded::DataTy(dty), ArgKinded::DataTy(dtyo)) => dty.equal(nat_ctx, dtyo), + (ArgKinded::Memory(mem), ArgKinded::Memory(memo)) => Ok(mem == memo), + _ => Ok(false), + } + } +} + +#[span_derive(PartialEq, Eq, Hash)] +#[derive(Debug, Clone)] +pub struct PlaceExpr<'a> { + pub pl_expr: PlaceExprKind<'a>, + // FIXME misusing span_derive_ignore to ignore type on equality checks + #[span_derive_ignore] + pub ty: Option<&'a Ty<'a>>, + #[span_derive_ignore] + pub span: Option, +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct View<'a> { + pub name: Ident<'a>, + pub gen_args: BumpVec<'a, ArgKinded<'a>>, + pub args: BumpVec<'a, View<'a>>, +} + +impl<'a> View<'a> { + pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a View<'a>) -> NatEvalResult<'a, bool> { + if self.name.name != other.name.name { + return Ok(false); + } + + if self.gen_args.len() != other.gen_args.len() { + return Ok(false); + } + + for (ga, go) in self.gen_args.iter().zip(other.gen_args.iter()) { + if !ga.equal(nat_ctx, go)? { + return Ok(false); + } + } + + if self.args.len() != other.args.len() { + return Ok(false); + } + + for (v, vo) in self.args.iter().zip(other.args.iter()) { + if !v.equal(nat_ctx, vo)? { + return Ok(false); + } + } + + Ok(true) + } +} + +// TODO create generic View struct to enable easier extensibility by introducing only +// new predeclared types +// #[derive(PartialEq, Eq, Hash, Debug, Clone)] +// pub enum View { +// ToView, +// Group(Nat), +// SplitAt(Nat), +// Transpose, +// Rev, +// Map(Box), +// } + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum PlaceExprKind<'a> { + View(&'a PlaceExpr<'a>, &'a View<'a>), + // similar to a projection, but it projects an element for each provided execution resource + // (similar to indexing) + // p[[x]] + Select(&'a PlaceExpr<'a>, &'a ExecExpr<'a>), + // p.0 | p.1 + Proj(&'a PlaceExpr<'a>, usize), + FieldProj(&'a PlaceExpr<'a>, &'a Ident<'a>), + // *p + Deref(&'a PlaceExpr<'a>), + // Index into array, e.g., arr[i] + Idx(&'a PlaceExpr<'a>, &'a Nat<'a>), + // x + Ident(Ident<'a>), +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum PlExprPathElem<'a> { + View(View<'a>), + Select(&'a ExecExpr<'a>), + Proj(usize), + FieldProj(Ident<'a>), + Deref, + Idx(&'a Nat<'a>), + RangeSelec(&'a Nat<'a>, &'a Nat<'a>), +} + +impl<'a> PlaceExpr<'a> { + pub fn new(pl_expr: PlaceExprKind<'a>) -> Self { + PlaceExpr { + pl_expr, + ty: None, + span: None, + } + } + + pub fn with_span(pl_expr: PlaceExprKind<'a>, span: Span) -> Self { + PlaceExpr { + pl_expr, + ty: None, + span: Some(span), + } + } + + pub fn is_place(&self) -> bool { + match &self.pl_expr { + PlaceExprKind::Ident(_) => true, + PlaceExprKind::Proj(ple, _) | PlaceExprKind::FieldProj(ple, _) => ple.is_place(), + PlaceExprKind::Select(_, _) + | PlaceExprKind::Deref(_) + | PlaceExprKind::Idx(_, _) + | PlaceExprKind::View(_, _) => false, + } + } + + // TODO refactor. Places are only needed during typechecking and codegen + pub fn to_place(&self, arena: &'a bumpalo::Bump) -> Option { + if self.is_place() { + Some(self.to_pl_ctx_and_most_specif_pl(arena).1) + } else { + None + } + } + + // TODO refactor see to_place + pub fn to_pl_ctx_and_most_specif_pl( + &'a self, + arena: &'a bumpalo::Bump, + ) -> (internal::PlaceCtx<'a>, internal::Place<'a>) { + match &self.pl_expr { + PlaceExprKind::Select(inner_ple, exec_idents) => { + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + ( + internal::PlaceCtx::Select(arena.alloc(pl_ctx), exec_idents.clone()), + pl, + ) + } + PlaceExprKind::Deref(inner_ple) => { + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + (internal::PlaceCtx::Deref(arena.alloc(pl_ctx)), pl) + } + PlaceExprKind::View(inner_ple, view) => { + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + ( + internal::PlaceCtx::View(arena.alloc(pl_ctx), view.clone()), + pl, + ) + } + PlaceExprKind::Proj(inner_ple, n) => { + let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + match pl_ctx { + internal::PlaceCtx::Hole => { + pl.path.push(PathElem::Proj(*n)); + (pl_ctx, internal::Place::new(pl.ident, pl.path)) + } + _ => (internal::PlaceCtx::Proj(arena.alloc(pl_ctx), *n), pl), + } + } + PlaceExprKind::FieldProj(inner_ple, field_name) => { + let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + match pl_ctx { + internal::PlaceCtx::Hole => { + pl.path.push(PathElem::FieldProj(field_name.clone())); + (pl_ctx, internal::Place::new(pl.ident, pl.path)) + } + _ => ( + internal::PlaceCtx::FieldProj( + arena.alloc(pl_ctx), + field_name.clone().clone(), + ), + pl, + ), + } + } + PlaceExprKind::Idx(inner_ple, idx) => { + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + ( + internal::PlaceCtx::Idx(arena.alloc(pl_ctx), idx.clone()), + pl, + ) + } + PlaceExprKind::Ident(ident) => ( + internal::PlaceCtx::Hole, + internal::Place::new(ident.clone(), BumpVec::new_in(arena)), + ), + } + } + + pub fn equiv(&'a self, arena: &'a bumpalo::Bump, place: &'a internal::Place) -> bool { + if let (internal::PlaceCtx::Hole, pl) = self.to_pl_ctx_and_most_specif_pl(arena) { + &pl == place + } else { + false + } + } + + pub fn as_ident_and_path( + &'a self, + arena: &'a bumpalo::Bump, + ) -> (Ident<'a>, BumpVec<'a, PlExprPathElem<'a>>) { + fn as_ident_and_path_rec<'a>( + pl_expr: &'a PlaceExpr, + mut path: BumpVec<'a, PlExprPathElem<'a>>, + ) -> (Ident<'a>, BumpVec<'a, PlExprPathElem<'a>>) { + match &pl_expr.pl_expr { + PlaceExprKind::Ident(i) => { + path.reverse(); + (i.clone(), path) + } + PlaceExprKind::Select(inner_ple, exec_idents) => { + path.push(PlExprPathElem::Select(exec_idents.clone())); + as_ident_and_path_rec(inner_ple, path) + } + PlaceExprKind::Deref(inner_ple) => { + path.push(PlExprPathElem::Deref); + as_ident_and_path_rec(inner_ple, path) + } + PlaceExprKind::View(inner_ple, view) => { + path.push(PlExprPathElem::View(view.clone().clone())); // formerly as_ref().clone() ? Can that just work with double cloning? + as_ident_and_path_rec(inner_ple, path) + } + PlaceExprKind::Proj(inner_ple, n) => { + path.push(PlExprPathElem::Proj(*n)); + as_ident_and_path_rec(inner_ple, path) + } + PlaceExprKind::FieldProj(inner_ple, ident) => { + path.push(PlExprPathElem::FieldProj(ident.clone().clone())); // formerly as_ref().clone() ? Can that just work with double cloning? + as_ident_and_path_rec(inner_ple, path) + } + PlaceExprKind::Idx(inner_ple, idx) => { + path.push(PlExprPathElem::Idx(idx.clone())); + as_ident_and_path_rec(inner_ple, path) + } + } + } + as_ident_and_path_rec(self, BumpVec::new_in(arena)) // BumpVec Stuff into it + } +} + +// Problem with not beeing boxed +#[span_derive(PartialEq, Eq, Hash)] +#[derive(Debug, Clone)] +pub struct ExecExpr<'a> { + pub exec: &'a ExecExprKind<'a>, + #[span_derive_ignore] + pub ty: Option<&'a ExecTy<'a>>, + #[span_derive_ignore] + pub span: Option, +} +impl<'a> ExecExpr<'a> { + pub fn new(arena: &'a bumpalo::Bump, exec: ExecExprKind<'a>) -> Self { + Self { + exec: arena.alloc(exec), + ty: None, + span: None, + } + } + + // TODO how does this relate to is_prefix_of. Refactor. + pub fn is_sub_exec_of(&self, exec: &ExecExpr) -> bool { + if self.exec.path.len() > exec.exec.path.len() { + return self.exec.path[..exec.exec.path.len()] == exec.exec.path[..]; + } + false + } + + pub fn remove_last_distrib(&self, arena: &'a bumpalo::Bump) -> ExecExpr { + let last_distrib_pos = self + .exec + .path + .iter() + .rposition(|e| matches!(e, ExecPathElem::ForAll(_))); + + // What did i do here? + let removed_distrib_path = if let Some(ldp) = last_distrib_pos { + let mut vec = BumpVec::new_in(arena); + // self.exec.path[..ldp].to_vec() --> changed this to BumpVec + vec.extend_from_slice(&self.exec.path[..ldp]); + vec + } else { + //vec![] --> changed this to BumpVec + BumpVec::new_in(arena) + }; + + ExecExpr::new( + arena, + ExecExprKind::with_path(self.exec.base.clone(), removed_distrib_path), + ) + } + + pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { + match (&self.exec.base, &other.exec.base) { + (BaseExec::Ident(i), BaseExec::Ident(o)) => { + if i != o { + return Ok(false); + } + } + (BaseExec::CpuThread, BaseExec::CpuThread) => (), + (BaseExec::GpuGrid(gdim, bdim), BaseExec::GpuGrid(gdimo, bdimo)) => { + if !(gdim.equal(nat_ctx, gdimo)? && bdim.equal(nat_ctx, bdimo)?) { + return Ok(false); + } + } + _ => return Ok(false), + } + if self.exec.path.len() != other.exec.path.len() { + return Ok(false); + } + for path_elems in self.exec.path.iter().zip(&other.exec.path) { + match path_elems { + (ExecPathElem::ToWarps, ExecPathElem::ToWarps) => (), + (ExecPathElem::ForAll(d), ExecPathElem::ForAll(o)) => { + if d != o { + return Ok(false); + } + } + (ExecPathElem::ToThreads(d), ExecPathElem::ToThreads(o)) => { + if d != o { + return Ok(false); + } + } + (ExecPathElem::TakeRange(r), ExecPathElem::TakeRange(ro)) => { + if !(r.split_dim == ro.split_dim + && r.left_or_right == ro.left_or_right + && r.pos.eval(nat_ctx)? == ro.pos.eval(nat_ctx)?) + { + return Ok(false); + } + } + _ => return Ok(false), + } + } + Ok(true) + } + + pub fn clone_in(&self, arena: &'a bumpalo::Bump) -> Self { + ExecExpr { + exec: arena.alloc(self.exec.clone_in(arena)), + ty: self.ty.as_ref().map(|t| { + let t_mut: &mut ExecTy<'a> = arena.alloc(t.clone_in(arena)); + &*t_mut // Reborrow as immutable reference, somehow feels illegal + }), + span: self.span, + } + } +} + +#[test] +fn equal_exec_exprs() { + let arena = Bump::new(); + + let exec1 = ExecExpr::new( + &arena, + ExecExprKind::with_path( + BaseExec::Ident(Ident::new(&arena, "grid")), + bumpalo::collections::Vec::from_iter_in([ExecPathElem::ForAll(DimCompo::X)], &arena), + ), + ); + + let exec2 = ExecExpr::new( + &arena, + ExecExprKind::with_path( + BaseExec::Ident(Ident::new(&arena, "grid")), + bumpalo::collections::Vec::from_iter_in([ExecPathElem::ForAll(DimCompo::X)], &arena), + ), + ); + + assert_eq!(exec1, exec2, "Unequal execs that should be equal"); +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] +pub enum LeftOrRight { + Left, + Right, +} + +impl fmt::Display for LeftOrRight { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + LeftOrRight::Left => write!(f, "left"), + LeftOrRight::Right => write!(f, "right"), + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct TakeRange<'a> { + pub split_dim: DimCompo, + pub pos: Nat<'a>, + pub left_or_right: LeftOrRight, +} + +impl<'a> TakeRange<'a> { + pub fn new(split_dim: DimCompo, pos: Nat<'a>, proj: LeftOrRight) -> Self { + TakeRange { + split_dim, + pos, + left_or_right: proj, + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct ExecExprKind<'a> { + pub base: BaseExec<'a>, + pub path: BumpVec<'a, ExecPathElem<'a>>, +} + +impl<'a> ExecExprKind<'a> { + pub fn new(arena: &'a bumpalo::Bump, base: BaseExec<'a>) -> Self { + ExecExprKind { + base, + path: BumpVec::new_in(arena), + } + } + + pub fn clone_in(&self, arena: &'a bumpalo::Bump) -> Self { + ExecExprKind { + base: self.base.clone(), + path: { + let mut new_path = BumpVec::new_in(arena); + new_path.extend(self.path.iter().cloned()); + new_path + }, + } + } + + pub fn with_path(base: BaseExec<'a>, path: BumpVec<'a, ExecPathElem<'a>>) -> Self { + ExecExprKind { base, path } + } + + /** + pub fn with_path(base: BaseExec, path: impl IntoIterator>, arena: &'a Bump) -> Self { + let mut bump_vec = BumpVec::new_in(arena); + bump_vec.extend(path); + Self { base, path: bump_vec } + }*/ + + pub fn split_proj( + mut self, + arena: &'a bumpalo::Bump, + dim_compo: DimCompo, + pos: Nat<'a>, + proj: LeftOrRight, + ) -> Self { + self.path.push(ExecPathElem::TakeRange( + arena.alloc(TakeRange::new(dim_compo, pos, proj)), + )); + self + } + + pub fn forall(mut self, dim_compo: DimCompo) -> Self { + self.path.push(ExecPathElem::ForAll(dim_compo)); + self + } + + pub fn active_distrib_dim(&self) -> Option { + for e in self.path.iter().rev() { + if let ExecPathElem::ForAll(dim) = e { + return Some(*dim); + } + } + None + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum BaseExec<'a> { + Ident(Ident<'a>), + CpuThread, + GpuGrid(Dim<'a>, Dim<'a>), +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum ExecPathElem<'a> { + TakeRange(&'a TakeRange<'a>), + ForAll(DimCompo), + ToWarps, + ToThreads(DimCompo), +} + +// ExecTy +// fn size(DimCompo) -> usize +// fn take_range(DimCompo, Nat) -> ExecTy +// fn elem_type(DimCompo) -> ExecTy +#[span_derive(PartialEq, Eq, Hash)] +#[derive(Debug, Clone)] +pub struct ExecTy<'a> { + pub ty: ExecTyKind<'a>, + #[span_derive_ignore] + pub span: Option, +} + +impl<'a> ExecTy<'a> { + pub fn new(exec: ExecTyKind<'a>) -> Self { + ExecTy { + ty: exec, + span: None, + } + } + + pub fn clone_in(&self, _arena: &'a bumpalo::Bump) -> ExecTy<'a> { + ExecTy { + ty: self.ty.clone(), + span: self.span, + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum ExecTyKind<'a> { + CpuThread, + GpuThread, + GpuWarp, + GpuBlock(Dim<'a>), + GpuGrid(Dim<'a>, Dim<'a>), + GpuToThreads(Dim<'a>, &'a ExecTy<'a>), + GpuThreadGrp(Dim<'a>), + GpuWarpGrp(Nat<'a>), + GpuBlockGrp(Dim<'a>, Dim<'a>), + Any, +} + +#[span_derive(PartialEq, Eq, Hash)] +#[derive(Debug, Clone)] +pub struct Ty<'a> { + pub ty: TyKind<'a>, + #[span_derive_ignore] + pub span: Option, +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct ParamSig<'a> { + pub exec_expr: ExecExpr<'a>, + pub ty: &'a Ty<'a>, +} + +impl<'a> ParamSig<'a> { + pub fn new(exec_expr: ExecExpr<'a>, ty: &'a Ty<'a>) -> Self { + ParamSig { exec_expr, ty } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct FnTy<'a> { + pub generics: BumpVec<'a, IdentKinded<'a>>, + pub generic_exec: Option>, + pub param_sigs: BumpVec<'a, ParamSig<'a>>, + pub exec: ExecExpr<'a>, + pub ret_ty: &'a Ty<'a>, + pub nat_constrs: BumpVec<'a, NatConstr<'a>>, +} + +impl<'a> FnTy<'a> { + pub fn new( + arena: &'a Bump, + generics: impl IntoIterator>, + generic_exec: Option>, + param_sigs: impl IntoIterator>, + exec: ExecExpr<'a>, + ret_ty: &'a Ty<'a>, + nat_constrs: impl IntoIterator>, + ) -> Self { + let mut generics_vec = BumpVec::new_in(arena); + generics_vec.extend(generics); + + let mut param_vec = BumpVec::new_in(arena); + param_vec.extend(param_sigs); + + let mut nat_vec = BumpVec::new_in(arena); + nat_vec.extend(nat_constrs); + + FnTy { + generics: generics_vec, + generic_exec, + param_sigs: param_vec, + exec, + ret_ty: arena.alloc(ret_ty), + nat_constrs: nat_vec, + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum NatConstr<'a> { + True, + Eq(Box>, Box>), + Lt(Box>, Box>), + And(Box>, Box>), + Or(Box>, Box>), +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum TyKind<'a> { + Data(&'a DataTy<'a>), + // (ty..) -[x:exec]-> ty + FnTy(&'a FnTy<'a>), +} + +// TODO remove +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] +pub enum Constraint { + Copyable, +} + +impl<'a> Ty<'a> { + pub fn new(ty: TyKind<'a>) -> Self { + Ty { ty, span: None } + } + + pub fn with_span(ty: TyKind<'a>, span: Span) -> Ty<'a> { + Ty { + ty, + span: Some(span), + } + } + + pub fn dty(&self) -> &'a DataTy<'a> { + match &self.ty { + TyKind::Data(dty) => dty, + _ => panic!("Expected data type but found {:?}", self), + } + } + + pub fn copyable(&self) -> bool { + match &self.ty { + TyKind::Data(dty) => dty.copyable(), + TyKind::FnTy(_) => true, + } + } + + pub fn is_fully_alive(&self) -> bool { + match &self.ty { + TyKind::Data(dty) => dty.is_fully_alive(), + TyKind::FnTy(_) => true, + } + } + + pub fn contains_ref_to_prv(&self, prv_val_name: &str) -> bool { + match &self.ty { + TyKind::Data(dty) => dty.contains_ref_to_prv(prv_val_name), + TyKind::FnTy(fn_ty) => { + fn_ty + .param_sigs + .iter() + .any(|param_sig| param_sig.ty.contains_ref_to_prv(prv_val_name)) + || fn_ty.ret_ty.contains_ref_to_prv(prv_val_name) + } + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct Dim1d<'a>(pub Nat<'a>); +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct Dim2d<'a>(pub Nat<'a>, pub Nat<'a>); +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct Dim3d<'a>(pub Nat<'a>, pub Nat<'a>, pub Nat<'a>); +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum Dim<'a> { + XYZ(&'a Dim3d<'a>), + XY(&'a Dim2d<'a>), + XZ(&'a Dim2d<'a>), + YZ(&'a Dim2d<'a>), + X(&'a Dim1d<'a>), + Y(&'a Dim1d<'a>), + Z(&'a Dim1d<'a>), +} + +impl<'a> Dim<'a> { + pub fn new_3d(arena: &'a Bump, n1: Nat<'a>, n2: Nat<'a>, n3: Nat<'a>) -> Self { + Dim::XYZ(arena.alloc(Dim3d(n1, n2, n3))) + } + + pub fn new_2d Self>( + arena: &'a Bump, + constr: F, + n1: Nat<'a>, + n2: Nat<'a>, + ) -> Self { + constr(arena.alloc(Dim2d(n1, n2))) + } + + pub fn new_1d Self>(arena: &'a Bump, constr: F, n: Nat<'a>) -> Self { + constr(arena.alloc(Dim1d(n))) + } + + pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { + match (self, other) { + (Dim::XYZ(d), Dim::XYZ(o)) => Ok(d.0.eval(nat_ctx)? == o.0.eval(nat_ctx)? + && d.1.eval(nat_ctx)? == o.1.eval(nat_ctx)? + && d.2.eval(nat_ctx)? == o.2.eval(nat_ctx)?), + (Dim::XY(d), Dim::XY(o)) | (Dim::XZ(d), Dim::XZ(o)) | (Dim::YZ(d), Dim::YZ(o)) => { + Ok(d.0.eval(nat_ctx)? == o.0.eval(nat_ctx)? + && d.1.eval(nat_ctx)? == o.1.eval(nat_ctx)?) + } + (Dim::X(d), Dim::X(o)) | (Dim::Y(d), Dim::Y(o)) | (Dim::Z(d), Dim::Z(o)) => { + Ok(d.0.eval(nat_ctx)? == o.0.eval(nat_ctx)?) + } + _ => Ok(false), + } + } +} + +#[derive(PartialEq, Eq, PartialOrd, Hash, Debug, Copy, Clone)] +pub enum DimCompo { + X, + Y, + Z, +} + +#[span_derive(PartialEq, Eq, Hash)] +#[derive(Debug, Clone)] +pub struct DataTy<'a> { + pub dty: DataTyKind<'a>, + // TODO remove with introduction of traits + pub constraints: BumpVec<'a, Constraint>, + #[span_derive_ignore] + pub span: Option, +} + +impl<'a> DataTy<'a> { + pub fn new(bump: &'a bumpalo::Bump, dty: DataTyKind<'a>) -> Self { + DataTy { + dty, + constraints: BumpVec::new_in(bump), + span: None, + } + } + + pub fn with_constr( + bump: &'a bumpalo::Bump, + dty: DataTyKind<'a>, + constraints: impl IntoIterator, + ) -> Self { + let mut v = BumpVec::new_in(bump); + v.extend(constraints); + DataTy { + dty, + constraints: v, + span: None, + } + } + + pub fn with_span(bump: &'a bumpalo::Bump, dty: DataTyKind<'a>, span: Span) -> Self { + DataTy { + dty, + constraints: BumpVec::new_in(bump), + span: Some(span), + } + } + + pub fn non_copyable(&'a self) -> bool { + use DataTyKind::*; + + match &self.dty { + Scalar(_) => false, + Atomic(_) => false, + Ident(_) => true, + Ref(reff) => reff.own == Ownership::Uniq, + At(_, _) => true, + ArrayShape(_, _) => true, + Tuple(elem_tys) => elem_tys.iter().any(|ty| ty.non_copyable()), + Array(_, _) => false, + RawPtr(_) => true, + Range => true, + Dead(_) => panic!( + "This case is not expected to mean anything.\ + The type is dead. There is nothing we can do with it." + ), + } + } + + pub fn copyable(&'a self) -> bool { + !self.non_copyable() + } + + pub fn is_fully_alive(&'a self) -> bool { + use DataTyKind::*; + match &self.dty { + Scalar(_) + | RawPtr(_) + | Atomic(_) + | Ident(_) + | Ref(_) + | At(_, _) + | Array(_, _) + | ArrayShape(_, _) => true, + Tuple(elem_tys) => elem_tys + .iter() + .fold(true, |acc, dty| acc & dty.is_fully_alive()), + Struct(struct_decl) => struct_decl + .fields + .iter() + .fold(true, |acc, (_, dty)| acc & dty.is_fully_alive()), + Dead(_) => false, + } + } + + pub fn occurs_in(&'a self, dty: &DataTy) -> bool { + if self == dty { + return true; + } + match &dty.dty { + DataTyKind::Scalar(_) | DataTyKind::Ident(_) => false, + DataTyKind::Dead(_) => panic!("unexpected"), + DataTyKind::Atomic(aty) => &self.dty == &DataTyKind::Atomic(aty.clone()), + DataTyKind::Ref(reff) => self.occurs_in(&reff.dty), + DataTyKind::RawPtr(elem_dty) => self.occurs_in(elem_dty), + DataTyKind::Tuple(elem_dtys) => { + let mut found = false; + for elem_dty in elem_dtys { + found = self.occurs_in(elem_dty); + } + found + } + DataTyKind::Struct(struct_decl) => { + let mut found = false; + for (_, dty) in &struct_decl.fields { + found = self.occurs_in(dty) + } + found + } + DataTyKind::Array(elem_dty, _) => self.occurs_in(elem_dty), + DataTyKind::ArrayShape(elem_dty, _) => self.occurs_in(elem_dty), + DataTyKind::At(elem_dty, _) => self.occurs_in(elem_dty), + } + } + + pub fn contains_ref_to_prv(&'a self, prv_val_name: &str) -> bool { + use DataTyKind::*; + match &self.dty { + Scalar(_) | Atomic(_) | Ident(_) | Dead(_) => false, + Ref(reff) => { + let found_reference = if let Provenance::Value(prv_val_n) = &reff.rgn { + prv_val_name == prv_val_n + } else { + false + }; + found_reference || reff.dty.contains_ref_to_prv(prv_val_name) + } + RawPtr(dty) => dty.contains_ref_to_prv(prv_val_name), + At(dty, _) => dty.contains_ref_to_prv(prv_val_name), + Array(dty, _) => dty.contains_ref_to_prv(prv_val_name), + ArrayShape(dty, _) => dty.contains_ref_to_prv(prv_val_name), + Tuple(elem_tys) => elem_tys + .iter() + .any(|ty| ty.contains_ref_to_prv(prv_val_name)), + Struct(struct_decl) => struct_decl + .fields + .iter() + .any(|(_, dty)| dty.contains_ref_to_prv(prv_val_name)), + } + } + + pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a Self) -> NatEvalResult<'a, bool> { + match (&self.dty, &other.dty) { + (DataTyKind::Ident(i), DataTyKind::Ident(o)) => Ok(i == o), + (DataTyKind::Tuple(dtys), DataTyKind::Tuple(dtyos)) => { + for (d, o) in dtys.iter().zip(dtyos) { + if !d.equal(nat_ctx, o)? { + return Ok(false); + } + } + Ok(true) + } + (DataTyKind::Ref(ref_dty), DataTyKind::Ref(ref_dtyo)) => Ok(ref_dty.own + == ref_dtyo.own + && ref_dty.rgn == ref_dtyo.rgn + && ref_dty.mem == ref_dtyo.mem + && ref_dty.dty.equal(nat_ctx, &ref_dtyo.dty)?), + (DataTyKind::Array(dty, n), DataTyKind::Array(dtyo, no)) + | (DataTyKind::ArrayShape(dty, n), DataTyKind::ArrayShape(dtyo, no)) => { + Ok(dty.equal(nat_ctx, dtyo)? && n.eval(nat_ctx)? == no.eval(nat_ctx)?) + } + (DataTyKind::At(dty, mem), DataTyKind::At(dtyo, memo)) => { + Ok(dty.equal(nat_ctx, dtyo)? && mem == memo) + } + (DataTyKind::Struct(struct_decl), DataTyKind::Struct(struct_declo)) => { + Ok(struct_decl.ident == struct_declo.ident) + } + (DataTyKind::Atomic(aty), DataTyKind::Atomic(atyo)) => Ok(aty == atyo), + (DataTyKind::Scalar(sty), DataTyKind::Scalar(styo)) => Ok(sty == styo), + _ => Ok(false), + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct RefDty<'a> { + pub rgn: Provenance<'a>, + pub own: Ownership, + pub mem: Memory<'a>, + pub dty: &'a DataTy<'a>, +} + +impl<'a> RefDty<'a> { + pub fn new( + bump: &'a Bump, + rgn: Provenance<'a>, + own: Ownership, + mem: Memory<'a>, + dty: DataTy<'a>, + ) -> Self { + RefDty { + rgn, + own, + mem, + dty: bump.alloc(dty), + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum DataTyKind<'a> { + Ident(Ident<'a>), + Scalar(ScalarTy), + Atomic(AtomicTy), + Array(&'a DataTy<'a>, Nat<'a>), + ArrayShape(&'a DataTy<'a>, Nat<'a>), + Tuple(BumpVec<'a, DataTy<'a>>), + Struct(&'a StructDecl<'a>), + At(&'a DataTy<'a>, Memory<'a>), + Ref(&'a RefDty<'a>), + RawPtr(&'a DataTy<'a>), + //Range, + // TODO remove. This is an attribute of a typing context entry, not the type. + // Only for type checking purposes. + Dead(&'a DataTy<'a>), +} + +#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] +pub enum ScalarTy { + Unit, + U8, + U32, + U64, + I32, + I64, + F32, + F64, + Bool, + Gpu, +} + +#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] +pub enum AtomicTy { + AtomicU32, + AtomicI32, +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum Provenance<'a> { + Value(String), + Ident(Ident<'a>), +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum Memory<'a> { + CpuMem, + GpuGlobal, + GpuShared, + GpuLocal, + Ident(Ident<'a>), +} + +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct PrvRel<'a> { + pub longer: Ident<'a>, + pub shorter: Ident<'a>, +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct IdentKinded<'a> { + pub ident: Ident<'a>, + pub kind: Kind, +} + +impl<'a> IdentKinded<'a> { + pub fn new(ident: &Ident<'a>, kind: Kind) -> Self { + IdentKinded { + ident: ident.clone(), + kind, + } + } +} + +#[derive(PartialEq, Eq, Debug, Clone)] +pub enum NatRange<'a> { + Simple { lower: Nat<'a>, upper: Nat<'a> }, + Halved { upper: Nat<'a> }, + Doubled { upper: Nat<'a> }, +} + +impl<'a> NatRange<'a> { + pub fn lift(&self, arena: &'a Bump, nat_ctx: &NatCtx) -> NatEvalResult { + let range_iter = match self { + NatRange::Simple { lower, upper } => { + let lower = lower.eval(nat_ctx)?; + let upper = upper.eval(nat_ctx)?; + NatRangeIter::new( + lower, + arena.alloc(|x| x + 1), + arena.alloc(move |c| c >= upper), + ) + } + NatRange::Halved { upper } => { + let upper = upper.eval(nat_ctx)?; + NatRangeIter::new(upper, arena.alloc(|x| x / 2), arena.alloc(|c| c == 0)) + } + NatRange::Doubled { upper } => { + let upper = upper.eval(nat_ctx)?; + NatRangeIter::new(1, arena.alloc(|x| x * 2), arena.alloc(move |c| c >= upper)) + } + }; + Ok(range_iter) + } +} + +pub struct NatRangeIter<'a> { + current: usize, + // go from current to next value + step_fun: &'a dyn Fn(usize) -> usize, + // determine whether the current value is still within range + end_cond: &'a dyn Fn(usize) -> bool, +} + +impl<'a> NatRangeIter<'a> { + fn new( + start: usize, + step_fun: &'a dyn Fn(usize) -> usize, + end_cond: &'a dyn Fn(usize) -> bool, + ) -> Self { + NatRangeIter { + current: start, + step_fun, + end_cond, + } + } +} + +impl<'a> Iterator for NatRangeIter<'a> { + type Item = usize; + + fn next(&mut self) -> Option { + self.current = (self.step_fun)(self.current); + + if !(self.end_cond)(self.current) { + Some(self.current) + } else { + None + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum Nat<'a> { + Ident(Ident<'a>), + Lit(usize), + ThreadIdx(DimCompo), + BlockIdx(DimCompo), + BlockDim(DimCompo), + WarpGrpIdx, + WarpIdx, + LaneIdx, + // Dummy that is always 0, i.e. equivalent to Lit(0) + GridIdx, + BinOp(BinOpNat, Box>, Box>), + // Use Box<[Nat]> to safe 8 bytes compared to Vec + App(Ident<'a>, Box<[Nat<'a>]>), +} + +pub struct NatCtx { + frames: Vec, usize)>>, +} + +impl NatCtx { + pub fn new() -> Self { + NatCtx { + frames: vec![vec![]], + } + } + + pub fn with_frame(frame: Vec<(Box, usize)>) -> Self { + let mut ctx = NatCtx { frames: vec![] }; + ctx.push_frame(frame); + ctx + } + + pub fn append(&mut self, nat_name: &str, val: usize) { + self.frames + .last_mut() + .unwrap() + .push((Box::from(nat_name), val)) + } + + pub fn find(&self, name: &str) -> Option { + self.frames.iter().flatten().rev().find_map(|(i, n)| { + if i.as_ref() == name { + Some(*n) + } else { + None + } + }) + } + + pub fn push_empty_frame(&mut self) -> &mut Self { + self.frames.push(vec![]); + self + } + + fn push_frame(&mut self, frame: Vec<(Box, usize)>) -> &mut Self { + self.frames.push(frame); + self + } + + pub fn pop_frame(&mut self) -> &mut Self { + self.frames.pop().expect("There must always be a scope."); + self + } +} + +#[derive(Debug)] +pub struct NatEvalError<'a> { + unevaluable: Nat<'a>, +} + +pub type NatEvalResult<'a, T> = Result>; + +impl<'a> Nat<'a> { + pub fn eval(&self, nat_ctx: &NatCtx) -> NatEvalResult { + match self { + Nat::GridIdx + | Nat::BlockIdx(_) + | Nat::BlockDim(_) + | Nat::ThreadIdx(_) + | Nat::WarpGrpIdx + | Nat::WarpIdx + | Nat::LaneIdx => Err(NatEvalError { + unevaluable: self.clone(), + }), + Nat::Ident(i) => { + if let Some(n) = nat_ctx.find(&i.name) { + Ok(n) + } else { + Err(NatEvalError { + unevaluable: self.clone(), + }) + } + } + Nat::Lit(n) => Ok(*n), + Nat::BinOp(op, l, r) => match op { + BinOpNat::Add => Ok(l.eval(nat_ctx)? + r.eval(nat_ctx)?), + BinOpNat::Sub => Ok(l.eval(nat_ctx)? - r.eval(nat_ctx)?), + BinOpNat::Mul => Ok(l.eval(nat_ctx)? * r.eval(nat_ctx)?), + BinOpNat::Div => Ok(l.eval(nat_ctx)? / r.eval(nat_ctx)?), + BinOpNat::Mod => Ok(l.eval(nat_ctx)? % r.eval(nat_ctx)?), + }, + Nat::App(_, _) => unimplemented!(), + } + } +} + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub enum BinOpNat { + Add, + Sub, + Mul, + Div, + Mod, +} + +// When changing the AST, the types can quickly grow and lead to stack overflows in the different +// compiler stages. +// +// Taken from the rustc implementation and adjusted for this AST: +// Some nodes are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +mod size_asserts { + use super::*; + // Type size assertion. The first argument is a type and the second argument is its expected size. + macro_rules! static_assert_size { + ($ty:ty, $size:expr) => { + const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()]; + }; + } + static_assert_size!(Dim, 16); + static_assert_size!(DataTy, 112); + static_assert_size!(DataTyKind, 64); + static_assert_size!(ExecExpr, 32); + static_assert_size!(ExecExprKind, 72); + static_assert_size!(ExecPathElem, 16); + static_assert_size!(ExecTy, 64); + static_assert_size!(ExecTyKind, 48); + static_assert_size!(Expr, 104); + static_assert_size!(ExprKind, 80); + static_assert_size!(FunDef, 216); + static_assert_size!(Ident, 32); // maybe too large? + static_assert_size!(IdentExec, 40); + static_assert_size!(Lit, 16); + static_assert_size!(Memory, 32); + static_assert_size!(Nat, 48); + static_assert_size!(ParamDecl, 80); + static_assert_size!(Pattern, 40); + static_assert_size!(PlaceExpr, 56); + static_assert_size!(PlaceExprKind, 32); + static_assert_size!(ScalarTy, 1); + static_assert_size!(Ty, 32); + static_assert_size!(TyKind, 16); +} diff --git a/src/arena_ast/printer.rs b/src/arena_ast/printer.rs new file mode 100644 index 00000000..bbb2d20b --- /dev/null +++ b/src/arena_ast/printer.rs @@ -0,0 +1,380 @@ +use crate::arena_ast::{ + AtomicTy, BaseExec, BinOpNat, DataTy, DataTyKind, Dim, DimCompo, ExecExpr, ExecPathElem, + ExecTy, ExecTyKind, FnTy, Ident, IdentExec, IdentKinded, Kind, LeftOrRight, Memory, Nat, + Ownership, ParamSig, Provenance, ScalarTy, TakeRange, Ty, TyKind, +}; +use std::fmt::Write; + +pub struct PrintState { + string: String, +} + +macro_rules! print_list { + ($print_state: ident, $print_fun: path, $list: expr) => { + for elem in $list { + $print_fun($print_state, elem); + $print_state.string.push(','); + } + }; +} + +macro_rules! print_static_list { + ($print_state: ident, $print_fun: path, $($item: expr),*) => { + $( + $print_fun($print_state, $item); + $print_state.string.push(','); + )* + }; +} + +impl PrintState { + pub fn new() -> Self { + PrintState { + string: String::new(), + } + } + + pub fn get(&self) -> String { + self.string.clone() + } + + fn print_ident(&mut self, ident: &Ident) { + self.string.push_str(&ident.name); + } + + fn print_ty(&mut self, ty: &Ty) { + match &ty.ty { + TyKind::FnTy(fn_ty) => { + self.print_fn_ty(fn_ty); + } + TyKind::Data(dty) => self.print_dty(dty), + } + } + + fn print_fn_ty(&mut self, fn_ty: &FnTy) { + self.string.push('<'); + print_list!(self, Self::print_ident_kinded, &fn_ty.generics); + self.string.push_str(">("); + print_list!(self, Self::print_param_sig, &fn_ty.param_sigs); + self.string.push_str(") -["); + if let Some(ident_exec) = &fn_ty.generic_exec { + self.print_ident_exec(ident_exec); + } else { + self.print_exec_expr(&fn_ty.exec); + } + self.string.push_str("]-> "); + self.print_ty(&fn_ty.ret_ty); + } + + fn print_param_sig(&mut self, param_sig: &ParamSig) { + self.print_exec_expr(¶m_sig.exec_expr); + self.print_ty(¶m_sig.ty); + } + + fn print_ident_exec(&mut self, ident_exec: &IdentExec) { + self.print_ident(&ident_exec.ident); + self.print_exec_ty(&ident_exec.ty); + } + + fn print_ident_kinded(&mut self, ident_kinded: &IdentKinded) { + self.print_ident(&ident_kinded.ident); + self.print_kind(ident_kinded.kind); + } + + fn print_kind(&mut self, kind: Kind) { + let kind_str = match kind { + Kind::DataTy => "dty", + Kind::Provenance => "prv", + Kind::Memory => "mem", + Kind::Nat => "nat", + }; + self.string.push_str(kind_str); + } + + pub fn print_exec_ty(&mut self, exec_ty: &ExecTy) { + match &exec_ty.ty { + ExecTyKind::CpuThread => self.string.push_str("cpu.thread"), + ExecTyKind::GpuGrid(gdim, bdim) => { + self.string.push_str("gpu.grid<"); + print_static_list!(self, Self::print_dim, gdim, bdim); + self.string.push('>'); + } + ExecTyKind::GpuToThreads(dim, exec_ty) => { + self.string.push_str("gpu.global_threads<"); + self.print_dim(dim); + self.string.push_str(", "); + self.print_exec_ty(exec_ty); + self.string.push('>'); + } + ExecTyKind::GpuBlock(bdim) => { + self.string.push_str("gpu.block<"); + self.print_dim(bdim); + self.string.push('>'); + } + ExecTyKind::GpuThread => self.string.push_str("gpu.thread"), + ExecTyKind::GpuBlockGrp(gdim, bdim) => { + self.string.push_str("gpu.block_grp<"); + print_static_list!(self, Self::print_dim, gdim, bdim); + self.string.push('>'); + } + ExecTyKind::GpuThreadGrp(dim) => { + self.string.push_str("gpu.thread_grp<"); + self.print_dim(dim); + self.string.push('>'); + } + ExecTyKind::Any => self.string.push_str("view"), + ExecTyKind::GpuWarpGrp(n) => { + self.string.push_str("gpu.warp_grp<"); + self.print_nat(n); + self.string.push('>'); + } + ExecTyKind::GpuWarp => {} + } + } + + pub fn print_exec_expr(&mut self, exec_expr: &ExecExpr) { + match &exec_expr.exec.base { + BaseExec::Ident(ident) => self.print_ident(ident), + BaseExec::CpuThread => self.string.push_str("cpu.thread"), + BaseExec::GpuGrid(gdim, bdim) => { + self.string.push_str("gpu.grid<"); + self.print_dim(gdim); + self.string.push_str(", "); + self.print_dim(bdim); + self.string.push('>'); + } + } + for pe in &exec_expr.exec.path { + self.string.push('.'); + match pe { + ExecPathElem::TakeRange(split_proj) => self.print_take_range(split_proj), + ExecPathElem::ForAll(dim_compo) => { + self.string.push_str("forall("); + self.print_dim_compo(dim_compo); + self.string.push(')'); + } + ExecPathElem::ToThreads(dim_compo) => { + self.string.push_str("to_threads("); + self.print_dim_compo(dim_compo); + self.string.push(')'); + } + ExecPathElem::ToWarps => self.string.push_str("to_warps"), + } + } + } + + fn print_take_range(&mut self, take_range: &TakeRange) { + self.string.push('['); + self.print_dim_compo(&take_range.split_dim); + self.string.push_str("; "); + match &take_range.left_or_right { + LeftOrRight::Left => { + self.string.push_str(".."); + self.print_nat(&take_range.pos); + } + LeftOrRight::Right => { + self.print_nat(&take_range.pos); + self.string.push_str(".."); + } + } + self.string.push(']'); + } + + fn print_dim(&mut self, dim: &Dim) { + match dim { + Dim::XYZ(dim3d) => { + self.string.push_str("XYZ<"); + print_static_list!(self, Self::print_nat, &dim3d.0, &dim3d.1, &dim3d.2); + } + Dim::XY(dim2d) => { + self.string.push_str("XY<"); + print_static_list!(self, Self::print_nat, &dim2d.0, &dim2d.1); + } + Dim::XZ(dim2d) => { + self.string.push_str("XZ<"); + print_static_list!(self, Self::print_nat, &dim2d.0, &dim2d.1); + } + Dim::YZ(dim2d) => { + self.string.push_str("YZ<"); + print_static_list!(self, Self::print_nat, &dim2d.0, &dim2d.1); + } + Dim::X(dim1d) => { + self.string.push_str("X<"); + self.print_nat(&dim1d.0) + } + Dim::Y(dim1d) => { + self.string.push_str("Y<"); + self.print_nat(&dim1d.0) + } + Dim::Z(dim1d) => { + self.string.push_str("Z<"); + self.print_nat(&dim1d.0) + } + } + self.string.push('>'); + } + + fn print_dim_compo(&mut self, dim_compo: &DimCompo) { + match dim_compo { + DimCompo::X => self.string.push('X'), + DimCompo::Y => self.string.push('Y'), + DimCompo::Z => self.string.push('Z'), + } + } + + pub fn print_aty(&mut self, aty: &AtomicTy) { + match &aty { + AtomicTy::AtomicU32 => self.string.push_str("AtomicU32"), + AtomicTy::AtomicI32 => self.string.push_str("AtomicI32"), + } + } + + pub fn print_dty(&mut self, dty: &DataTy) { + match &dty.dty { + DataTyKind::Ident(ident) => self.print_ident(ident), + DataTyKind::Scalar(sty) => self.print_sty(sty), + DataTyKind::Atomic(aty) => self.print_aty(aty), + DataTyKind::Array(dty, n) => { + self.string.push('['); + self.print_dty(dty); + self.string.push(';'); + self.print_nat(n); + self.string.push(']'); + } + DataTyKind::ArrayShape(dty, n) => { + self.string.push_str("[["); + self.print_dty(dty); + self.string.push(';'); + self.print_nat(n); + self.string.push_str("]]"); + } + DataTyKind::Tuple(dtys) => { + self.string.push('('); + print_list!(self, Self::print_dty, dtys); + self.string.push(')'); + } + DataTyKind::Struct(struct_decl) => { + self.string.push_str("struct "); + self.print_ident(&struct_decl.ident); + self.string.push_str(" { "); + print_list!(self, Self::print_field, &struct_decl.fields); + self.string.push_str(" }"); + } + DataTyKind::At(dty, mem) => { + self.print_dty(dty); + self.string.push('@'); + self.print_mem(mem); + } + DataTyKind::Ref(ref_dty) => { + self.string.push('&'); + self.print_prv(&ref_dty.rgn); + self.string.push(' '); + self.print_own(ref_dty.own); + self.string.push(' '); + self.print_mem(&ref_dty.mem); + self.string.push(' '); + self.print_dty(&ref_dty.dty); + } + DataTyKind::RawPtr(_) => { + unimplemented!() + } + DataTyKind::Dead(dty) => self.print_dty(dty), + } + } + + fn print_field(&mut self, field: &(Ident, DataTy)) { + self.print_ident(&field.0); + self.string.push_str(" : "); + self.print_dty(&field.1) + } + + fn print_sty(&mut self, sty: &ScalarTy) { + match sty { + ScalarTy::Unit => self.string.push_str("()"), + ScalarTy::U32 => self.string.push_str("u32"), + ScalarTy::U64 => self.string.push_str("u64"), + ScalarTy::I32 => self.string.push_str("i32"), + ScalarTy::I64 => self.string.push_str("i64"), + ScalarTy::F32 => self.string.push_str("f32"), + ScalarTy::F64 => self.string.push_str("f64"), + ScalarTy::Bool => self.string.push_str("bool"), + ScalarTy::Gpu => self.string.push_str("Gpu"), + ScalarTy::U8 => self.string.push_str("u8"), + } + } + + fn print_mem(&mut self, mem: &Memory) { + match mem { + Memory::CpuMem => self.string.push_str("cpu.mem"), + Memory::GpuGlobal => self.string.push_str("gpu.global"), + Memory::GpuShared => self.string.push_str("gpu.shared"), + Memory::GpuLocal => self.string.push_str("gpu.local"), + Memory::Ident(x) => self.print_ident(x), + } + } + + fn print_prv(&mut self, prv: &Provenance) { + match prv { + Provenance::Value(name) => self.string.push_str(&name), + Provenance::Ident(ident) => self.print_ident(ident), + } + } + + fn print_own(&mut self, own: Ownership) { + match own { + Ownership::Shrd => self.string.push_str("shrd"), + Ownership::Uniq => self.string.push_str("uniq"), + } + } + + fn print_nat(&mut self, n: &Nat) { + match n { + Nat::Ident(ident) => self.print_ident(ident), + Nat::GridIdx => {} // print nothing + Nat::BlockIdx(d) => { + self.string.push_str("blockIdx."); + self.print_dim_compo(d); + } + Nat::BlockDim(d) => { + self.string.push_str("blockDim."); + self.print_dim_compo(d); + } + Nat::ThreadIdx(d) => { + self.string.push_str("threadIdx."); + self.print_dim_compo(d); + } + Nat::Lit(n) => write!(&mut self.string, "{}", n).unwrap(), + Nat::BinOp(op, lhs, rhs) => { + self.string.push('('); + self.print_nat(lhs); + self.print_bin_op_nat(op); + self.print_nat(rhs); + self.string.push(')'); + } + Nat::App(func, args) => { + self.string.push_str("{}("); + self.print_ident(func); + if let Some((last, leading)) = args.split_last() { + for arg in leading { + self.print_nat(arg); + } + self.print_nat(last); + self.string.push(')'); + } + } + Nat::WarpGrpIdx => self.string.push_str("warpGrpIdx"), + Nat::WarpIdx => self.string.push_str("warpIdx"), + Nat::LaneIdx => self.string.push_str("laneIdx"), + } + } + + fn print_bin_op_nat(&mut self, bin_op_nat: &BinOpNat) { + match bin_op_nat { + BinOpNat::Add => self.string.push('+'), + BinOpNat::Sub => self.string.push('-'), + BinOpNat::Mul => self.string.push('*'), + BinOpNat::Div => self.string.push('/'), + BinOpNat::Mod => self.string.push('%'), + } + } +} diff --git a/src/arena_ast/span.rs b/src/arena_ast/span.rs new file mode 100644 index 00000000..4ca5a53a --- /dev/null +++ b/src/arena_ast/span.rs @@ -0,0 +1,21 @@ +//! Components for mapping between sources and AST nodes + +// Can deal with a source file of up to 4 GiB +// Before, this was storing a begin and end position with 64 bits each. The 16 Bytes are too large +// and not necessary. Span is used extensively and the new size of 8 bytes is much more suitable. +#[derive(Clone, Copy, Debug)] +pub struct Span { + pub begin: u32, + // TODO optimize space? by: change to offset from begin which enables u16 or u8 for the offset + // and is still a realistic span + pub end: u32, +} + +impl Span { + pub fn new(begin: usize, end: usize) -> Self { + Self { + begin: u32::try_from(begin).expect("The input source string is unexpectedly large."), + end: u32::try_from(end).expect("The input source string is unexpectedly large."), + } + } +} diff --git a/src/arena_ast/utils.rs b/src/arena_ast/utils.rs new file mode 100644 index 00000000..5a0e1375 --- /dev/null +++ b/src/arena_ast/utils.rs @@ -0,0 +1,443 @@ +use crate::arena_ast::visit::walk_list; +use crate::arena_ast::visit::Visit; +use crate::arena_ast::visit_mut::VisitMut; +use crate::arena_ast::{ + visit, visit_mut, ArgKinded, BaseExec, DataTy, DataTyKind, Dim, ExecExpr, ExecExprKind, ExecTy, + Expr, ExprKind, FnTy, FunDef, Ident, IdentExec, IdentKinded, Kind, Memory, Nat, ParamSig, + Provenance, Ty, TyKind, +}; +use std::collections::{HashMap, HashSet}; +use std::sync::atomic::{AtomicI32, Ordering}; + +static mut COUNTER: AtomicI32 = AtomicI32::new(0); + +pub(crate) fn fresh_ident<'a, F, R>(arena: &'a bumpalo::Bump, name: &str, ident_constr: F) -> R +where + F: Fn(Ident) -> R, +{ + ident_constr(Ident::new_impli(&arena, &fresh_name(name))) +} + +pub(crate) fn fresh_name(name: &str) -> String { + let prefix = format!("${}", name); + let i; + unsafe { + i = COUNTER.fetch_add(1, Ordering::SeqCst); + } + format!("{}_{}", prefix, i) +} + +pub fn implicit_idents<'a>(f: &FunDef<'a>) -> Option>> { + struct ImplicitIdents<'b>(HashSet>); + impl<'b> Visit<'b> for ImplicitIdents<'b> { + fn visit_ident(&mut self, ident: &Ident<'b>) { + if ident.is_implicit { + self.0.insert(ident.clone()); + } + } + } + + let mut impl_idents = ImplicitIdents(HashSet::new()); + impl_idents.visit_fun_def(f); + if impl_idents.0.is_empty() { + None + } else { + Some(impl_idents.0) + } +} + +pub trait VisitableMut<'a> { + fn visit_mut>(&mut self, visitor: &mut V); +} +macro_rules! visitable_mut { + ($t:ident, $f:ident) => { + impl<'a> VisitableMut<'a> for $t<'a> { + fn visit_mut>(&mut self, visitor: &mut V) { + visitor.$f(self); + } + } + }; +} +visitable_mut!(Ty, visit_ty); +visitable_mut!(Expr, visit_expr); +visitable_mut!(ExecExpr, visit_exec_expr); +visitable_mut!(IdentExec, visit_ident_exec); +visitable_mut!(ParamSig, visit_param_sig); +visitable_mut!(FnTy, visit_fn_ty); + +/* + * gen_idents: a list of generic identifiers to be substituted (this list can be longer than + * gen_args. In that case, only the first gen_args.len() many identifiers are substituted. + * gen_args: the kinded expressions that are substituting the generic identifiers + * t: the term to substitute in + */ +pub fn subst_idents_kinded<'a, I, J, T: VisitableMut<'a>>(gen_idents: I, gen_args: J, t: &mut T) +where + I: IntoIterator>, + J: IntoIterator>, +{ + let subst_map = HashMap::from_iter( + gen_idents + .into_iter() + .map(|p| p.ident.name.as_ref()) + .zip(gen_args), + ); + let mut subst_idents_kinded = SubstIdentsKinded::new(subst_map); + t.visit_mut(&mut subst_idents_kinded); +} + +pub fn subst_ident_exec<'a, T: VisitableMut<'a>>( + ident: &'a Ident<'a>, + exec: &'a ExecExpr<'a>, + t: &mut T, +) { + let mut subst_ident_exec = SubstIdentExec::new(ident, exec); + t.visit_mut(&mut subst_ident_exec); +} +/* + * substitute kinded arguments for free identifiers + * + * When substituting within a function definition or function type, the generic parameters are + * bound. In order to substitute generic identifiers with their arguments, the relevant generic + * identifiers must be removed from the list, first. + */ +struct SubstIdentsKinded<'a> { + pub subst_map: HashMap<&'a str, &'a ArgKinded<'a>>, + pub bound_idents: HashSet>, +} + +impl<'a> SubstIdentsKinded<'a> { + fn new(subst_map: HashMap<&'a str, &'a ArgKinded<'a>>) -> Self { + SubstIdentsKinded { + subst_map, + bound_idents: HashSet::new(), + } + } + + fn with_bound_idents( + subst_map: HashMap<&'a str, &'a ArgKinded<'a>>, + bound_idents: HashSet>, + ) -> Self { + SubstIdentsKinded { + subst_map, + bound_idents, + } + } +} + +impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { + fn visit_nat(&mut self, nat: &mut Nat<'a>) { + match nat { + Nat::Ident(ident) => { + let ident_kinded = IdentKinded::new(ident, Kind::Nat); + if !self.bound_idents.contains(&ident_kinded) { + if let Some(ArgKinded::Nat(nat_arg)) = + self.subst_map.get::(ident.name.as_ref()) + { + *nat = nat_arg.clone() + } + } + } + _ => visit_mut::walk_nat(self, nat), + } + } + + fn visit_mem(&mut self, mem: &mut Memory<'a>) { + match mem { + Memory::Ident(ident) => { + let ident_kinded = IdentKinded::new(ident, Kind::Memory); + if !self.bound_idents.contains(&ident_kinded) { + if let Some(ArgKinded::Memory(mem_arg)) = + self.subst_map.get::(ident.name.as_ref()) + { + *mem = mem_arg.clone() + } + } + } + _ => visit_mut::walk_mem(self, mem), + } + } + + fn visit_prv(&mut self, prv: &mut Provenance<'a>) { + match prv { + Provenance::Ident(ident) => { + let ident_kinded = IdentKinded::new(ident, Kind::Provenance); + if !self.bound_idents.contains(&ident_kinded) { + if let Some(ArgKinded::Provenance(prv_arg)) = + self.subst_map.get::(ident.name.as_ref()) + { + *prv = prv_arg.clone() + } + } + } + _ => visit_mut::walk_prv(self, prv), + } + } + + fn visit_dty(&mut self, dty: &mut DataTy<'a>) { + match &mut dty.dty { + DataTyKind::Ident(ident) => { + let ident_kinded = IdentKinded::new(ident, Kind::DataTy); + if !self.bound_idents.contains(&ident_kinded) { + if let Some(ArgKinded::DataTy(dty_arg)) = + self.subst_map.get::(ident.name.as_ref()) + { + *dty = dty_arg.clone() + } + } + } + _ => visit_mut::walk_dty(self, dty), + } + } + + // add generic paramters to list of bound identifiers + fn visit_fn_ty(&mut self, fn_ty: &mut FnTy<'a>) { + let fun_bound_idents = fn_ty.generics.clone(); + let mut all_bound_idents = self.bound_idents.clone(); + all_bound_idents.extend(fun_bound_idents); + let mut visitor_subst_generic_ident = + SubstIdentsKinded::with_bound_idents(self.subst_map, all_bound_idents); + walk_list!( + &mut visitor_subst_generic_ident, + visit_param_sig, + &mut fn_ty.param_sigs + ); + for ident_exec in &mut fn_ty.generic_exec { + visitor_subst_generic_ident.visit_exec_ty(&mut ident_exec.ty); + } + visitor_subst_generic_ident.visit_exec_expr(&mut fn_ty.exec); + visitor_subst_generic_ident.visit_ty(&mut fn_ty.ret_ty); + } + + // only required to introduce a new scope of bound identifiers + fn visit_expr(&mut self, expr: &mut Expr<'a>) { + match &mut expr.expr { + ExprKind::ForNat(ident, collec, body) => { + self.visit_nat_range(collec); + let mut scoped_bound_idents = self.bound_idents.clone(); + scoped_bound_idents.extend(std::iter::once(IdentKinded::new(ident, Kind::Nat))); + let mut subst_inner_kinded_idents = + SubstIdentsKinded::with_bound_idents(self.subst_map, scoped_bound_idents); + subst_inner_kinded_idents.visit_expr(body); + } + _ => visit_mut::walk_expr(self, expr), + } + } + + // add generic paramters to list of bound identifiers + fn visit_fun_def(&mut self, fun_def: &mut FunDef<'a>) { + let fun_bound_idents = fun_def.generic_params.clone(); + let mut all_bound_idents = self.bound_idents.clone(); + all_bound_idents.extend(fun_bound_idents); + let mut subst_fun_free_kind_idents = + SubstIdentsKinded::with_bound_idents(self.subst_map, all_bound_idents); + walk_list!( + &mut subst_fun_free_kind_idents, + visit_param_decl, + &mut fun_def.param_decls + ); + subst_fun_free_kind_idents.visit_dty(&mut fun_def.ret_dty); + for ident_exec in &mut fun_def.generic_exec { + subst_fun_free_kind_idents.visit_ident_exec(ident_exec); + } + subst_fun_free_kind_idents.visit_exec_expr(&mut fun_def.exec); + walk_list!( + subst_fun_free_kind_idents, + visit_prv_rel, + &mut fun_def.prv_rels + ); + subst_fun_free_kind_idents.visit_block(&mut fun_def.body) + } +} + +/* + * Substitue a generic exec identifier with specific exec. + * This substitution ignores whehter an execution identifier is bound by a function type. + */ +struct SubstIdentExec<'a> { + pub ident: &'a Ident<'a>, + pub exec: &'a ExecExpr<'a>, +} + +impl<'a> SubstIdentExec<'a> { + fn new(ident: &'a Ident<'a>, exec: &'a ExecExpr<'a>) -> Self { + SubstIdentExec { ident, exec } + } +} +impl<'a> VisitMut<'a> for SubstIdentExec<'a> { + fn visit_exec_expr(&mut self, bump: &'a bumpalo::Bump, exec_expr: &mut ExecExpr<'a>) { + insert_for_ident(bump, self.exec, &self.ident, exec_expr) + } +} + +/** +fn insert_for_ident<'a>(exec: &ExecExpr<'a>, ident: &Ident<'a>, in_exec: &mut ExecExpr<'a>) { + if let BaseExec::Ident(i) = &mut in_exec.exec.base { + if i == ident { + let mut subst_exec = exec.clone(); + subst_exec.exec.path.extend(in_exec.exec.path.clone()); + *in_exec = subst_exec; + } + } +} +*/ + +fn insert_for_ident<'a>( + bump: &'a bumpalo::Bump, + exec: &ExecExpr<'a>, + ident: &Ident<'a>, + in_exec: &mut ExecExpr<'a>, +) { + if let BaseExec::Ident(i) = &in_exec.exec.base { + if i == ident { + let mut merged_path = exec.exec.path.clone(); + merged_path.extend(in_exec.exec.path.iter().cloned()); + + let new_exec = bump.alloc(ExecExprKind { + base: exec.exec.base.clone(), + path: merged_path, + }); + + let new_exec_expr = ExecExpr { + exec: new_exec, + ty: in_exec.ty, + span: in_exec.span, + }; + + *in_exec = new_exec_expr; + } + } +} + +pub trait Visitable<'a> { + fn visit>(&self, visitor: &mut V); +} +macro_rules! visitable { + ($t:ident, $f:ident) => { + impl<'a> Visitable<'a> for $t<'a> { + fn visit>(&self, visitor: &mut V) { + visitor.$f(self); + } + } + }; +} +visitable!(Ty, visit_ty); +visitable!(FnTy, visit_fn_ty); +visitable!(ParamSig, visit_param_sig); +visitable!(DataTy, visit_dty); +visitable!(Memory, visit_mem); +visitable!(Provenance, visit_prv); +visitable!(ExecExpr, visit_exec_expr); +visitable!(ExecTy, visit_exec_ty); +visitable!(Dim, visit_dim); +visitable!(Expr, visit_expr); +visitable!(Nat, visit_nat); + +pub fn free_kinded_idents<'a, T: Visitable<'a>>(t: &T) -> HashSet> { + let mut free_kinded_idents = FreeKindedIdents::new(); + t.visit(&mut free_kinded_idents); + free_kinded_idents.set +} + +pub struct FreeKindedIdents<'a> { + pub set: HashSet>, + pub bound_idents: HashSet>, +} + +impl<'a> FreeKindedIdents<'a> { + fn new() -> Self { + FreeKindedIdents { + set: HashSet::new(), + bound_idents: HashSet::new(), + } + } + + fn with_bound_idents(idents: HashSet>) -> Self { + FreeKindedIdents { + set: HashSet::new(), + bound_idents: idents, + } + } +} + +impl<'a> Visit<'a> for FreeKindedIdents<'a> { + fn visit_nat(&mut self, nat: &Nat<'a>) { + match nat { + Nat::Ident(ident) => { + let ident_kinded = IdentKinded::new(ident, Kind::Nat); + if !self.bound_idents.contains(&ident_kinded) { + self.set.extend(std::iter::once(ident_kinded)) + } + } + _ => visit::walk_nat(self, nat), + } + } + + fn visit_mem(&mut self, mem: &Memory<'a>) { + match mem { + Memory::Ident(ident) => { + let ident_kinded = IdentKinded::new(ident, Kind::Memory); + if !self.bound_idents.contains(&ident_kinded) { + self.set.extend(std::iter::once(ident_kinded)) + } + } + _ => visit::walk_mem(self, mem), + } + } + + fn visit_prv(&mut self, prv: &Provenance<'a>) { + match prv { + Provenance::Ident(ident) => { + let ident_kinded = IdentKinded::new(ident, Kind::Provenance); + if !self.bound_idents.contains(&ident_kinded) { + self.set.extend(std::iter::once(ident_kinded)) + } + } + _ => visit::walk_prv(self, prv), + } + } + + fn visit_dty(&mut self, dty: &DataTy<'a>) { + match &dty.dty { + DataTyKind::Ident(ident) => { + let ident_kinded = IdentKinded::new(ident, Kind::DataTy); + if !self.bound_idents.contains(&ident_kinded) { + self.set.extend(std::iter::once(ident_kinded)) + } + } + _ => visit::walk_dty(self, dty), + } + } + + fn visit_ty(&mut self, ty: &Ty<'a>) { + match &ty.ty { + TyKind::FnTy(fn_ty) => { + if !fn_ty.generics.is_empty() { + panic!( + "Generic function types can not appear,\ + only their instatiated counter parts." + ) + } + + walk_list!(self, visit_param_sig, &fn_ty.param_sigs); + self.visit_ty(fn_ty.ret_ty) + } + _ => visit::walk_ty(self, ty), + } + } + + fn visit_expr(&mut self, expr: &Expr<'a>) { + match &expr.expr { + ExprKind::ForNat(ident, collec, body) => { + self.visit_nat_range(collec); + let mut scoped_bound_idents = self.bound_idents.clone(); + scoped_bound_idents.extend(std::iter::once(IdentKinded::new(ident, Kind::Nat))); + let mut inner_free_idents = + FreeKindedIdents::with_bound_idents(scoped_bound_idents); + inner_free_idents.visit_expr(body); + self.set.extend(inner_free_idents.set) + } + _ => visit::walk_expr(self, expr), + } + } +} diff --git a/src/arena_ast/visit.rs b/src/arena_ast/visit.rs new file mode 100644 index 00000000..56198026 --- /dev/null +++ b/src/arena_ast/visit.rs @@ -0,0 +1,580 @@ +use crate::arena_ast::*; + +#[rustfmt::skip] +pub trait Visit<'a>: Sized { + fn visit_binary_op_nat(&mut self, _op: &BinOpNat) {} + fn visit_nat(&mut self, n: &Nat<'a>) { walk_nat(self, n) } + fn visit_nat_range(&mut self, nr: &NatRange<'a>) { walk_nat_range(self, nr) } + fn visit_ident_kinded(&mut self, id_kind: &IdentKinded<'a>) { walk_ident_kinded(self, id_kind) } + fn visit_ident_exec(&mut self, ident_exec: &IdentExec<'a>) { walk_ident_exec(self, ident_exec) } + fn visit_prv_rel(&mut self, prv_rel: &PrvRel<'a>) { walk_prv_rel(self, prv_rel) } + fn visit_exec_ty(&mut self, _exec: &ExecTy<'a>) {} + fn visit_mem(&mut self, mem: &Memory<'a>) { walk_mem(self, mem) } + fn visit_prv(&mut self, prv: &Provenance<'a>) { walk_prv(self, prv) } + fn visit_scalar_ty(&mut self, _sty: &ScalarTy) {} + fn visit_atomic_ty(&mut self, _aty: &AtomicTy) {} + fn visit_dim_compo(&mut self, _dim_compo: &DimCompo) { } + fn visit_dim(&mut self, dim: &Dim<'a>) { walk_dim(self, dim) } + fn visit_dim3d(&mut self, dim3d: &Dim3d<'a>) { walk_dim3d(self, dim3d) } + fn visit_dim2d(&mut self, dim2d: &Dim2d<'a>) { walk_dim2d(self, dim2d) } + fn visit_dim1d(&mut self, dim1d: &Dim1d<'a>) { walk_dim1d(self, dim1d) } + fn visit_ref(&mut self, reff: &RefDty<'a>) { walk_ref(self, reff) } + fn visit_dty(&mut self, dty: &DataTy<'a>) { walk_dty(self, dty) } + fn visit_fn_ty(&mut self, fn_ty: &FnTy<'a>) { walk_fn_ty(self, fn_ty) } + fn visit_nat_constr(&mut self, nat_constr: &NatConstr<'a>) { walk_nat_constr(self, nat_constr) } + fn visit_ty(&mut self, ty: &Ty<'a>) { walk_ty(self, ty) } + fn visit_view(&mut self, view: &View<'a>) { walk_view(self, view) } + fn visit_pl_expr(&mut self, pl_expr: &PlaceExpr<'a>) { walk_pl_expr(self, pl_expr) } + fn visit_arg_kinded(&mut self, arg_kinded: &ArgKinded<'a>) { walk_arg_kinded(self, arg_kinded) } + fn visit_kind(&mut self, _kind: &Kind) {} + fn visit_binary_op(&mut self, _op: &BinOp) {} + fn visit_unary_op(&mut self, _op: &UnOp) {} + fn visit_own(&mut self, _own: &Ownership) {} + fn visit_mutability(&mut self, _mutbl: &Mutability) {} + fn visit_lit(&mut self, _lit: &Lit) {} + fn visit_ident(&mut self, _ident: &Ident<'a>) {} + fn visit_pattern(&mut self, pattern: &Pattern<'a>) { walk_pattern(self, pattern) } + fn visit_split(&mut self, split: &Split<'a>) { walk_split(self, split) } + fn visit_sched(&mut self, par_for: &Sched<'a>) { walk_sched(self, par_for) } + fn visit_expr(&mut self, expr: &Expr<'a>) { walk_expr(self, expr) } + fn visit_app_kernel(&mut self, app_kernel: &AppKernel<'a>) { walk_app_kernel(self, app_kernel) } + fn visit_block(&mut self, block: &Block<'a>) { walk_block(self, block) } + fn visit_split_proj(&mut self, exec_split: &TakeRange<'a>) { walk_split_proj(self, exec_split) } + fn visit_exec_expr(&mut self, exec_expr: &ExecExpr<'a>) { walk_exec_expr(self, exec_expr) } + fn visit_exec(&mut self, exec: &ExecExprKind<'a>) { walk_exec(self, exec) } + fn visit_param_decl(&mut self, param_decl: &ParamDecl<'a>) { walk_param_decl(self, param_decl) } + fn visit_fun_def(&mut self, fun_def: &FunDef<'a>) { walk_fun_def(self, fun_def) } + fn visit_fun_decl(&mut self, fun_decl: &FunDecl<'a>) { walk_fun_decl(self, fun_decl) } + fn visit_param_sig(&mut self, param_sig: &ParamSig<'a>) { walk_param_sig(self, param_sig) } + fn visit_field(&mut self, field: &(Ident<'a>, DataTy<'a>)) { walk_field(self, field) } +} + +macro_rules! walk_list { + ($visitor: expr, $method: ident, $list: expr) => { + for elem in $list.iter_mut() { + $visitor.$method(elem) + } + }; +} +pub(crate) use walk_list; + +pub fn walk_nat<'a, V: Visit<'a>>(visitor: &mut V, n: &Nat<'a>) { + match n { + Nat::Ident(ident) => visitor.visit_ident(ident), + Nat::BinOp(op, l, r) => { + visitor.visit_binary_op_nat(op); + visitor.visit_nat(l); + visitor.visit_nat(r) + } + Nat::GridIdx + | Nat::BlockIdx(_) + | Nat::BlockDim(_) + | Nat::ThreadIdx(_) + | Nat::WarpGrpIdx + | Nat::WarpIdx + | Nat::LaneIdx + | Nat::Lit(_) => {} + Nat::App(func, args) => { + visitor.visit_ident(func); + walk_list!(visitor, visit_nat, args.as_ref()) + } + } +} + +pub fn walk_nat_range<'a, V: Visit<'a>>(visitor: &mut V, nr: &NatRange<'a>) { + match nr { + NatRange::Simple { lower, upper } => { + visitor.visit_nat(lower); + visitor.visit_nat(upper); + } + NatRange::Halved { upper } | NatRange::Doubled { upper } => visitor.visit_nat(upper), + } +} + +pub fn walk_ident_kinded<'a, V: Visit<'a>>(visitor: &mut V, id_kind: &IdentKinded<'a>) { + let IdentKinded { ident, kind } = id_kind; + visitor.visit_ident(ident); + visitor.visit_kind(kind) +} + +pub fn walk_ident_exec<'a, V: Visit<'a>>(visitor: &mut V, id_exec: &IdentExec<'a>) { + let IdentExec { ident, ty } = id_exec; + visitor.visit_ident(ident); + visitor.visit_exec_ty(ty) +} + +pub fn walk_prv_rel<'a, V: Visit<'a>>(visitor: &mut V, prv_rel: &PrvRel<'a>) { + let PrvRel { longer, shorter } = prv_rel; + visitor.visit_ident(longer); + visitor.visit_ident(shorter) +} + +pub fn walk_mem<'a, V: Visit<'a>>(visitor: &mut V, mem: &Memory<'a>) { + if let Memory::Ident(ident) = mem { + visitor.visit_ident(ident) + } +} + +pub fn walk_prv<'a, V: Visit<'a>>(visitor: &mut V, prv: &Provenance<'a>) { + match prv { + Provenance::Ident(ident) => visitor.visit_ident(ident), + Provenance::Value(_) => {} + } +} + +pub fn walk_dim3d<'a, V: Visit<'a>>(visitor: &mut V, dim3d: &Dim3d<'a>) { + let Dim3d(n1, n2, n3) = dim3d; + visitor.visit_nat(n1); + visitor.visit_nat(n2); + visitor.visit_nat(n3); +} + +pub fn walk_dim2d<'a, V: Visit<'a>>(visitor: &mut V, dim2d: &Dim2d<'a>) { + let Dim2d(n1, n2) = dim2d; + visitor.visit_nat(n1); + visitor.visit_nat(n2); +} + +pub fn walk_dim1d<'a, V: Visit<'a>>(visitor: &mut V, dim1d: &Dim1d<'a>) { + let Dim1d(n) = dim1d; + visitor.visit_nat(n); +} + +pub fn walk_dim<'a, V: Visit<'a>>(visitor: &mut V, dim: &Dim<'a>) { + match dim { + Dim::XYZ(dim3d) => { + visitor.visit_dim3d(dim3d); + } + Dim::XY(dim2d) | Dim::XZ(dim2d) | Dim::YZ(dim2d) => { + visitor.visit_dim2d(dim2d); + } + Dim::X(dim1d) | Dim::Y(dim1d) | Dim::Z(dim1d) => visitor.visit_dim1d(dim1d), + } +} + +pub fn walk_ref<'a, V: Visit<'a>>(visitor: &mut V, reff: &RefDty<'a>) { + let RefDty { rgn, own, mem, dty } = reff; + visitor.visit_prv(rgn); + visitor.visit_own(own); + visitor.visit_mem(mem); + visitor.visit_dty(dty); +} + +pub fn walk_dty<'a, V: Visit<'a>>(visitor: &mut V, dty: &DataTy<'a>) { + match &dty.dty { + DataTyKind::Ident(ident) => visitor.visit_ident(ident), + DataTyKind::Scalar(sty) => visitor.visit_scalar_ty(sty), + DataTyKind::Atomic(aty) => visitor.visit_atomic_ty(aty), + DataTyKind::Tuple(elem_dtys) => walk_list!(visitor, visit_dty, elem_dtys), + DataTyKind::Struct(struct_decl) => { + visitor.visit_ident(&struct_decl.ident); + walk_list!(visitor, visit_field, &struct_decl.fields) + } + DataTyKind::Array(dty, n) => { + visitor.visit_dty(dty); + visitor.visit_nat(n) + } + DataTyKind::ArrayShape(dty, n) => { + visitor.visit_dty(dty); + visitor.visit_nat(n); + } + DataTyKind::At(dty, mem) => { + visitor.visit_dty(dty); + visitor.visit_mem(mem) + } + DataTyKind::Ref(reff) => { + visitor.visit_ref(reff); + } + DataTyKind::RawPtr(dty) => visitor.visit_dty(dty), + DataTyKind::Dead(dty) => visitor.visit_dty(dty), + } +} + +pub fn walk_fn_ty<'a, V: Visit<'a>>(visitor: &mut V, fn_ty: &FnTy<'a>) { + let FnTy { + generics, + generic_exec, + param_sigs, + exec, + ret_ty, + nat_constrs, + } = fn_ty; + walk_list!(visitor, visit_ident_kinded, generics); + for exec_decl in generic_exec { + visitor.visit_ident_exec(exec_decl) + } + walk_list!(visitor, visit_param_sig, param_sigs); + visitor.visit_exec_expr(exec); + visitor.visit_ty(ret_ty); + walk_list!(visitor, visit_nat_constr, nat_constrs); +} + +pub fn walk_nat_constr<'a, V: Visit<'a>>(visitor: &mut V, nat_constr: &NatConstr<'a>) { + match nat_constr { + NatConstr::True => {} + NatConstr::Eq(l, r) => { + visitor.visit_nat(l); + visitor.visit_nat(r); + } + NatConstr::Lt(l, r) => { + visitor.visit_nat(l); + visitor.visit_nat(r); + } + NatConstr::And(l, r) => { + visitor.visit_nat_constr(l); + visitor.visit_nat_constr(r); + } + NatConstr::Or(l, r) => { + visitor.visit_nat_constr(l); + visitor.visit_nat_constr(r); + } + } +} + +pub fn walk_ty<'a, V: Visit<'a>>(visitor: &mut V, ty: &Ty<'a>) { + match &ty.ty { + TyKind::Data(dty) => visitor.visit_dty(dty), + TyKind::FnTy(fn_ty) => { + visitor.visit_fn_ty(fn_ty); + } + } +} + +pub fn walk_view<'a, V: Visit<'a>>(visitor: &mut V, view: &View<'a>) { + visitor.visit_ident(&view.name); + walk_list!(visitor, visit_arg_kinded, &view.gen_args); + for v in &view.args { + visitor.visit_view(v) + } +} + +pub fn walk_pl_expr<'a, V: Visit<'a>>(visitor: &mut V, pl_expr: &PlaceExpr<'a>) { + match &pl_expr.pl_expr { + PlaceExprKind::Ident(ident) => visitor.visit_ident(ident), + PlaceExprKind::Deref(pl_expr) => visitor.visit_pl_expr(pl_expr), + PlaceExprKind::Select(p, distrib_exec) => { + visitor.visit_pl_expr(p); + visitor.visit_exec_expr(distrib_exec); + } + PlaceExprKind::Proj(pl_expr, _) => { + visitor.visit_pl_expr(pl_expr); + } + PlaceExprKind::FieldProj(pl_expr, field_name) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_ident(field_name); + } + PlaceExprKind::View(pl_expr, view) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_view(view); + } + PlaceExprKind::Idx(pl_expr, n) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_nat(n) + } + } +} + +pub fn walk_arg_kinded<'a, V: Visit<'a>>(visitor: &mut V, arg_kinded: &ArgKinded<'a>) { + match arg_kinded { + ArgKinded::Ident(ident) => visitor.visit_ident(ident), + ArgKinded::Nat(n) => visitor.visit_nat(n), + ArgKinded::Memory(mem) => visitor.visit_mem(mem), + ArgKinded::DataTy(dty) => visitor.visit_dty(dty), + ArgKinded::Provenance(prv) => visitor.visit_prv(prv), + } +} + +pub fn walk_pattern<'a, V: Visit<'a>>(visitor: &mut V, pattern: &Pattern<'a>) { + match pattern { + Pattern::Ident(mutab, ident) => { + visitor.visit_mutability(mutab); + visitor.visit_ident(ident); + } + Pattern::Tuple(patterns) => { + walk_list!(visitor, visit_pattern, patterns) + } + Pattern::Wildcard => {} + } +} + +pub fn walk_split<'a, V: Visit<'a>>(visitor: &mut V, indep: &Split<'a>) { + let Split { + dim_compo, + pos, + split_exec, + branch_idents, + branch_bodies, + } = indep; + visitor.visit_dim_compo(dim_compo); + visitor.visit_nat(pos); + visitor.visit_exec_expr(split_exec); + walk_list!(visitor, visit_ident, branch_idents); + walk_list!(visitor, visit_expr, branch_bodies); +} + +pub fn walk_sched<'a, V: Visit<'a>>(visitor: &mut V, sched: &Sched<'a>) { + let Sched { + dim, + inner_exec_ident, + sched_exec, + body, + } = sched; + visitor.visit_dim_compo(dim); + for ident in inner_exec_ident { + visitor.visit_ident(ident) + } + visitor.visit_exec_expr(sched_exec); + visitor.visit_block(body); +} + +pub fn walk_expr<'a, V: Visit<'a>>(visitor: &mut V, expr: &Expr<'a>) { + // For now, only visit ExprKind + match &expr.expr { + ExprKind::Lit(l) => visitor.visit_lit(l), + ExprKind::PlaceExpr(pl_expr) => visitor.visit_pl_expr(pl_expr), + + ExprKind::Ref(_, own, pl_expr) => { + visitor.visit_own(own); + visitor.visit_pl_expr(pl_expr); + } + ExprKind::Block(block) => visitor.visit_block(block), + ExprKind::LetUninit(maybe_exec_expr, ident, ty) => { + for e in maybe_exec_expr { + visitor.visit_exec_expr(e); + } + visitor.visit_ident(ident); + visitor.visit_ty(ty); + } + ExprKind::Let(pattern, ty, e) => { + visitor.visit_pattern(pattern); + for ty in ty.as_ref() { + visitor.visit_ty(ty); + } + visitor.visit_expr(e); + } + ExprKind::Assign(pl_expr, expr) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_expr(expr) + } + ExprKind::IdxAssign(pl_expr, idx, expr) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_nat(idx); + visitor.visit_expr(expr); + } + ExprKind::Seq(es) => { + for e in es { + visitor.visit_expr(e) + } + } + // ExprKind::Lambda(params, exec_decl, dty, expr) => { + // walk_list!(visitor, visit_param_decl, params); + // visitor.visit_ident_exec(exec_decl); + // visitor.visit_dty(dty); + // visitor.visit_expr(expr) + // } + ExprKind::App(f, gen_args, args) => { + visitor.visit_ident(f); + walk_list!(visitor, visit_arg_kinded, gen_args); + walk_list!(visitor, visit_expr, args); + } + ExprKind::DepApp(f, gen_args) => { + visitor.visit_ident(f); + walk_list!(visitor, visit_arg_kinded, gen_args); + } + ExprKind::AppKernel(app_kernel) => { + visitor.visit_app_kernel(app_kernel); + } + ExprKind::IfElse(cond, tt, ff) => { + visitor.visit_expr(cond); + visitor.visit_expr(tt); + visitor.visit_expr(ff) + } + ExprKind::If(cond, tt) => { + visitor.visit_expr(cond); + visitor.visit_expr(tt) + } + ExprKind::Array(elems) => { + walk_list!(visitor, visit_expr, elems); + } + ExprKind::Tuple(elems) => { + walk_list!(visitor, visit_expr, elems); + } + ExprKind::For(ident, coll, body) => { + visitor.visit_ident(ident); + visitor.visit_expr(coll); + visitor.visit_expr(body); + } + ExprKind::Split(par_branch) => { + visitor.visit_split(par_branch); + } + ExprKind::Sched(sched) => { + visitor.visit_sched(sched); + } + ExprKind::ForNat(ident, range, body) => { + visitor.visit_ident(ident); + visitor.visit_nat_range(range); + visitor.visit_expr(body) + } + ExprKind::While(cond, body) => { + visitor.visit_expr(cond); + visitor.visit_expr(body); + } + ExprKind::BinOp(op, l, r) => { + visitor.visit_binary_op(op); + visitor.visit_expr(l); + visitor.visit_expr(r) + } + ExprKind::UnOp(op, expr) => { + visitor.visit_unary_op(op); + visitor.visit_expr(expr) + } + ExprKind::Sync(exec) => { + for e in exec { + visitor.visit_exec_expr(e) + } + } + ExprKind::Unsafe(expr) => visitor.visit_expr(expr), + ExprKind::Cast(expr, dty) => { + visitor.visit_expr(expr); + visitor.visit_dty(dty) + } + ExprKind::Range(_, _) | ExprKind::Hole => (), + } +} + +pub fn walk_app_kernel<'a, V: Visit<'a>>(visitor: &mut V, app_kernel: &AppKernel<'a>) { + let AppKernel { + grid_dim, + block_dim, + shared_mem_dtys, + shared_mem_prvs: _, + fun_ident, + gen_args, + args, + } = app_kernel; + visitor.visit_dim(grid_dim); + visitor.visit_dim(block_dim); + for dty in shared_mem_dtys { + visitor.visit_dty(dty); + } + visitor.visit_ident(fun_ident); + for garg in gen_args { + visitor.visit_arg_kinded(garg); + } + for arg in args { + visitor.visit_expr(arg); + } +} + +pub fn walk_block<'a, V: Visit<'a>>(visitor: &mut V, block: &Block<'a>) { + let Block { body, .. } = block; + visitor.visit_expr(body); +} + +pub fn walk_split_proj<'a, V: Visit<'a>>(visitor: &mut V, split_proj: &TakeRange<'a>) { + let TakeRange { + split_dim, + pos, + left_or_right: _, + } = split_proj; + visitor.visit_dim_compo(split_dim); + visitor.visit_nat(pos); +} + +pub fn walk_exec_expr<'a, V: Visit<'a>>(visitor: &mut V, exec_expr: &ExecExpr<'a>) { + visitor.visit_exec(&exec_expr.exec); + for t in &exec_expr.ty { + visitor.visit_exec_ty(t); + } +} + +pub fn walk_exec<'a, V: Visit<'a>>(visitor: &mut V, exec: &ExecExprKind<'a>) { + let ExecExprKind { base, path } = exec; + match base { + BaseExec::CpuThread => (), + BaseExec::Ident(ident) => visitor.visit_ident(ident), + BaseExec::GpuGrid(gdim, bdim) => { + visitor.visit_dim(gdim); + visitor.visit_dim(bdim); + } + }; + for e in path { + match e { + ExecPathElem::TakeRange(split_proj) => visitor.visit_split_proj(split_proj), + ExecPathElem::ForAll(dim_compo) => visitor.visit_dim_compo(dim_compo), + ExecPathElem::ToThreads(dim_compo) => visitor.visit_dim_compo(dim_compo), + ExecPathElem::ToWarps => {} + } + } +} + +pub fn walk_param_decl<'a, V: Visit<'a>>(visitor: &mut V, param_decl: &ParamDecl<'a>) { + let ParamDecl { + ident, + ty, + mutbl, + exec_expr, + } = param_decl; + visitor.visit_ident(ident); + if let Some(tty) = ty { + visitor.visit_ty(tty); + } + visitor.visit_mutability(mutbl); + for ex in exec_expr { + visitor.visit_exec_expr(ex); + } +} + +pub fn walk_fun_def<'a, V: Visit<'a>>(visitor: &mut V, fun_def: &FunDef<'a>) { + let FunDef { + ident: _, + generic_params, + generic_exec, + param_decls: params, + ret_dty, + exec, + prv_rels, + body, + } = fun_def; + walk_list!(visitor, visit_ident_kinded, generic_params); + for exec_decl in generic_exec { + visitor.visit_ident_exec(exec_decl); + } + walk_list!(visitor, visit_param_decl, params); + visitor.visit_dty(ret_dty); + visitor.visit_exec_expr(exec); + walk_list!(visitor, visit_prv_rel, prv_rels); + visitor.visit_block(body) +} + +pub fn walk_fun_decl<'a, V: Visit<'a>>(visitor: &mut V, fun_decl: &FunDecl<'a>) { + let FunDecl { + ident: _, + generic_params, + generic_exec, + param_decls: params, + ret_dty, + exec, + prv_rels, + } = fun_decl; + walk_list!(visitor, visit_ident_kinded, generic_params); + for exec_decl in generic_exec { + visitor.visit_ident_exec(exec_decl); + } + walk_list!(visitor, visit_param_decl, params); + visitor.visit_dty(ret_dty); + visitor.visit_exec_expr(exec); + walk_list!(visitor, visit_prv_rel, prv_rels); +} + +pub fn walk_param_sig<'a, V: Visit<'a>>(visitor: &mut V, param_sig: &ParamSig<'a>) { + let ParamSig { exec_expr, ty } = param_sig; + visitor.visit_exec_expr(exec_expr); + visitor.visit_ty(ty); +} + +pub fn walk_field<'a, V: Visit<'a>>(visitor: &mut V, field: &(Ident<'a>, DataTy<'a>)) { + let (ident, dty) = field; + visitor.visit_ident(ident); + visitor.visit_dty(dty); +} diff --git a/src/arena_ast/visit_mut.rs b/src/arena_ast/visit_mut.rs new file mode 100644 index 00000000..b82a9d3a --- /dev/null +++ b/src/arena_ast/visit_mut.rs @@ -0,0 +1,587 @@ +use crate::arena_ast::*; + +#[rustfmt::skip] +pub trait VisitMut<'a>: Sized { + fn visit_binary_op_nat(&mut self, _op: &mut BinOpNat) {} + fn visit_nat(&mut self, n: &mut Nat<'a>) { walk_nat(self, n) } + fn visit_nat_range(&mut self, nr: &mut NatRange<'a>) { walk_nat_range(self, nr) } + fn visit_ident_kinded(&mut self, id_kind: &mut IdentKinded<'a>) { walk_ident_kinded(self, id_kind) } + fn visit_ident_exec(&mut self, id_exec: &mut IdentExec<'a>) { walk_ident_exec(self, id_exec) } + fn visit_prv_rel(&mut self, prv_rel: &mut PrvRel<'a>) { walk_prv_rel(self, prv_rel) } + fn visit_exec_ty(&mut self, _exec: &mut ExecTy<'a>) {} + fn visit_mem(&mut self, mem: &mut Memory<'a>) { walk_mem(self, mem) } + fn visit_prv(&mut self, prv: &mut Provenance<'a>) { walk_prv(self, prv) } + fn visit_scalar_ty(&mut self, _sty: &mut ScalarTy) {} + fn visit_atomic_ty(&mut self, _aty: &mut AtomicTy) {} + fn visit_dim_compo(&mut self, _dim_compo: &mut DimCompo) {} + fn visit_dim(&mut self, dim: &mut Dim<'a>) { walk_dim(self, dim) } + fn visit_dim3d(&mut self, dim3d: &mut Dim3d<'a>) { walk_dim3d(self, dim3d) } + fn visit_dim2d(&mut self, dim2d: &mut Dim2d<'a>) { walk_dim2d(self, dim2d) } + fn visit_dim1d(&mut self, dim1d: &mut Dim1d<'a>) { walk_dim1d(self, dim1d) } + fn visit_ref(&mut self, reff: &mut RefDty<'a>) { walk_ref(self, reff) } + fn visit_dty(&mut self, dty: &mut DataTy<'a>) { walk_dty(self, dty) } + fn visit_fn_ty(&mut self, fn_ty: &mut FnTy<'a>) { walk_fn_ty(self, fn_ty) } + fn visit_nat_constr(&mut self, nat_constr: &mut NatConstr<'a>) { walk_nat_constr(self, nat_constr) } + fn visit_ty(&mut self, ty: &mut Ty<'a>) { walk_ty(self, ty) } + fn visit_view(&mut self, view: &mut View<'a>) { walk_view(self, view) } + fn visit_pl_expr(&mut self, pl_expr: &mut PlaceExpr<'a>) { walk_pl_expr(self, pl_expr) } + fn visit_arg_kinded(&mut self, arg_kinded: &mut ArgKinded<'a>) { walk_arg_kinded(self, arg_kinded) } + fn visit_kind(&mut self, _kind: &mut Kind) {} + fn visit_binary_op(&mut self, _op: &mut BinOp) {} + fn visit_unary_op(&mut self, _op: &mut UnOp) {} + fn visit_own(&mut self, _own: &mut Ownership) {} + fn visit_mutability(&mut self, _mutbl: &mut Mutability) {} + fn visit_lit(&mut self, _lit: &mut Lit) {} + fn visit_ident(&mut self, _ident: &mut Ident<'a>) {} + fn visit_pattern(&mut self, pattern: &mut Pattern<'a>) { walk_pattern(self, pattern) } + fn visit_split(&mut self, split: &mut Split<'a>) { walk_split(self, split) } + fn visit_sched(&mut self, sched: &mut Sched<'a>) { walk_sched(self, sched) } + fn visit_expr(&mut self, expr: &mut Expr<'a>) { walk_expr(self, expr) } + fn visit_app_kernel(&mut self, app_kernel: &mut AppKernel<'a>) { walk_app_kernel(self, app_kernel) } + fn visit_block(&mut self, block: &mut Block<'a>) { walk_block(self, block) } + fn visit_split_proj(&mut self, exec_split: &mut TakeRange<'a>) { walk_split_proj(self, exec_split) } + fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr<'a>) { walk_exec_expr(self, exec_expr) } + fn visit_exec(&mut self, exec: &mut ExecExprKind<'a>) { walk_exec(self, exec) } + fn visit_exec_path_elem(&mut self, exec_path_elem: &mut ExecPathElem<'a>) { walk_exec_path_elem(self, exec_path_elem) } + fn visit_param_decl(&mut self, param_decl: &mut ParamDecl<'a>) { walk_param_decl(self, param_decl) } + fn visit_fun_def(&mut self, fun_def: &mut FunDef<'a>) { walk_fun_def(self, fun_def) } + fn visit_fun_decl(&mut self, fun_decl: &mut FunDecl<'a>) { walk_fun_decl(self, fun_decl) } + fn visit_param_sig(&mut self, param_sig: &mut ParamSig<'a>) { walk_param_sig(self, param_sig) } + fn visit_field(&mut self, field: &mut (Ident<'a>, DataTy<'a>)) { walk_field(self, field) } +} + +// Taken from the Rust compiler +macro_rules! walk_list { + ($visitor: expr, $method: ident, $list: expr) => { + for elem in $list.iter_mut() { + $visitor.$method(elem) + } + }; +} +pub(crate) use walk_list; + +pub fn walk_nat<'a, V: VisitMut<'a>>(visitor: &mut V, n: &mut Nat<'a>) { + match n { + Nat::Ident(ident) => visitor.visit_ident(ident), + Nat::BinOp(op, l, r) => { + visitor.visit_binary_op_nat(op); + visitor.visit_nat(l); + visitor.visit_nat(r) + } + Nat::GridIdx + | Nat::BlockIdx(_) + | Nat::BlockDim(_) + | Nat::ThreadIdx(_) + | Nat::WarpGrpIdx + | Nat::WarpIdx + | Nat::LaneIdx + | Nat::Lit(_) => {} + Nat::App(func, args) => { + visitor.visit_ident(func); + walk_list!(visitor, visit_nat, args.as_mut()) + } + } +} + +pub fn walk_nat_range<'a, V: VisitMut<'a>>(visitor: &mut V, nr: &mut NatRange<'a>) { + match nr { + NatRange::Simple { lower, upper } => { + visitor.visit_nat(lower); + visitor.visit_nat(upper); + } + NatRange::Halved { upper } | NatRange::Doubled { upper } => visitor.visit_nat(upper), + } +} + +pub fn walk_ident_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, id_kind: &mut IdentKinded<'a>) { + let IdentKinded { ident, kind } = id_kind; + visitor.visit_ident(ident); + visitor.visit_kind(kind) +} + +pub fn walk_ident_exec<'a, V: VisitMut<'a>>(visitor: &mut V, id_exec: &mut IdentExec<'a>) { + let IdentExec { ident, ty } = id_exec; + visitor.visit_ident(ident); + visitor.visit_exec_ty(ty) +} + +pub fn walk_prv_rel<'a, V: VisitMut<'a>>(visitor: &mut V, prv_rel: &mut PrvRel<'a>) { + let PrvRel { longer, shorter } = prv_rel; + visitor.visit_ident(longer); + visitor.visit_ident(shorter) +} + +pub fn walk_mem<'a, V: VisitMut<'a>>(visitor: &mut V, mem: &mut Memory<'a>) { + if let Memory::Ident(ident) = mem { + visitor.visit_ident(ident) + } +} + +pub fn walk_prv<'a, V: VisitMut<'a>>(visitor: &mut V, prv: &mut Provenance<'a>) { + match prv { + Provenance::Ident(ident) => visitor.visit_ident(ident), + Provenance::Value(_) => {} + } +} + +pub fn walk_dim3d<'a, V: VisitMut<'a>>(visitor: &mut V, dim3d: &mut Dim3d<'a>) { + let Dim3d(n1, n2, n3) = dim3d; + visitor.visit_nat(n1); + visitor.visit_nat(n2); + visitor.visit_nat(n3); +} + +pub fn walk_dim2d<'a, V: VisitMut<'a>>(visitor: &mut V, dim2d: &mut Dim2d<'a>) { + let Dim2d(n1, n2) = dim2d; + visitor.visit_nat(n1); + visitor.visit_nat(n2); +} + +pub fn walk_dim1d<'a, V: VisitMut<'a>>(visitor: &mut V, dim1d: &mut Dim1d<'a>) { + let Dim1d(n) = dim1d; + visitor.visit_nat(n); +} + +pub fn walk_dim<'a, V: VisitMut<'a>>(visitor: &mut V, dim: &mut Dim<'a>) { + match dim { + Dim::XYZ(dim3d) => { + visitor.visit_dim3d(dim3d); + } + Dim::XY(dim2d) | Dim::XZ(dim2d) | Dim::YZ(dim2d) => { + visitor.visit_dim2d(dim2d); + } + Dim::X(dim1d) | Dim::Y(dim1d) | Dim::Z(dim1d) => visitor.visit_dim1d(dim1d), + } +} + +pub fn walk_ref<'a, V: VisitMut<'a>>(visitor: &mut V, reff: &mut RefDty<'a>) { + let RefDty { rgn, own, mem, dty } = reff; + visitor.visit_prv(rgn); + visitor.visit_own(own); + visitor.visit_mem(mem); + visitor.visit_dty(dty); +} + +pub fn walk_dty<'a, V: VisitMut<'a>>(visitor: &mut V, dty: &mut DataTy<'a>) { + match &mut dty.dty { + DataTyKind::Ident(ident) => visitor.visit_ident(ident), + DataTyKind::Scalar(sty) => visitor.visit_scalar_ty(sty), + DataTyKind::Atomic(aty) => visitor.visit_atomic_ty(aty), + DataTyKind::Tuple(elem_dtys) => walk_list!(visitor, visit_dty, elem_dtys), + DataTyKind::Struct(struct_decl) => { + visitor.visit_ident(&mut struct_decl.ident); + walk_list!(visitor, visit_field, &mut struct_decl.fields) + } + DataTyKind::Array(dty, n) => { + visitor.visit_dty(dty); + visitor.visit_nat(n) + } + DataTyKind::ArrayShape(dty, n) => { + visitor.visit_dty(dty); + visitor.visit_nat(n); + } + DataTyKind::At(dty, mem) => { + visitor.visit_dty(dty); + visitor.visit_mem(mem) + } + DataTyKind::Ref(reff) => { + visitor.visit_ref(reff); + } + DataTyKind::RawPtr(dty) => visitor.visit_dty(dty), + DataTyKind::Dead(dty) => visitor.visit_dty(dty), + } +} + +pub fn walk_fn_ty<'a, V: VisitMut<'a>>(visitor: &mut V, fn_ty: &mut FnTy<'a>) { + let FnTy { + generics, + generic_exec, + param_sigs, + exec, + ret_ty, + nat_constrs, + } = fn_ty; + walk_list!(visitor, visit_ident_kinded, generics); + for exec_decl in generic_exec { + visitor.visit_ident_exec(exec_decl) + } + walk_list!(visitor, visit_param_sig, param_sigs); + visitor.visit_exec_expr(exec); + visitor.visit_ty(ret_ty); + walk_list!(visitor, visit_nat_constr, nat_constrs); +} + +pub fn walk_nat_constr<'a, V: VisitMut<'a>>(visitor: &mut V, nat_constr: &mut NatConstr<'a>) { + match nat_constr { + NatConstr::True => {} + NatConstr::Eq(l, r) => { + visitor.visit_nat(l); + visitor.visit_nat(r); + } + NatConstr::Lt(l, r) => { + visitor.visit_nat(l); + visitor.visit_nat(r); + } + NatConstr::And(l, r) => { + visitor.visit_nat_constr(l); + visitor.visit_nat_constr(r); + } + NatConstr::Or(l, r) => { + visitor.visit_nat_constr(l); + visitor.visit_nat_constr(r); + } + } +} + +pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, ty: &mut Ty<'a>) { + match &mut ty.ty { + TyKind::Data(dty) => visitor.visit_dty(dty), + TyKind::FnTy(fn_ty) => { + visitor.visit_fn_ty(fn_ty); + } + } +} + +pub fn walk_view<'a, V: VisitMut<'a>>(visitor: &mut V, view: &mut View<'a>) { + visitor.visit_ident(&mut view.name); + walk_list!(visitor, visit_arg_kinded, &mut view.gen_args); + for v in &mut view.args { + visitor.visit_view(v) + } +} + +pub fn walk_pl_expr<'a, V: VisitMut<'a>>(visitor: &mut V, pl_expr: &mut PlaceExpr<'a>) { + match &mut pl_expr.pl_expr { + PlaceExprKind::Ident(ident) => visitor.visit_ident(ident), + PlaceExprKind::Deref(pl_expr) => visitor.visit_pl_expr(pl_expr), + PlaceExprKind::Select(p, distrib_exec) => { + visitor.visit_pl_expr(p); + visitor.visit_exec_expr(distrib_exec); + } + PlaceExprKind::Proj(pl_expr, _) => { + visitor.visit_pl_expr(pl_expr); + } + PlaceExprKind::FieldProj(pl_expr, field_name) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_ident(field_name); + } + PlaceExprKind::View(pl_expr, view) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_view(view); + } + PlaceExprKind::Idx(pl_expr, n) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_nat(n) + } + } +} + +pub fn walk_arg_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, arg_kinded: &mut ArgKinded<'a>) { + match arg_kinded { + ArgKinded::Ident(ident) => visitor.visit_ident(ident), + ArgKinded::Nat(n) => visitor.visit_nat(n), + ArgKinded::Memory(mem) => visitor.visit_mem(mem), + ArgKinded::DataTy(dty) => visitor.visit_dty(dty), + ArgKinded::Provenance(prv) => visitor.visit_prv(prv), + } +} + +pub fn walk_pattern<'a, V: VisitMut<'a>>(visitor: &mut V, pattern: &mut Pattern<'a>) { + match pattern { + Pattern::Ident(mutab, ident) => { + visitor.visit_mutability(mutab); + visitor.visit_ident(ident); + } + Pattern::Tuple(patterns) => { + walk_list!(visitor, visit_pattern, patterns) + } + Pattern::Wildcard => {} + } +} + +pub fn walk_split<'a, V: VisitMut<'a>>(visitor: &mut V, indep: &mut Split<'a>) { + let Split { + dim_compo, + pos, + split_exec, + branch_idents, + branch_bodies, + } = indep; + visitor.visit_dim_compo(dim_compo); + visitor.visit_nat(pos); + visitor.visit_exec_expr(split_exec); + walk_list!(visitor, visit_ident, branch_idents); + walk_list!(visitor, visit_expr, branch_bodies); +} + +pub fn walk_sched<'a, V: VisitMut<'a>>(visitor: &mut V, sched: &mut Sched<'a>) { + let Sched { + dim, + inner_exec_ident, + sched_exec, + body, + } = sched; + visitor.visit_dim_compo(dim); + for ident in inner_exec_ident { + visitor.visit_ident(ident) + } + visitor.visit_exec_expr(sched_exec); + visitor.visit_block(body); +} + +pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, expr: &mut Expr<'a>) { + // For now, only visit ExprKind + match &mut expr.expr { + ExprKind::Lit(l) => visitor.visit_lit(l), + ExprKind::PlaceExpr(pl_expr) => visitor.visit_pl_expr(pl_expr), + + ExprKind::Ref(_, own, pl_expr) => { + visitor.visit_own(own); + visitor.visit_pl_expr(pl_expr); + } + ExprKind::Block(block) => visitor.visit_block(block), + ExprKind::LetUninit(maybe_exec_expr, ident, ty) => { + for e in maybe_exec_expr { + visitor.visit_exec_expr(e); + } + visitor.visit_ident(ident); + visitor.visit_ty(ty); + } + ExprKind::Let(pattern, ty, e) => { + visitor.visit_pattern(pattern); + for ty in ty.as_mut() { + visitor.visit_ty(ty); + } + visitor.visit_expr(e); + } + ExprKind::Assign(pl_expr, expr) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_expr(expr) + } + ExprKind::IdxAssign(pl_expr, idx, expr) => { + visitor.visit_pl_expr(pl_expr); + visitor.visit_nat(idx); + visitor.visit_expr(expr); + } + ExprKind::Seq(es) => { + for e in es { + visitor.visit_expr(e) + } + } + // ExprKind::Lambda(params, exec_decl, dty, expr) => { + // walk_list!(visitor, visit_param_decl, params); + // visitor.visit_ident_exec(exec_decl); + // visitor.visit_dty(dty); + // visitor.visit_expr(expr) + // } + ExprKind::App(f, gen_args, args) => { + visitor.visit_ident(f); + walk_list!(visitor, visit_arg_kinded, gen_args); + walk_list!(visitor, visit_expr, args); + } + ExprKind::DepApp(f, gen_args) => { + visitor.visit_ident(f); + walk_list!(visitor, visit_arg_kinded, gen_args); + } + ExprKind::AppKernel(app_kernel) => visitor.visit_app_kernel(app_kernel), + ExprKind::IfElse(cond, tt, ff) => { + visitor.visit_expr(cond); + visitor.visit_expr(tt); + visitor.visit_expr(ff) + } + ExprKind::If(cond, tt) => { + visitor.visit_expr(cond); + visitor.visit_expr(tt) + } + ExprKind::Array(elems) => { + walk_list!(visitor, visit_expr, elems); + } + ExprKind::Tuple(elems) => { + walk_list!(visitor, visit_expr, elems); + } + ExprKind::For(ident, coll, body) => { + visitor.visit_ident(ident); + visitor.visit_expr(coll); + visitor.visit_expr(body); + } + ExprKind::Split(par_branch) => { + visitor.visit_split(par_branch); + } + ExprKind::Sched(sched) => { + visitor.visit_sched(sched); + } + ExprKind::ForNat(ident, range, body) => { + visitor.visit_ident(ident); + visitor.visit_nat_range(range); + visitor.visit_expr(body) + } + ExprKind::While(cond, body) => { + visitor.visit_expr(cond); + visitor.visit_expr(body); + } + ExprKind::BinOp(op, l, r) => { + visitor.visit_binary_op(op); + visitor.visit_expr(l); + visitor.visit_expr(r) + } + ExprKind::UnOp(op, expr) => { + visitor.visit_unary_op(op); + visitor.visit_expr(expr) + } + ExprKind::Sync(exec) => { + for e in exec { + visitor.visit_exec_expr(e) + } + } + ExprKind::Unsafe(expr) => visitor.visit_expr(expr), + ExprKind::Cast(expr, dty) => { + visitor.visit_expr(expr); + visitor.visit_dty(dty) + } + ExprKind::Range(_, _) | ExprKind::Hole => (), + } +} + +pub fn walk_app_kernel<'a, V: VisitMut<'a>>(visitor: &mut V, app_kernel: &mut AppKernel<'a>) { + let AppKernel { + grid_dim, + block_dim, + shared_mem_dtys, + shared_mem_prvs: _, + fun_ident, + gen_args, + args, + } = app_kernel; + visitor.visit_dim(grid_dim); + visitor.visit_dim(block_dim); + for dty in shared_mem_dtys { + visitor.visit_dty(dty); + } + visitor.visit_ident(fun_ident); + for garg in gen_args { + visitor.visit_arg_kinded(garg); + } + for arg in args { + visitor.visit_expr(arg); + } +} + +pub fn walk_block<'a, V: VisitMut<'a>>(visitor: &mut V, block: &mut Block<'a>) { + let Block { body, .. } = block; + visitor.visit_expr(body); +} + +pub fn walk_split_proj<'a, V: VisitMut<'a>>(visitor: &mut V, split_proj: &mut TakeRange<'a>) { + let TakeRange { + split_dim, + pos, + left_or_right: _, + } = split_proj; + visitor.visit_dim_compo(split_dim); + visitor.visit_nat(pos); +} + +pub fn walk_exec_expr<'a, V: VisitMut<'a>>(visitor: &mut V, exec_expr: &mut ExecExpr<'a>) { + visitor.visit_exec(&mut exec_expr.exec); + for t in &mut exec_expr.ty { + visitor.visit_exec_ty(t); + } +} + +pub fn walk_exec<'a, V: VisitMut<'a>>(visitor: &mut V, exec: &mut ExecExprKind<'a>) { + let ExecExprKind { base, path } = exec; + match base { + BaseExec::CpuThread => (), + BaseExec::Ident(ident) => visitor.visit_ident(ident), + BaseExec::GpuGrid(gdim, bdim) => { + visitor.visit_dim(gdim); + visitor.visit_dim(bdim); + } + }; + for e in path { + visitor.visit_exec_path_elem(e) + } +} + +pub fn walk_exec_path_elem<'a, V: VisitMut<'a>>( + visitor: &mut V, + exec_path_elem: &mut ExecPathElem<'a>, +) { + match exec_path_elem { + ExecPathElem::TakeRange(split_proj) => visitor.visit_split_proj(split_proj), + ExecPathElem::ForAll(dim_compo) => visitor.visit_dim_compo(dim_compo), + ExecPathElem::ToWarps => {} + ExecPathElem::ToThreads(dim_compo) => visitor.visit_dim_compo(dim_compo), + } +} + +pub fn walk_param_decl<'a, V: VisitMut<'a>>(visitor: &mut V, param_decl: &mut ParamDecl<'a>) { + let ParamDecl { + ident, + ty, + mutbl, + exec_expr, + } = param_decl; + visitor.visit_ident(ident); + if let Some(tty) = ty { + visitor.visit_ty(tty); + } + visitor.visit_mutability(mutbl); + for ex in exec_expr { + visitor.visit_exec_expr(ex); + } +} + +pub fn walk_fun_def<'a, V: VisitMut<'a>>(visitor: &mut V, fun_def: &mut FunDef<'a>) { + let FunDef { + ident: _, + generic_params, + generic_exec, + param_decls: params, + ret_dty, + exec, + prv_rels, + body, + } = fun_def; + walk_list!(visitor, visit_ident_kinded, generic_params); + for exec_decl in generic_exec { + visitor.visit_ident_exec(exec_decl); + } + walk_list!(visitor, visit_param_decl, params); + visitor.visit_dty(ret_dty); + visitor.visit_exec_expr(exec); + walk_list!(visitor, visit_prv_rel, prv_rels); + visitor.visit_block(body) +} + +pub fn walk_fun_decl<'a, V: VisitMut<'a>>(visitor: &mut V, fun_decl: &mut FunDecl<'a>) { + let FunDecl { + ident: _, + generic_params, + generic_exec, + param_decls: params, + ret_dty, + exec, + prv_rels, + } = fun_decl; + walk_list!(visitor, visit_ident_kinded, generic_params); + for exec_decl in generic_exec { + visitor.visit_ident_exec(exec_decl); + } + walk_list!(visitor, visit_param_decl, params); + visitor.visit_dty(ret_dty); + visitor.visit_exec_expr(exec); + walk_list!(visitor, visit_prv_rel, prv_rels); +} + +pub fn walk_param_sig<'a, V: VisitMut<'a>>(visitor: &mut V, param_sig: &mut ParamSig<'a>) { + let ParamSig { exec_expr, ty } = param_sig; + visitor.visit_exec_expr(exec_expr); + visitor.visit_ty(ty); +} + +pub fn walk_field<'a, V: VisitMut<'a>>(visitor: &mut V, field: &mut (Ident<'a>, DataTy<'a>)) { + let (ident, dty) = field; + visitor.visit_ident(ident); + visitor.visit_dty(dty); +} diff --git a/src/ast/internal.rs b/src/ast/internal.rs index 3435b33d..38db945f 100644 --- a/src/ast/internal.rs +++ b/src/ast/internal.rs @@ -5,58 +5,48 @@ use super::{Ident, Ownership, PlaceExpr, Ty}; use crate::ast::{ExecExpr, Mutability, Nat, PlaceExprKind, View}; -use bumpalo::collections::Vec as BumpVec; use std::collections::HashSet; -// TODO: Removed the Default trait here, see what kind of consequences has this later -// Otherwise implement the trait -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Frame<'a> { - pub bindings: BumpVec<'a, FrameEntry<'a>>, +#[derive(Default, Clone, Debug, PartialEq, Eq)] +pub struct Frame { + pub bindings: Vec, } -impl<'a> Frame<'a> { - pub fn new_in(bump: &'a bumpalo::Bump) -> Self { - Self { - bindings: BumpVec::new_in(bump), - } +impl Frame { + pub fn new() -> Self { + Self::default() } - pub fn append_idents_typed(&mut self, idents_typed: I) - where - I: IntoIterator>, - { - for ident in idents_typed { - self.bindings.push(FrameEntry::Var(ident)); - } + pub fn append_idents_typed(&mut self, idents_typed: Vec) -> &mut Frame { + self.bindings.append( + &mut idents_typed + .into_iter() + .map(FrameEntry::Var) + .collect::>(), + ); + self } } #[derive(PartialEq, Eq, Debug, Clone)] -pub enum FrameEntry<'a> { - Var(IdentTyped<'a>), - ExecMapping(ExecMapping<'a>), - PrvMapping(PrvMapping<'a>), +pub enum FrameEntry { + Var(IdentTyped), + ExecMapping(ExecMapping), + PrvMapping(PrvMapping), } #[derive(PartialEq, Eq, Debug, Clone)] -pub struct IdentTyped<'a> { - pub ident: Ident<'a>, - pub ty: Ty<'a>, +pub struct IdentTyped { + pub ident: Ident, + pub ty: Ty, pub mutbl: Mutability, - pub exec: ExecExpr<'a>, + pub exec: ExecExpr, } -impl<'a> IdentTyped<'a> { - pub fn new_in( - arena: &'a bumpalo::Bump, - ident: &'a str, - ty: Ty<'a>, - mutbl: Mutability, - exec: ExecExpr<'a>, - ) -> Self { +impl IdentTyped { + pub fn new(ident: Ident, ty: Ty, mutbl: Mutability, exec: ExecExpr) -> Self { IdentTyped { - ident: Ident::new(arena, ident), + ident, ty, mutbl, exec, @@ -65,25 +55,24 @@ impl<'a> IdentTyped<'a> { } #[derive(PartialEq, Eq, Debug, Clone)] -pub struct ExecMapping<'a> { - pub ident: Ident<'a>, - pub exec_expr: ExecExpr<'a>, +pub struct ExecMapping { + pub ident: Ident, + pub exec_expr: ExecExpr, } -impl<'a> ExecMapping<'a> { - pub fn new(ident: Ident<'a>, exec_expr: ExecExpr<'a>) -> Self { +impl ExecMapping { + pub fn new(ident: Ident, exec_expr: ExecExpr) -> Self { ExecMapping { ident, exec_expr } } } -// TODO: Problems with HashSet and String in the Arena implementation --> Find a work #[derive(PartialEq, Eq, Debug, Clone)] -pub struct PrvMapping<'a> { +pub struct PrvMapping { pub prv: String, - pub loans: HashSet>, + pub loans: HashSet, } -impl<'a> PrvMapping<'a> { +impl PrvMapping { pub fn new(name: &str) -> Self { PrvMapping { prv: name.to_string(), @@ -93,127 +82,129 @@ impl<'a> PrvMapping<'a> { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Loan<'a> { - pub place_expr: PlaceExpr<'a>, +pub struct Loan { + pub place_expr: PlaceExpr, pub own: Ownership, } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum PathElem<'a> { +pub enum PathElem { Proj(usize), - FieldProj(&'a Ident<'a>), + FieldProj(Box), } -pub type Path<'a> = BumpVec<'a, PathElem<'a>>; - +pub type Path = Vec; #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Place<'a> { - pub ident: Ident<'a>, - pub path: Path<'a>, +pub struct Place { + pub ident: Ident, + pub path: Path, } -impl<'a> Place<'a> { - pub fn new(ident: Ident<'a>, path: Path<'a>) -> Self { +impl Place { + pub fn new(ident: Ident, path: Path) -> Self { Place { ident, path } } - pub fn to_place_expr(&self, arena: &'a bumpalo::Bump) -> PlaceExpr { + pub fn to_place_expr(&self) -> PlaceExpr { self.path.iter().fold( PlaceExpr::new(PlaceExprKind::Ident(self.ident.clone())), |pl_expr, path_entry| match path_entry { - PathElem::Proj(n) => PlaceExpr::new(PlaceExprKind::Proj(arena.alloc(pl_expr), *n)), + PathElem::Proj(n) => PlaceExpr::new(PlaceExprKind::Proj(Box::new(pl_expr), *n)), PathElem::FieldProj(field) => { - PlaceExpr::new(PlaceExprKind::FieldProj(arena.alloc(pl_expr), field)) + PlaceExpr::new(PlaceExprKind::FieldProj(Box::new(pl_expr), field.clone())) } }, ) } - /** pub fn prefix_of(&self, other: &Self) -> bool { if self.path.len() > other.path.len() { return false; } self.ident == other.ident && &self.path == &other.path[..self.path.len()] - }*/ - - pub fn prefix_of(&self, other: &Self) -> bool { - if self.ident != other.ident || self.path.len() > other.path.len() { - return false; - } - - other.path.iter().zip(&self.path).all(|(a, b)| a == b) } } -pub enum PlaceCtx<'a> { - Proj(&'a PlaceCtx<'a>, usize), - FieldProj(&'a PlaceCtx<'a>, Ident<'a>), - Deref(&'a PlaceCtx<'a>), - Select(&'a PlaceCtx<'a>, &'a ExecExpr<'a>), - View(&'a PlaceCtx<'a>, &'a View<'a>), - Idx(&'a PlaceCtx<'a>, &'a Nat<'a>), +pub enum PlaceCtx { + Proj(Box, usize), + FieldProj(Box, Box), + Deref(Box), + Select(Box, Box), + View(Box, Box), + Idx(Box, Box), Hole, } -impl<'a> PlaceCtx<'a> { - pub fn insert_pl_expr( - &'a self, - arena: &'a bumpalo::Bump, - pl_expr: PlaceExpr<'a>, - ) -> PlaceExpr<'a> { +impl PlaceCtx { + pub fn insert_pl_expr(&self, pl_expr: PlaceExpr) -> PlaceExpr { match self { Self::Hole => pl_expr, Self::Proj(pl_ctx, n) => PlaceExpr::new(PlaceExprKind::Proj( - arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), - *n, + Box::new(pl_ctx.insert_pl_expr(pl_expr)), + n.clone(), )), - Self::FieldProj(pl_ctx, field) => PlaceExpr::new(PlaceExprKind::FieldProj( - arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), - field, - )), - Self::Deref(pl_ctx) => PlaceExpr::new(PlaceExprKind::Deref( - arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + Self::FieldProj(pl_ctx, field_name) => PlaceExpr::new(PlaceExprKind::FieldProj( + Box::new(pl_ctx.insert_pl_expr(pl_expr)), + field_name.clone(), )), + Self::Deref(pl_ctx) => PlaceExpr::new(PlaceExprKind::Deref(Box::new( + pl_ctx.insert_pl_expr(pl_expr), + ))), Self::Select(pl_ctx, exec) => PlaceExpr::new(PlaceExprKind::Select( - arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + Box::new(pl_ctx.insert_pl_expr(pl_expr)), exec.clone(), )), - Self::View(pl_ctx, view) => PlaceExpr::new(PlaceExprKind::View( - arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), - view.clone(), - )), Self::Idx(pl_ctx, idx) => PlaceExpr::new(PlaceExprKind::Idx( - arena.alloc(pl_ctx.insert_pl_expr(arena, pl_expr)), + Box::new(pl_ctx.insert_pl_expr(pl_expr)), idx.clone(), )), + Self::View(pl_ctx, view) => PlaceExpr::new(PlaceExprKind::View( + Box::new(pl_ctx.insert_pl_expr(pl_expr)), + view.clone(), + )), } } - pub fn without_innermost_deref(&'a self, arena: &'a bumpalo::Bump) -> &'a PlaceCtx<'a> { + // Assumes the PlaceCtx HAS an innermost deref, meaning the Hole is wrapped by a Deref. + // This is always true for PlaceCtxs created by PlaceExpr.to_pl_ctx_and_most_specif_pl + pub fn without_innermost_deref(&self) -> Self { match self { - PlaceCtx::Hole => self, - PlaceCtx::Proj(pl_ctx, idx) => { - arena.alloc(PlaceCtx::Proj(pl_ctx.without_innermost_deref(arena), *idx)) + PlaceCtx::Hole => PlaceCtx::Hole, + PlaceCtx::Proj(pl_ctx, i) => { + if let PlaceCtx::Hole = **pl_ctx { + panic!("There must be an innermost deref context as created by PlaceExpr.to_pl_ctx_and_most_specif_pl.") + } else { + let inner_ctx = pl_ctx.without_innermost_deref(); + PlaceCtx::Proj(Box::new(inner_ctx), *i) + } + } + PlaceCtx::FieldProj(pl_ctx, field_name) => { + if let PlaceCtx::Hole = **pl_ctx { + panic!("There must be an innermost deref context as created by PlaceExpr.to_pl_ctx_and_most_specif_pl.") + } else { + let inner_ctx = pl_ctx.without_innermost_deref(); + PlaceCtx::FieldProj(Box::new(inner_ctx), field_name.clone()) + } + } + PlaceCtx::Deref(pl_ctx) => { + if let PlaceCtx::Hole = **pl_ctx { + PlaceCtx::Hole + } else { + let inner_ctx = pl_ctx.without_innermost_deref(); + PlaceCtx::Deref(Box::new(inner_ctx)) + } + } + PlaceCtx::Select(pl_ctx, exec_idents) => { + let inner_ctx = pl_ctx.without_innermost_deref(); + PlaceCtx::Select(Box::new(inner_ctx), exec_idents.clone()) + } + PlaceCtx::View(pl_ctx, view) => { + let inner_ctx = pl_ctx.without_innermost_deref(); + PlaceCtx::View(Box::new(inner_ctx), view.clone()) + } + + PlaceCtx::Idx(pl_ctx, idx) => { + let inner_ctx = pl_ctx.without_innermost_deref(); + PlaceCtx::Idx(Box::new(inner_ctx), idx.clone()) } - PlaceCtx::FieldProj(pl_ctx, ident) => arena.alloc(PlaceCtx::FieldProj( - pl_ctx.without_innermost_deref(arena), - ident.clone(), - )), - PlaceCtx::Deref(pl_ctx) => match **pl_ctx { - PlaceCtx::Hole => arena.alloc(PlaceCtx::Hole), - _ => arena.alloc(PlaceCtx::Deref(pl_ctx.without_innermost_deref(arena))), - }, - PlaceCtx::Select(pl_ctx, exec) => arena.alloc(PlaceCtx::Select( - pl_ctx.without_innermost_deref(arena), - exec.clone(), - )), - PlaceCtx::View(pl_ctx, view) => arena.alloc(PlaceCtx::View( - pl_ctx.without_innermost_deref(arena), - view.clone(), - )), - PlaceCtx::Idx(pl_ctx, idx) => arena.alloc(PlaceCtx::Idx( - pl_ctx.without_innermost_deref(arena), - idx.clone(), - )), } } } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 28f2c933..d02ae97c 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1,11 +1,12 @@ use std::fmt; use crate::ast::internal::PathElem; -use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; use descend_derive::span_derive; pub use span::*; +use crate::arena_ast; use crate::parser::SourceCode; +use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; pub mod internal; @@ -15,149 +16,204 @@ pub mod utils; pub mod visit; pub mod visit_mut; -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct CompilUnit<'a> { - pub items: BumpVec<'a, Item<'a>>, + pub items: Vec, pub source: &'a SourceCode<'a>, } impl<'a> CompilUnit<'a> { - pub fn new(items: BumpVec<'a, Item<'a>>, source: &'a SourceCode<'a>) -> Self { + pub fn new(items: Vec, source: &'a SourceCode<'a>) -> Self { CompilUnit { items, source } } } -#[derive(Debug)] -pub enum Item<'a> { - FunDef(BumpBox<'a, FunDef<'a>>), - FunDecl(BumpBox<'a, FunDecl<'a>>), - StructDecl(BumpBox<'a, StructDecl<'a>>), +#[derive(Debug, Clone)] +pub enum Item { + FunDef(Box), + FunDecl(Box), + StructDecl(Box), } -#[derive(Debug, Clone, PartialEq)] -pub struct FunDecl<'a> { - pub ident: Ident<'a>, - pub generic_params: BumpVec<'a, IdentKinded<'a>>, - pub generic_exec: Option>, - pub param_decls: BumpVec<'a, ParamDecl<'a>>, - pub ret_dty: &'a DataTy<'a>, - pub exec: ExecExpr<'a>, - pub prv_rels: BumpVec<'a, PrvRel<'a>>, -} - -impl<'a> FunDecl<'a> { - pub fn fn_ty(&self, bump: &'a Bump) -> FnTy<'a> { - let mut param_sigs = BumpVec::new_in(bump); - for p_decl in &self.param_decls { - let exec_expr = p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(); - let ty = p_decl.ty.as_ref().unwrap().clone(); // This may need arena allocation too - param_sigs.push(ParamSig::new(exec_expr, ty)); +impl Item { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Item<'a> { + match self { + Item::FunDef(f) => { + let arena_f = f.into_arena(arena); + arena_ast::Item::FunDef(BumpBox::new_in(arena_f, arena)) + } + Item::FunDecl(f) => { + let arena_fd = f.into_arena(arena); + arena_ast::Item::FunDecl(BumpBox::new_in(arena_fd, arena)) + } + Item::StructDecl(s) => { + let arena_s = s.into_arena(arena); + arena_ast::Item::StructDecl(BumpBox::new_in(arena_s, arena)) + } } + } +} - let mut generics = BumpVec::new_in(bump); - generics.extend(self.generic_params.iter().cloned()); - - FnTy::new( - bump, - generics, - self.generic_exec.clone(), +#[derive(Debug, Clone, PartialEq)] +pub struct FunDecl { + pub ident: Ident, + pub generic_params: Vec, + pub generic_exec: Option, + pub param_decls: Vec, + pub ret_dty: Box, + pub exec: ExecExpr, + pub prv_rels: Vec, +} + +impl FunDecl { + pub fn fn_ty(&self) -> FnTy { + let param_sigs: Vec<_> = self + .param_decls + .iter() + .map(|p_decl| { + ParamSig::new( + p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(), + p_decl.ty.as_ref().unwrap().clone(), + ) + }) + .collect(); + FnTy { + generics: self.generic_params.clone(), + generic_exec: self.generic_exec.clone(), param_sigs, - self.exec.clone(), - bump.alloc(Ty { - ty: TyKind::Data(self.ret_dty), - span: None, - }), - [], - ) + exec: self.exec.clone(), + ret_ty: Box::new(Ty::new(TyKind::Data(self.ret_dty.clone()))), + nat_constrs: vec![], + } + } + + pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::FunDecl<'a> { + arena_ast::FunDecl { + ident: self.ident, + generic_params: self.generic_params, + generic_exec: self.generic_exec, + param_decls: self + .param_decls + .into_iter() + .map(|p| p.into_arena(arena)) + .collect(), + ret_dty: BumpBox::new_in(*self.ret_dty, arena), + exec: self.exec, + prv_rels: self.prv_rels, + } } } #[derive(Debug, Clone, Eq, Hash, PartialEq)] -pub struct StructDecl<'a> { - pub ident: Ident<'a>, - pub generic_params: BumpVec<'a, IdentKinded<'a>>, - pub fields: BumpVec<'a, (Ident<'a>, DataTy<'a>)>, +pub struct StructDecl { + pub ident: Ident, + pub generic_params: Vec, + pub fields: Vec<(Ident, DataTy)>, +} + +impl StructDecl { + pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::StructDecl<'a> { + arena_ast::StructDecl { + ident: self.ident, + generic_params: self.generic_params, + fields: self + .fields + .into_iter() + .map(|(i, dty)| (i, dty.into_arena(arena))) + .collect(), + } + } } // TODO refactor to make use of FunDecl #[derive(Debug, Clone, PartialEq)] -pub struct FunDef<'a> { - pub ident: Ident<'a>, - pub generic_params: BumpVec<'a, IdentKinded<'a>>, - pub generic_exec: Option>, - pub param_decls: BumpVec<'a, ParamDecl<'a>>, - pub ret_dty: &'a DataTy<'a>, - pub exec: ExecExpr<'a>, - pub prv_rels: BumpVec<'a, PrvRel<'a>>, - pub body: &'a Block<'a>, -} - -impl<'a> FunDef<'a> { - pub fn fn_ty(&self, bump: &'a Bump) -> FnTy<'a> { - let mut param_sigs = BumpVec::new_in(bump); - for p_decl in &self.param_decls { - let exec_expr = p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(); - let ty = p_decl.ty.expect("Missing parameter type"); - let ty_ref = bump.alloc(ty.clone()); - param_sigs.push(ParamSig::new(exec_expr, ty_ref)); +pub struct FunDef { + pub ident: Ident, + pub generic_params: Vec, + pub generic_exec: Option, + pub param_decls: Vec, + pub ret_dty: Box, + pub exec: ExecExpr, + pub prv_rels: Vec, + pub body: Box, +} + +impl FunDef { + pub fn fn_ty(&self) -> FnTy { + let param_sigs: Vec<_> = self + .param_decls + .iter() + .map(|p_decl| { + ParamSig::new( + p_decl.exec_expr.as_ref().unwrap_or(&self.exec).clone(), + p_decl.ty.as_ref().unwrap().clone(), + ) + }) + .collect(); + FnTy { + generics: self.generic_params.clone(), + generic_exec: self.generic_exec.clone(), + param_sigs, + exec: self.exec.clone(), + ret_ty: Box::new(Ty::new(TyKind::Data(self.ret_dty.clone()))), + nat_constrs: vec![], } + } - let mut generics = BumpVec::new_in(bump); - generics.extend(self.generic_params.iter().cloned()); - - let ret_ty = bump.alloc(Ty { - ty: TyKind::Data(self.ret_dty), - span: None, - }); - - FnTy::new( - bump, - generics, - self.generic_exec.clone(), - param_sigs, - self.exec.clone(), - ret_ty, - [], - ) + pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::FunDef<'a> { + arena_ast::FunDef { + ident: self.ident, + generic_params: self.generic_params, + generic_exec: self.generic_exec, + param_decls: self + .param_decls + .into_iter() + .map(|p| p.into_arena(arena)) + .collect(), + ret_dty: BumpBox::new_in(*self.ret_dty, arena), + exec: self.exec, + prv_rels: self.prv_rels, + body: BumpBox::new_in(*self.body, arena), + } } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct IdentExec<'a> { - pub ident: Ident<'a>, - pub ty: &'a ExecTy<'a>, +pub struct IdentExec { + pub ident: Ident, + pub ty: Box, } -impl<'a> IdentExec<'a> { - pub fn new_in(bump: &'a bumpalo::Bump, ident: Ident<'a>, exec_ty: ExecTy<'a>) -> Self { +impl IdentExec { + pub fn new(ident: Ident, exec_ty: ExecTy) -> Self { IdentExec { ident, - ty: bump.alloc(exec_ty), + ty: Box::new(exec_ty), } } } #[derive(Debug, Clone, PartialEq, Eq)] -pub struct ParamDecl<'a> { - pub ident: Ident<'a>, - pub ty: Option<&'a Ty<'a>>, +pub struct ParamDecl { + pub ident: Ident, + pub ty: Option, pub mutbl: Mutability, - pub exec_expr: Option>, + pub exec_expr: Option, } #[span_derive(PartialEq)] -#[derive(Debug)] -pub struct Expr<'a> { - pub expr: ExprKind<'a>, +#[derive(Debug, Clone)] +pub struct Expr { + pub expr: ExprKind, // FIXME misusing span_derive_ignore to ignore type on equality checks #[span_derive_ignore] - pub ty: Option<&'a Ty<'a>>, + pub ty: Option>, #[span_derive_ignore] pub span: Option, } -impl<'a> Expr<'a> { - pub fn new(expr: ExprKind<'a>) -> Self { +impl Expr { + pub fn new(expr: ExprKind) -> Expr { Expr { expr, ty: None, @@ -165,7 +221,7 @@ impl<'a> Expr<'a> { } } - pub fn with_span(expr: ExprKind<'a>, span: Span) -> Self { + pub fn with_span(expr: ExprKind, span: Span) -> Expr { Expr { expr, ty: None, @@ -173,10 +229,10 @@ impl<'a> Expr<'a> { } } - pub fn with_type(expr: ExprKind<'a>, ty: &'a Ty<'a>) -> Self { + pub fn with_type(expr: ExprKind, ty: Ty) -> Expr { Expr { expr, - ty: Some(ty), + ty: Some(Box::new(ty)), span: None, } } @@ -264,197 +320,178 @@ impl<'a> Expr<'a> { } #[derive(PartialEq, Debug, Clone)] -pub struct Sched<'a> { +pub struct Sched { pub dim: DimCompo, - pub inner_exec_ident: Option>, - pub sched_exec: &'a ExecExpr<'a>, - pub body: &'a Block<'a>, + pub inner_exec_ident: Option, + pub sched_exec: Box, + pub body: Box, } -impl<'a> Sched<'a> { - pub fn new_in( - bump: &'a bumpalo::Bump, +impl Sched { + pub fn new( dim: DimCompo, - inner_exec_ident: Option>, - sched_exec: ExecExpr<'a>, - body: Block<'a>, + inner_exec_ident: Option, + sched_exec: ExecExpr, + body: Block, ) -> Self { Sched { dim, inner_exec_ident, - sched_exec: bump.alloc(sched_exec), - body: bump.alloc(body), + sched_exec: Box::new(sched_exec), + body: Box::new(body), } } } -#[derive(PartialEq, Debug)] -pub struct Split<'a> { +#[derive(PartialEq, Debug, Clone)] +pub struct Split { pub dim_compo: DimCompo, - pub pos: Nat<'a>, - pub split_exec: &'a ExecExpr<'a>, - pub branch_idents: BumpVec<'a, Ident<'a>>, - pub branch_bodies: BumpVec<'a, Expr<'a>>, + pub pos: Nat, + pub split_exec: Box, + pub branch_idents: Vec, + pub branch_bodies: Vec, } -impl<'a> Split<'a> { +impl Split { pub fn new( - bump: &'a bumpalo::Bump, dim_compo: DimCompo, - pos: Nat<'a>, - split_exec: ExecExpr<'a>, - branch_idents: impl IntoIterator>, - branch_bodies: impl IntoIterator>, + pos: Nat, + split_exec: ExecExpr, + branch_idents: Vec, + branch_bodies: Vec, ) -> Self { - let split_exec = bump.alloc(split_exec); - - let mut idents = BumpVec::new_in(bump); - idents.extend(branch_idents); - - let mut bodies = BumpVec::new_in(bump); - bodies.extend(branch_bodies); - Split { dim_compo, pos, - split_exec, - branch_idents: idents, - branch_bodies: bodies, + split_exec: Box::new(split_exec), + branch_idents, + branch_bodies, } } } #[derive(PartialEq, Debug, Clone)] -pub struct Block<'a> { - pub prvs: BumpVec<'a, String>, - pub body: &'a Expr<'a>, +pub struct Block { + pub prvs: Vec, + pub body: Box, } -impl<'a> Block<'a> { - pub fn new(bump: &'a bumpalo::Bump, body: Expr<'a>) -> Self { +impl Block { + pub fn new(body: Expr) -> Self { Block { - prvs: BumpVec::new_in(bump), - body: bump.alloc(body), + prvs: vec![], + body: Box::new(body), } } - pub fn with_prvs( - bump: &'a bumpalo::Bump, - prvs: impl IntoIterator, - body: Expr<'a>, - ) -> Self { - let mut prvs_vec = BumpVec::new_in(bump); - prvs_vec.extend(prvs); + pub fn with_prvs(prvs: Vec, body: Expr) -> Self { Block { - prvs: prvs_vec, - body: bump.alloc(body), + prvs, + body: Box::new(body), } } } -#[derive(PartialEq, Debug)] -pub struct AppKernel<'a> { - pub grid_dim: Dim<'a>, - pub block_dim: Dim<'a>, - pub shared_mem_dtys: BumpVec<'a, DataTy<'a>>, - pub shared_mem_prvs: BumpVec<'a, String>, - pub fun_ident: BumpBox<'a, Ident<'a>>, - pub gen_args: BumpVec<'a, ArgKinded<'a>>, - pub args: BumpVec<'a, Expr<'a>>, +#[derive(PartialEq, Debug, Clone)] +pub struct AppKernel { + pub grid_dim: Dim, + pub block_dim: Dim, + pub shared_mem_dtys: Vec, + pub shared_mem_prvs: Vec, + pub fun_ident: Box, + pub gen_args: Vec, + pub args: Vec, } -#[derive(PartialEq, Debug)] -pub enum ExprKind<'a> { +#[derive(PartialEq, Debug, Clone)] +pub enum ExprKind { Hole, Lit(Lit), // An l-value equivalent: *p, p.n, x - PlaceExpr(&'a PlaceExpr<'a>), + PlaceExpr(Box), // e.g., [1, 2 + 3, 4] - Array(BumpVec<'a, Expr<'a>>), - Tuple(BumpVec<'a, Expr<'a>>), + Array(Vec), + Tuple(Vec), // Borrow Expressions - Ref(Option, Ownership, &'a PlaceExpr<'a>), - Block(&'a Block<'a>), + Ref(Option, Ownership, Box), + Block(Block), // Variable declaration // let mut x: ty; - LetUninit(Option<&'a ExecExpr<'a>>, Ident<'a>, &'a Ty<'a>), + LetUninit(Option>, Ident, Box), + // Variable declaration, assignment and sequencing // let w x: ty = e1 - Let(Pattern<'a>, Option<&'a Ty<'a>>, &'a Expr<'a>), + Let(Pattern, Option>, Box), // Assignment to existing place [expression] - Assign(&'a PlaceExpr<'a>, &'a Expr<'a>), + Assign(Box, Box), // e1[i] = e2 - IdxAssign(&'a PlaceExpr<'a>, Nat<'a>, &'a Expr<'a>), + IdxAssign(Box, Nat, Box), // e1 ; e2 - Seq(BumpVec<'a, Expr<'a>>), + Seq(Vec), // Anonymous function which can capture its surrounding context // | x_n: d_1, ..., x_n: d_n | [exec]-> d_r { e } // TODO body expression should always be block?! No but treated like one. - //Lambda(Vec, Ident<'a>Exec, Box, Box), + //Lambda(Vec, IdentExec, Box, Box), // Function application // e_f(e_1, ..., e_n) - App( - &'a Ident<'a>, - BumpVec<'a, ArgKinded<'a>>, - BumpVec<'a, Expr<'a>>, - ), - DepApp(Ident<'a>, BumpVec<'a, ArgKinded<'a>>), - //AppKernel(&'a AppKernel<'a>), - AppKernel(BumpBox<'a, AppKernel<'a>>), + App(Box, Vec, Vec), + DepApp(Ident, Vec), + AppKernel(Box), // TODO branches must be blocks - IfElse(&'a Expr<'a>, &'a Expr<'a>, &'a Expr<'a>), + IfElse(Box, Box, Box), // TODO branch must be block - If(&'a Expr<'a>, &'a Expr<'a>), + If(Box, Box), // For-each loop. // for x in e_1 { e_2 } // TODO body must be block - For(Ident<'a>, &'a Expr<'a>, &'a Expr<'a>), + For(Ident, Box, Box), // for n in range(..) { e } // TODO body must be block - ForNat(Ident<'a>, &'a NatRange<'a>, &'a Expr<'a>), + ForNat(Ident, Box, Box), // while( e_1 ) { e_2 } // TODO body must be block - While(&'a Expr<'a>, &'a Expr<'a>), - BinOp(BinOp, &'a Expr<'a>, &'a Expr<'a>), - UnOp(UnOp, &'a Expr<'a>), - Cast(&'a Expr<'a>, &'a DataTy<'a>), + While(Box, Box), + BinOp(BinOp, Box, Box), + UnOp(UnOp, Box), + Cast(Box, Box), // TODO branches must be blocks or treated like blocks - Split(&'a Split<'a>), - Sched(&'a Sched<'a>), - Sync(Option>), - Unsafe(&'a Expr<'a>), - Range(&'a Expr<'a>, &'a Expr<'a>), + Split(Box), + Sched(Box), + Sync(Option), + Unsafe(Box), + Range(Box, Box), } -#[derive(Clone, Debug)] #[span_derive(PartialEq, Eq, Hash)] -pub struct Ident<'a> { +#[derive(Clone, Debug)] +pub struct Ident { // Identifier names never change. Instead a new identifier is created. Therefore it is not // necessary to keep the capacity that is stored in a String for efficient appending. - pub name: &'a str, + pub name: Box, #[span_derive_ignore] pub span: Option, pub is_implicit: bool, } -impl<'a> Ident<'a> { - pub fn new(bump: &'a bumpalo::Bump, name: &'a str) -> Self { + +impl Ident { + pub fn new(name: &str) -> Self { Self { - name: bump.alloc_str(name), + name: Box::from(name), span: None, is_implicit: false, } } - pub fn new_impli(bump: &'a bumpalo::Bump, name: &'a str) -> Self { + pub fn new_impli(name: &str) -> Self { Self { - name: bump.alloc_str(name), + name: Box::from(name), span: None, is_implicit: true, } } - pub fn with_span(bump: &'a bumpalo::Bump, name: &'a str, span: Span) -> Self { + pub fn with_span(name: &str, span: Span) -> Self { Self { - name: bump.alloc_str(name), + name: Box::from(name), span: Some(span), is_implicit: false, } @@ -462,9 +499,9 @@ impl<'a> Ident<'a> { } #[derive(Debug, Clone, PartialEq)] -pub enum Pattern<'a> { - Ident(Mutability, Ident<'a>), - Tuple(BumpVec<'a, Pattern<'a>>), +pub enum Pattern { + Ident(Mutability, Ident), + Tuple(Vec), Wildcard, } @@ -601,15 +638,15 @@ pub enum Kind { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ArgKinded<'a> { - Ident(Ident<'a>), - Nat(Nat<'a>), - Memory(Memory<'a>), - DataTy(DataTy<'a>), - Provenance(Provenance<'a>), +pub enum ArgKinded { + Ident(Ident), + Nat(Nat), + Memory(Memory), + DataTy(DataTy), + Provenance(Provenance), } -impl<'a> ArgKinded<'a> { +impl ArgKinded { pub fn kind(&self) -> Kind { match self { ArgKinded::Ident(_) => { @@ -622,7 +659,7 @@ impl<'a> ArgKinded<'a> { } } - pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a Self) -> NatEvalResult<'a, bool> { + pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { match (self, other) { (ArgKinded::Ident(i), ArgKinded::Ident(o)) => Ok(i == o), (ArgKinded::Nat(n), ArgKinded::Nat(no)) => Ok(n.eval(nat_ctx)? == no.eval(nat_ctx)?), @@ -636,48 +673,43 @@ impl<'a> ArgKinded<'a> { #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct PlaceExpr<'a> { - pub pl_expr: PlaceExprKind<'a>, +pub struct PlaceExpr { + pub pl_expr: PlaceExprKind, // FIXME misusing span_derive_ignore to ignore type on equality checks #[span_derive_ignore] - pub ty: Option<&'a Ty<'a>>, + pub ty: Option>, #[span_derive_ignore] pub span: Option, } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct View<'a> { - pub name: Ident<'a>, - pub gen_args: BumpVec<'a, ArgKinded<'a>>, - pub args: BumpVec<'a, View<'a>>, +pub struct View { + pub name: Ident, + pub gen_args: Vec, + pub args: Vec, } -impl<'a> View<'a> { - pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a View<'a>) -> NatEvalResult<'a, bool> { +impl View { + pub fn equal(&self, nat_ctx: &NatCtx, other: &View) -> NatEvalResult { if self.name.name != other.name.name { return Ok(false); } - if self.gen_args.len() != other.gen_args.len() { return Ok(false); } - - for (ga, go) in self.gen_args.iter().zip(other.gen_args.iter()) { + for (ga, go) in self.gen_args.iter().zip(&other.gen_args) { if !ga.equal(nat_ctx, go)? { return Ok(false); } } - if self.args.len() != other.args.len() { return Ok(false); } - - for (v, vo) in self.args.iter().zip(other.args.iter()) { + for (v, vo) in self.args.iter().zip(&other.args) { if !v.equal(nat_ctx, vo)? { return Ok(false); } } - Ok(true) } } @@ -695,36 +727,36 @@ impl<'a> View<'a> { // } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum PlaceExprKind<'a> { - View(&'a PlaceExpr<'a>, &'a View<'a>), +pub enum PlaceExprKind { + View(Box, Box), // similar to a projection, but it projects an element for each provided execution resource // (similar to indexing) // p[[x]] - Select(&'a PlaceExpr<'a>, &'a ExecExpr<'a>), + Select(Box, Box), // p.0 | p.1 - Proj(&'a PlaceExpr<'a>, usize), - FieldProj(&'a PlaceExpr<'a>, &'a Ident<'a>), + Proj(Box, usize), + FieldProj(Box, Box), // *p - Deref(&'a PlaceExpr<'a>), + Deref(Box), // Index into array, e.g., arr[i] - Idx(&'a PlaceExpr<'a>, &'a Nat<'a>), + Idx(Box, Box), // x - Ident(Ident<'a>), + Ident(Ident), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum PlExprPathElem<'a> { - View(View<'a>), - Select(&'a ExecExpr<'a>), +pub enum PlExprPathElem { + View(View), + Select(Box), Proj(usize), - FieldProj(Ident<'a>), + FieldProj(Ident), Deref, - Idx(&'a Nat<'a>), - RangeSelec(&'a Nat<'a>, &'a Nat<'a>), + Idx(Box), + RangeSelec(Box, Box), } -impl<'a> PlaceExpr<'a> { - pub fn new(pl_expr: PlaceExprKind<'a>) -> Self { +impl PlaceExpr { + pub fn new(pl_expr: PlaceExprKind) -> Self { PlaceExpr { pl_expr, ty: None, @@ -732,7 +764,7 @@ impl<'a> PlaceExpr<'a> { } } - pub fn with_span(pl_expr: PlaceExprKind<'a>, span: Span) -> Self { + pub fn with_span(pl_expr: PlaceExprKind, span: Span) -> Self { PlaceExpr { pl_expr, ty: None, @@ -752,94 +784,79 @@ impl<'a> PlaceExpr<'a> { } // TODO refactor. Places are only needed during typechecking and codegen - pub fn to_place(&self, arena: &'a bumpalo::Bump) -> Option { + pub fn to_place(&self) -> Option { if self.is_place() { - Some(self.to_pl_ctx_and_most_specif_pl(arena).1) + Some(self.to_pl_ctx_and_most_specif_pl().1) } else { None } } // TODO refactor see to_place - pub fn to_pl_ctx_and_most_specif_pl( - &'a self, - arena: &'a bumpalo::Bump, - ) -> (internal::PlaceCtx<'a>, internal::Place<'a>) { + pub fn to_pl_ctx_and_most_specif_pl(&self) -> (internal::PlaceCtx, internal::Place) { match &self.pl_expr { PlaceExprKind::Select(inner_ple, exec_idents) => { - let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); ( - internal::PlaceCtx::Select(arena.alloc(pl_ctx), exec_idents.clone()), + internal::PlaceCtx::Select(Box::new(pl_ctx), exec_idents.clone()), pl, ) } PlaceExprKind::Deref(inner_ple) => { - let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); - (internal::PlaceCtx::Deref(arena.alloc(pl_ctx)), pl) + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); + (internal::PlaceCtx::Deref(Box::new(pl_ctx)), pl) } PlaceExprKind::View(inner_ple, view) => { - let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); - ( - internal::PlaceCtx::View(arena.alloc(pl_ctx), view.clone()), - pl, - ) + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); + (internal::PlaceCtx::View(Box::new(pl_ctx), view.clone()), pl) } PlaceExprKind::Proj(inner_ple, n) => { - let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); match pl_ctx { internal::PlaceCtx::Hole => { pl.path.push(PathElem::Proj(*n)); (pl_ctx, internal::Place::new(pl.ident, pl.path)) } - _ => (internal::PlaceCtx::Proj(arena.alloc(pl_ctx), *n), pl), + _ => (internal::PlaceCtx::Proj(Box::new(pl_ctx), *n), pl), } } PlaceExprKind::FieldProj(inner_ple, field_name) => { - let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); + let (pl_ctx, mut pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); match pl_ctx { internal::PlaceCtx::Hole => { pl.path.push(PathElem::FieldProj(field_name.clone())); (pl_ctx, internal::Place::new(pl.ident, pl.path)) } _ => ( - internal::PlaceCtx::FieldProj( - arena.alloc(pl_ctx), - field_name.clone().clone(), - ), + internal::PlaceCtx::FieldProj(Box::new(pl_ctx), field_name.clone()), pl, ), } } PlaceExprKind::Idx(inner_ple, idx) => { - let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(arena); - ( - internal::PlaceCtx::Idx(arena.alloc(pl_ctx), idx.clone()), - pl, - ) + let (pl_ctx, pl) = inner_ple.to_pl_ctx_and_most_specif_pl(); + (internal::PlaceCtx::Idx(Box::new(pl_ctx), idx.clone()), pl) } PlaceExprKind::Ident(ident) => ( internal::PlaceCtx::Hole, - internal::Place::new(ident.clone(), BumpVec::new_in(arena)), + internal::Place::new(ident.clone(), vec![]), ), } } - pub fn equiv(&'a self, arena: &'a bumpalo::Bump, place: &'a internal::Place) -> bool { - if let (internal::PlaceCtx::Hole, pl) = self.to_pl_ctx_and_most_specif_pl(arena) { + pub fn equiv(&'_ self, place: &'_ internal::Place) -> bool { + if let (internal::PlaceCtx::Hole, pl) = self.to_pl_ctx_and_most_specif_pl() { &pl == place } else { false } } - pub fn as_ident_and_path( - &'a self, - arena: &'a bumpalo::Bump, - ) -> (Ident<'a>, BumpVec<'a, PlExprPathElem<'a>>) { - fn as_ident_and_path_rec<'a>( - pl_expr: &'a PlaceExpr, - mut path: BumpVec<'a, PlExprPathElem<'a>>, - ) -> (Ident<'a>, BumpVec<'a, PlExprPathElem<'a>>) { + pub fn as_ident_and_path(&self) -> (Ident, Vec) { + fn as_ident_and_path_rec( + pl_expr: &PlaceExpr, + mut path: Vec, + ) -> (Ident, Vec) { match &pl_expr.pl_expr { PlaceExprKind::Ident(i) => { path.reverse(); @@ -854,7 +871,7 @@ impl<'a> PlaceExpr<'a> { as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::View(inner_ple, view) => { - path.push(PlExprPathElem::View(view.clone().clone())); // formerly as_ref().clone() ? Can that just work with double cloning? + path.push(PlExprPathElem::View(view.as_ref().clone())); as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::Proj(inner_ple, n) => { @@ -862,7 +879,7 @@ impl<'a> PlaceExpr<'a> { as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::FieldProj(inner_ple, ident) => { - path.push(PlExprPathElem::FieldProj(ident.clone().clone())); // formerly as_ref().clone() ? Can that just work with double cloning? + path.push(PlExprPathElem::FieldProj(ident.as_ref().clone())); as_ident_and_path_rec(inner_ple, path) } PlaceExprKind::Idx(inner_ple, idx) => { @@ -871,23 +888,25 @@ impl<'a> PlaceExpr<'a> { } } } - as_ident_and_path_rec(self, BumpVec::new_in(arena)) // BumpVec Stuff into it + as_ident_and_path_rec(self, vec![]) } } #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct ExecExpr<'a> { - pub exec: &'a ExecExprKind<'a>, +pub struct ExecExpr { + pub exec: Box, + // FIXME misusing span_derive_ignore to ignore type on equality checks #[span_derive_ignore] - pub ty: Option<&'a ExecTy<'a>>, + pub ty: Option>, #[span_derive_ignore] pub span: Option, } -impl<'a> ExecExpr<'a> { - pub fn new(arena: &'a bumpalo::Bump, exec: ExecExprKind<'a>) -> Self { - Self { - exec: arena.alloc(exec), + +impl ExecExpr { + pub fn new(exec: ExecExprKind) -> Self { + ExecExpr { + exec: Box::new(exec), ty: None, span: None, } @@ -896,52 +915,27 @@ impl<'a> ExecExpr<'a> { // TODO how does this relate to is_prefix_of. Refactor. pub fn is_sub_exec_of(&self, exec: &ExecExpr) -> bool { if self.exec.path.len() > exec.exec.path.len() { - return self.exec.path[..exec.exec.path.len()] == exec.exec.path[..]; + return self.exec.path[..exec.exec.path.len()] == exec.exec.path; } false } - pub fn remove_last_distrib(&self, arena: &'a bumpalo::Bump) -> ExecExpr { + pub fn remove_last_distrib(&self) -> ExecExpr { let last_distrib_pos = self .exec .path .iter() .rposition(|e| matches!(e, ExecPathElem::ForAll(_))); - - // What did i do here? let removed_distrib_path = if let Some(ldp) = last_distrib_pos { - let mut vec = BumpVec::new_in(arena); - // self.exec.path[..ldp].to_vec() --> changed this to BumpVec - vec.extend_from_slice(&self.exec.path[..ldp]); - vec + self.exec.path[..ldp].to_vec() } else { - //vec![] --> changed this to BumpVec - BumpVec::new_in(arena) + vec![] }; - - ExecExpr::new( - arena, - ExecExprKind::with_path(self.exec.base.clone(), removed_distrib_path), - ) - } - - /** Kind of idea how to do it - pub fn remove_last_distrib(&self, arena: &'a Bump) -> ExecExpr<'a> { - let last_distrib_pos = self - .exec - .path - .iter() - .rposition(|e| matches!(e, ExecPathElem::ForAll(_))); - - let removed_path = match last_distrib_pos { - Some(pos) => &self.exec.path[..pos], - None => &[], - }; - - let exec_kind = ExecExprKind::with_path(self.exec.base.clone(), removed_path.iter().cloned(), arena); - ExecExpr::new(arena, exec_kind) + ExecExpr::new(ExecExprKind::with_path( + self.exec.base.clone(), + removed_distrib_path, + )) } - */ pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { match (&self.exec.base, &other.exec.base) { @@ -991,25 +985,17 @@ impl<'a> ExecExpr<'a> { #[test] fn equal_exec_exprs() { - let arena = Bump::new(); - - let exec1 = ExecExpr::new( - &arena, - ExecExprKind::with_path( - BaseExec::Ident(Ident::new(&arena, "grid")), - bumpalo::collections::Vec::from_iter_in([ExecPathElem::ForAll(DimCompo::X)], &arena), - ), - ); - - let exec2 = ExecExpr::new( - &arena, - ExecExprKind::with_path( - BaseExec::Ident(Ident::new(&arena, "grid")), - bumpalo::collections::Vec::from_iter_in([ExecPathElem::ForAll(DimCompo::X)], &arena), - ), - ); - - assert_eq!(exec1, exec2, "Unequal execs that should be equal"); + let exec1 = ExecExpr::new(ExecExprKind::with_path( + BaseExec::Ident(Ident::new("grid")), + vec![ExecPathElem::ForAll(DimCompo::X)], + )); + let exec2 = ExecExpr::new(ExecExprKind::with_path( + BaseExec::Ident(Ident::new("grid")), + vec![ExecPathElem::ForAll(DimCompo::X)], + )); + if exec1 != exec2 { + panic!("Unequal execs, that should be equal") + } } #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] @@ -1028,14 +1014,14 @@ impl fmt::Display for LeftOrRight { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct TakeRange<'a> { +pub struct TakeRange { pub split_dim: DimCompo, - pub pos: Nat<'a>, + pub pos: Nat, pub left_or_right: LeftOrRight, } -impl<'a> TakeRange<'a> { - pub fn new(split_dim: DimCompo, pos: Nat<'a>, proj: LeftOrRight) -> Self { +impl TakeRange { + pub fn new(split_dim: DimCompo, pos: Nat, proj: LeftOrRight) -> Self { TakeRange { split_dim, pos, @@ -1045,40 +1031,25 @@ impl<'a> TakeRange<'a> { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct ExecExprKind<'a> { - pub base: BaseExec<'a>, - pub path: BumpVec<'a, ExecPathElem<'a>>, +pub struct ExecExprKind { + pub base: BaseExec, + pub path: Vec, } -impl<'a> ExecExprKind<'a> { - pub fn new(arena: &'a bumpalo::Bump, base: BaseExec<'a>) -> Self { - ExecExprKind { - base, - path: BumpVec::new_in(arena), - } +impl ExecExprKind { + pub fn new(base: BaseExec) -> Self { + ExecExprKind { base, path: vec![] } } - pub fn with_path(base: BaseExec<'a>, path: BumpVec<'a, ExecPathElem<'a>>) -> Self { + pub fn with_path(base: BaseExec, path: Vec) -> Self { ExecExprKind { base, path } } - /** - pub fn with_path(base: BaseExec, path: impl IntoIterator>, arena: &'a Bump) -> Self { - let mut bump_vec = BumpVec::new_in(arena); - bump_vec.extend(path); - Self { base, path: bump_vec } - }*/ - - pub fn split_proj( - mut self, - arena: &'a bumpalo::Bump, - dim_compo: DimCompo, - pos: Nat<'a>, - proj: LeftOrRight, - ) -> Self { - self.path.push(ExecPathElem::TakeRange( - arena.alloc(TakeRange::new(dim_compo, pos, proj)), - )); + pub fn split_proj(mut self, dim_compo: DimCompo, pos: Nat, proj: LeftOrRight) -> Self { + self.path + .push(ExecPathElem::TakeRange(Box::new(TakeRange::new( + dim_compo, pos, proj, + )))); self } @@ -1098,15 +1069,15 @@ impl<'a> ExecExprKind<'a> { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum BaseExec<'a> { - Ident(Ident<'a>), +pub enum BaseExec { + Ident(Ident), CpuThread, - GpuGrid(Dim<'a>, Dim<'a>), + GpuGrid(Dim, Dim), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum ExecPathElem<'a> { - TakeRange(&'a TakeRange<'a>), +pub enum ExecPathElem { + TakeRange(Box), ForAll(DimCompo), ToWarps, ToThreads(DimCompo), @@ -1118,14 +1089,14 @@ pub enum ExecPathElem<'a> { // fn elem_type(DimCompo) -> ExecTy #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct ExecTy<'a> { - pub ty: ExecTyKind<'a>, +pub struct ExecTy { + pub ty: ExecTyKind, #[span_derive_ignore] pub span: Option, } -impl<'a> ExecTy<'a> { - pub fn new(exec: ExecTyKind<'a>) -> Self { +impl ExecTy { + pub fn new(exec: ExecTyKind) -> Self { ExecTy { ty: exec, span: None, @@ -1134,93 +1105,83 @@ impl<'a> ExecTy<'a> { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum ExecTyKind<'a> { +pub enum ExecTyKind { CpuThread, GpuThread, GpuWarp, - GpuBlock(Dim<'a>), - GpuGrid(Dim<'a>, Dim<'a>), - GpuToThreads(Dim<'a>, &'a ExecTy<'a>), - GpuThreadGrp(Dim<'a>), - GpuWarpGrp(Nat<'a>), - GpuBlockGrp(Dim<'a>, Dim<'a>), + GpuBlock(Dim), + GpuGrid(Dim, Dim), + GpuToThreads(Dim, Box), + GpuThreadGrp(Dim), + GpuWarpGrp(Nat), + GpuBlockGrp(Dim, Dim), Any, } #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct Ty<'a> { - pub ty: TyKind<'a>, +pub struct Ty { + pub ty: TyKind, #[span_derive_ignore] pub span: Option, } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct ParamSig<'a> { - pub exec_expr: ExecExpr<'a>, - pub ty: &'a Ty<'a>, +pub struct ParamSig { + pub exec_expr: ExecExpr, + pub ty: Ty, } -impl<'a> ParamSig<'a> { - pub fn new(exec_expr: ExecExpr<'a>, ty: &'a Ty<'a>) -> Self { +impl ParamSig { + pub fn new(exec_expr: ExecExpr, ty: Ty) -> Self { ParamSig { exec_expr, ty } } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct FnTy<'a> { - pub generics: BumpVec<'a, IdentKinded<'a>>, - pub generic_exec: Option>, - pub param_sigs: BumpVec<'a, ParamSig<'a>>, - pub exec: ExecExpr<'a>, - pub ret_ty: &'a Ty<'a>, - pub nat_constrs: BumpVec<'a, NatConstr<'a>>, +pub struct FnTy { + pub generics: Vec, + pub generic_exec: Option, + pub param_sigs: Vec, + pub exec: ExecExpr, + pub ret_ty: Box, + pub nat_constrs: Vec, } -impl<'a> FnTy<'a> { +impl FnTy { pub fn new( - arena: &'a Bump, - generics: impl IntoIterator>, - generic_exec: Option>, - param_sigs: impl IntoIterator>, - exec: ExecExpr<'a>, - ret_ty: &'a Ty<'a>, - nat_constrs: impl IntoIterator>, + generics: Vec, + generic_exec: Option, + param_sigs: Vec, + exec: ExecExpr, + ret_ty: Ty, + nat_constrs: Vec, ) -> Self { - let mut generics_vec = BumpVec::new_in(arena); - generics_vec.extend(generics); - - let mut param_vec = BumpVec::new_in(arena); - param_vec.extend(param_sigs); - - let mut nat_vec = BumpVec::new_in(arena); - nat_vec.extend(nat_constrs); - FnTy { - generics: generics_vec, + generics, generic_exec, - param_sigs: param_vec, + param_sigs, exec, - ret_ty: arena.alloc(ret_ty), - nat_constrs: nat_vec, + ret_ty: Box::new(ret_ty), + nat_constrs, } } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum NatConstr<'a> { +pub enum NatConstr { True, - Eq(Box>, Box>), - Lt(Box>, Box>), - And(Box>, Box>), - Or(Box>, Box>), + Eq(Box, Box), + Lt(Box, Box), + And(Box, Box), + Or(Box, Box), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum TyKind<'a> { - Data(&'a DataTy<'a>), +pub enum TyKind { + Data(Box), // (ty..) -[x:exec]-> ty - FnTy(&'a FnTy<'a>), + FnTy(Box), } // TODO remove @@ -1229,19 +1190,19 @@ pub enum Constraint { Copyable, } -impl<'a> Ty<'a> { - pub fn new(ty: TyKind<'a>) -> Self { +impl Ty { + pub fn new(ty: TyKind) -> Self { Ty { ty, span: None } } - pub fn with_span(ty: TyKind<'a>, span: Span) -> Ty<'a> { + pub fn with_span(ty: TyKind, span: Span) -> Ty { Ty { ty, span: Some(span), } } - pub fn dty(&self) -> &'a DataTy<'a> { + pub fn dty(&self) -> &DataTy { match &self.ty { TyKind::Data(dty) => dty, _ => panic!("Expected data type but found {:?}", self), @@ -1277,38 +1238,32 @@ impl<'a> Ty<'a> { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Dim1d<'a>(pub Nat<'a>); +pub struct Dim1d(pub Nat); #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Dim2d<'a>(pub Nat<'a>, pub Nat<'a>); +pub struct Dim2d(pub Nat, pub Nat); #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct Dim3d<'a>(pub Nat<'a>, pub Nat<'a>, pub Nat<'a>); +pub struct Dim3d(pub Nat, pub Nat, pub Nat); #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum Dim<'a> { - XYZ(&'a Dim3d<'a>), - XY(&'a Dim2d<'a>), - XZ(&'a Dim2d<'a>), - YZ(&'a Dim2d<'a>), - X(&'a Dim1d<'a>), - Y(&'a Dim1d<'a>), - Z(&'a Dim1d<'a>), -} - -impl<'a> Dim<'a> { - pub fn new_3d(arena: &'a Bump, n1: Nat<'a>, n2: Nat<'a>, n3: Nat<'a>) -> Self { - Dim::XYZ(arena.alloc(Dim3d(n1, n2, n3))) - } - - pub fn new_2d Self>( - arena: &'a Bump, - constr: F, - n1: Nat<'a>, - n2: Nat<'a>, - ) -> Self { - constr(arena.alloc(Dim2d(n1, n2))) +pub enum Dim { + XYZ(Box), + XY(Box), + XZ(Box), + YZ(Box), + X(Box), + Y(Box), + Z(Box), +} + +impl Dim { + pub fn new_3d(n1: Nat, n2: Nat, n3: Nat) -> Self { + Dim::XYZ(Box::new(Dim3d(n1, n2, n3))) } - pub fn new_1d Self>(arena: &'a Bump, constr: F, n: Nat<'a>) -> Self { - constr(arena.alloc(Dim1d(n))) + pub fn new_2d) -> Self>(constr: F, n1: Nat, n2: Nat) -> Self { + constr(Box::new(Dim2d(n1, n2))) + } + pub fn new_1d) -> Self>(constr: F, n: Nat) -> Self { + constr(Box::new(Dim1d(n))) } pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { @@ -1337,46 +1292,40 @@ pub enum DimCompo { #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] -pub struct DataTy<'a> { - pub dty: DataTyKind<'a>, +pub struct DataTy { + pub dty: DataTyKind, // TODO remove with introduction of traits - pub constraints: BumpVec<'a, Constraint>, + pub constraints: Vec, #[span_derive_ignore] pub span: Option, } -impl<'a> DataTy<'a> { - pub fn new(bump: &'a bumpalo::Bump, dty: DataTyKind<'a>) -> Self { +impl DataTy { + pub fn new(dty: DataTyKind) -> Self { DataTy { dty, - constraints: BumpVec::new_in(bump), + constraints: vec![], span: None, } } - pub fn with_constr( - bump: &'a bumpalo::Bump, - dty: DataTyKind<'a>, - constraints: impl IntoIterator, - ) -> Self { - let mut v = BumpVec::new_in(bump); - v.extend(constraints); + pub fn with_constr(dty: DataTyKind, constraints: Vec) -> Self { DataTy { dty, - constraints: v, + constraints, span: None, } } - pub fn with_span(bump: &'a bumpalo::Bump, dty: DataTyKind<'a>, span: Span) -> Self { + pub fn with_span(dty: DataTyKind, span: Span) -> Self { DataTy { dty, - constraints: BumpVec::new_in(bump), + constraints: vec![], span: Some(span), } } - pub fn non_copyable(&'a self) -> bool { + pub fn non_copyable(&self) -> bool { use DataTyKind::*; match &self.dty { @@ -1392,16 +1341,16 @@ impl<'a> DataTy<'a> { Range => true, Dead(_) => panic!( "This case is not expected to mean anything.\ - The type is dead. There is nothing we can do with it." + The type is dead. There is nothign we can do with it." ), } } - pub fn copyable(&'a self) -> bool { + pub fn copyable(&self) -> bool { !self.non_copyable() } - pub fn is_fully_alive(&'a self) -> bool { + pub fn is_fully_alive(&self) -> bool { use DataTyKind::*; match &self.dty { Scalar(_) @@ -1423,7 +1372,7 @@ impl<'a> DataTy<'a> { } } - pub fn occurs_in(&'a self, dty: &DataTy) -> bool { + pub fn occurs_in(&self, dty: &DataTy) -> bool { if self == dty { return true; } @@ -1453,7 +1402,7 @@ impl<'a> DataTy<'a> { } } - pub fn contains_ref_to_prv(&'a self, prv_val_name: &str) -> bool { + pub fn contains_ref_to_prv(&self, prv_val_name: &str) -> bool { use DataTyKind::*; match &self.dty { Scalar(_) | Atomic(_) | Ident(_) | Dead(_) => false, @@ -1479,7 +1428,7 @@ impl<'a> DataTy<'a> { } } - pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a Self) -> NatEvalResult<'a, bool> { + pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { match (&self.dty, &other.dty) { (DataTyKind::Ident(i), DataTyKind::Ident(o)) => Ok(i == o), (DataTyKind::Tuple(dtys), DataTyKind::Tuple(dtyos)) => { @@ -1513,46 +1462,41 @@ impl<'a> DataTy<'a> { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct RefDty<'a> { - pub rgn: Provenance<'a>, +pub struct RefDty { + pub rgn: Provenance, pub own: Ownership, - pub mem: Memory<'a>, - pub dty: &'a DataTy<'a>, + pub mem: Memory, + pub dty: Box, } -impl<'a> RefDty<'a> { - pub fn new( - bump: &'a Bump, - rgn: Provenance<'a>, - own: Ownership, - mem: Memory<'a>, - dty: DataTy<'a>, - ) -> Self { +impl RefDty { + pub fn new(rgn: Provenance, own: Ownership, mem: Memory, dty: DataTy) -> Self { RefDty { rgn, own, mem, - dty: bump.alloc(dty), + dty: Box::new(dty), } } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum DataTyKind<'a> { - Ident(Ident<'a>), +pub enum DataTyKind { + Ident(Ident), Scalar(ScalarTy), Atomic(AtomicTy), - Array(&'a DataTy<'a>, Nat<'a>), - ArrayShape(&'a DataTy<'a>, Nat<'a>), - Tuple(BumpVec<'a, DataTy<'a>>), - Struct(&'a StructDecl<'a>), - At(&'a DataTy<'a>, Memory<'a>), - Ref(&'a RefDty<'a>), - RawPtr(&'a DataTy<'a>), + Array(Box, Nat), + // [[ dty; n ]] + ArrayShape(Box, Nat), + Tuple(Vec), + Struct(Box), + At(Box, Memory), + Ref(Box), + RawPtr(Box), //Range, // TODO remove. This is an attribute of a typing context entry, not the type. // Only for type checking purposes. - Dead(&'a DataTy<'a>), + Dead(Box), } #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] @@ -1576,34 +1520,34 @@ pub enum AtomicTy { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum Provenance<'a> { +pub enum Provenance { Value(String), - Ident(Ident<'a>), + Ident(Ident), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum Memory<'a> { +pub enum Memory { CpuMem, GpuGlobal, GpuShared, GpuLocal, - Ident(Ident<'a>), + Ident(Ident), } #[derive(PartialEq, Eq, Debug, Clone)] -pub struct PrvRel<'a> { - pub longer: Ident<'a>, - pub shorter: Ident<'a>, +pub struct PrvRel { + pub longer: Ident, + pub shorter: Ident, } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub struct IdentKinded<'a> { - pub ident: Ident<'a>, +pub struct IdentKinded { + pub ident: Ident, pub kind: Kind, } -impl<'a> IdentKinded<'a> { - pub fn new(ident: &Ident<'a>, kind: Kind) -> Self { +impl IdentKinded { + pub fn new(ident: &Ident, kind: Kind) -> Self { IdentKinded { ident: ident.clone(), kind, @@ -1612,50 +1556,46 @@ impl<'a> IdentKinded<'a> { } #[derive(PartialEq, Eq, Debug, Clone)] -pub enum NatRange<'a> { - Simple { lower: Nat<'a>, upper: Nat<'a> }, - Halved { upper: Nat<'a> }, - Doubled { upper: Nat<'a> }, +pub enum NatRange { + Simple { lower: Nat, upper: Nat }, + Halved { upper: Nat }, + Doubled { upper: Nat }, } -impl<'a> NatRange<'a> { - pub fn lift(&self, arena: &'a Bump, nat_ctx: &NatCtx) -> NatEvalResult { +impl NatRange { + pub fn lift(&self, nat_ctx: &NatCtx) -> NatEvalResult { let range_iter = match self { NatRange::Simple { lower, upper } => { let lower = lower.eval(nat_ctx)?; let upper = upper.eval(nat_ctx)?; - NatRangeIter::new( - lower, - arena.alloc(|x| x + 1), - arena.alloc(move |c| c >= upper), - ) + NatRangeIter::new(lower, Box::new(|x| x + 1), Box::new(move |c| c >= upper)) } NatRange::Halved { upper } => { let upper = upper.eval(nat_ctx)?; - NatRangeIter::new(upper, arena.alloc(|x| x / 2), arena.alloc(|c| c == 0)) + NatRangeIter::new(upper, Box::new(|x| x / 2), Box::new(|c| c == 0)) } NatRange::Doubled { upper } => { let upper = upper.eval(nat_ctx)?; - NatRangeIter::new(1, arena.alloc(|x| x * 2), arena.alloc(move |c| c >= upper)) + NatRangeIter::new(1, Box::new(|x| x * 2), Box::new(move |c| c >= upper)) } }; Ok(range_iter) } } -pub struct NatRangeIter<'a> { +pub struct NatRangeIter { current: usize, // go from current to next value - step_fun: &'a dyn Fn(usize) -> usize, + step_fun: Box usize>, // determine whether the current value is still within range - end_cond: &'a dyn Fn(usize) -> bool, + end_cond: Box bool>, } -impl<'a> NatRangeIter<'a> { +impl NatRangeIter { fn new( start: usize, - step_fun: &'a dyn Fn(usize) -> usize, - end_cond: &'a dyn Fn(usize) -> bool, + step_fun: Box usize>, + end_cond: Box bool>, ) -> Self { NatRangeIter { current: start, @@ -1665,7 +1605,7 @@ impl<'a> NatRangeIter<'a> { } } -impl<'a> Iterator for NatRangeIter<'a> { +impl Iterator for NatRangeIter { type Item = usize; fn next(&mut self) -> Option { @@ -1680,8 +1620,8 @@ impl<'a> Iterator for NatRangeIter<'a> { } #[derive(PartialEq, Eq, Hash, Debug, Clone)] -pub enum Nat<'a> { - Ident(Ident<'a>), +pub enum Nat { + Ident(Ident), Lit(usize), ThreadIdx(DimCompo), BlockIdx(DimCompo), @@ -1691,9 +1631,9 @@ pub enum Nat<'a> { LaneIdx, // Dummy that is always 0, i.e. equivalent to Lit(0) GridIdx, - BinOp(BinOpNat, Box>, Box>), + BinOp(BinOpNat, Box, Box), // Use Box<[Nat]> to safe 8 bytes compared to Vec - App(Ident<'a>, Box<[Nat<'a>]>), + App(Ident, Box<[Nat]>), } pub struct NatCtx { @@ -1747,13 +1687,13 @@ impl NatCtx { } #[derive(Debug)] -pub struct NatEvalError<'a> { - unevaluable: Nat<'a>, +pub struct NatEvalError { + unevaluable: Nat, } -pub type NatEvalResult<'a, T> = Result>; +pub type NatEvalResult = Result; -impl<'a> Nat<'a> { +impl Nat { pub fn eval(&self, nat_ctx: &NatCtx) -> NatEvalResult { match self { Nat::GridIdx @@ -1811,22 +1751,22 @@ mod size_asserts { }; } static_assert_size!(Dim, 16); - static_assert_size!(DataTy, 112); + static_assert_size!(DataTy, 104); static_assert_size!(DataTyKind, 64); static_assert_size!(ExecExpr, 32); - static_assert_size!(ExecExprKind, 72); + static_assert_size!(ExecExprKind, 64); static_assert_size!(ExecPathElem, 16); static_assert_size!(ExecTy, 64); static_assert_size!(ExecTyKind, 48); - static_assert_size!(Expr, 104); - static_assert_size!(ExprKind, 80); - static_assert_size!(FunDef, 216); + static_assert_size!(Expr, 96); + static_assert_size!(ExprKind, 72); + static_assert_size!(FunDef, 192); static_assert_size!(Ident, 32); // maybe too large? static_assert_size!(IdentExec, 40); static_assert_size!(Lit, 16); static_assert_size!(Memory, 32); static_assert_size!(Nat, 48); - static_assert_size!(ParamDecl, 80); + static_assert_size!(ParamDecl, 104); static_assert_size!(Pattern, 40); static_assert_size!(PlaceExpr, 56); static_assert_size!(PlaceExprKind, 32); diff --git a/src/ast/utils.rs b/src/ast/utils.rs index 9ad2d457..e50614ba 100644 --- a/src/ast/utils.rs +++ b/src/ast/utils.rs @@ -2,20 +2,20 @@ use crate::ast::visit::walk_list; use crate::ast::visit::Visit; use crate::ast::visit_mut::VisitMut; use crate::ast::{ - visit, visit_mut, ArgKinded, BaseExec, DataTy, DataTyKind, Dim, ExecExpr, ExecExprKind, ExecTy, - Expr, ExprKind, FnTy, FunDef, Ident, IdentExec, IdentKinded, Kind, Memory, Nat, ParamSig, - Provenance, Ty, TyKind, + visit, visit_mut, ArgKinded, BaseExec, DataTy, DataTyKind, Dim, ExecExpr, ExecTy, Expr, + ExprKind, FnTy, FunDef, Ident, IdentExec, IdentKinded, Kind, Memory, Nat, ParamSig, Provenance, + Ty, TyKind, }; use std::collections::{HashMap, HashSet}; use std::sync::atomic::{AtomicI32, Ordering}; static mut COUNTER: AtomicI32 = AtomicI32::new(0); -pub(crate) fn fresh_ident<'a, F, R>(arena: &'a bumpalo::Bump, name: &str, ident_constr: F) -> R +pub(crate) fn fresh_ident(name: &str, ident_constr: F) -> R where F: Fn(Ident) -> R, { - ident_constr(Ident::new_impli(&arena, &fresh_name(name))) + ident_constr(Ident::new_impli(&fresh_name(name))) } pub(crate) fn fresh_name(name: &str) -> String { @@ -27,10 +27,10 @@ pub(crate) fn fresh_name(name: &str) -> String { format!("{}_{}", prefix, i) } -pub fn implicit_idents<'a>(f: &FunDef<'a>) -> Option>> { - struct ImplicitIdents<'b>(HashSet>); - impl<'b> Visit<'b> for ImplicitIdents<'b> { - fn visit_ident(&mut self, ident: &Ident<'b>) { +pub fn implicit_idents(f: &FunDef) -> Option> { + struct ImplicitIdents(HashSet); + impl Visit for ImplicitIdents { + fn visit_ident(&mut self, ident: &Ident) { if ident.is_implicit { self.0.insert(ident.clone()); } @@ -46,13 +46,13 @@ pub fn implicit_idents<'a>(f: &FunDef<'a>) -> Option>> { } } -pub trait VisitableMut<'a> { - fn visit_mut>(&mut self, visitor: &mut V); +pub trait VisitableMut { + fn visit_mut(&mut self, visitor: &mut V); } macro_rules! visitable_mut { ($t:ident, $f:ident) => { - impl<'a> VisitableMut<'a> for $t<'a> { - fn visit_mut>(&mut self, visitor: &mut V) { + impl VisitableMut for $t { + fn visit_mut(&mut self, visitor: &mut V) { visitor.$f(self); } } @@ -71,10 +71,10 @@ visitable_mut!(FnTy, visit_fn_ty); * gen_args: the kinded expressions that are substituting the generic identifiers * t: the term to substitute in */ -pub fn subst_idents_kinded<'a, I, J, T: VisitableMut<'a>>(gen_idents: I, gen_args: J, t: &mut T) +pub fn subst_idents_kinded<'a, I, J, T: VisitableMut>(gen_idents: I, gen_args: J, t: &mut T) where - I: IntoIterator>, - J: IntoIterator>, + I: IntoIterator, + J: IntoIterator, { let subst_map = HashMap::from_iter( gen_idents @@ -82,18 +82,15 @@ where .map(|p| p.ident.name.as_ref()) .zip(gen_args), ); - let mut subst_idents_kinded = SubstIdentsKinded::new(subst_map); + let mut subst_idents_kinded = SubstIdentsKinded::new(&subst_map); t.visit_mut(&mut subst_idents_kinded); } -pub fn subst_ident_exec<'a, T: VisitableMut<'a>>( - ident: &'a Ident<'a>, - exec: &'a ExecExpr<'a>, - t: &mut T, -) { +pub fn subst_ident_exec<'a, T: VisitableMut>(ident: &Ident, exec: &ExecExpr, t: &mut T) { let mut subst_ident_exec = SubstIdentExec::new(ident, exec); t.visit_mut(&mut subst_ident_exec); } + /* * substitute kinded arguments for free identifiers * @@ -102,12 +99,12 @@ pub fn subst_ident_exec<'a, T: VisitableMut<'a>>( * identifiers must be removed from the list, first. */ struct SubstIdentsKinded<'a> { - pub subst_map: HashMap<&'a str, &'a ArgKinded<'a>>, - pub bound_idents: HashSet>, + pub subst_map: &'a HashMap<&'a str, &'a ArgKinded>, + pub bound_idents: HashSet, } impl<'a> SubstIdentsKinded<'a> { - fn new(subst_map: HashMap<&'a str, &'a ArgKinded<'a>>) -> Self { + fn new(subst_map: &'a HashMap<&'a str, &'a ArgKinded>) -> Self { SubstIdentsKinded { subst_map, bound_idents: HashSet::new(), @@ -115,8 +112,8 @@ impl<'a> SubstIdentsKinded<'a> { } fn with_bound_idents( - subst_map: HashMap<&'a str, &'a ArgKinded<'a>>, - bound_idents: HashSet>, + subst_map: &'a HashMap<&'a str, &'a ArgKinded>, + bound_idents: HashSet, ) -> Self { SubstIdentsKinded { subst_map, @@ -125,8 +122,8 @@ impl<'a> SubstIdentsKinded<'a> { } } -impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { - fn visit_nat(&mut self, nat: &mut Nat<'a>) { +impl VisitMut for SubstIdentsKinded<'_> { + fn visit_nat(&mut self, nat: &mut Nat) { match nat { Nat::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Nat); @@ -142,7 +139,7 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } } - fn visit_mem(&mut self, mem: &mut Memory<'a>) { + fn visit_mem(&mut self, mem: &mut Memory) { match mem { Memory::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Memory); @@ -158,7 +155,7 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } } - fn visit_prv(&mut self, prv: &mut Provenance<'a>) { + fn visit_prv(&mut self, prv: &mut Provenance) { match prv { Provenance::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Provenance); @@ -174,7 +171,7 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } } - fn visit_dty(&mut self, dty: &mut DataTy<'a>) { + fn visit_dty(&mut self, dty: &mut DataTy) { match &mut dty.dty { DataTyKind::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::DataTy); @@ -191,7 +188,7 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } // add generic paramters to list of bound identifiers - fn visit_fn_ty(&mut self, fn_ty: &mut FnTy<'a>) { + fn visit_fn_ty(&mut self, fn_ty: &mut FnTy) { let fun_bound_idents = fn_ty.generics.clone(); let mut all_bound_idents = self.bound_idents.clone(); all_bound_idents.extend(fun_bound_idents); @@ -210,7 +207,7 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } // only required to introduce a new scope of bound identifiers - fn visit_expr(&mut self, expr: &mut Expr<'a>) { + fn visit_expr(&mut self, expr: &mut Expr) { match &mut expr.expr { ExprKind::ForNat(ident, collec, body) => { self.visit_nat_range(collec); @@ -225,7 +222,7 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } // add generic paramters to list of bound identifiers - fn visit_fun_def(&mut self, fun_def: &mut FunDef<'a>) { + fn visit_fun_def(&mut self, fun_def: &mut FunDef) { let fun_bound_idents = fun_def.generic_params.clone(); let mut all_bound_idents = self.bound_idents.clone(); all_bound_idents.extend(fun_bound_idents); @@ -255,23 +252,22 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { * This substitution ignores whehter an execution identifier is bound by a function type. */ struct SubstIdentExec<'a> { - pub ident: &'a Ident<'a>, - pub exec: &'a ExecExpr<'a>, + pub ident: &'a Ident, + pub exec: &'a ExecExpr, } impl<'a> SubstIdentExec<'a> { - fn new(ident: &'a Ident<'a>, exec: &'a ExecExpr<'a>) -> Self { + fn new(ident: &'a Ident, exec: &'a ExecExpr) -> Self { SubstIdentExec { ident, exec } } } -impl<'a> VisitMut<'a> for SubstIdentExec<'a> { - fn visit_exec_expr(&mut self, bump: &'a bumpalo::Bump, exec_expr: &mut ExecExpr<'a>) { - insert_for_ident(bump, self.exec, &self.ident, exec_expr) +impl VisitMut for SubstIdentExec<'_> { + fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr) { + insert_for_ident(self.exec, &self.ident, exec_expr) } } -/** -fn insert_for_ident<'a>(exec: &ExecExpr<'a>, ident: &Ident<'a>, in_exec: &mut ExecExpr<'a>) { +fn insert_for_ident(exec: &ExecExpr, ident: &Ident, in_exec: &mut ExecExpr) { if let BaseExec::Ident(i) = &mut in_exec.exec.base { if i == ident { let mut subst_exec = exec.clone(); @@ -280,42 +276,14 @@ fn insert_for_ident<'a>(exec: &ExecExpr<'a>, ident: &Ident<'a>, in_exec: &mut Ex } } } -*/ - -fn insert_for_ident<'a>( - bump: &'a bumpalo::Bump, - exec: &ExecExpr<'a>, - ident: &Ident<'a>, - in_exec: &mut ExecExpr<'a>, -) { - if let BaseExec::Ident(i) = &in_exec.exec.base { - if i == ident { - let mut merged_path = exec.exec.path.clone(); - merged_path.extend(in_exec.exec.path.iter().cloned()); - - let new_exec = bump.alloc(ExecExprKind { - base: exec.exec.base.clone(), - path: merged_path, - }); - - let new_exec_expr = ExecExpr { - exec: new_exec, - ty: in_exec.ty, - span: in_exec.span, - }; - - *in_exec = new_exec_expr; - } - } -} -pub trait Visitable<'a> { - fn visit>(&self, visitor: &mut V); +pub trait Visitable { + fn visit(&self, visitor: &mut V); } macro_rules! visitable { ($t:ident, $f:ident) => { - impl<'a> Visitable<'a> for $t<'a> { - fn visit>(&self, visitor: &mut V) { + impl Visitable for $t { + fn visit(&self, visitor: &mut V) { visitor.$f(self); } } @@ -333,18 +301,18 @@ visitable!(Dim, visit_dim); visitable!(Expr, visit_expr); visitable!(Nat, visit_nat); -pub fn free_kinded_idents<'a, T: Visitable<'a>>(t: &T) -> HashSet> { +pub fn free_kinded_idents(t: &T) -> HashSet { let mut free_kinded_idents = FreeKindedIdents::new(); t.visit(&mut free_kinded_idents); free_kinded_idents.set } -pub struct FreeKindedIdents<'a> { - pub set: HashSet>, - pub bound_idents: HashSet>, +pub struct FreeKindedIdents { + pub set: HashSet, + pub bound_idents: HashSet, } -impl<'a> FreeKindedIdents<'a> { +impl FreeKindedIdents { fn new() -> Self { FreeKindedIdents { set: HashSet::new(), @@ -352,7 +320,7 @@ impl<'a> FreeKindedIdents<'a> { } } - fn with_bound_idents(idents: HashSet>) -> Self { + fn with_bound_idents(idents: HashSet) -> Self { FreeKindedIdents { set: HashSet::new(), bound_idents: idents, @@ -360,8 +328,8 @@ impl<'a> FreeKindedIdents<'a> { } } -impl<'a> Visit<'a> for FreeKindedIdents<'a> { - fn visit_nat(&mut self, nat: &Nat<'a>) { +impl Visit for FreeKindedIdents { + fn visit_nat(&mut self, nat: &Nat) { match nat { Nat::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Nat); @@ -373,7 +341,7 @@ impl<'a> Visit<'a> for FreeKindedIdents<'a> { } } - fn visit_mem(&mut self, mem: &Memory<'a>) { + fn visit_mem(&mut self, mem: &Memory) { match mem { Memory::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Memory); @@ -385,7 +353,7 @@ impl<'a> Visit<'a> for FreeKindedIdents<'a> { } } - fn visit_prv(&mut self, prv: &Provenance<'a>) { + fn visit_prv(&mut self, prv: &Provenance) { match prv { Provenance::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Provenance); @@ -397,7 +365,7 @@ impl<'a> Visit<'a> for FreeKindedIdents<'a> { } } - fn visit_dty(&mut self, dty: &DataTy<'a>) { + fn visit_dty(&mut self, dty: &DataTy) { match &dty.dty { DataTyKind::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::DataTy); @@ -409,7 +377,7 @@ impl<'a> Visit<'a> for FreeKindedIdents<'a> { } } - fn visit_ty(&mut self, ty: &Ty<'a>) { + fn visit_ty(&mut self, ty: &Ty) { match &ty.ty { TyKind::FnTy(fn_ty) => { if !fn_ty.generics.is_empty() { @@ -420,13 +388,13 @@ impl<'a> Visit<'a> for FreeKindedIdents<'a> { } walk_list!(self, visit_param_sig, &fn_ty.param_sigs); - self.visit_ty(fn_ty.ret_ty) + self.visit_ty(fn_ty.ret_ty.as_ref()) } _ => visit::walk_ty(self, ty), } } - fn visit_expr(&mut self, expr: &Expr<'a>) { + fn visit_expr(&mut self, expr: &Expr) { match &expr.expr { ExprKind::ForNat(ident, collec, body) => { self.visit_nat_range(collec); diff --git a/src/ast/visit.rs b/src/ast/visit.rs index 5f47ab59..e14556a7 100644 --- a/src/ast/visit.rs +++ b/src/ast/visit.rs @@ -1,64 +1,64 @@ use crate::ast::*; #[rustfmt::skip] -pub trait Visit<'a>: Sized { +pub trait Visit: Sized { fn visit_binary_op_nat(&mut self, _op: &BinOpNat) {} - fn visit_nat(&mut self, n: &Nat<'a>) { walk_nat(self, n) } - fn visit_nat_range(&mut self, nr: &NatRange<'a>) { walk_nat_range(self, nr) } - fn visit_ident_kinded(&mut self, id_kind: &IdentKinded<'a>) { walk_ident_kinded(self, id_kind) } - fn visit_ident_exec(&mut self, ident_exec: &IdentExec<'a>) { walk_ident_exec(self, ident_exec) } - fn visit_prv_rel(&mut self, prv_rel: &PrvRel<'a>) { walk_prv_rel(self, prv_rel) } - fn visit_exec_ty(&mut self, _exec: &ExecTy<'a>) {} - fn visit_mem(&mut self, mem: &Memory<'a>) { walk_mem(self, mem) } - fn visit_prv(&mut self, prv: &Provenance<'a>) { walk_prv(self, prv) } + fn visit_nat(&mut self, n: &Nat) { walk_nat(self, n) } + fn visit_nat_range(&mut self, nr: &NatRange) { walk_nat_range(self, nr) } + fn visit_ident_kinded(&mut self, id_kind: &IdentKinded) { walk_ident_kinded(self, id_kind) } + fn visit_ident_exec(&mut self, ident_exec: &IdentExec) { walk_ident_exec(self, ident_exec) } + fn visit_prv_rel(&mut self, prv_rel: &PrvRel) { walk_prv_rel(self, prv_rel) } + fn visit_exec_ty(&mut self, _exec: &ExecTy) {} + fn visit_mem(&mut self, mem: &Memory) { walk_mem(self, mem) } + fn visit_prv(&mut self, prv: &Provenance) { walk_prv(self, prv) } fn visit_scalar_ty(&mut self, _sty: &ScalarTy) {} fn visit_atomic_ty(&mut self, _aty: &AtomicTy) {} fn visit_dim_compo(&mut self, _dim_compo: &DimCompo) { } - fn visit_dim(&mut self, dim: &Dim<'a>) { walk_dim(self, dim) } - fn visit_dim3d(&mut self, dim3d: &Dim3d<'a>) { walk_dim3d(self, dim3d) } - fn visit_dim2d(&mut self, dim2d: &Dim2d<'a>) { walk_dim2d(self, dim2d) } - fn visit_dim1d(&mut self, dim1d: &Dim1d<'a>) { walk_dim1d(self, dim1d) } - fn visit_ref(&mut self, reff: &RefDty<'a>) { walk_ref(self, reff) } - fn visit_dty(&mut self, dty: &DataTy<'a>) { walk_dty(self, dty) } - fn visit_fn_ty(&mut self, fn_ty: &FnTy<'a>) { walk_fn_ty(self, fn_ty) } - fn visit_nat_constr(&mut self, nat_constr: &NatConstr<'a>) { walk_nat_constr(self, nat_constr) } - fn visit_ty(&mut self, ty: &Ty<'a>) { walk_ty(self, ty) } - fn visit_view(&mut self, view: &View<'a>) { walk_view(self, view) } - fn visit_pl_expr(&mut self, pl_expr: &PlaceExpr<'a>) { walk_pl_expr(self, pl_expr) } - fn visit_arg_kinded(&mut self, arg_kinded: &ArgKinded<'a>) { walk_arg_kinded(self, arg_kinded) } + fn visit_dim(&mut self, dim: &Dim) { walk_dim(self, dim) } + fn visit_dim3d(&mut self, dim3d: &Dim3d) { walk_dim3d(self, dim3d) } + fn visit_dim2d(&mut self, dim2d: &Dim2d) { walk_dim2d(self, dim2d) } + fn visit_dim1d(&mut self, dim1d: &Dim1d) { walk_dim1d(self, dim1d) } + fn visit_ref(&mut self, reff: &RefDty) { walk_ref(self, reff) } + fn visit_dty(&mut self, dty: &DataTy) { walk_dty(self, dty) } + fn visit_fn_ty(&mut self, fn_ty: &FnTy) { walk_fn_ty(self, fn_ty) } + fn visit_nat_constr(&mut self, nat_constr: &NatConstr) { walk_nat_constr(self, nat_constr) } + fn visit_ty(&mut self, ty: &Ty) { walk_ty(self, ty) } + fn visit_view(&mut self, view: &View) { walk_view(self, view) } + fn visit_pl_expr(&mut self, pl_expr: &PlaceExpr) { walk_pl_expr(self, pl_expr) } + fn visit_arg_kinded(&mut self, arg_kinded: &ArgKinded) { walk_arg_kinded(self, arg_kinded) } fn visit_kind(&mut self, _kind: &Kind) {} fn visit_binary_op(&mut self, _op: &BinOp) {} fn visit_unary_op(&mut self, _op: &UnOp) {} fn visit_own(&mut self, _own: &Ownership) {} fn visit_mutability(&mut self, _mutbl: &Mutability) {} fn visit_lit(&mut self, _lit: &Lit) {} - fn visit_ident(&mut self, _ident: &Ident<'a>) {} - fn visit_pattern(&mut self, pattern: &Pattern<'a>) { walk_pattern(self, pattern) } - fn visit_split(&mut self, split: &Split<'a>) { walk_split(self, split) } - fn visit_sched(&mut self, par_for: &Sched<'a>) { walk_sched(self, par_for) } - fn visit_expr(&mut self, expr: &Expr<'a>) { walk_expr(self, expr) } - fn visit_app_kernel(&mut self, app_kernel: &AppKernel<'a>) { walk_app_kernel(self, app_kernel) } - fn visit_block(&mut self, block: &Block<'a>) { walk_block(self, block) } - fn visit_split_proj(&mut self, exec_split: &TakeRange<'a>) { walk_split_proj(self, exec_split) } - fn visit_exec_expr(&mut self, exec_expr: &ExecExpr<'a>) { walk_exec_expr(self, exec_expr) } - fn visit_exec(&mut self, exec: &ExecExprKind<'a>) { walk_exec(self, exec) } - fn visit_param_decl(&mut self, param_decl: &ParamDecl<'a>) { walk_param_decl(self, param_decl) } - fn visit_fun_def(&mut self, fun_def: &FunDef<'a>) { walk_fun_def(self, fun_def) } - fn visit_fun_decl(&mut self, fun_decl: &FunDecl<'a>) { walk_fun_decl(self, fun_decl) } - fn visit_param_sig(&mut self, param_sig: &ParamSig<'a>) { walk_param_sig(self, param_sig) } - fn visit_field(&mut self, field: &(Ident<'a>, DataTy<'a>)) { walk_field(self, field) } + fn visit_ident(&mut self, _ident: &Ident) {} + fn visit_pattern(&mut self, pattern: &Pattern) { walk_pattern(self, pattern) } + fn visit_split(&mut self, split: &Split) { walk_split(self, split) } + fn visit_sched(&mut self, par_for: &Sched) { walk_sched(self, par_for) } + fn visit_expr(&mut self, expr: &Expr) { walk_expr(self, expr) } + fn visit_app_kernel(&mut self, app_kernel: &AppKernel) { walk_app_kernel(self, app_kernel) } + fn visit_block(&mut self, block: &Block) { walk_block(self, block) } + fn visit_split_proj(&mut self, exec_split: &TakeRange) { walk_split_proj(self, exec_split) } + fn visit_exec_expr(&mut self, exec_expr: &ExecExpr) { walk_exec_expr(self, exec_expr) } + fn visit_exec(&mut self, exec: &ExecExprKind) { walk_exec(self, exec) } + fn visit_param_decl(&mut self, param_decl: &ParamDecl) { walk_param_decl(self, param_decl) } + fn visit_fun_def(&mut self, fun_def: &FunDef) { walk_fun_def(self, fun_def) } + fn visit_fun_decl(&mut self, fun_decl: &FunDecl) { walk_fun_decl(self, fun_decl) } + fn visit_param_sig(&mut self, param_sig: &ParamSig) { walk_param_sig(self, param_sig) } + fn visit_field(&mut self, field: &(Ident, DataTy)) { walk_field(self, field) } } macro_rules! walk_list { ($visitor: expr, $method: ident, $list: expr) => { - for elem in $list.iter_mut() { + for elem in $list { $visitor.$method(elem) } }; } pub(crate) use walk_list; -pub fn walk_nat<'a, V: Visit<'a>>(visitor: &mut V, n: &Nat<'a>) { +pub fn walk_nat(visitor: &mut V, n: &Nat) { match n { Nat::Ident(ident) => visitor.visit_ident(ident), Nat::BinOp(op, l, r) => { @@ -81,7 +81,7 @@ pub fn walk_nat<'a, V: Visit<'a>>(visitor: &mut V, n: &Nat<'a>) { } } -pub fn walk_nat_range<'a, V: Visit<'a>>(visitor: &mut V, nr: &NatRange<'a>) { +pub fn walk_nat_range(visitor: &mut V, nr: &NatRange) { match nr { NatRange::Simple { lower, upper } => { visitor.visit_nat(lower); @@ -91,56 +91,56 @@ pub fn walk_nat_range<'a, V: Visit<'a>>(visitor: &mut V, nr: &NatRange<'a>) { } } -pub fn walk_ident_kinded<'a, V: Visit<'a>>(visitor: &mut V, id_kind: &IdentKinded<'a>) { +pub fn walk_ident_kinded(visitor: &mut V, id_kind: &IdentKinded) { let IdentKinded { ident, kind } = id_kind; visitor.visit_ident(ident); visitor.visit_kind(kind) } -pub fn walk_ident_exec<'a, V: Visit<'a>>(visitor: &mut V, id_exec: &IdentExec<'a>) { +pub fn walk_ident_exec(visitor: &mut V, id_exec: &IdentExec) { let IdentExec { ident, ty } = id_exec; visitor.visit_ident(ident); visitor.visit_exec_ty(ty) } -pub fn walk_prv_rel<'a, V: Visit<'a>>(visitor: &mut V, prv_rel: &PrvRel<'a>) { +pub fn walk_prv_rel(visitor: &mut V, prv_rel: &PrvRel) { let PrvRel { longer, shorter } = prv_rel; visitor.visit_ident(longer); visitor.visit_ident(shorter) } -pub fn walk_mem<'a, V: Visit<'a>>(visitor: &mut V, mem: &Memory<'a>) { +pub fn walk_mem(visitor: &mut V, mem: &Memory) { if let Memory::Ident(ident) = mem { visitor.visit_ident(ident) } } -pub fn walk_prv<'a, V: Visit<'a>>(visitor: &mut V, prv: &Provenance<'a>) { +pub fn walk_prv(visitor: &mut V, prv: &Provenance) { match prv { Provenance::Ident(ident) => visitor.visit_ident(ident), Provenance::Value(_) => {} } } -pub fn walk_dim3d<'a, V: Visit<'a>>(visitor: &mut V, dim3d: &Dim3d<'a>) { +pub fn walk_dim3d(visitor: &mut V, dim3d: &Dim3d) { let Dim3d(n1, n2, n3) = dim3d; visitor.visit_nat(n1); visitor.visit_nat(n2); visitor.visit_nat(n3); } -pub fn walk_dim2d<'a, V: Visit<'a>>(visitor: &mut V, dim2d: &Dim2d<'a>) { +pub fn walk_dim2d(visitor: &mut V, dim2d: &Dim2d) { let Dim2d(n1, n2) = dim2d; visitor.visit_nat(n1); visitor.visit_nat(n2); } -pub fn walk_dim1d<'a, V: Visit<'a>>(visitor: &mut V, dim1d: &Dim1d<'a>) { +pub fn walk_dim1d(visitor: &mut V, dim1d: &Dim1d) { let Dim1d(n) = dim1d; visitor.visit_nat(n); } -pub fn walk_dim<'a, V: Visit<'a>>(visitor: &mut V, dim: &Dim<'a>) { +pub fn walk_dim(visitor: &mut V, dim: &Dim) { match dim { Dim::XYZ(dim3d) => { visitor.visit_dim3d(dim3d); @@ -152,7 +152,7 @@ pub fn walk_dim<'a, V: Visit<'a>>(visitor: &mut V, dim: &Dim<'a>) { } } -pub fn walk_ref<'a, V: Visit<'a>>(visitor: &mut V, reff: &RefDty<'a>) { +pub fn walk_ref(visitor: &mut V, reff: &RefDty) { let RefDty { rgn, own, mem, dty } = reff; visitor.visit_prv(rgn); visitor.visit_own(own); @@ -160,7 +160,7 @@ pub fn walk_ref<'a, V: Visit<'a>>(visitor: &mut V, reff: &RefDty<'a>) { visitor.visit_dty(dty); } -pub fn walk_dty<'a, V: Visit<'a>>(visitor: &mut V, dty: &DataTy<'a>) { +pub fn walk_dty(visitor: &mut V, dty: &DataTy) { match &dty.dty { DataTyKind::Ident(ident) => visitor.visit_ident(ident), DataTyKind::Scalar(sty) => visitor.visit_scalar_ty(sty), @@ -190,7 +190,7 @@ pub fn walk_dty<'a, V: Visit<'a>>(visitor: &mut V, dty: &DataTy<'a>) { } } -pub fn walk_fn_ty<'a, V: Visit<'a>>(visitor: &mut V, fn_ty: &FnTy<'a>) { +pub fn walk_fn_ty(visitor: &mut V, fn_ty: &FnTy) { let FnTy { generics, generic_exec, @@ -209,7 +209,7 @@ pub fn walk_fn_ty<'a, V: Visit<'a>>(visitor: &mut V, fn_ty: &FnTy<'a>) { walk_list!(visitor, visit_nat_constr, nat_constrs); } -pub fn walk_nat_constr<'a, V: Visit<'a>>(visitor: &mut V, nat_constr: &NatConstr<'a>) { +pub fn walk_nat_constr(visitor: &mut V, nat_constr: &NatConstr) { match nat_constr { NatConstr::True => {} NatConstr::Eq(l, r) => { @@ -231,7 +231,7 @@ pub fn walk_nat_constr<'a, V: Visit<'a>>(visitor: &mut V, nat_constr: &NatConstr } } -pub fn walk_ty<'a, V: Visit<'a>>(visitor: &mut V, ty: &Ty<'a>) { +pub fn walk_ty(visitor: &mut V, ty: &Ty) { match &ty.ty { TyKind::Data(dty) => visitor.visit_dty(dty), TyKind::FnTy(fn_ty) => { @@ -240,7 +240,7 @@ pub fn walk_ty<'a, V: Visit<'a>>(visitor: &mut V, ty: &Ty<'a>) { } } -pub fn walk_view<'a, V: Visit<'a>>(visitor: &mut V, view: &View<'a>) { +pub fn walk_view(visitor: &mut V, view: &View) { visitor.visit_ident(&view.name); walk_list!(visitor, visit_arg_kinded, &view.gen_args); for v in &view.args { @@ -248,7 +248,7 @@ pub fn walk_view<'a, V: Visit<'a>>(visitor: &mut V, view: &View<'a>) { } } -pub fn walk_pl_expr<'a, V: Visit<'a>>(visitor: &mut V, pl_expr: &PlaceExpr<'a>) { +pub fn walk_pl_expr(visitor: &mut V, pl_expr: &PlaceExpr) { match &pl_expr.pl_expr { PlaceExprKind::Ident(ident) => visitor.visit_ident(ident), PlaceExprKind::Deref(pl_expr) => visitor.visit_pl_expr(pl_expr), @@ -274,7 +274,7 @@ pub fn walk_pl_expr<'a, V: Visit<'a>>(visitor: &mut V, pl_expr: &PlaceExpr<'a>) } } -pub fn walk_arg_kinded<'a, V: Visit<'a>>(visitor: &mut V, arg_kinded: &ArgKinded<'a>) { +pub fn walk_arg_kinded(visitor: &mut V, arg_kinded: &ArgKinded) { match arg_kinded { ArgKinded::Ident(ident) => visitor.visit_ident(ident), ArgKinded::Nat(n) => visitor.visit_nat(n), @@ -284,7 +284,7 @@ pub fn walk_arg_kinded<'a, V: Visit<'a>>(visitor: &mut V, arg_kinded: &ArgKinded } } -pub fn walk_pattern<'a, V: Visit<'a>>(visitor: &mut V, pattern: &Pattern<'a>) { +pub fn walk_pattern(visitor: &mut V, pattern: &Pattern) { match pattern { Pattern::Ident(mutab, ident) => { visitor.visit_mutability(mutab); @@ -297,7 +297,7 @@ pub fn walk_pattern<'a, V: Visit<'a>>(visitor: &mut V, pattern: &Pattern<'a>) { } } -pub fn walk_split<'a, V: Visit<'a>>(visitor: &mut V, indep: &Split<'a>) { +pub fn walk_split(visitor: &mut V, indep: &Split) { let Split { dim_compo, pos, @@ -312,7 +312,7 @@ pub fn walk_split<'a, V: Visit<'a>>(visitor: &mut V, indep: &Split<'a>) { walk_list!(visitor, visit_expr, branch_bodies); } -pub fn walk_sched<'a, V: Visit<'a>>(visitor: &mut V, sched: &Sched<'a>) { +pub fn walk_sched(visitor: &mut V, sched: &Sched) { let Sched { dim, inner_exec_ident, @@ -327,7 +327,7 @@ pub fn walk_sched<'a, V: Visit<'a>>(visitor: &mut V, sched: &Sched<'a>) { visitor.visit_block(body); } -pub fn walk_expr<'a, V: Visit<'a>>(visitor: &mut V, expr: &Expr<'a>) { +pub fn walk_expr(visitor: &mut V, expr: &Expr) { // For now, only visit ExprKind match &expr.expr { ExprKind::Lit(l) => visitor.visit_lit(l), @@ -442,7 +442,7 @@ pub fn walk_expr<'a, V: Visit<'a>>(visitor: &mut V, expr: &Expr<'a>) { } } -pub fn walk_app_kernel<'a, V: Visit<'a>>(visitor: &mut V, app_kernel: &AppKernel<'a>) { +pub fn walk_app_kernel(visitor: &mut V, app_kernel: &AppKernel) { let AppKernel { grid_dim, block_dim, @@ -466,12 +466,12 @@ pub fn walk_app_kernel<'a, V: Visit<'a>>(visitor: &mut V, app_kernel: &AppKernel } } -pub fn walk_block<'a, V: Visit<'a>>(visitor: &mut V, block: &Block<'a>) { +pub fn walk_block(visitor: &mut V, block: &Block) { let Block { body, .. } = block; visitor.visit_expr(body); } -pub fn walk_split_proj<'a, V: Visit<'a>>(visitor: &mut V, split_proj: &TakeRange<'a>) { +pub fn walk_split_proj(visitor: &mut V, split_proj: &TakeRange) { let TakeRange { split_dim, pos, @@ -481,14 +481,14 @@ pub fn walk_split_proj<'a, V: Visit<'a>>(visitor: &mut V, split_proj: &TakeRange visitor.visit_nat(pos); } -pub fn walk_exec_expr<'a, V: Visit<'a>>(visitor: &mut V, exec_expr: &ExecExpr<'a>) { +pub fn walk_exec_expr(visitor: &mut V, exec_expr: &ExecExpr) { visitor.visit_exec(&exec_expr.exec); for t in &exec_expr.ty { visitor.visit_exec_ty(t); } } -pub fn walk_exec<'a, V: Visit<'a>>(visitor: &mut V, exec: &ExecExprKind<'a>) { +pub fn walk_exec(visitor: &mut V, exec: &ExecExprKind) { let ExecExprKind { base, path } = exec; match base { BaseExec::CpuThread => (), @@ -508,7 +508,7 @@ pub fn walk_exec<'a, V: Visit<'a>>(visitor: &mut V, exec: &ExecExprKind<'a>) { } } -pub fn walk_param_decl<'a, V: Visit<'a>>(visitor: &mut V, param_decl: &ParamDecl<'a>) { +pub fn walk_param_decl(visitor: &mut V, param_decl: &ParamDecl) { let ParamDecl { ident, ty, @@ -525,7 +525,7 @@ pub fn walk_param_decl<'a, V: Visit<'a>>(visitor: &mut V, param_decl: &ParamDecl } } -pub fn walk_fun_def<'a, V: Visit<'a>>(visitor: &mut V, fun_def: &FunDef<'a>) { +pub fn walk_fun_def(visitor: &mut V, fun_def: &FunDef) { let FunDef { ident: _, generic_params, @@ -547,7 +547,7 @@ pub fn walk_fun_def<'a, V: Visit<'a>>(visitor: &mut V, fun_def: &FunDef<'a>) { visitor.visit_block(body) } -pub fn walk_fun_decl<'a, V: Visit<'a>>(visitor: &mut V, fun_decl: &FunDecl<'a>) { +pub fn walk_fun_decl(visitor: &mut V, fun_decl: &FunDecl) { let FunDecl { ident: _, generic_params, @@ -567,13 +567,13 @@ pub fn walk_fun_decl<'a, V: Visit<'a>>(visitor: &mut V, fun_decl: &FunDecl<'a>) walk_list!(visitor, visit_prv_rel, prv_rels); } -pub fn walk_param_sig<'a, V: Visit<'a>>(visitor: &mut V, param_sig: &ParamSig<'a>) { +pub fn walk_param_sig(visitor: &mut V, param_sig: &ParamSig) { let ParamSig { exec_expr, ty } = param_sig; visitor.visit_exec_expr(exec_expr); visitor.visit_ty(ty); } -pub fn walk_field<'a, V: Visit<'a>>(visitor: &mut V, field: &(Ident<'a>, DataTy<'a>)) { +pub fn walk_field(visitor: &mut V, field: &(Ident, DataTy)) { let (ident, dty) = field; visitor.visit_ident(ident); visitor.visit_dty(dty); diff --git a/src/ast/visit_mut.rs b/src/ast/visit_mut.rs index 46f9ddac..cf35402d 100644 --- a/src/ast/visit_mut.rs +++ b/src/ast/visit_mut.rs @@ -1,66 +1,66 @@ use crate::ast::*; #[rustfmt::skip] -pub trait VisitMut<'a>: Sized { +pub trait VisitMut: Sized { fn visit_binary_op_nat(&mut self, _op: &mut BinOpNat) {} - fn visit_nat(&mut self, n: &mut Nat<'a>) { walk_nat(self, n) } - fn visit_nat_range(&mut self, nr: &mut NatRange<'a>) { walk_nat_range(self, nr) } - fn visit_ident_kinded(&mut self, id_kind: &mut IdentKinded<'a>) { walk_ident_kinded(self, id_kind) } - fn visit_ident_exec(&mut self, id_exec: &mut IdentExec<'a>) { walk_ident_exec(self, id_exec) } - fn visit_prv_rel(&mut self, prv_rel: &mut PrvRel<'a>) { walk_prv_rel(self, prv_rel) } - fn visit_exec_ty(&mut self, _exec: &mut ExecTy<'a>) {} - fn visit_mem(&mut self, mem: &mut Memory<'a>) { walk_mem(self, mem) } - fn visit_prv(&mut self, prv: &mut Provenance<'a>) { walk_prv(self, prv) } + fn visit_nat(&mut self, n: &mut Nat) { walk_nat(self, n) } + fn visit_nat_range(&mut self, nr: &mut NatRange) { walk_nat_range(self, nr) } + fn visit_ident_kinded(&mut self, id_kind: &mut IdentKinded) { walk_ident_kinded(self, id_kind) } + fn visit_ident_exec(&mut self, id_exec: &mut IdentExec) { walk_ident_exec(self, id_exec) } + fn visit_prv_rel(&mut self, prv_rel: &mut PrvRel) { walk_prv_rel(self, prv_rel) } + fn visit_exec_ty(&mut self, _exec: &mut ExecTy) {} + fn visit_mem(&mut self, mem: &mut Memory) { walk_mem(self, mem) } + fn visit_prv(&mut self, prv: &mut Provenance) { walk_prv(self, prv) } fn visit_scalar_ty(&mut self, _sty: &mut ScalarTy) {} fn visit_atomic_ty(&mut self, _aty: &mut AtomicTy) {} fn visit_dim_compo(&mut self, _dim_compo: &mut DimCompo) {} - fn visit_dim(&mut self, dim: &mut Dim<'a>) { walk_dim(self, dim) } - fn visit_dim3d(&mut self, dim3d: &mut Dim3d<'a>) { walk_dim3d(self, dim3d) } - fn visit_dim2d(&mut self, dim2d: &mut Dim2d<'a>) { walk_dim2d(self, dim2d) } - fn visit_dim1d(&mut self, dim1d: &mut Dim1d<'a>) { walk_dim1d(self, dim1d) } - fn visit_ref(&mut self, reff: &mut RefDty<'a>) { walk_ref(self, reff) } - fn visit_dty(&mut self, dty: &mut DataTy<'a>) { walk_dty(self, dty) } - fn visit_fn_ty(&mut self, fn_ty: &mut FnTy<'a>) { walk_fn_ty(self, fn_ty) } - fn visit_nat_constr(&mut self, nat_constr: &mut NatConstr<'a>) { walk_nat_constr(self, nat_constr) } - fn visit_ty(&mut self, ty: &mut Ty<'a>) { walk_ty(self, ty) } - fn visit_view(&mut self, view: &mut View<'a>) { walk_view(self, view) } - fn visit_pl_expr(&mut self, pl_expr: &mut PlaceExpr<'a>) { walk_pl_expr(self, pl_expr) } - fn visit_arg_kinded(&mut self, arg_kinded: &mut ArgKinded<'a>) { walk_arg_kinded(self, arg_kinded) } + fn visit_dim(&mut self, dim: &mut Dim) { walk_dim(self, dim) } + fn visit_dim3d(&mut self, dim3d: &mut Dim3d) { walk_dim3d(self, dim3d) } + fn visit_dim2d(&mut self, dim2d: &mut Dim2d) { walk_dim2d(self, dim2d) } + fn visit_dim1d(&mut self, dim1d: &mut Dim1d) { walk_dim1d(self, dim1d) } + fn visit_ref(&mut self, reff: &mut RefDty) { walk_ref(self, reff) } + fn visit_dty(&mut self, dty: &mut DataTy) { walk_dty(self, dty) } + fn visit_fn_ty(&mut self, fn_ty: &mut FnTy) { walk_fn_ty(self, fn_ty) } + fn visit_nat_constr(&mut self, nat_constr: &mut NatConstr) { walk_nat_constr(self, nat_constr) } + fn visit_ty(&mut self, ty: &mut Ty) { walk_ty(self, ty) } + fn visit_view(&mut self, view: &mut View) { walk_view(self, view) } + fn visit_pl_expr(&mut self, pl_expr: &mut PlaceExpr) { walk_pl_expr(self, pl_expr) } + fn visit_arg_kinded(&mut self, arg_kinded: &mut ArgKinded) { walk_arg_kinded(self, arg_kinded) } fn visit_kind(&mut self, _kind: &mut Kind) {} fn visit_binary_op(&mut self, _op: &mut BinOp) {} fn visit_unary_op(&mut self, _op: &mut UnOp) {} fn visit_own(&mut self, _own: &mut Ownership) {} fn visit_mutability(&mut self, _mutbl: &mut Mutability) {} fn visit_lit(&mut self, _lit: &mut Lit) {} - fn visit_ident(&mut self, _ident: &mut Ident<'a>) {} - fn visit_pattern(&mut self, pattern: &mut Pattern<'a>) { walk_pattern(self, pattern) } - fn visit_split(&mut self, split: &mut Split<'a>) { walk_split(self, split) } - fn visit_sched(&mut self, sched: &mut Sched<'a>) { walk_sched(self, sched) } - fn visit_expr(&mut self, expr: &mut Expr<'a>) { walk_expr(self, expr) } - fn visit_app_kernel(&mut self, app_kernel: &mut AppKernel<'a>) { walk_app_kernel(self, app_kernel) } - fn visit_block(&mut self, block: &mut Block<'a>) { walk_block(self, block) } - fn visit_split_proj(&mut self, exec_split: &mut TakeRange<'a>) { walk_split_proj(self, exec_split) } - fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr<'a>) { walk_exec_expr(self, exec_expr) } - fn visit_exec(&mut self, exec: &mut ExecExprKind<'a>) { walk_exec(self, exec) } - fn visit_exec_path_elem(&mut self, exec_path_elem: &mut ExecPathElem<'a>) { walk_exec_path_elem(self, exec_path_elem) } - fn visit_param_decl(&mut self, param_decl: &mut ParamDecl<'a>) { walk_param_decl(self, param_decl) } - fn visit_fun_def(&mut self, fun_def: &mut FunDef<'a>) { walk_fun_def(self, fun_def) } - fn visit_fun_decl(&mut self, fun_decl: &mut FunDecl<'a>) { walk_fun_decl(self, fun_decl) } - fn visit_param_sig(&mut self, param_sig: &mut ParamSig<'a>) { walk_param_sig(self, param_sig) } - fn visit_field(&mut self, field: &mut (Ident<'a>, DataTy<'a>)) { walk_field(self, field) } + fn visit_ident(&mut self, _ident: &mut Ident) {} + fn visit_pattern(&mut self, pattern: &mut Pattern) { walk_pattern(self, pattern) } + fn visit_split(&mut self, split: &mut Split) { walk_split(self, split) } + fn visit_sched(&mut self, sched: &mut Sched) { walk_sched(self, sched) } + fn visit_expr(&mut self, expr: &mut Expr) { walk_expr(self, expr) } + fn visit_app_kernel(&mut self, app_kernel: &mut AppKernel) { walk_app_kernel(self, app_kernel) } + fn visit_block(&mut self, block: &mut Block) { walk_block(self, block) } + fn visit_split_proj(&mut self, exec_split: &mut TakeRange) { walk_split_proj(self, exec_split) } + fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr) { walk_exec_expr(self, exec_expr) } + fn visit_exec(&mut self, exec: &mut ExecExprKind) { walk_exec(self, exec) } + fn visit_exec_path_elem(&mut self, exec_path_elem: &mut ExecPathElem) { walk_exec_path_elem(self, exec_path_elem) } + fn visit_param_decl(&mut self, param_decl: &mut ParamDecl) { walk_param_decl(self, param_decl) } + fn visit_fun_def(&mut self, fun_def: &mut FunDef) { walk_fun_def(self, fun_def) } + fn visit_fun_decl(&mut self, fun_decl: &mut FunDecl) { walk_fun_decl(self, fun_decl) } + fn visit_param_sig(&mut self, param_sig: &mut ParamSig) { walk_param_sig(self, param_sig) } + fn visit_field(&mut self, field: &mut (Ident, DataTy)) { walk_field(self, field) } } // Taken from the Rust compiler macro_rules! walk_list { ($visitor: expr, $method: ident, $list: expr) => { - for elem in $list.iter_mut() { + for elem in $list { $visitor.$method(elem) } }; } pub(crate) use walk_list; -pub fn walk_nat<'a, V: VisitMut<'a>>(visitor: &mut V, n: &mut Nat<'a>) { +pub fn walk_nat(visitor: &mut V, n: &mut Nat) { match n { Nat::Ident(ident) => visitor.visit_ident(ident), Nat::BinOp(op, l, r) => { @@ -83,7 +83,7 @@ pub fn walk_nat<'a, V: VisitMut<'a>>(visitor: &mut V, n: &mut Nat<'a>) { } } -pub fn walk_nat_range<'a, V: VisitMut<'a>>(visitor: &mut V, nr: &mut NatRange<'a>) { +pub fn walk_nat_range(visitor: &mut V, nr: &mut NatRange) { match nr { NatRange::Simple { lower, upper } => { visitor.visit_nat(lower); @@ -93,56 +93,56 @@ pub fn walk_nat_range<'a, V: VisitMut<'a>>(visitor: &mut V, nr: &mut NatRange<'a } } -pub fn walk_ident_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, id_kind: &mut IdentKinded<'a>) { +pub fn walk_ident_kinded(visitor: &mut V, id_kind: &mut IdentKinded) { let IdentKinded { ident, kind } = id_kind; visitor.visit_ident(ident); visitor.visit_kind(kind) } -pub fn walk_ident_exec<'a, V: VisitMut<'a>>(visitor: &mut V, id_exec: &mut IdentExec<'a>) { +pub fn walk_ident_exec(visitor: &mut V, id_exec: &mut IdentExec) { let IdentExec { ident, ty } = id_exec; visitor.visit_ident(ident); visitor.visit_exec_ty(ty) } -pub fn walk_prv_rel<'a, V: VisitMut<'a>>(visitor: &mut V, prv_rel: &mut PrvRel<'a>) { +pub fn walk_prv_rel(visitor: &mut V, prv_rel: &mut PrvRel) { let PrvRel { longer, shorter } = prv_rel; visitor.visit_ident(longer); visitor.visit_ident(shorter) } -pub fn walk_mem<'a, V: VisitMut<'a>>(visitor: &mut V, mem: &mut Memory<'a>) { +pub fn walk_mem(visitor: &mut V, mem: &mut Memory) { if let Memory::Ident(ident) = mem { visitor.visit_ident(ident) } } -pub fn walk_prv<'a, V: VisitMut<'a>>(visitor: &mut V, prv: &mut Provenance<'a>) { +pub fn walk_prv(visitor: &mut V, prv: &mut Provenance) { match prv { Provenance::Ident(ident) => visitor.visit_ident(ident), Provenance::Value(_) => {} } } -pub fn walk_dim3d<'a, V: VisitMut<'a>>(visitor: &mut V, dim3d: &mut Dim3d<'a>) { +pub fn walk_dim3d(visitor: &mut V, dim3d: &mut Dim3d) { let Dim3d(n1, n2, n3) = dim3d; visitor.visit_nat(n1); visitor.visit_nat(n2); visitor.visit_nat(n3); } -pub fn walk_dim2d<'a, V: VisitMut<'a>>(visitor: &mut V, dim2d: &mut Dim2d<'a>) { +pub fn walk_dim2d(visitor: &mut V, dim2d: &mut Dim2d) { let Dim2d(n1, n2) = dim2d; visitor.visit_nat(n1); visitor.visit_nat(n2); } -pub fn walk_dim1d<'a, V: VisitMut<'a>>(visitor: &mut V, dim1d: &mut Dim1d<'a>) { +pub fn walk_dim1d(visitor: &mut V, dim1d: &mut Dim1d) { let Dim1d(n) = dim1d; visitor.visit_nat(n); } -pub fn walk_dim<'a, V: VisitMut<'a>>(visitor: &mut V, dim: &mut Dim<'a>) { +pub fn walk_dim(visitor: &mut V, dim: &mut Dim) { match dim { Dim::XYZ(dim3d) => { visitor.visit_dim3d(dim3d); @@ -154,7 +154,7 @@ pub fn walk_dim<'a, V: VisitMut<'a>>(visitor: &mut V, dim: &mut Dim<'a>) { } } -pub fn walk_ref<'a, V: VisitMut<'a>>(visitor: &mut V, reff: &mut RefDty<'a>) { +pub fn walk_ref(visitor: &mut V, reff: &mut RefDty) { let RefDty { rgn, own, mem, dty } = reff; visitor.visit_prv(rgn); visitor.visit_own(own); @@ -162,7 +162,7 @@ pub fn walk_ref<'a, V: VisitMut<'a>>(visitor: &mut V, reff: &mut RefDty<'a>) { visitor.visit_dty(dty); } -pub fn walk_dty<'a, V: VisitMut<'a>>(visitor: &mut V, dty: &mut DataTy<'a>) { +pub fn walk_dty(visitor: &mut V, dty: &mut DataTy) { match &mut dty.dty { DataTyKind::Ident(ident) => visitor.visit_ident(ident), DataTyKind::Scalar(sty) => visitor.visit_scalar_ty(sty), @@ -192,7 +192,7 @@ pub fn walk_dty<'a, V: VisitMut<'a>>(visitor: &mut V, dty: &mut DataTy<'a>) { } } -pub fn walk_fn_ty<'a, V: VisitMut<'a>>(visitor: &mut V, fn_ty: &mut FnTy<'a>) { +pub fn walk_fn_ty(visitor: &mut V, fn_ty: &mut FnTy) { let FnTy { generics, generic_exec, @@ -211,7 +211,7 @@ pub fn walk_fn_ty<'a, V: VisitMut<'a>>(visitor: &mut V, fn_ty: &mut FnTy<'a>) { walk_list!(visitor, visit_nat_constr, nat_constrs); } -pub fn walk_nat_constr<'a, V: VisitMut<'a>>(visitor: &mut V, nat_constr: &mut NatConstr<'a>) { +pub fn walk_nat_constr(visitor: &mut V, nat_constr: &mut NatConstr) { match nat_constr { NatConstr::True => {} NatConstr::Eq(l, r) => { @@ -233,7 +233,7 @@ pub fn walk_nat_constr<'a, V: VisitMut<'a>>(visitor: &mut V, nat_constr: &mut Na } } -pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, ty: &mut Ty<'a>) { +pub fn walk_ty(visitor: &mut V, ty: &mut Ty) { match &mut ty.ty { TyKind::Data(dty) => visitor.visit_dty(dty), TyKind::FnTy(fn_ty) => { @@ -242,7 +242,7 @@ pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, ty: &mut Ty<'a>) { } } -pub fn walk_view<'a, V: VisitMut<'a>>(visitor: &mut V, view: &mut View<'a>) { +pub fn walk_view(visitor: &mut V, view: &mut View) { visitor.visit_ident(&mut view.name); walk_list!(visitor, visit_arg_kinded, &mut view.gen_args); for v in &mut view.args { @@ -250,7 +250,7 @@ pub fn walk_view<'a, V: VisitMut<'a>>(visitor: &mut V, view: &mut View<'a>) { } } -pub fn walk_pl_expr<'a, V: VisitMut<'a>>(visitor: &mut V, pl_expr: &mut PlaceExpr<'a>) { +pub fn walk_pl_expr(visitor: &mut V, pl_expr: &mut PlaceExpr) { match &mut pl_expr.pl_expr { PlaceExprKind::Ident(ident) => visitor.visit_ident(ident), PlaceExprKind::Deref(pl_expr) => visitor.visit_pl_expr(pl_expr), @@ -276,7 +276,7 @@ pub fn walk_pl_expr<'a, V: VisitMut<'a>>(visitor: &mut V, pl_expr: &mut PlaceExp } } -pub fn walk_arg_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, arg_kinded: &mut ArgKinded<'a>) { +pub fn walk_arg_kinded(visitor: &mut V, arg_kinded: &mut ArgKinded) { match arg_kinded { ArgKinded::Ident(ident) => visitor.visit_ident(ident), ArgKinded::Nat(n) => visitor.visit_nat(n), @@ -286,7 +286,7 @@ pub fn walk_arg_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, arg_kinded: &mut Ar } } -pub fn walk_pattern<'a, V: VisitMut<'a>>(visitor: &mut V, pattern: &mut Pattern<'a>) { +pub fn walk_pattern(visitor: &mut V, pattern: &mut Pattern) { match pattern { Pattern::Ident(mutab, ident) => { visitor.visit_mutability(mutab); @@ -299,7 +299,7 @@ pub fn walk_pattern<'a, V: VisitMut<'a>>(visitor: &mut V, pattern: &mut Pattern< } } -pub fn walk_split<'a, V: VisitMut<'a>>(visitor: &mut V, indep: &mut Split<'a>) { +pub fn walk_split(visitor: &mut V, indep: &mut Split) { let Split { dim_compo, pos, @@ -314,7 +314,7 @@ pub fn walk_split<'a, V: VisitMut<'a>>(visitor: &mut V, indep: &mut Split<'a>) { walk_list!(visitor, visit_expr, branch_bodies); } -pub fn walk_sched<'a, V: VisitMut<'a>>(visitor: &mut V, sched: &mut Sched<'a>) { +pub fn walk_sched(visitor: &mut V, sched: &mut Sched) { let Sched { dim, inner_exec_ident, @@ -329,7 +329,7 @@ pub fn walk_sched<'a, V: VisitMut<'a>>(visitor: &mut V, sched: &mut Sched<'a>) { visitor.visit_block(body); } -pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, expr: &mut Expr<'a>) { +pub fn walk_expr(visitor: &mut V, expr: &mut Expr) { // For now, only visit ExprKind match &mut expr.expr { ExprKind::Lit(l) => visitor.visit_lit(l), @@ -442,7 +442,7 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, expr: &mut Expr<'a>) { } } -pub fn walk_app_kernel<'a, V: VisitMut<'a>>(visitor: &mut V, app_kernel: &mut AppKernel<'a>) { +pub fn walk_app_kernel(visitor: &mut V, app_kernel: &mut AppKernel) { let AppKernel { grid_dim, block_dim, @@ -466,12 +466,12 @@ pub fn walk_app_kernel<'a, V: VisitMut<'a>>(visitor: &mut V, app_kernel: &mut Ap } } -pub fn walk_block<'a, V: VisitMut<'a>>(visitor: &mut V, block: &mut Block<'a>) { +pub fn walk_block(visitor: &mut V, block: &mut Block) { let Block { body, .. } = block; visitor.visit_expr(body); } -pub fn walk_split_proj<'a, V: VisitMut<'a>>(visitor: &mut V, split_proj: &mut TakeRange<'a>) { +pub fn walk_split_proj(visitor: &mut V, split_proj: &mut TakeRange) { let TakeRange { split_dim, pos, @@ -481,14 +481,14 @@ pub fn walk_split_proj<'a, V: VisitMut<'a>>(visitor: &mut V, split_proj: &mut Ta visitor.visit_nat(pos); } -pub fn walk_exec_expr<'a, V: VisitMut<'a>>(visitor: &mut V, exec_expr: &mut ExecExpr<'a>) { +pub fn walk_exec_expr(visitor: &mut V, exec_expr: &mut ExecExpr) { visitor.visit_exec(&mut exec_expr.exec); for t in &mut exec_expr.ty { visitor.visit_exec_ty(t); } } -pub fn walk_exec<'a, V: VisitMut<'a>>(visitor: &mut V, exec: &mut ExecExprKind<'a>) { +pub fn walk_exec(visitor: &mut V, exec: &mut ExecExprKind) { let ExecExprKind { base, path } = exec; match base { BaseExec::CpuThread => (), @@ -503,10 +503,7 @@ pub fn walk_exec<'a, V: VisitMut<'a>>(visitor: &mut V, exec: &mut ExecExprKind<' } } -pub fn walk_exec_path_elem<'a, V: VisitMut<'a>>( - visitor: &mut V, - exec_path_elem: &mut ExecPathElem<'a>, -) { +pub fn walk_exec_path_elem(visitor: &mut V, exec_path_elem: &mut ExecPathElem) { match exec_path_elem { ExecPathElem::TakeRange(split_proj) => visitor.visit_split_proj(split_proj), ExecPathElem::ForAll(dim_compo) => visitor.visit_dim_compo(dim_compo), @@ -515,7 +512,7 @@ pub fn walk_exec_path_elem<'a, V: VisitMut<'a>>( } } -pub fn walk_param_decl<'a, V: VisitMut<'a>>(visitor: &mut V, param_decl: &mut ParamDecl<'a>) { +pub fn walk_param_decl(visitor: &mut V, param_decl: &mut ParamDecl) { let ParamDecl { ident, ty, @@ -532,7 +529,7 @@ pub fn walk_param_decl<'a, V: VisitMut<'a>>(visitor: &mut V, param_decl: &mut Pa } } -pub fn walk_fun_def<'a, V: VisitMut<'a>>(visitor: &mut V, fun_def: &mut FunDef<'a>) { +pub fn walk_fun_def(visitor: &mut V, fun_def: &mut FunDef) { let FunDef { ident: _, generic_params, @@ -554,7 +551,7 @@ pub fn walk_fun_def<'a, V: VisitMut<'a>>(visitor: &mut V, fun_def: &mut FunDef<' visitor.visit_block(body) } -pub fn walk_fun_decl<'a, V: VisitMut<'a>>(visitor: &mut V, fun_decl: &mut FunDecl<'a>) { +pub fn walk_fun_decl(visitor: &mut V, fun_decl: &mut FunDecl) { let FunDecl { ident: _, generic_params, @@ -574,13 +571,13 @@ pub fn walk_fun_decl<'a, V: VisitMut<'a>>(visitor: &mut V, fun_decl: &mut FunDec walk_list!(visitor, visit_prv_rel, prv_rels); } -pub fn walk_param_sig<'a, V: VisitMut<'a>>(visitor: &mut V, param_sig: &mut ParamSig<'a>) { +pub fn walk_param_sig(visitor: &mut V, param_sig: &mut ParamSig) { let ParamSig { exec_expr, ty } = param_sig; visitor.visit_exec_expr(exec_expr); visitor.visit_ty(ty); } -pub fn walk_field<'a, V: VisitMut<'a>>(visitor: &mut V, field: &mut (Ident<'a>, DataTy<'a>)) { +pub fn walk_field(visitor: &mut V, field: &mut (Ident, DataTy)) { let (ident, dty) = field; visitor.visit_ident(ident); visitor.visit_dty(dty); diff --git a/src/codegen/cu_ast.rs b/src/codegen/cu_ast.rs index 0e4320a0..eda2f46e 100644 --- a/src/codegen/cu_ast.rs +++ b/src/codegen/cu_ast.rs @@ -1,4 +1,4 @@ -use crate::ast::Nat; +use crate::arena_ast::Nat; pub(super) enum Item<'a> { Include(String), @@ -115,7 +115,7 @@ pub(super) enum Expr { rhs: Box, }, Lambda { - captures: Vec, + captures: Vec, params: Vec, body: Box, ret_ty: Ty, diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 71931425..1628aa55 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1,9 +1,9 @@ mod cu_ast; mod printer; -use crate::ast as desc; -use crate::ast::visit::Visit; -use crate::ast::visit_mut::VisitMut; +use crate::arena_ast as desc; +use crate::arena_ast::visit::Visit; +use crate::arena_ast::visit_mut::VisitMut; use crate::ty_check; use cu_ast as cu; use std::collections::HashMap; @@ -645,7 +645,7 @@ fn gen_for_each( codegen_ctx: &mut CodegenCtx, ) -> cu::Stmt { todo!(); - let i_name = crate::ast::utils::fresh_name("i__"); + let i_name = crate::arena_ast::utils::fresh_name("i__"); let i_decl = cu::Stmt::VarDecl { name: i_name.clone(), ty: cu::Ty::Scalar(cu::ScalarTy::SizeT), diff --git a/src/codegen/printer.rs b/src/codegen/printer.rs index 8dca7f2a..c845b737 100644 --- a/src/codegen/printer.rs +++ b/src/codegen/printer.rs @@ -2,7 +2,7 @@ use super::cu_ast::{ BinOp, BufferKind, ExecKind, Expr, FnDef, FnSig, GpuAddrSpace, Item, Lit, ParamDecl, ScalarTy, Stmt, TemplParam, TemplateArg, Ty, UnOp, }; -use crate::ast::{BinOpNat, DimCompo, Ident, Nat}; +use crate::arena_ast::{BinOpNat, DimCompo, Ident, Nat}; use std::env; use std::fmt::Formatter; diff --git a/src/lib.rs b/src/lib.rs index 87a0c26d..77626c3a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ extern crate core; use crate::error::ErrorReported; +mod arena_ast; mod ast; mod codegen; pub mod error; diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0149bc5b..efd5f2d0 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -2,103 +2,132 @@ pub mod source; mod utils; +use crate::arena_ast::visit_mut as arena_visit_mut; +use crate::arena_ast::visit_mut::VisitMut as ArenaVisitMut; +use crate::arena_ast::AppKernel as ArenaAppKernel; +use crate::arena_ast::ArgKinded as ArenaArgKinded; +use crate::arena_ast::BaseExec as ArenaBaseExec; +use crate::arena_ast::CompilUnit as ArenaCompilUnit; +use crate::arena_ast::DataTy as ArenaDataTy; +use crate::arena_ast::DataTyKind as ArenaDataTyKind; +use crate::arena_ast::ExecExpr as ArenaExecExpr; +use crate::arena_ast::ExecExprKind as ArenaExecExprKind; +use crate::arena_ast::ExecTyKind as ArenaExecTyKind; +use crate::arena_ast::Expr as ArenaExpr; +use crate::arena_ast::ExprKind as ArenaExprKind; +use crate::arena_ast::FunDef as ArenaFunDef; +use crate::arena_ast::Ident as ArenaIdent; +use crate::arena_ast::IdentKinded as ArenaIdentKinded; +use crate::arena_ast::Item as ArenaItem; +use crate::arena_ast::Kind as ArenaKind; +use crate::arena_ast::LeftOrRight as ArenaLeftOrRight; +use crate::arena_ast::Memory as ArenaMemory; +use crate::arena_ast::Nat as ArenaNat; +use crate::arena_ast::Provenance as ArenaProvenance; +use crate::arena_ast::Sched as ArenaSched; +use crate::arena_ast::Split as ArenaSplit; +use crate::arena_ast::StructDecl as ArenaStructDecl; +use crate::arena_ast::View as ArenaView; use crate::ast::*; + use core::iter; use error::ParseError; use std::collections::HashMap; -use crate::ast::visit_mut::VisitMut; use crate::error::ErrorReported; use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; pub use source::*; -impl<'s> Item<'s> { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> Item<'a> { - match self { - Item::FunDef(boxed) => Item::FunDef(BumpBox::new_in(*boxed, arena)), - Item::FunDecl(boxed) => Item::FunDecl(BumpBox::new_in(*boxed, arena)), - Item::StructDecl(boxed) => Item::StructDecl(BumpBox::new_in(*boxed, arena)), - } - } -} - pub fn parse<'a>( arena: &'a bumpalo::Bump, source: &'a SourceCode<'a>, -) -> Result, ErrorReported> { - let parser = Parser::new(arena, source); - let parsed_items = parser.parse().map_err(|err| err.emit())?; - - // Allocate Items into arena - let mut items = BumpVec::new_in(arena); - for item in parsed_items { - items.push(item.into_arena(arena)); +) -> Result, ErrorReported> { + let parser = Parser::new(source); + let heap_items = parser.parse().map_err(|err| err.emit())?; + + // Step 1: Convert heap AST -> arena AST + let mut arena_items = BumpVec::new_in(arena); + for heap_item in heap_items { + arena_items.push(heap_item.into_arena(arena)) // into arena will be the converter } - // Collect StructDecls - let struct_copies: Vec<&'a StructDecl<'a>> = items + // Step 2: Postprocess + // TODO refactor to not require unnecessary copying out of items + let struct_copies: Vec<&ArenaStructDecl<'_>> = arena_items .iter() - .filter_map(|item| match item { - Item::StructDecl(decl_box) => Some(&**decl_box), - _ => None, + .filter_map(|i| { + if let ArenaItem::StructDecl(struct_dty) = i { + //Some(struct_dty.as_ref()) + Some(struct_dty.as_ref()) + } else { + None + } }) + //.cloned() + //.collect::>(); .collect(); - // Mutate FunDefs - for item in items.iter_mut() { - if let Item::FunDef(fun_def) = item { - replace_arg_kinded_idents(fun_def.as_mut()); - replace_exec_idents_with_specific_execs(arena, fun_def.as_mut()); + for fun_def in arena_items.iter_mut().filter_map(|i| { + if let ArenaItem::FunDef(fun_def) = i { + Some(fun_def) + } else { + None } + }) { + replace_arg_kinded_idents(fun_def); + replace_exec_idents_with_specific_execs(arena, fun_def); } - // Apply struct replacements - for item in &mut items { - replace_struct_idents_with_specific_struct_dtys(&struct_copies, item); + for i in &mut arena_items.iter_mut() { + replace_struct_idents_with_specific_struct_dtys(&struct_copies, i); } - Ok(CompilUnit::new(items, source)) + Ok(ArenaCompilUnit::new(arena_items, source)) } #[derive(Debug)] struct Parser<'a> { - arena: &'a Bump, source: &'a SourceCode<'a>, } impl<'a> Parser<'a> { - fn new(arena: &'a Bump, source: &'a SourceCode<'a>) -> Self { - Parser { arena, source } + fn new(source: &'a SourceCode<'a>) -> Self { + Parser { source } } - fn parse(&self) -> Result>, ParseError<'_>> { + fn parse(&self) -> Result, ParseError<'_>> { descend::compil_unit(self.source.str()).map_err(|peg_err| ParseError::new(self, peg_err)) } } -fn replace_arg_kinded_idents<'a>(fun_def: &mut FunDef) { +fn replace_arg_kinded_idents<'a>(fun_def: &mut ArenaFunDef) { struct ReplaceArgKindedIdents { - ident_names_to_kinds: HashMap, Kind>, + ident_names_to_kinds: HashMap, ArenaKind>, } impl<'a> ReplaceArgKindedIdents { - fn subst_in_gen_args(&self, arena: &'a Bump, gen_args: &mut [ArgKinded<'a>]) { + fn subst_in_gen_args(&self, arena: &'a Bump, gen_args: &mut [ArenaArgKinded<'a>]) { for gen_arg in gen_args { - if let ArgKinded::Ident(ident) = gen_arg { + if let ArenaArgKinded::Ident(ident) = gen_arg { let to_be_kinded = ident.clone(); match self .ident_names_to_kinds .get::(ident.name.as_ref()) .unwrap() { - Kind::Provenance => { - *gen_arg = ArgKinded::Provenance(Provenance::Ident(to_be_kinded)) + ArenaKind::Provenance => { + *gen_arg = + ArenaArgKinded::Provenance(ArenaProvenance::Ident(to_be_kinded)) + } + ArenaKind::Memory => { + *gen_arg = ArenaArgKinded::Memory(ArenaMemory::Ident(to_be_kinded)) + } + ArenaKind::Nat => { + *gen_arg = ArenaArgKinded::Nat(ArenaNat::Ident(to_be_kinded)) } - Kind::Memory => *gen_arg = ArgKinded::Memory(Memory::Ident(to_be_kinded)), - Kind::Nat => *gen_arg = ArgKinded::Nat(Nat::Ident(to_be_kinded)), - Kind::DataTy => { - *gen_arg = ArgKinded::DataTy(DataTy::new( + ArenaKind::DataTy => { + *gen_arg = ArenaArgKinded::DataTy(ArenaDataTy::new( arena, - DataTyKind::Ident(to_be_kinded), + ArenaDataTyKind::Ident(to_be_kinded), )) } } @@ -107,24 +136,24 @@ fn replace_arg_kinded_idents<'a>(fun_def: &mut FunDef) { } } - impl<'a> VisitMut<'a> for ReplaceArgKindedIdents { - fn visit_expr(&mut self, arena: &'a Bump, expr: &mut Expr) { + impl<'a> ArenaVisitMut<'a> for ReplaceArgKindedIdents { + fn visit_expr(&mut self, arena: &'a Bump, expr: &mut ArenaExpr) { match &mut expr.expr { - ExprKind::Block(block) => { + ArenaExprKind::Block(block) => { self.ident_names_to_kinds.extend( block .prvs .iter() - .map(|prv| (prv.clone().into_boxed_str(), Kind::Provenance)), + .map(|prv| (prv.clone().into_boxed_str(), ArenaKind::Provenance)), ); self.visit_expr(&mut block.body) } - ExprKind::DepApp(fun_ident, gen_args) => { + ArenaExprKind::DepApp(fun_ident, gen_args) => { self.visit_ident(fun_ident); self.subst_in_gen_args(arena, gen_args); } - ExprKind::AppKernel(app_kernel) => { - let AppKernel { + ArenaExprKind::AppKernel(app_kernel) => { + let ArenaAppKernel { fun_ident, gen_args, args, @@ -132,38 +161,40 @@ fn replace_arg_kinded_idents<'a>(fun_def: &mut FunDef) { } = app_kernel.as_mut(); self.visit_ident(fun_ident); self.subst_in_gen_args(arena, gen_args); - visit_mut::walk_list!(self, visit_expr, args) + arena_visit_mut::walk_list!(self, visit_expr, args) } - ExprKind::App(fun_ident, gen_args, args) => { + ArenaExprKind::App(fun_ident, gen_args, args) => { self.visit_ident(fun_ident); self.subst_in_gen_args(arena, gen_args); - visit_mut::walk_list!(self, visit_expr, args) + arena_visit_mut::walk_list!(self, visit_expr, args) } - ExprKind::ForNat(ident, _, body) => { + ArenaExprKind::ForNat(ident, _, body) => { self.ident_names_to_kinds.extend(iter::once(( ident.name.to_owned().into_boxed_str(), - Kind::Nat, + ArenaKind::Nat, ))); self.visit_expr(body) } - _ => visit_mut::walk_expr(self, expr), + _ => arena_visit_mut::walk_expr(self, expr), } } - fn visit_view(&mut self, arena: &'a Bump, view: &mut View) { + fn visit_view(&mut self, arena: &'a Bump, view: &mut ArenaView) { self.subst_in_gen_args(arena, &mut view.gen_args); for v in &mut view.args { self.visit_view(v) } } - fn visit_fun_def(&mut self, fun_def: &mut FunDef) { + fn visit_fun_def(&mut self, fun_def: &mut ArenaFunDef) { self.ident_names_to_kinds = fun_def .generic_params .iter() - .map(|IdentKinded { ident, kind }| (ident.name.to_owned().into_boxed_str(), *kind)) + .map(|ArenaIdentKinded { ident, kind }| { + (ident.name.to_owned().into_boxed_str(), *kind) + }) .collect(); - visit_mut::walk_fun_def(self, fun_def) + arena_visit_mut::walk_fun_def(self, fun_def) } } let mut replace = ReplaceArgKindedIdents { @@ -172,30 +203,31 @@ fn replace_arg_kinded_idents<'a>(fun_def: &mut FunDef) { replace.visit_fun_def(fun_def); } -fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut FunDef) { +fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut ArenaFunDef) { struct ReplaceExecIdents<'a> { - ident_names_to_exec_expr: Vec<(Box, ExecExpr<'a>)>, + ident_names_to_exec_expr: Vec<(Box, ArenaExecExpr<'a>)>, } - impl<'a> VisitMut<'a> for ReplaceExecIdents<'a> { - fn visit_split(&mut self, arena: &'a Bump, indep: &mut Split) { + + impl<'a> ArenaVisitMut<'a> for ReplaceExecIdents<'a> { + fn visit_split(&mut self, arena: &'a Bump, indep: &mut ArenaSplit<'a>) { // manually expand to keep scopes for different branches of split - expand_exec_expr(&self.ident_names_to_exec_expr, &mut indep.split_exec); + expand_exec_expr(arena, &self.ident_names_to_exec_expr, &mut indep.split_exec); for (i, (ident, branch)) in indep .branch_idents .iter() .zip(&mut indep.branch_bodies) .enumerate() { - let branch_exec_expr = ExecExpr::new( + let branch_exec_expr = ArenaExecExpr::new( arena, indep.split_exec.exec.clone().split_proj( arena, indep.dim_compo, indep.pos.clone(), if i == 0 { - LeftOrRight::Left + ArenaLeftOrRight::Left } else if i == 1 { - LeftOrRight::Right + ArenaLeftOrRight::Right } else { panic!("Unexpected projection.") }, @@ -208,52 +240,45 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Fu } } - fn visit_sched(&mut self, arena: &'a Bump, sched: &mut Sched) { + fn visit_sched(&mut self, arena: &'a Bump, sched: &mut ArenaSched<'a>) { // manually expand to map inner_exec_ident to expanded exec - expand_exec_expr(&self.ident_names_to_exec_expr, &mut sched.sched_exec); - let body_exec = ExecExpr::new(arena, sched.sched_exec.exec.clone().forall(sched.dim)); + expand_exec_expr(arena, &self.ident_names_to_exec_expr, &mut sched.sched_exec); + let body_exec = + ArenaExecExpr::new(arena, sched.sched_exec.exec.clone().forall(sched.dim)); if let Some(ident) = &sched.inner_exec_ident { self.ident_names_to_exec_expr .push((ident.name.to_owned().into_boxed_str(), body_exec)); } - visit_mut::walk_sched(self, sched); + arena_visit_mut::walk_sched(self, sched); self.ident_names_to_exec_expr.pop(); // self.visit_block(&mut sched.body); } - fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr) { - expand_exec_expr(&self.ident_names_to_exec_expr, exec_expr) + fn visit_exec_expr(&mut self, arena: &'a Bump, exec_expr: &mut ArenaExecExpr<'a>) { + expand_exec_expr(arena, &self.ident_names_to_exec_expr, exec_expr); } - // fn visit_expr(&mut self, expr: &mut Expr) { - // match &mut expr.expr { - // ExprKind::Sync(exec) => { - // for exec in exec { - // expand_exec_expr(&self.ident_names_to_exec_expr, exec); - // } - // } - // _ => visit_mut::walk_expr(self, expr), - // } - // } - - fn visit_fun_def(&mut self, arena: &'a Bump, fun_def: &mut FunDef) { + fn visit_fun_def(&mut self, arena: &'a Bump, fun_def: &mut ArenaFunDef) { if let Some(ident_exec) = fun_def.generic_exec.as_ref() { match &ident_exec.ty.ty { - ExecTyKind::CpuThread => { + ArenaExecTyKind::CpuThread => { self.ident_names_to_exec_expr.push(( ident_exec.ident.name.to_owned().into_boxed_str(), - ExecExpr::new(arena, ExecExprKind::new(arena, BaseExec::CpuThread)), + ArenaExecExpr::new( + arena, + ArenaExecExprKind::new(arena, ArenaBaseExec::CpuThread), + ), )); fun_def.generic_exec = None; } - ExecTyKind::GpuGrid(gdim, bdim) => { + ArenaExecTyKind::GpuGrid(gdim, bdim) => { self.ident_names_to_exec_expr.push(( ident_exec.ident.name.to_owned().into_boxed_str(), - ExecExpr::new( + ArenaExecExpr::new( arena, - ExecExprKind::new( + ArenaExecExprKind::new( arena, - BaseExec::GpuGrid(gdim.clone(), bdim.clone()), + ArenaBaseExec::GpuGrid(gdim.clone(), bdim.clone()), ), ), )); @@ -262,14 +287,18 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Fu _ => {} } } - visit_mut::walk_fun_def(self, fun_def) + arena_visit_mut::walk_fun_def(self, fun_def) } } - fn expand_exec_expr<'a>(exec_mapping: &[(Box, ExecExpr)], exec_expr: &mut ExecExpr<'a>) { + /** + fn expand_exec_expr<'a>( + exec_mapping: &'a [(Box, ArenaExecExpr)], + exec_expr: &mut ArenaExecExpr<'a>, + ) { match &exec_expr.exec.base { - BaseExec::CpuThread | BaseExec::GpuGrid(_, _) => {} - BaseExec::Ident(ident) => { + ArenaBaseExec::CpuThread | ArenaBaseExec::GpuGrid(_, _) => {} + ArenaBaseExec::Ident(ident) => { if let Some(exec) = get_exec_expr(exec_mapping, ident) { let new_base = exec.exec.base.clone(); let mut new_exec_path = exec.exec.path.clone(); @@ -279,12 +308,34 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Fu }; } } + }*/ + + fn expand_exec_expr<'a>( + arena: &'a bumpalo::Bump, + exec_mapping: &'a [(Box, ArenaExecExpr<'a>)], + exec_expr: &ArenaExecExpr<'a>, + ) -> ArenaExecExpr<'a> { + match &exec_expr.exec.base { + ArenaBaseExec::CpuThread | ArenaBaseExec::GpuGrid(_, _) => exec_expr.clone_in(arena), + ArenaBaseExec::Ident(ident) => { + if let Some(mapped_exec) = get_exec_expr(exec_mapping, ident) { + let new_base = mapped_exec.exec.base.clone(); + let mut new_path = BumpVec::new_in(arena); + new_path.extend(mapped_exec.exec.path.iter().cloned()); + new_path.extend(exec_expr.exec.path.iter().cloned()); + + ArenaExecExpr::new(arena, ArenaExecExprKind::with_path(new_base, new_path)) + } else { + exec_expr.clone_in(arena) + } + } + } } fn get_exec_expr<'a>( - exec_mapping: &[(Box, ExecExpr)], - ident: &Ident, - ) -> Option> { + exec_mapping: &'a [(Box, ArenaExecExpr)], + ident: &'a ArenaIdent<'a>, + ) -> Option> { for (i, exec) in exec_mapping.iter().rev() { if i.as_ref() == ident.name { return Some(exec.clone()); @@ -300,32 +351,34 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Fu } fn replace_struct_idents_with_specific_struct_dtys<'a>( - struct_dtys: &[&'a StructDecl<'a>], - item: &mut Item, + struct_dtys: &[&'a ArenaStructDecl<'a>], + item: &mut ArenaItem, ) { struct ReplaceStructIdents<'a> { - struct_dtys: &'a [&'a StructDecl<'a>], + struct_dtys: &'a [&'a ArenaStructDecl<'a>], } - impl<'a> VisitMut<'a> for ReplaceStructIdents<'a> { - fn visit_dty(&mut self, dty: &mut DataTy) { - if let DataTyKind::Ident(ident) = &mut dty.dty { + impl<'a> ArenaVisitMut<'a> for ReplaceStructIdents<'a> { + fn visit_dty(&mut self, dty: &mut ArenaDataTy) { + if let ArenaDataTyKind::Ident(ident) = &mut dty.dty { if let Some(struct_decl) = self.struct_dtys.iter().find(|s| &s.ident == ident) { - dty.dty = DataTyKind::Struct(struct_decl) + dty.dty = ArenaDataTyKind::Struct(struct_decl) } } else { - visit_mut::walk_dty(self, dty) + arena_visit_mut::walk_dty(self, dty) } } } let mut replace_struct_idents = ReplaceStructIdents { struct_dtys }; match item { - Item::FunDef(fun_def) => replace_struct_idents.visit_fun_def(fun_def), - Item::FunDecl(fun_decl) => replace_struct_idents.visit_fun_decl(fun_decl), + ArenaItem::FunDef(fun_def) => replace_struct_idents.visit_fun_def(fun_def), + ArenaItem::FunDecl(fun_decl) => replace_struct_idents.visit_fun_decl(fun_decl), _ => {} } } +// + pub mod error { use crate::error::ErrorReported; use crate::parser::{Parser, SourceCode}; diff --git a/src/parser/utils.rs b/src/parser/utils.rs index 37d8e596..b0f194c9 100644 --- a/src/parser/utils.rs +++ b/src/parser/utils.rs @@ -1,24 +1,21 @@ //! Helper functions for parsing + use crate::ast::{BinOp, BinOpNat, DataTy, DataTyKind, Expr, ExprKind, Lit, Nat, ScalarTy, UnOp}; -use bumpalo::Bump; -pub fn type_from_lit<'a>(bump: &'a Bump, lit: &Lit) -> DataTy<'a> { - DataTy::new( - bump, - DataTyKind::Scalar(match lit { - Lit::Bool(_) => ScalarTy::Bool, - Lit::Unit => ScalarTy::Unit, - Lit::I32(_) => ScalarTy::I32, - Lit::U8(_) => ScalarTy::U8, - Lit::U32(_) => ScalarTy::U32, - Lit::U64(_) => ScalarTy::U64, - Lit::F32(_) => ScalarTy::F32, - Lit::F64(_) => ScalarTy::F64, - }), - ) +pub fn type_from_lit(lit: &Lit) -> DataTy { + DataTy::new(DataTyKind::Scalar(match lit { + Lit::Bool(_) => ScalarTy::Bool, + Lit::Unit => ScalarTy::Unit, + Lit::I32(_) => ScalarTy::I32, + Lit::U8(_) => ScalarTy::U8, + Lit::U32(_) => ScalarTy::U32, + Lit::U64(_) => ScalarTy::U64, + Lit::F32(_) => ScalarTy::F32, + Lit::F64(_) => ScalarTy::F64, + })) } -pub fn make_binary<'a>(bump: &'a Bump, op: BinOp, lhs: Expr<'a>, rhs: Expr<'a>) -> Expr<'a> { +pub fn make_binary(op: BinOp, lhs: Expr, rhs: Expr) -> Expr { // TODO make operators functions? How do we deal with execution resources? // Expr::new(ExprKind::App( // Box::new(Expr::new(ExprKind::PlaceExpr(PlaceExpr::new( @@ -28,17 +25,17 @@ pub fn make_binary<'a>(bump: &'a Bump, op: BinOp, lhs: Expr<'a>, rhs: Expr<'a>) // vec![lhs, rhs], // )) Expr { - expr: ExprKind::BinOp(op, bump.alloc(lhs), bump.alloc(rhs)), + expr: ExprKind::BinOp(op, Box::new(lhs), Box::new(rhs)), ty: None, span: None, } } -pub fn make_binary_nat<'a>(op: BinOpNat, lhs: Nat<'a>, rhs: Nat<'a>) -> Nat<'a> { +pub fn make_binary_nat(op: BinOpNat, lhs: Nat, rhs: Nat) -> Nat { Nat::BinOp(op, Box::new(lhs), Box::new(rhs)) } -pub fn make_unary<'a>(bump: &'a Bump, op: UnOp, rhs: Expr<'a>) -> Expr<'a> { +pub fn make_unary(op: UnOp, rhs: Expr) -> Expr { // TODO see above // Expr::new(ExprKind::App( // Box::new(Expr::new(ExprKind::PlaceExpr(PlaceExpr::new( @@ -48,7 +45,7 @@ pub fn make_unary<'a>(bump: &'a Bump, op: UnOp, rhs: Expr<'a>) -> Expr<'a> { // vec![rhs], // )) Expr { - expr: ExprKind::UnOp(op, bump.alloc(rhs)), + expr: ExprKind::UnOp(op, Box::new(rhs)), ty: None, span: None, } diff --git a/src/ty_check/borrow_check.rs b/src/ty_check/borrow_check.rs index 91c4823a..1c99caea 100644 --- a/src/ty_check/borrow_check.rs +++ b/src/ty_check/borrow_check.rs @@ -1,6 +1,6 @@ use super::ctxs::TyCtx; -use crate::ast::internal::{Loan, PlaceCtx, PrvMapping}; -use crate::ast::*; +use crate::arena_ast::internal::{Loan, PlaceCtx, PrvMapping}; +use crate::arena_ast::*; use crate::parser::descend::nat; use crate::ty_check::ctxs::{AccessCtx, GlobalCtx, KindCtx}; use crate::ty_check::error::BorrowingError; diff --git a/src/ty_check/ctxs.rs b/src/ty_check/ctxs.rs index 3283105c..4418bdf9 100644 --- a/src/ty_check/ctxs.rs +++ b/src/ty_check/ctxs.rs @@ -1,7 +1,7 @@ -use crate::ast::internal::{ +use crate::arena_ast::internal::{ ExecMapping, Frame, FrameEntry, IdentTyped, Loan, PathElem, PrvMapping, }; -use crate::ast::*; +use crate::arena_ast::*; use crate::ty_check::error::CtxError; use std::collections::HashSet; diff --git a/src/ty_check/error.rs b/src/ty_check/error.rs index 69174329..5542e4fa 100644 --- a/src/ty_check/error.rs +++ b/src/ty_check/error.rs @@ -1,7 +1,7 @@ use super::Ty; -use crate::ast::internal::Place; -use crate::ast::printer::PrintState; -use crate::ast::{BaseExec, DataTy, Expr, Ident, NatEvalError, Ownership, PlaceExpr, TyKind}; +use crate::arena_ast::internal::Place; +use crate::arena_ast::printer::PrintState; +use crate::arena_ast::{BaseExec, DataTy, Expr, Ident, NatEvalError, Ownership, PlaceExpr, TyKind}; use crate::error; use crate::error::{default_format, ErrorReported}; use crate::parser::SourceCode; diff --git a/src/ty_check/exec.rs b/src/ty_check/exec.rs index cb031d39..ff8db715 100644 --- a/src/ty_check/exec.rs +++ b/src/ty_check/exec.rs @@ -2,7 +2,7 @@ use super::{ BaseExec, BinOpNat, Dim, Dim1d, Dim2d, DimCompo, ExecExpr, ExecPathElem, ExecTy, ExecTyKind, IdentExec, Nat, TyCtx, TyError, TyResult, }; -use crate::ast::{LeftOrRight, NatCtx}; +use crate::arena_ast::{LeftOrRight, NatCtx}; pub(super) fn ty_check( nat_ctx: &NatCtx, diff --git a/src/ty_check/infer_kinded_args.rs b/src/ty_check/infer_kinded_args.rs index 94bb916c..ce526556 100644 --- a/src/ty_check/infer_kinded_args.rs +++ b/src/ty_check/infer_kinded_args.rs @@ -1,5 +1,5 @@ use super::{TyError, TyResult}; -use crate::ast::{ +use crate::arena_ast::{ ArgKinded, BaseExec, DataTy, DataTyKind, Dim, ExecExpr, ExecTy, ExecTyKind, FnTy, Ident, Memory, Nat, ParamSig, Provenance, Ty, TyKind, }; diff --git a/src/ty_check/mod.rs b/src/ty_check/mod.rs index c2a36e01..3e2bc564 100644 --- a/src/ty_check/mod.rs +++ b/src/ty_check/mod.rs @@ -9,9 +9,9 @@ mod subty; mod unify; use self::pl_expr::PlExprTyCtx; -use crate::ast::internal::{Frame, IdentTyped, Loan, Place, PrvMapping}; -use crate::ast::utils; -use crate::ast::*; +use crate::arena_ast::internal::{Frame, IdentTyped, Loan, Place, PrvMapping}; +use crate::arena_ast::utils; +use crate::arena_ast::*; use crate::error::ErrorReported; use bumpalo::Bump; use ctxs::{AccessCtx, GlobalCtx, KindCtx, TyCtx}; @@ -29,7 +29,7 @@ macro_rules! matches_dty { } }; } -use crate::ast::printer::PrintState; +use crate::arena_ast::printer::PrintState; use crate::ty_check::borrow_check::BorrowCheckCtx; use crate::ty_check::ctxs::GlobalDecl; pub(crate) use matches_dty; diff --git a/src/ty_check/pl_expr.rs b/src/ty_check/pl_expr.rs index 3739792e..062b54fc 100644 --- a/src/ty_check/pl_expr.rs +++ b/src/ty_check/pl_expr.rs @@ -1,7 +1,7 @@ use super::borrow_check::BorrowCheckCtx; use super::error::TyError; use super::TyResult; -use crate::ast::{ +use crate::arena_ast::{ utils, DataTy, DataTyKind, ExecExpr, ExecTyKind, FnTy, Ident, IdentExec, Memory, Nat, NatCtx, Ownership, ParamSig, PlaceExpr, PlaceExprKind, Provenance, Ty, TyKind, View, }; diff --git a/src/ty_check/pre_decl.rs b/src/ty_check/pre_decl.rs index 82f17996..14b816bf 100644 --- a/src/ty_check/pre_decl.rs +++ b/src/ty_check/pre_decl.rs @@ -1,4 +1,4 @@ -use crate::ast::{ +use crate::arena_ast::{ AtomicTy, BaseExec, BinOpNat, DataTy, DataTyKind, DimCompo, ExecExpr, ExecExprKind, ExecTy, ExecTyKind, FnTy, Ident, IdentExec, IdentKinded, Kind, Memory, Nat, NatConstr, Ownership, ParamSig, Provenance, RefDty, ScalarTy, Ty, TyKind, diff --git a/src/ty_check/subty.rs b/src/ty_check/subty.rs index 343095fa..99fe6155 100644 --- a/src/ty_check/subty.rs +++ b/src/ty_check/subty.rs @@ -1,12 +1,12 @@ use super::ctxs::{KindCtx, TyCtx}; -use crate::ast::internal::Loan; +use crate::arena_ast::internal::Loan; // // Subtyping and Provenance Subtyping from Oxide // use super::error::{CtxError, SubTyError}; -use crate::ast::*; +use crate::arena_ast::*; use std::collections::HashSet; type SubTyResult = Result; diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index 5b469759..b625d196 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -1,7 +1,7 @@ -use crate::ast::utils; -use crate::ast::utils::Visitable; -use crate::ast::visit_mut::VisitMut; -use crate::ast::*; +use crate::arena_ast::utils; +use crate::arena_ast::utils::Visitable; +use crate::arena_ast::visit_mut::VisitMut; +use crate::arena_ast::*; use crate::ty_check::ctxs::{KindCtx, TyCtx}; use crate::ty_check::error::UnifyError; use crate::ty_check::subty; From 785bf3652039560d4e9429fc53a112071226b946 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 16 Jul 2025 11:55:15 +0200 Subject: [PATCH 27/57] allocator stuff --- src/arena_ast/mod.rs | 25 +- src/arena_ast/span.rs | 21 - src/ast/mod.rs | 947 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 926 insertions(+), 67 deletions(-) delete mode 100644 src/arena_ast/span.rs diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index 96a8f0d1..3e9ed103 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -3,14 +3,12 @@ use std::fmt; use crate::arena_ast::internal::PathElem; use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; use descend_derive::span_derive; -pub use span::*; +use crate::ast::Span; use crate::parser::SourceCode; - pub mod internal; pub mod printer; -mod span; pub mod utils; pub mod visit; pub mod visit_mut; @@ -752,7 +750,7 @@ impl<'a> PlaceExpr<'a> { } // TODO refactor. Places are only needed during typechecking and codegen - pub fn to_place(&self, arena: &'a bumpalo::Bump) -> Option { + pub fn to_place(&'a self, arena: &'a bumpalo::Bump) -> Option> { if self.is_place() { Some(self.to_pl_ctx_and_most_specif_pl(arena).1) } else { @@ -875,7 +873,6 @@ impl<'a> PlaceExpr<'a> { } } -// Problem with not beeing boxed #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] pub struct ExecExpr<'a> { @@ -1179,7 +1176,7 @@ impl<'a> ParamSig<'a> { } } -#[derive(PartialEq, Eq, Hash, Debug, Clone)] +#[derive(PartialEq, Eq, Hash, Debug)] pub struct FnTy<'a> { pub generics: BumpVec<'a, IdentKinded<'a>>, pub generic_exec: Option>, @@ -1219,13 +1216,13 @@ impl<'a> FnTy<'a> { } } -#[derive(PartialEq, Eq, Hash, Debug, Clone)] +#[derive(PartialEq, Eq, Hash, Debug)] pub enum NatConstr<'a> { True, - Eq(Box>, Box>), - Lt(Box>, Box>), - And(Box>, Box>), - Or(Box>, Box>), + Eq(BumpBox<'a, Nat<'a>>, BumpBox<'a, Nat<'a>>), + Lt(BumpBox<'a, Nat<'a>>, BumpBox<'a, Nat<'a>>), + And(BumpBox<'a, NatConstr<'a>>, BumpBox<'a, NatConstr<'a>>), + Or(BumpBox<'a, NatConstr<'a>>, BumpBox<'a, NatConstr<'a>>), } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1471,7 +1468,7 @@ impl<'a> DataTy<'a> { Scalar(_) | Atomic(_) | Ident(_) | Dead(_) => false, Ref(reff) => { let found_reference = if let Provenance::Value(prv_val_n) = &reff.rgn { - prv_val_name == prv_val_n + prv_val_name == *prv_val_n } else { false }; @@ -1589,7 +1586,7 @@ pub enum AtomicTy { #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum Provenance<'a> { - Value(String), + Value(&'a str), Ident(Ident<'a>), } @@ -1760,7 +1757,7 @@ impl NatCtx { #[derive(Debug)] pub struct NatEvalError<'a> { - unevaluable: Nat<'a>, + pub unevaluable: Nat<'a>, } pub type NatEvalResult<'a, T> = Result>; diff --git a/src/arena_ast/span.rs b/src/arena_ast/span.rs deleted file mode 100644 index 4ca5a53a..00000000 --- a/src/arena_ast/span.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! Components for mapping between sources and AST nodes - -// Can deal with a source file of up to 4 GiB -// Before, this was storing a begin and end position with 64 bits each. The 16 Bytes are too large -// and not necessary. Span is used extensively and the new size of 8 bytes is much more suitable. -#[derive(Clone, Copy, Debug)] -pub struct Span { - pub begin: u32, - // TODO optimize space? by: change to offset from begin which enables u16 or u8 for the offset - // and is still a realistic span - pub end: u32, -} - -impl Span { - pub fn new(begin: usize, end: usize) -> Self { - Self { - begin: u32::try_from(begin).expect("The input source string is unexpectedly large."), - end: u32::try_from(end).expect("The input source string is unexpectedly large."), - } - } -} diff --git a/src/ast/mod.rs b/src/ast/mod.rs index d02ae97c..6cced55c 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -6,7 +6,7 @@ pub use span::*; use crate::arena_ast; use crate::parser::SourceCode; -use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; +use bumpalo::{boxed::Box as BumpBox, collections::CollectIn, collections::Vec as BumpVec, Bump}; pub mod internal; @@ -88,18 +88,32 @@ impl FunDecl { } pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::FunDecl<'a> { + let generic_params = self + .generic_params + .into_iter() + .map(|g| g.into_arena(arena)) + .collect_in(arena); + + let param_decls = self + .param_decls + .into_iter() + .map(|p| p.into_arena(arena)) + .collect_in(arena); + + let prv_rels = self + .prv_rels + .into_iter() + .map(|r| r.into_arena(arena)) + .collect_in(arena); + arena_ast::FunDecl { - ident: self.ident, - generic_params: self.generic_params, - generic_exec: self.generic_exec, - param_decls: self - .param_decls - .into_iter() - .map(|p| p.into_arena(arena)) - .collect(), - ret_dty: BumpBox::new_in(*self.ret_dty, arena), - exec: self.exec, - prv_rels: self.prv_rels, + ident: self.ident.into_arena(arena), + generic_params, + generic_exec: self.generic_exec.map(|g| g.into_arena(arena)), + param_decls, + ret_dty: arena.alloc(self.ret_dty.into_arena(arena)), + exec: self.exec.into_arena(arena), + prv_rels, } } } @@ -113,14 +127,22 @@ pub struct StructDecl { impl StructDecl { pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::StructDecl<'a> { + let generic_params = self + .generic_params + .into_iter() + .map(|gp| gp.into_arena(arena)) + .collect_in(arena); + + let fields = self + .fields + .into_iter() + .map(|(i, dty)| (i.into_arena(arena), dty.into_arena(arena))) + .collect_in(arena); + arena_ast::StructDecl { - ident: self.ident, - generic_params: self.generic_params, - fields: self - .fields - .into_iter() - .map(|(i, dty)| (i, dty.into_arena(arena))) - .collect(), + ident: self.ident.into_arena(arena), + generic_params, + fields, } } } @@ -161,19 +183,39 @@ impl FunDef { } pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::FunDef<'a> { + let generic_params = self + .generic_params + .into_iter() + .map(|g| g.into_arena(arena)) + .collect_in(arena); + + let generic_exec = self.generic_exec.map(|g| g.into_arena(arena)); + + let param_decls = self + .param_decls + .into_iter() + .map(|p| p.into_arena(arena)) + .collect_in(arena); + + let ret_dty = arena.alloc(self.ret_dty.into_arena(arena)); + + let prv_rels = self + .prv_rels + .into_iter() + .map(|r| r.into_arena(arena)) + .collect_in(arena); + + let body = arena.alloc(self.body.into_arena(arena)); + arena_ast::FunDef { - ident: self.ident, - generic_params: self.generic_params, - generic_exec: self.generic_exec, - param_decls: self - .param_decls - .into_iter() - .map(|p| p.into_arena(arena)) - .collect(), - ret_dty: BumpBox::new_in(*self.ret_dty, arena), - exec: self.exec, - prv_rels: self.prv_rels, - body: BumpBox::new_in(*self.body, arena), + ident: self.ident.into_arena(arena), + generic_params, + generic_exec, + param_decls, + ret_dty, + exec: self.exec.into_arena(arena), + prv_rels, + body, } } } @@ -191,6 +233,13 @@ impl IdentExec { ty: Box::new(exec_ty), } } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::IdentExec<'a> { + arena_ast::IdentExec { + ident: self.ident.into_arena(arena), + ty: arena.alloc(self.ty.into_arena(arena)), + } + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -201,6 +250,22 @@ pub struct ParamDecl { pub exec_expr: Option, } +impl ParamDecl { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ParamDecl<'a> { + let ty = self.ty.map(|t| &*arena.alloc(t.into_arena(arena))); + let exec_expr = self + .exec_expr + .map(|e| arena.alloc(e.into_arena(arena)).clone()); + + arena_ast::ParamDecl { + ident: self.ident.into_arena(arena), + ty, + mutbl: self.mutbl.into_arena(), + exec_expr, + } + } +} + #[span_derive(PartialEq)] #[derive(Debug, Clone)] pub struct Expr { @@ -237,6 +302,14 @@ impl Expr { } } + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Expr<'a> { + arena_ast::Expr { + expr: self.expr.into_arena(arena), + ty: self.ty.map(|t| &*arena.alloc(t.into_arena(arena))), + span: self.span, + } + } + // pub fn subst_idents(&mut self, subst_map: &HashMap<&str, &Expr>) { // fn pl_expr_contains_name_in<'a, I>(pl_expr: &PlaceExpr, mut idents: I) -> bool // where @@ -341,6 +414,15 @@ impl Sched { body: Box::new(body), } } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Sched<'a> { + arena_ast::Sched { + dim: self.dim.into_arena(), + inner_exec_ident: self.inner_exec_ident.map(|id| id.into_arena(arena)), + sched_exec: BumpBox::new_in(self.sched_exec.into_arena(arena), arena), + body: BumpBox::new_in(self.body.into_arena(arena), arena), + } + } } #[derive(PartialEq, Debug, Clone)] @@ -368,6 +450,30 @@ impl Split { branch_bodies, } } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Split<'a> { + let mut branch_idents = bumpalo::collections::Vec::new_in(arena); + branch_idents.extend( + self.branch_idents + .into_iter() + .map(|ident| ident.into_arena(arena)), + ); + + let mut branch_bodies = bumpalo::collections::Vec::new_in(arena); + branch_bodies.extend( + self.branch_bodies + .into_iter() + .map(|expr| expr.into_arena(arena)), + ); + + arena_ast::Split { + dim_compo: self.dim_compo.into_arena(), + pos: self.pos.into_arena(arena), + split_exec: arena.alloc(self.split_exec.into_arena(arena)), + branch_idents, + branch_bodies, + } + } } #[derive(PartialEq, Debug, Clone)] @@ -384,6 +490,15 @@ impl Block { } } + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Block<'a> { + let prvs: bumpalo::collections::Vec<'a, String> = self.prvs.into_iter().collect_in(arena); + + arena_ast::Block { + prvs, + body: arena.alloc(self.body.into_arena(arena)), + } + } + pub fn with_prvs(prvs: Vec, body: Expr) -> Self { Block { prvs, @@ -403,6 +518,36 @@ pub struct AppKernel { pub args: Vec, } +impl AppKernel { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::AppKernel<'a> { + arena_ast::AppKernel { + grid_dim: self.grid_dim.into_arena(arena), + block_dim: self.block_dim.into_arena(arena), + shared_mem_dtys: self + .shared_mem_dtys + .iter() + .map(|dty| dty.clone().into_arena(arena)) + .collect_in(arena), + shared_mem_prvs: self + .shared_mem_prvs + .iter() + .map(|s| arena.alloc_str(s).to_string()) + .collect_in(arena), + fun_ident: BumpBox::new_in(self.fun_ident.clone().into_arena(arena), arena), + gen_args: self + .gen_args + .iter() + .map(|arg| arg.into_arena(arena)) + .collect_in(arena), + args: self + .args + .iter() + .map(|arg| arg.clone().into_arena(arena)) + .collect_in(arena), + } + } +} + #[derive(PartialEq, Debug, Clone)] pub enum ExprKind { Hole, @@ -461,6 +606,122 @@ pub enum ExprKind { Range(Box, Box), } +impl ExprKind { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExprKind<'a> { + use ExprKind::*; + match self { + Hole => arena_ast::ExprKind::Hole, + Lit(l) => arena_ast::ExprKind::Lit(l), // assuming `Lit` is Copy or doesn't need arena + PlaceExpr(p) => arena_ast::ExprKind::PlaceExpr(arena.alloc(p.into_arena(arena))), + Array(exprs) => { + let mut bump_vec = bumpalo::collections::Vec::new_in(arena); + for e in exprs { + bump_vec.push(e.into_arena(arena)); + } + arena_ast::ExprKind::Array(bump_vec) + } + Tuple(exprs) => { + let mut bump_vec = bumpalo::collections::Vec::new_in(arena); + for e in exprs { + bump_vec.push(e.into_arena(arena)); + } + arena_ast::ExprKind::Tuple(bump_vec) + } + Ref(ann, own, pl) => { + arena_ast::ExprKind::Ref(ann, own.into_arena(), arena.alloc(pl.into_arena(arena))) + } + Block(b) => arena_ast::ExprKind::Block(&b.into_arena(arena)), + LetUninit(exec, ident, ty) => arena_ast::ExprKind::LetUninit( + exec.map(|e| arena.alloc(e.into_arena(arena))).as_deref(), + ident.into_arena(arena), + arena.alloc(ty.into_arena(arena)), + ), + Let(pat, ty, expr) => arena_ast::ExprKind::Let( + pat.into_arena(arena), + ty.map(|t| arena.alloc(t.into_arena(arena))).as_deref(), + arena.alloc(expr.into_arena(arena)), + ), + Assign(pl, val) => arena_ast::ExprKind::Assign( + arena.alloc(pl.into_arena(arena)), + arena.alloc(val.into_arena(arena)), + ), + IdxAssign(pl, nat, val) => arena_ast::ExprKind::IdxAssign( + arena.alloc(pl.into_arena(arena)), + nat.into_arena(arena), + arena.alloc(val.into_arena(arena)), + ), + Seq(exprs) => arena_ast::ExprKind::Seq( + exprs + .into_iter() + .map(|e| e.into_arena(arena)) + .collect_in(arena), + ), + App(ident, args, exprs) => arena_ast::ExprKind::App( + arena.alloc(ident.into_arena(arena)), + args.into_iter() + .map(|a| a.into_arena(arena)) + .collect_in(arena), + exprs + .into_iter() + .map(|e| e.into_arena(arena)) + .collect_in(arena), + ), + DepApp(ident, args) => arena_ast::ExprKind::DepApp( + ident.into_arena(arena), + args.into_iter() + .map(|a| a.into_arena(arena)) + .collect_in(arena), + ), + ExprKind::AppKernel(kern) => arena_ast::ExprKind::AppKernel( + bumpalo::boxed::Box::new_in(kern.into_arena(arena), arena), + ), + IfElse(cond, then_, else_) => arena_ast::ExprKind::IfElse( + arena.alloc(cond.into_arena(arena)), + arena.alloc(then_.into_arena(arena)), + arena.alloc(else_.into_arena(arena)), + ), + If(cond, body) => arena_ast::ExprKind::If( + arena.alloc(cond.into_arena(arena)), + arena.alloc(body.into_arena(arena)), + ), + For(ident, iter, body) => arena_ast::ExprKind::For( + ident.into_arena(arena), + arena.alloc(iter.into_arena(arena)), + arena.alloc(body.into_arena(arena)), + ), + ForNat(ident, range, body) => arena_ast::ExprKind::ForNat( + ident.into_arena(arena), + arena.alloc(range.into_arena(arena)), + arena.alloc(body.into_arena(arena)), + ), + While(cond, body) => arena_ast::ExprKind::While( + arena.alloc(cond.into_arena(arena)), + arena.alloc(body.into_arena(arena)), + ), + BinOp(op, lhs, rhs) => arena_ast::ExprKind::BinOp( + op.into_arena(), + arena.alloc(lhs.into_arena(arena)), + arena.alloc(rhs.into_arena(arena)), + ), + UnOp(op, expr) => { + arena_ast::ExprKind::UnOp(op.into_arena(), arena.alloc(expr.into_arena(arena))) + } + Cast(expr, dty) => arena_ast::ExprKind::Cast( + arena.alloc(expr.into_arena(arena)), + arena.alloc(dty.into_arena(arena)), + ), + Split(split) => arena_ast::ExprKind::Split(arena.alloc(split.into_arena(arena))), + Sched(sched) => arena_ast::ExprKind::Sched(arena.alloc(sched.into_arena(arena))), + Sync(exec_opt) => arena_ast::ExprKind::Sync(exec_opt.map(|e| e.into_arena(arena))), + Unsafe(expr) => arena_ast::ExprKind::Unsafe(arena.alloc(expr.into_arena(arena))), + Range(start, end) => arena_ast::ExprKind::Range( + arena.alloc(start.into_arena(arena)), + arena.alloc(end.into_arena(arena)), + ), + } + } +} + #[span_derive(PartialEq, Eq, Hash)] #[derive(Clone, Debug)] pub struct Ident { @@ -496,6 +757,14 @@ impl Ident { is_implicit: false, } } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Ident<'a> { + arena_ast::Ident { + name: arena.alloc_str(&self.name), + span: self.span, + is_implicit: self.is_implicit, + } + } } #[derive(Debug, Clone, PartialEq)] @@ -505,6 +774,23 @@ pub enum Pattern { Wildcard, } +impl Pattern { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Pattern<'a> { + use Pattern::*; + match self { + Ident(mutability, ident) => { + arena_ast::Pattern::Ident(mutability.into_arena(), ident.clone().into_arena(arena)) + } + Tuple(pats) => { + let arena_vec: bumpalo::collections::Vec<'a, _> = + pats.iter().map(|p| p.into_arena(arena)).collect_in(arena); + arena_ast::Pattern::Tuple(arena_vec) + } + Wildcard => arena_ast::Pattern::Wildcard, + } + } +} + #[derive(Debug, Copy, Clone, PartialEq)] pub enum Lit { Unit, @@ -517,6 +803,24 @@ pub enum Lit { F64(f64), } +impl Lit { + pub fn into_arena<'a>(&self, _arena: &'a bumpalo::Bump) -> arena_ast::Lit { + use arena_ast::Lit as ALit; + use Lit::*; + + match self { + Unit => ALit::Unit, + Bool(b) => ALit::Bool(*b), + I32(i) => ALit::I32(*i), + U8(u) => ALit::U8(*u), + U32(u) => ALit::U32(*u), + U64(u) => ALit::U64(*u), + F32(f) => ALit::F32(*f), + F64(f) => ALit::F64(*f), + } + } +} + // impl PartialEq for Lit{ // fn eq(&self, other:&Self) -> bool { // let b = match (self, other) { @@ -551,6 +855,15 @@ pub enum Mutability { Mut, } +impl Mutability { + pub fn into_arena(&self) -> arena_ast::Mutability { + match self { + Mutability::Mut => arena_ast::Mutability::Mut, + Mutability::Const => arena_ast::Mutability::Const, + } + } +} + impl fmt::Display for Mutability { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let str = match self { @@ -567,12 +880,30 @@ pub enum Ownership { Uniq, } +impl Ownership { + pub fn into_arena(&self) -> arena_ast::Ownership { + match self { + Ownership::Shrd => arena_ast::Ownership::Shrd, + Ownership::Uniq => arena_ast::Ownership::Uniq, + } + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum UnOp { Not, Neg, } +impl UnOp { + pub fn into_arena(&self) -> arena_ast::UnOp { + match self { + UnOp::Not => arena_ast::UnOp::Not, + UnOp::Neg => arena_ast::UnOp::Neg, + } + } +} + impl fmt::Display for UnOp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let str = match self { @@ -604,6 +935,30 @@ pub enum BinOp { BitAnd, } +impl BinOp { + pub fn into_arena(&self) -> arena_ast::BinOp { + match self { + BinOp::Add => arena_ast::BinOp::Add, + BinOp::Sub => arena_ast::BinOp::Sub, + BinOp::Mul => arena_ast::BinOp::Mul, + BinOp::Div => arena_ast::BinOp::Div, + BinOp::Mod => arena_ast::BinOp::Mod, + BinOp::And => arena_ast::BinOp::And, + BinOp::Or => arena_ast::BinOp::Or, + BinOp::Eq => arena_ast::BinOp::Eq, + BinOp::Lt => arena_ast::BinOp::Lt, + BinOp::Le => arena_ast::BinOp::Le, + BinOp::Gt => arena_ast::BinOp::Gt, + BinOp::Ge => arena_ast::BinOp::Ge, + BinOp::Neq => arena_ast::BinOp::Neq, + BinOp::Shl => arena_ast::BinOp::Shl, + BinOp::Shr => arena_ast::BinOp::Shr, + BinOp::BitOr => arena_ast::BinOp::BitOr, + BinOp::BitAnd => arena_ast::BinOp::BitAnd, + } + } +} + impl fmt::Display for BinOp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let str = match self { @@ -637,6 +992,17 @@ pub enum Kind { Provenance, } +impl Kind { + pub fn into_arena(&self, _arena: &bumpalo::Bump) -> arena_ast::Kind { + match self { + Kind::Nat => arena_ast::Kind::Nat, + Kind::Memory => arena_ast::Kind::Memory, + Kind::DataTy => arena_ast::Kind::DataTy, + Kind::Provenance => arena_ast::Kind::Provenance, + } + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ArgKinded { Ident(Ident), @@ -669,6 +1035,18 @@ impl ArgKinded { _ => Ok(false), } } + + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::ArgKinded<'a> { + use ArgKinded::*; + + match self { + Ident(ident) => arena_ast::ArgKinded::Ident(ident.clone().into_arena(arena)), + Nat(nat) => arena_ast::ArgKinded::Nat(nat.into_arena(arena)), + Memory(mem) => arena_ast::ArgKinded::Memory(mem.into_arena(arena)), + DataTy(dty) => arena_ast::ArgKinded::DataTy(dty.clone().into_arena(arena)), + Provenance(prv) => arena_ast::ArgKinded::Provenance(prv.into_arena(arena)), + } + } } #[span_derive(PartialEq, Eq, Hash)] @@ -682,6 +1060,16 @@ pub struct PlaceExpr { pub span: Option, } +impl PlaceExpr { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::PlaceExpr<'a> { + arena_ast::PlaceExpr { + pl_expr: self.pl_expr.into_arena(arena), + ty: self.ty.map(|t| &*arena.alloc(t.into_arena(arena))), + span: self.span, + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub struct View { pub name: Ident, @@ -712,6 +1100,26 @@ impl View { } Ok(true) } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::View<'a> { + let gen_args = self + .gen_args + .into_iter() + .map(|g| g.into_arena(arena)) + .collect_in(arena); + + let args = self + .args + .into_iter() + .map(|v| v.into_arena(arena)) + .collect_in(arena); + + arena_ast::View { + name: self.name.into_arena(arena), + gen_args, + args, + } + } } // TODO create generic View struct to enable easier extensibility by introducing only @@ -744,6 +1152,34 @@ pub enum PlaceExprKind { Ident(Ident), } +impl PlaceExprKind { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::PlaceExprKind<'a> { + use PlaceExprKind::*; + + match self { + View(pl, view) => arena_ast::PlaceExprKind::View( + arena.alloc(pl.into_arena(arena)), + arena.alloc(view.into_arena(arena)), + ), + Select(pl, exec) => arena_ast::PlaceExprKind::Select( + arena.alloc(pl.into_arena(arena)), + arena.alloc(exec.into_arena(arena)), + ), + Proj(pl, idx) => arena_ast::PlaceExprKind::Proj(arena.alloc(pl.into_arena(arena)), idx), + FieldProj(pl, ident) => arena_ast::PlaceExprKind::FieldProj( + arena.alloc(pl.into_arena(arena)), + arena.alloc(ident.into_arena(arena)), + ), + Deref(pl) => arena_ast::PlaceExprKind::Deref(arena.alloc(pl.into_arena(arena))), + Idx(pl, nat) => arena_ast::PlaceExprKind::Idx( + arena.alloc(pl.into_arena(arena)), + arena.alloc(nat.into_arena(arena)), + ), + Ident(ident) => arena_ast::PlaceExprKind::Ident(ident.into_arena(arena)), + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum PlExprPathElem { View(View), @@ -912,6 +1348,17 @@ impl ExecExpr { } } + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExecExpr<'a> { + arena_ast::ExecExpr { + exec: arena.alloc(self.exec.into_arena(arena)), + ty: self.ty.map(|t| { + let tmp: &mut arena_ast::ExecTy<'a> = arena.alloc(t.into_arena(arena)); + &*tmp + }), + span: self.span, + } + } + // TODO how does this relate to is_prefix_of. Refactor. pub fn is_sub_exec_of(&self, exec: &ExecExpr) -> bool { if self.exec.path.len() > exec.exec.path.len() { @@ -1004,6 +1451,15 @@ pub enum LeftOrRight { Right, } +impl LeftOrRight { + pub fn into_arena(self) -> crate::arena_ast::LeftOrRight { + match self { + LeftOrRight::Left => crate::arena_ast::LeftOrRight::Left, + LeftOrRight::Right => crate::arena_ast::LeftOrRight::Right, + } + } +} + impl fmt::Display for LeftOrRight { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -1028,6 +1484,14 @@ impl TakeRange { left_or_right: proj, } } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::TakeRange<'a> { + arena_ast::TakeRange { + split_dim: self.split_dim.into_arena(), + pos: self.pos.into_arena(arena), + left_or_right: self.left_or_right.into_arena(), + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1066,6 +1530,18 @@ impl ExecExprKind { } None } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExecExprKind<'a> { + let path = bumpalo::collections::Vec::from_iter_in( + self.path.into_iter().map(|elem| elem.into_arena(arena)), + arena, + ); + + arena_ast::ExecExprKind { + base: self.base.into_arena(arena), + path, + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1075,6 +1551,19 @@ pub enum BaseExec { GpuGrid(Dim, Dim), } +impl BaseExec { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::BaseExec<'a> { + use BaseExec::*; + match self { + Ident(ident) => arena_ast::BaseExec::Ident(ident.into_arena(arena)), + CpuThread => arena_ast::BaseExec::CpuThread, + GpuGrid(d1, d2) => { + arena_ast::BaseExec::GpuGrid(d1.into_arena(arena), d2.into_arena(arena)) + } + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum ExecPathElem { TakeRange(Box), @@ -1083,6 +1572,22 @@ pub enum ExecPathElem { ToThreads(DimCompo), } +impl ExecPathElem { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExecPathElem<'a> { + use ExecPathElem::*; + + match self { + TakeRange(take_range) => { + let arena_take_range = arena.alloc(take_range.clone().into_arena(arena)); + arena_ast::ExecPathElem::TakeRange(arena_take_range) + } + ForAll(dim_compo) => arena_ast::ExecPathElem::ForAll(dim_compo.into_arena()), + ToWarps => arena_ast::ExecPathElem::ToWarps, + ToThreads(dim_compo) => arena_ast::ExecPathElem::ToThreads(dim_compo.into_arena()), + } + } +} + // ExecTy // fn size(DimCompo) -> usize // fn take_range(DimCompo, Nat) -> ExecTy @@ -1102,6 +1607,13 @@ impl ExecTy { span: None, } } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExecTy<'a> { + arena_ast::ExecTy { + ty: self.ty.into_arena(arena), + span: self.span, + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1118,6 +1630,32 @@ pub enum ExecTyKind { Any, } +impl ExecTyKind { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::ExecTyKind<'a> { + use ExecTyKind::*; + + match self { + CpuThread => arena_ast::ExecTyKind::CpuThread, + GpuThread => arena_ast::ExecTyKind::GpuThread, + GpuWarp => arena_ast::ExecTyKind::GpuWarp, + GpuBlock(dim) => arena_ast::ExecTyKind::GpuBlock(dim.into_arena(arena)), + GpuGrid(d1, d2) => { + arena_ast::ExecTyKind::GpuGrid(d1.into_arena(arena), d2.into_arena(arena)) + } + GpuToThreads(dim, inner) => arena_ast::ExecTyKind::GpuToThreads( + dim.into_arena(arena), + arena.alloc(inner.clone().into_arena(arena)), + ), + GpuThreadGrp(dim) => arena_ast::ExecTyKind::GpuThreadGrp(dim.into_arena(arena)), + GpuWarpGrp(nat) => arena_ast::ExecTyKind::GpuWarpGrp(nat.into_arena(arena)), + GpuBlockGrp(d1, d2) => { + arena_ast::ExecTyKind::GpuBlockGrp(d1.into_arena(arena), d2.into_arena(arena)) + } + Any => arena_ast::ExecTyKind::Any, + } + } +} + #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] pub struct Ty { @@ -1126,6 +1664,15 @@ pub struct Ty { pub span: Option, } +impl Ty { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Ty<'a> { + arena_ast::Ty { + ty: self.ty.into_arena(arena), + span: self.span, + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub struct ParamSig { pub exec_expr: ExecExpr, @@ -1136,6 +1683,14 @@ impl ParamSig { pub fn new(exec_expr: ExecExpr, ty: Ty) -> Self { ParamSig { exec_expr, ty } } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ParamSig<'a> { + let ty = self.ty.into_arena(arena); + arena_ast::ParamSig { + exec_expr: self.exec_expr.into_arena(arena), + ty: arena.alloc(ty), + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1166,6 +1721,37 @@ impl FnTy { nat_constrs, } } + + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::FnTy<'a> { + let generics = self + .generics + .into_iter() + .map(|g| g.into_arena(arena)) + .collect_in(arena); + + let generic_exec = self.generic_exec.map(|g| g.into_arena(arena)); + + let param_sigs = self + .param_sigs + .into_iter() + .map(|p| p.into_arena(arena)) + .collect_in(arena); + + let nat_constrs = self + .nat_constrs + .into_iter() + .map(|c| c.into_arena(arena)) + .collect_in(arena); + + arena_ast::FnTy { + generics, + generic_exec, + param_sigs, + exec: self.exec.into_arena(arena), + ret_ty: arena.alloc(self.ret_ty.into_arena(arena)), + nat_constrs, + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1177,6 +1763,32 @@ pub enum NatConstr { Or(Box, Box), } +impl NatConstr { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::NatConstr<'a> { + use NatConstr::*; + + match self { + True => arena_ast::NatConstr::True, + Eq(lhs, rhs) => arena_ast::NatConstr::Eq( + bumpalo::boxed::Box::new_in(lhs.into_arena(arena), arena), + bumpalo::boxed::Box::new_in(rhs.into_arena(arena), arena), + ), + Lt(lhs, rhs) => arena_ast::NatConstr::Lt( + bumpalo::boxed::Box::new_in(lhs.into_arena(arena), arena), + bumpalo::boxed::Box::new_in(rhs.into_arena(arena), arena), + ), + And(lhs, rhs) => arena_ast::NatConstr::And( + bumpalo::boxed::Box::new_in(lhs.into_arena(arena), arena), + bumpalo::boxed::Box::new_in(rhs.into_arena(arena), arena), + ), + Or(lhs, rhs) => arena_ast::NatConstr::Or( + bumpalo::boxed::Box::new_in(lhs.into_arena(arena), arena), + bumpalo::boxed::Box::new_in(rhs.into_arena(arena), arena), + ), + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum TyKind { Data(Box), @@ -1184,12 +1796,35 @@ pub enum TyKind { FnTy(Box), } +impl TyKind { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::TyKind<'a> { + match self { + TyKind::Data(dty) => { + let boxed = bumpalo::boxed::Box::new_in(dty.into_arena(arena), arena); + arena_ast::TyKind::Data(arena.alloc(boxed)) + } + TyKind::FnTy(fn_ty) => { + let boxed = bumpalo::boxed::Box::new_in(fn_ty.into_arena(arena), arena); + arena_ast::TyKind::FnTy(arena.alloc(boxed)) + } + } + } +} + // TODO remove #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub enum Constraint { Copyable, } +impl Constraint { + pub fn into_arena(&self) -> arena_ast::Constraint { + match self { + Constraint::Copyable => arena_ast::Constraint::Copyable, + } + } +} + impl Ty { pub fn new(ty: TyKind) -> Self { Ty { ty, span: None } @@ -1281,6 +1916,33 @@ impl Dim { _ => Ok(false), } } + + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Dim<'a> { + use Dim::*; + + match self { + XYZ(boxed) => arena_ast::Dim::XYZ(arena.alloc(arena_ast::Dim3d( + boxed.0.into_arena(arena), + boxed.1.into_arena(arena), + boxed.2.into_arena(arena), + ))), + XY(boxed) => arena_ast::Dim::XY(arena.alloc(arena_ast::Dim2d( + boxed.0.into_arena(arena), + boxed.1.into_arena(arena), + ))), + XZ(boxed) => arena_ast::Dim::XZ(arena.alloc(arena_ast::Dim2d( + boxed.0.into_arena(arena), + boxed.1.into_arena(arena), + ))), + YZ(boxed) => arena_ast::Dim::YZ(arena.alloc(arena_ast::Dim2d( + boxed.0.into_arena(arena), + boxed.1.into_arena(arena), + ))), + X(boxed) => arena_ast::Dim::X(arena.alloc(arena_ast::Dim1d(boxed.0.into_arena(arena)))), + Y(boxed) => arena_ast::Dim::Y(arena.alloc(arena_ast::Dim1d(boxed.0.into_arena(arena)))), + Z(boxed) => arena_ast::Dim::Z(arena.alloc(arena_ast::Dim1d(boxed.0.into_arena(arena)))), + } + } } #[derive(PartialEq, Eq, PartialOrd, Hash, Debug, Copy, Clone)] @@ -1290,6 +1952,16 @@ pub enum DimCompo { Z, } +impl DimCompo { + pub fn into_arena(self) -> crate::arena_ast::DimCompo { + match self { + DimCompo::X => crate::arena_ast::DimCompo::X, + DimCompo::Y => crate::arena_ast::DimCompo::Y, + DimCompo::Z => crate::arena_ast::DimCompo::Z, + } + } +} + #[span_derive(PartialEq, Eq, Hash)] #[derive(Debug, Clone)] pub struct DataTy { @@ -1309,6 +1981,18 @@ impl DataTy { } } + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::DataTy<'a> { + arena_ast::DataTy { + dty: self.dty.into_arena(arena), + constraints: self + .constraints + .into_iter() + .map(|c| c.into_arena()) + .collect_in(arena), + span: self.span, + } + } + pub fn with_constr(dty: DataTyKind, constraints: Vec) -> Self { DataTy { dty, @@ -1478,6 +2162,15 @@ impl RefDty { dty: Box::new(dty), } } + + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::RefDty<'a> { + arena_ast::RefDty { + rgn: self.rgn.into_arena(arena), + own: self.own.into_arena(), + mem: self.mem.into_arena(arena), + dty: arena.alloc(self.dty.clone().into_arena(arena)), + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1499,6 +2192,56 @@ pub enum DataTyKind { Dead(Box), } +impl DataTyKind { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::DataTyKind<'a> { + use DataTyKind::*; + + match self { + Ident(ident) => arena_ast::DataTyKind::Ident(ident.clone().into_arena(arena)), + Scalar(sty) => arena_ast::DataTyKind::Scalar(sty.into_arena()), + Atomic(aty) => arena_ast::DataTyKind::Atomic(aty.into_arena()), + + Array(dty, nat) => arena_ast::DataTyKind::Array( + arena.alloc(dty.clone().into_arena(arena)), + nat.into_arena(arena), + ), + + ArrayShape(dty, nat) => arena_ast::DataTyKind::ArrayShape( + arena.alloc(dty.clone().into_arena(arena)), + nat.into_arena(arena), + ), + + Tuple(elem_dtys) => { + let arena_vec = bumpalo::collections::Vec::from_iter_in( + elem_dtys.iter().map(|dty| dty.clone().into_arena(arena)), + arena, + ); + arena_ast::DataTyKind::Tuple(arena_vec) + } + + Struct(decl) => { + arena_ast::DataTyKind::Struct(arena.alloc(decl.clone().into_arena(arena))) + } + + At(dty, mem) => arena_ast::DataTyKind::At( + arena.alloc(dty.clone().into_arena(arena)), + mem.into_arena(arena), + ), + + Ref(refdty) => { + let refdty_in = arena.alloc(refdty.into_arena(arena)); + arena_ast::DataTyKind::Ref(refdty_in) + } + + RawPtr(dty) => { + arena_ast::DataTyKind::RawPtr(arena.alloc(dty.clone().into_arena(arena))) + } + + Dead(dty) => arena_ast::DataTyKind::Dead(arena.alloc(dty.clone().into_arena(arena))), + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] pub enum ScalarTy { Unit, @@ -1513,18 +2256,55 @@ pub enum ScalarTy { Gpu, } +impl ScalarTy { + pub fn into_arena(self) -> arena_ast::ScalarTy { + match self { + ScalarTy::Unit => arena_ast::ScalarTy::Unit, + ScalarTy::U8 => arena_ast::ScalarTy::U8, + ScalarTy::U32 => arena_ast::ScalarTy::U32, + ScalarTy::U64 => arena_ast::ScalarTy::U64, + ScalarTy::I32 => arena_ast::ScalarTy::I32, + ScalarTy::I64 => arena_ast::ScalarTy::I64, + ScalarTy::F32 => arena_ast::ScalarTy::F32, + ScalarTy::F64 => arena_ast::ScalarTy::F64, + ScalarTy::Bool => arena_ast::ScalarTy::Bool, + ScalarTy::Gpu => arena_ast::ScalarTy::Gpu, + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] pub enum AtomicTy { AtomicU32, AtomicI32, } +impl AtomicTy { + pub fn into_arena(self) -> arena_ast::AtomicTy { + match self { + AtomicTy::AtomicU32 => arena_ast::AtomicTy::AtomicU32, + AtomicTy::AtomicI32 => arena_ast::AtomicTy::AtomicI32, + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum Provenance { Value(String), Ident(Ident), } +impl Provenance { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Provenance<'a> { + match self { + Provenance::Value(s) => arena_ast::Provenance::Value(arena.alloc_str(s)), + Provenance::Ident(ident) => { + arena_ast::Provenance::Ident(ident.clone().into_arena(arena)) + } + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum Memory { CpuMem, @@ -1534,12 +2314,33 @@ pub enum Memory { Ident(Ident), } +impl Memory { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Memory<'a> { + match self { + Memory::CpuMem => arena_ast::Memory::CpuMem, + Memory::GpuGlobal => arena_ast::Memory::GpuGlobal, + Memory::GpuShared => arena_ast::Memory::GpuShared, + Memory::GpuLocal => arena_ast::Memory::GpuLocal, + Memory::Ident(ident) => arena_ast::Memory::Ident(ident.clone().into_arena(arena)), + } + } +} + #[derive(PartialEq, Eq, Debug, Clone)] pub struct PrvRel { pub longer: Ident, pub shorter: Ident, } +impl PrvRel { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::PrvRel<'a> { + arena_ast::PrvRel { + longer: self.longer.clone().into_arena(arena), + shorter: self.shorter.clone().into_arena(arena), + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub struct IdentKinded { pub ident: Ident, @@ -1553,6 +2354,13 @@ impl IdentKinded { kind, } } + + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::IdentKinded<'a> { + arena_ast::IdentKinded { + ident: self.ident.clone().into_arena(arena), + kind: self.kind.into_arena(arena), + } + } } #[derive(PartialEq, Eq, Debug, Clone)] @@ -1581,6 +2389,23 @@ impl NatRange { }; Ok(range_iter) } + + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::NatRange<'a> { + use NatRange::*; + + match self { + Simple { lower, upper } => arena_ast::NatRange::Simple { + lower: lower.into_arena(arena), + upper: upper.into_arena(arena), + }, + Halved { upper } => arena_ast::NatRange::Halved { + upper: upper.into_arena(arena), + }, + Doubled { upper } => arena_ast::NatRange::Doubled { + upper: upper.into_arena(arena), + }, + } + } } pub struct NatRangeIter { @@ -1688,12 +2513,58 @@ impl NatCtx { #[derive(Debug)] pub struct NatEvalError { - unevaluable: Nat, + pub unevaluable: Nat, +} + +impl NatEvalError { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::NatEvalError<'a> { + arena_ast::NatEvalError { + unevaluable: self.unevaluable.clone().into_arena(arena), + } + } } pub type NatEvalResult = Result; +fn convert_result<'a>( + result: NatEvalResult, + arena: &'a bumpalo::Bump, +) -> arena_ast::NatEvalResult<'a, usize> { + result.map_err(|e| e.into_arena(arena)) +} + impl Nat { + pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Nat<'a> { + use Nat::*; + + match self { + Ident(ident) => arena_ast::Nat::Ident(ident.clone().into_arena(arena)), + + Lit(n) => arena_ast::Nat::Lit(*n), + + ThreadIdx(dc) => arena_ast::Nat::ThreadIdx((*dc).into_arena()), + BlockIdx(dc) => arena_ast::Nat::BlockIdx((*dc).into_arena()), + BlockDim(dc) => arena_ast::Nat::BlockDim((*dc).into_arena()), + + WarpGrpIdx => arena_ast::Nat::WarpGrpIdx, + WarpIdx => arena_ast::Nat::WarpIdx, + LaneIdx => arena_ast::Nat::LaneIdx, + GridIdx => arena_ast::Nat::GridIdx, + + BinOp(op, lhs, rhs) => arena_ast::Nat::BinOp( + op.clone().into_arena(), + Box::new(lhs.into_arena(arena)), + Box::new(rhs.into_arena(arena)), + ), + + App(ident, args) => { + let new_args: Vec<_> = args.iter().map(|n| n.into_arena(arena)).collect(); + let boxed_slice: Box<[arena_ast::Nat<'a>]> = new_args.into_boxed_slice(); + arena_ast::Nat::App(ident.clone().into_arena(arena), boxed_slice) + } + } + } + pub fn eval(&self, nat_ctx: &NatCtx) -> NatEvalResult { match self { Nat::GridIdx @@ -1736,6 +2607,18 @@ pub enum BinOpNat { Mod, } +impl BinOpNat { + pub fn into_arena(self) -> crate::arena_ast::BinOpNat { + match self { + BinOpNat::Add => crate::arena_ast::BinOpNat::Add, + BinOpNat::Sub => crate::arena_ast::BinOpNat::Sub, + BinOpNat::Mul => crate::arena_ast::BinOpNat::Mul, + BinOpNat::Div => crate::arena_ast::BinOpNat::Div, + BinOpNat::Mod => crate::arena_ast::BinOpNat::Mod, + } + } +} + // When changing the AST, the types can quickly grow and lead to stack overflows in the different // compiler stages. // From 00f8541fbeb6b83d9ea29da69f087648ce5759fc Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 16 Jul 2025 13:08:38 +0200 Subject: [PATCH 28/57] some fixes regarding the into_arena methods in the heap allocated ast and lifetimes for visitors --- src/ast/mod.rs | 11 +++++++---- src/parser/mod.rs | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 6cced55c..ea9a9648 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -611,7 +611,7 @@ impl ExprKind { use ExprKind::*; match self { Hole => arena_ast::ExprKind::Hole, - Lit(l) => arena_ast::ExprKind::Lit(l), // assuming `Lit` is Copy or doesn't need arena + Lit(l) => arena_ast::ExprKind::Lit(l.into_arena(arena)), // assuming `Lit` is Copy or doesn't need arena PlaceExpr(p) => arena_ast::ExprKind::PlaceExpr(arena.alloc(p.into_arena(arena))), Array(exprs) => { let mut bump_vec = bumpalo::collections::Vec::new_in(arena); @@ -630,15 +630,18 @@ impl ExprKind { Ref(ann, own, pl) => { arena_ast::ExprKind::Ref(ann, own.into_arena(), arena.alloc(pl.into_arena(arena))) } - Block(b) => arena_ast::ExprKind::Block(&b.into_arena(arena)), + Block(b) => { + let b_ref = arena.alloc(b.into_arena(arena)); + arena_ast::ExprKind::Block(b_ref) + } LetUninit(exec, ident, ty) => arena_ast::ExprKind::LetUninit( - exec.map(|e| arena.alloc(e.into_arena(arena))).as_deref(), + exec.map(|e| &*arena.alloc(e.into_arena(arena))), ident.into_arena(arena), arena.alloc(ty.into_arena(arena)), ), Let(pat, ty, expr) => arena_ast::ExprKind::Let( pat.into_arena(arena), - ty.map(|t| arena.alloc(t.into_arena(arena))).as_deref(), + ty.map(|t| &*arena.alloc(t.into_arena(arena))), arena.alloc(expr.into_arena(arena)), ), Assign(pl, val) => arena_ast::ExprKind::Assign( diff --git a/src/parser/mod.rs b/src/parser/mod.rs index efd5f2d0..f721554b 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -203,7 +203,7 @@ fn replace_arg_kinded_idents<'a>(fun_def: &mut ArenaFunDef) { replace.visit_fun_def(fun_def); } -fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut ArenaFunDef) { +fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut ArenaFunDef<'a>) { struct ReplaceExecIdents<'a> { ident_names_to_exec_expr: Vec<(Box, ArenaExecExpr<'a>)>, } @@ -258,7 +258,7 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Ar expand_exec_expr(arena, &self.ident_names_to_exec_expr, exec_expr); } - fn visit_fun_def(&mut self, arena: &'a Bump, fun_def: &mut ArenaFunDef) { + fn visit_fun_def(&mut self, arena: &'a Bump, fun_def: &mut ArenaFunDef<'a>) { if let Some(ident_exec) = fun_def.generic_exec.as_ref() { match &ident_exec.ty.ty { ArenaExecTyKind::CpuThread => { @@ -358,7 +358,7 @@ fn replace_struct_idents_with_specific_struct_dtys<'a>( struct_dtys: &'a [&'a ArenaStructDecl<'a>], } impl<'a> ArenaVisitMut<'a> for ReplaceStructIdents<'a> { - fn visit_dty(&mut self, dty: &mut ArenaDataTy) { + fn visit_dty(&mut self, dty: &mut ArenaDataTy<'a>) { if let ArenaDataTyKind::Ident(ident) = &mut dty.dty { if let Some(struct_decl) = self.struct_dtys.iter().find(|s| &s.ident == ident) { dty.dty = ArenaDataTyKind::Struct(struct_decl) From 1fe53d7ebbecb6dbd76951c4abf60daefe2cffd0 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 16 Jul 2025 14:29:05 +0200 Subject: [PATCH 29/57] fixed test errors in parser --- src/parser/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index f721554b..1b5aada5 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -35,7 +35,7 @@ use error::ParseError; use std::collections::HashMap; use crate::error::ErrorReported; -use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; +use bumpalo::{collections::Vec as BumpVec, Bump}; pub use source::*; pub fn parse<'a>( @@ -2562,8 +2562,9 @@ mod tests { #[test] fn empty_annotate_snippet() { let source = SourceCode::new("fn\n".to_string()); + let bump: Bump = Bump::new(); assert!( - parse(&source).is_err(), + parse(&bump, &source).is_err(), "Expected a parsing error and specifically not a panic!" ); } @@ -2571,8 +2572,9 @@ mod tests { #[test] fn empty_annotate_snippet2() { let source = SourceCode::new("fn ".to_string()); + let bump: Bump = Bump::new(); assert!( - parse(&source).is_err(), + parse(&bump, &source).is_err(), "Expected a parsing error and specifically not a panic!" ); } From 15a580d77d5b6e85c749b54394bde0573f51b114 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 16 Jul 2025 14:49:15 +0200 Subject: [PATCH 30/57] fixed some bugs in the parse function --- src/parser/mod.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 1b5aada5..b28fa9ed 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -53,19 +53,17 @@ pub fn parse<'a>( // Step 2: Postprocess // TODO refactor to not require unnecessary copying out of items - let struct_copies: Vec<&ArenaStructDecl<'_>> = arena_items + let struct_copies = arena_items .iter() .filter_map(|i| { if let ArenaItem::StructDecl(struct_dty) = i { - //Some(struct_dty.as_ref()) Some(struct_dty.as_ref()) } else { None } }) - //.cloned() - //.collect::>(); - .collect(); + .cloned() + .collect::>(); for fun_def in arena_items.iter_mut().filter_map(|i| { if let ArenaItem::FunDef(fun_def) = i { @@ -351,11 +349,11 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Ar } fn replace_struct_idents_with_specific_struct_dtys<'a>( - struct_dtys: &[&'a ArenaStructDecl<'a>], + struct_dtys: &[ArenaStructDecl<'a>], item: &mut ArenaItem, ) { struct ReplaceStructIdents<'a> { - struct_dtys: &'a [&'a ArenaStructDecl<'a>], + struct_dtys: &'a [ArenaStructDecl<'a>], } impl<'a> ArenaVisitMut<'a> for ReplaceStructIdents<'a> { fn visit_dty(&mut self, dty: &mut ArenaDataTy<'a>) { From dbc50bcb3365196d07b1a951ca1b5ab6ac505b2f Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 23 Jul 2025 14:20:05 +0200 Subject: [PATCH 31/57] librs changes --- src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 77626c3a..2e681693 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ extern crate core; use crate::error::ErrorReported; - +use bumpalo::Bump; mod arena_ast; mod ast; mod codegen; @@ -11,7 +11,8 @@ pub mod ty_check; pub fn compile(file_path: &str) -> Result { let source = parser::SourceCode::from_file(file_path)?; - let mut compil_unit = parser::parse(&source)?; + let arena = Bump::new(); + let mut compil_unit = parser::parse(&arena, &source); ty_check::ty_check(&mut compil_unit)?; Ok(codegen::gen(&compil_unit, false)) } From 708a2505fc02c687d9ec3a9ef73945471e2c53e0 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Wed, 23 Jul 2025 21:17:53 +0200 Subject: [PATCH 32/57] some syntax changes to type checking --- src/ty_check/borrow_check.rs | 96 +++++----- src/ty_check/ctxs.rs | 71 ++++---- src/ty_check/error.rs | 106 ++++++------ src/ty_check/exec.rs | 45 +++-- src/ty_check/infer_kinded_args.rs | 75 +++++--- src/ty_check/mod.rs | 279 +++++++++++++++++------------- src/ty_check/pre_decl.rs | 58 +++---- src/ty_check/subty.rs | 61 ++++--- src/ty_check/unify.rs | 218 +++++++++++------------ 9 files changed, 550 insertions(+), 459 deletions(-) diff --git a/src/ty_check/borrow_check.rs b/src/ty_check/borrow_check.rs index 1c99caea..1954943b 100644 --- a/src/ty_check/borrow_check.rs +++ b/src/ty_check/borrow_check.rs @@ -1,11 +1,12 @@ use super::ctxs::TyCtx; use crate::arena_ast::internal::{Loan, PlaceCtx, PrvMapping}; -use crate::arena_ast::*; +use crate::arena_ast::{self, *}; use crate::parser::descend::nat; use crate::ty_check::ctxs::{AccessCtx, GlobalCtx, KindCtx}; use crate::ty_check::error::BorrowingError; use crate::ty_check::exec::normalize; use crate::ty_check::{exec, pre_decl, ExprTyCtx}; +use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; use std::collections::HashSet; type OwnResult = Result; @@ -15,11 +16,11 @@ pub(super) struct BorrowCheckCtx<'gl, 'src, 'ctxt> { pub gl_ctx: &'ctxt GlobalCtx<'gl, 'src>, pub nat_ctx: &'ctxt NatCtx, pub kind_ctx: &'ctxt KindCtx, - pub ident_exec: Option<&'ctxt IdentExec>, + pub ident_exec: Option<&'ctxt IdentExec<'a>>, pub ty_ctx: &'ctxt TyCtx, pub access_ctx: &'ctxt AccessCtx, - pub exec: ExecExpr, - pub reborrows: Vec, + pub exec: ExecExpr<'a>, + pub reborrows: Vec>, pub own: Ownership, pub unsafe_flag: bool, } @@ -46,7 +47,7 @@ impl<'gl, 'src, 'ctxt> BorrowCheckCtx<'gl, 'src, 'ctxt> { fn extend_reborrows(&self, iter: I) -> Self where - I: Iterator, + I: Iterator>, { let mut extended_reborrows = self.reborrows.clone(); extended_reborrows.extend(iter); @@ -69,7 +70,10 @@ impl<'gl, 'src, 'ctxt> BorrowCheckCtx<'gl, 'src, 'ctxt> { // Ownership Safety // //p is ω-safe under δ and γ, with reborrow exclusion list π , and may point to any of the loans in ωp -pub(super) fn access_safety_check(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult> { +pub(super) fn access_safety_check( + ctx: &BorrowCheckCtx, + p: &PlaceExpr, +) -> OwnResult>> { if !ctx.unsafe_flag { narrowing_check(ctx, p, &ctx.exec)?; access_conflict_check(ctx, p)?; @@ -77,7 +81,7 @@ pub(super) fn access_safety_check(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnRes borrow_check(ctx, p) } -pub(super) fn borrow_check(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult> { +pub(super) fn borrow_check(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult>> { let (pl_ctx, most_spec_pl) = p.to_pl_ctx_and_most_specif_pl(); if p.is_place() { ownership_safe_place(ctx, p) @@ -109,7 +113,7 @@ fn ownership_safe_deref_raw( ctx: &BorrowCheckCtx, pl_ctx_no_deref: &PlaceCtx, most_spec_pl: &internal::Place, -) -> OwnResult> { +) -> OwnResult>> { // TODO is this correct? let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr(PlaceExpr::new( PlaceExprKind::Deref(Box::new(most_spec_pl.to_place_expr())), @@ -122,7 +126,7 @@ fn ownership_safe_deref_raw( Ok(passed_through_prvs) } -fn ownership_safe_place(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult> { +fn ownership_safe_place(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult>> { ownership_safe_under_existing_borrows(ctx, p)?; let mut loan_set = HashSet::new(); loan_set.insert(Loan { @@ -138,7 +142,7 @@ fn ownership_safe_deref( most_spec_pl: &internal::Place, prv_val_name: &str, ref_own: Ownership, -) -> OwnResult> { +) -> OwnResult>> { // Γ(r) = { ω′pi } let loans_in_prv = ctx.ty_ctx.loans_in_prv(prv_val_name)?; // ω ≲ ωπ @@ -174,9 +178,9 @@ fn ownership_safe_deref( fn subst_pl_with_potential_prvs_ownership_safe( ctx: &BorrowCheckCtx, pl_ctx_no_deref: &PlaceCtx, - loans_in_prv: &HashSet, -) -> OwnResult> { - let mut loans: HashSet = HashSet::new(); + loans_in_prv: &HashSet>, +) -> OwnResult>> { + let mut loans: HashSet> = HashSet::new(); for pl_expr in loans_in_prv.iter().map(|loan| &loan.place_expr) { let insert_dereferenced_pl_expr = pl_ctx_no_deref.insert_pl_expr(pl_expr.clone()); let loans_for_possible_prv_pl_expr = @@ -191,7 +195,7 @@ fn ownership_safe_deref_abs( pl_ctx_no_deref: &PlaceCtx, most_spec_pl: &internal::Place, ref_own: Ownership, -) -> OwnResult> { +) -> OwnResult>> { let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr(PlaceExpr::new( PlaceExprKind::Deref(Box::new(most_spec_pl.to_place_expr())), )); @@ -210,8 +214,8 @@ fn ownership_safe_deref_abs( fn narrowing_check( ctx: &BorrowCheckCtx, - p: &PlaceExpr, - active_ctx_exec: &ExecExpr, + p: &'a PlaceExpr<'a>, + active_ctx_exec: &'a ExecExpr<'a>, ) -> OwnResult<()> { if ctx.own == Ownership::Shrd { return Ok(()); @@ -234,14 +238,14 @@ fn narrowing_check( } } -fn narrowable(from: &ExecExpr, to: &ExecExpr) -> OwnResult<()> { +fn narrowable(from: &'a ExecExpr<'a>, to: &'a ExecExpr<'a>) -> OwnResult<()> { let normal_from = normalize(from.clone()); let normal_to = normalize(to.clone()); exec_is_prefix_of(&normal_from, &normal_to)?; no_forall_in_diff(&normal_from, &normal_to) } -fn exec_is_prefix_of(prefix: &ExecExpr, of: &ExecExpr) -> OwnResult<()> { +fn exec_is_prefix_of(prefix: &&'a ExecExpr<'a>, of: &'a ExecExpr<'a>) -> OwnResult<()> { if prefix.exec.base != of.exec.base { return Err(BorrowingError::WrongDevice( of.exec.base.clone(), @@ -259,7 +263,7 @@ fn exec_is_prefix_of(prefix: &ExecExpr, of: &ExecExpr) -> OwnResult<()> { Ok(()) } -fn access_conflict_check(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult<()> { +fn access_conflict_check(ctx: &BorrowCheckCtx, p: &'a PlaceExpr<'a>) -> OwnResult<()> { for loan in ctx.access_ctx.hash_set() { if possible_conflict_with_previous_access(ctx.nat_ctx, ctx.own, p, loan)? { return Err(BorrowingError::Conflict { @@ -271,12 +275,12 @@ fn access_conflict_check(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult<()> { Ok(()) } -fn possible_conflict_with_previous_access( +fn possible_conflict_with_previous_access<'a>( nat_ctx: &NatCtx, own: Ownership, - p: &PlaceExpr, - previous: &Loan, -) -> NatEvalResult { + p: &'a PlaceExpr<'a>, + previous: &'a Loan<'a>, +) -> NatEvalResult<'a, bool> { if own == Ownership::Shrd && previous.own == Ownership::Shrd { return Ok(false); } @@ -335,20 +339,20 @@ fn possible_conflict_with_previous_access( Ok(false) } -fn range_intersects( - nat_ctx: &NatCtx, - lower_left: &Nat, - upper_left: &Nat, - lower_right: &Nat, - upper_right: &Nat, -) -> NatEvalResult { +fn range_intersects<'a>( + nat_ctx: &'a NatCtx<'a>, + lower_left: &'a Nat<'a>, + upper_left: &'a Nat<'a>, + lower_right: &'a Nat<'a>, + upper_right: &'a Nat<'a>, +) -> NatEvalResult<'a, bool> { Ok((lower_left.eval(nat_ctx)? < lower_right.eval(nat_ctx)? && upper_left.eval(nat_ctx)? <= lower_right.eval(nat_ctx)?) || (lower_left.eval(nat_ctx)? >= upper_right.eval(nat_ctx)? && upper_left.eval(nat_ctx)? > upper_right.eval(nat_ctx)?)) } -fn no_forall_in_diff(from: &ExecExpr, under: &ExecExpr) -> OwnResult<()> { +fn no_forall_in_diff<'a>(from: &'a ExecExpr<'a>, under: &'a ExecExpr<'a>) -> OwnResult<()> { if from.exec.path.len() > under.exec.path.len() { return Err(BorrowingError::CannotNarrow); } @@ -360,9 +364,9 @@ fn no_forall_in_diff(from: &ExecExpr, under: &ExecExpr) -> OwnResult<()> { Ok(()) } -fn pl_ctxs_and_places_in_loans( - loans: &HashSet, -) -> impl Iterator + '_ { +fn pl_ctxs_and_places_in_loans<'a>( + loans: &HashSet>, +) -> impl Iterator)> + '_ { loans .iter() .map(|loan| &loan.place_expr) @@ -377,9 +381,9 @@ fn new_own_weaker_equal(checked_own: Ownership, ref_own: Ownership) -> OwnResult } } -fn ownership_safe_under_existing_borrows( +fn ownership_safe_under_existing_borrows<'a>( ctx: &BorrowCheckCtx, - pl_expr: &PlaceExpr, + pl_expr: &'a PlaceExpr<'a>, ) -> OwnResult<()> { if !ctx.unsafe_flag { for prv_mapping in ctx.ty_ctx.prv_mappings() { @@ -398,11 +402,11 @@ fn ownership_safe_under_existing_borrows( } // returns None if there is no unique loan overlap or Some with the existing overlapping loan -fn no_uniq_loan_overlap( +fn no_uniq_loan_overlap<'a>( own: Ownership, - pl_expr: &PlaceExpr, - loans: &HashSet, -) -> Option { + pl_expr: &'a PlaceExpr<'a>, + loans: &HashSet>, +) -> Option> { for l in loans { if (own == Ownership::Uniq || l.own == Ownership::Uniq) && overlap(&l.place_expr, pl_expr) { return Some(l.clone()); @@ -411,10 +415,10 @@ fn no_uniq_loan_overlap( None } -fn at_least_one_borrowing_place_and_all_in_reborrow( +fn at_least_one_borrowing_place_and_all_in_reborrow<'a>( ty_ctx: &TyCtx, prv_name: &str, - reborrows: &[internal::Place], + reborrows: &[internal::Place<'a>], ) -> OwnResult<()> { let all_places = ty_ctx.all_places(); // check that a borrow with given provenance exists. @@ -439,7 +443,7 @@ fn at_least_one_borrowing_place_and_all_in_reborrow( Ok(()) } -fn conflicting_path(pathl: &[PlExprPathElem], pathr: &[PlExprPathElem]) -> bool { +fn conflicting_path<'a>(pathl: &[PlExprPathElem<'a>], pathr: &[PlExprPathElem<'a>]) -> bool { for lr in pathl.iter().zip(pathr) { match lr { (PlExprPathElem::Idx(_), _) => return true, @@ -483,9 +487,9 @@ fn conflicting_path(pathl: &[PlExprPathElem], pathr: &[PlExprPathElem]) -> bool true } -fn overlap(pll: &PlaceExpr, plr: &PlaceExpr) -> bool { - let (pl_ident, pl_path) = pll.as_ident_and_path(); - let (pr_ident, pr_path) = plr.as_ident_and_path(); +fn overlap<'a>(pll: &'a PlaceExpr<'a>, plr: &'a PlaceExpr<'a>, arena: &'a Bump) -> bool { + let (pl_ident, pl_path) = pll.as_ident_and_path(arena); + let (pr_ident, pr_path) = plr.as_ident_and_path(arena); if pl_ident == pr_ident { conflicting_path(&pl_path, &pr_path) || conflicting_path(&pr_path, &pl_path) } else { diff --git a/src/ty_check/ctxs.rs b/src/ty_check/ctxs.rs index 4418bdf9..49de5b0c 100644 --- a/src/ty_check/ctxs.rs +++ b/src/ty_check/ctxs.rs @@ -4,22 +4,23 @@ use crate::arena_ast::internal::{ use crate::arena_ast::*; use crate::ty_check::error::CtxError; use std::collections::HashSet; +use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; // TODO introduce proper struct -pub(super) type TypedPlace = (internal::Place, DataTy); +pub(super) type TypedPlace<'a> = (internal::Place<'a>, DataTy<'a>); #[derive(PartialEq, Eq, Debug, Clone)] -pub(super) struct TyCtx { - frames: Vec, +pub(super) struct TyCtx<'a> { + frames: BumpVec<'a, Frame<'a>>, } -impl TyCtx { - pub fn new() -> Self { - TyCtx { - frames: vec![Frame::new()], +impl<'a> TyCtx<'a> { + pub fn new(arena: &'a Bump) -> Self { + let mut frames = BumpVec::new_in(arena); + frames.push(Frame::new_in(arena)); + TyCtx { frames } } - } - + pub fn get_exec_expr_for_exec_ident(&self, ident: &Ident) -> CtxResult<&ExecExpr> { let exec_expr = self.flat_bindings().rev().find_map(|entry| match entry { FrameEntry::ExecMapping(em) if &em.ident == ident => Some(&em.exec_expr), @@ -48,7 +49,7 @@ impl TyCtx { } pub fn push_empty_frame(&mut self) -> &mut Self { - self.frames.push(Frame::new()); + self.frames.push(Frame<'a>::new()); self } @@ -144,7 +145,7 @@ impl TyCtx { pub fn extend_loans_for_prv(&mut self, base: &str, extension: I) -> CtxResult<&mut TyCtx> where - I: IntoIterator, + I: IntoIterator>, { let base_loans = self.loans_for_prv_mut(base)?; base_loans.extend(extension); @@ -200,13 +201,13 @@ impl TyCtx { .collect() } - fn explode_places(ident: &Ident, dty: &DataTy) -> Vec { - fn proj(mut pl: internal::Place, idx: PathElem) -> internal::Place { + fn explode_places(ident: &Ident, dty: &DataTy) -> Vec> { + fn proj(mut pl: internal::Place, idx: PathElem) -> internal::Place<'a> { pl.path.push(idx); pl } - fn explode(pl: internal::Place, dty: DataTy) -> Vec { + fn explode(pl: internal::Place, dty: DataTy) -> Vec> { use DataTyKind as d; match &dty.dty { @@ -264,8 +265,8 @@ impl TyCtx { self.idents_typed().any(|i| i.ident.name == ident.name) } - pub fn place_dty(&self, place: &internal::Place) -> CtxResult { - fn proj_ty(dty: DataTy, path: &[PathElem]) -> CtxResult { + pub fn place_dty(&self, place: &internal::Place<'a>) -> CtxResult> { + fn proj_ty(dty: DataTy, path: &[PathElem<'a>]) -> CtxResult> { let mut res_dty = dty; for pe in path { match (&res_dty.dty, pe) { @@ -482,19 +483,19 @@ fn trim_after_select_of(ty_ctx: &TyCtx, exec: &ExecExpr, pl_expr: PlaceExpr) -> } #[derive(PartialEq, Eq, Debug, Clone)] -enum KindingCtxEntry { - Ident(IdentKinded), - PrvRel(PrvRel), +enum KindingCtxEntry<'a> { + Ident(IdentKinded<'a>), + PrvRel(PrvRel<'a>), } pub(super) type CtxResult = Result; #[derive(PartialEq, Eq, Debug, Clone)] -pub(super) struct KindCtx { - ctx: Vec>, +pub(super) struct KindCtx<'a> { + ctx: Vec>>, } -impl KindCtx { +impl<'a> KindCtx<'a> { pub fn new() -> Self { KindCtx { ctx: vec![vec![]] } } @@ -515,7 +516,7 @@ impl KindCtx { self.ctx.pop(); } - pub fn append_idents>(&mut self, idents: I) -> &mut Self { + pub fn append_idents>>(&mut self, idents: I) -> &mut Self { let entries = idents.into_iter().map(KindingCtxEntry::Ident); for e in entries { self.ctx.last_mut().unwrap().push(e); @@ -523,7 +524,7 @@ impl KindCtx { self } - pub fn append_prv_rels + Clone>( + pub fn append_prv_rels> + Clone>( &mut self, prv_rels: I, ) -> CtxResult<&mut Self> { @@ -537,7 +538,7 @@ impl KindCtx { Ok(self) } - pub fn well_kinded_prv_rels>( + pub fn well_kinded_prv_rels>>( &self, prv_rels: I, ) -> CtxResult<()> { @@ -553,7 +554,7 @@ impl KindCtx { Ok(()) } - pub fn get_idents(&self, kind: Kind) -> impl Iterator { + pub fn get_idents(&self, kind: Kind) -> impl Iterator> { self.ctx.iter().flatten().filter_map(move |entry| { if let KindingCtxEntry::Ident(IdentKinded { ident, kind: k }) = entry { if k == &kind { @@ -567,11 +568,11 @@ impl KindCtx { }) } - pub fn ident_of_kind_exists(&self, ident: &Ident, kind: Kind) -> bool { + pub fn ident_of_kind_exists<'a>(&self, ident: &'a Ident<'a>, kind: Kind) -> bool { self.get_idents(kind).any(|id| ident == id) } - pub fn outlives(&self, l: &Ident, s: &Ident) -> CtxResult<()> { + pub fn outlives<'a>(&self, l: &'a Ident<'a>, s: &'a Ident<'a>) -> CtxResult<()> { if self.ctx.iter().flatten().any(|entry| match entry { KindingCtxEntry::PrvRel(PrvRel { longer, shorter }) => longer == l && shorter == s, _ => false, @@ -584,9 +585,9 @@ impl KindCtx { } #[derive(Debug, Clone)] -pub(super) enum GlobalDecl { - FnDecl(Box, Box), - StructDecl(Box), +pub(super) enum GlobalDecl<'a> { + FnDecl(Box, Box>), + StructDecl(Box>), } #[derive(Debug)] @@ -620,19 +621,19 @@ impl<'src, 'compil> GlobalCtx<'src, 'compil> { } } - pub fn has_been_checked(&self, name: &str, nat_args: &[usize]) -> bool { + pub fn has_been_checked<'a>(&self, name: &str, nat_args: &[usize]) -> bool { self.checked_funs .iter() .any(|(fun_name, nargs)| fun_name.as_ref() == name && nargs.as_ref() == nat_args) } - pub fn push_fun_checked_under_nats(&mut self, fun_def: Box, nat_vals: Box<[usize]>) { + pub fn push_fun_checked_under_nats<'a>(&mut self, fun_def: Box, nat_vals: Box<[usize]>) { let fun_name = fun_def.ident.name.clone(); self.compil_unit.items.push(Item::FunDef(fun_def)); self.checked_funs.push((fun_name, nat_vals)) } - pub fn pop_fun_def(&mut self, name: &str) -> Option> { + pub fn pop_fun_def<'a>(&mut self, name: &str) -> Option> { let index = self.compil_unit.items.iter().position(|item| { if let Item::FunDef(fun_def) = item { fun_def.ident.name.as_ref() == name @@ -651,7 +652,7 @@ impl<'src, 'compil> GlobalCtx<'src, 'compil> { } } - pub fn fn_ty_by_ident(&self, ident: &Ident) -> CtxResult<&FnTy> { + pub fn fn_ty_by_ident<'a>(&self, ident: &'a Ident<'a>) -> CtxResult<&'a FnTy<'a>> { if let Some(fn_ty) = self.decls.iter().find_map(|decl| match decl { GlobalDecl::FnDecl(name, fn_ty) if name == &ident.name => Some(fn_ty), GlobalDecl::FnDecl(_, _) | GlobalDecl::StructDecl(_) => None, diff --git a/src/ty_check/error.rs b/src/ty_check/error.rs index 5542e4fa..66d2428e 100644 --- a/src/ty_check/error.rs +++ b/src/ty_check/error.rs @@ -10,16 +10,16 @@ use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet}; #[must_use] #[derive(Debug)] -pub enum TyError { - MultiError(Vec), - MutabilityNotAllowed(Ty), - CtxError(CtxError), - SubTyError(SubTyError), +pub enum TyError<'a> { + MultiError(Vec>), + MutabilityNotAllowed(Ty<'a>), + CtxError(CtxError<'a>), + SubTyError(SubTyError<'a>), // Standard data type mismatch, expected type followed by actual type - MismatchedDataTypes(DataTy, DataTy, Expr), + MismatchedDataTypes(DataTy<'a>, DataTy<'a>, Expr<'a>), // "Trying to violate existing borrow of {:?}.", // p1 under own1 is in conflict because of BorrowingError - ConflictingBorrow(Box, Ownership, BorrowingError), + ConflictingBorrow(Box>, Ownership, BorrowingError<'a>), PrvValueAlreadyInUse(String), // No loan the reference points to has a type that fits the reference element type ReferenceToIncompatibleType, @@ -29,15 +29,15 @@ pub enum TyError { // out from under the reference which is forbidden. ReferenceToDeadTy, // Assignment to a constant place expression. - AssignToConst(PlaceExpr), //, Box), + AssignToConst(PlaceExpr<'a>), //, Box), // Assigning to a view is forbidden AssignToView, // Trying to split a non-view array. SplittingNonViewArray, // Expected a different type - ExpectedTupleType(TyKind, PlaceExpr), + ExpectedTupleType(TyKind<'a>, PlaceExpr<'a>), // Trying to borrow uniquely but place is not mutable - ConstBorrow(PlaceExpr), + ConstBorrow(PlaceExpr<'a>), // The borrowed view type is at least paritally dead BorrowingDeadView, IllegalExec, @@ -53,23 +53,23 @@ pub enum TyError { UnexpectedType, // The thread hierarchy dimension referred to does not exist IllegalDimension, - UnifyError(UnifyError), + UnifyError(UnifyError<'a>), MissingMain, - NatEvalError(NatEvalError), - CannotInferGenericArg(Ident), + NatEvalError(NatEvalError<'a>), + CannotInferGenericArg(Ident<'a>), UnsafeRequired, // TODO remove as soon as possible String(String), } -impl<'a> FromIterator for TyError { - fn from_iter>(iter: T) -> Self { +impl<'a> FromIterator> for TyError<'a> { + fn from_iter>>(iter: T) -> Self { TyError::MultiError(iter.into_iter().collect()) } } -impl TyError { - pub fn emit(&self, source: &SourceCode) -> ErrorReported { +impl<'a> TyError<'a> { + pub fn emit(&self, source: &'a SourceCode<'a>) -> ErrorReported { match &self { TyError::MultiError(errs) => { for err in errs { @@ -229,31 +229,31 @@ impl TyError { } } -impl From for TyError { - fn from(err: CtxError) -> Self { +impl<'a> From> for TyError<'a> { + fn from(err: CtxError<'a>) -> Self { TyError::CtxError(err) } } -impl From for TyError { - fn from(err: SubTyError) -> Self { +impl<'a> From> for TyError<'a> { + fn from(err: SubTyError<'a>) -> Self { TyError::SubTyError(err) } } -impl From for TyError { - fn from(err: UnifyError) -> Self { +impl<'a> From> for TyError<'a> { + fn from(err: UnifyError<'a>) -> Self { TyError::UnifyError(err) } } -impl From for TyError { - fn from(err: NatEvalError) -> Self { +impl<'a> From> for TyError<'a> { + fn from(err: NatEvalError<'a>) -> Self { TyError::NatEvalError(err) } } #[must_use] #[derive(Debug)] -pub enum SubTyError { - CtxError(CtxError), +pub enum SubTyError<'a> { + CtxError(CtxError<'a>), // format!("{} lives longer than {}.", shorter, longer) NotOutliving(String, String), // format!("No loans bound to provenance.") @@ -268,79 +268,79 @@ pub enum SubTyError { #[must_use] #[derive(Debug)] -pub enum UnifyError { +pub enum UnifyError<'a> { // Cannot unify the two terms CannotUnify, // A type variable has to be equal to a term that is referring to the same type variable InfiniteType, - SubTyError(SubTyError), + SubTyError(SubTyError<'a>), } -impl From for UnifyError { - fn from(err: SubTyError) -> Self { +impl<'a> From> for UnifyError<'a> { + fn from(err: SubTyError<'a>) -> Self { UnifyError::SubTyError(err) } } #[must_use] #[derive(Debug)] -pub enum CtxError { +pub enum CtxError<'a> { //format!("Identifier: {} not found in context.", ident)), - IdentNotFound(Ident), + IdentNotFound(Ident<'a>), //"Cannot find identifier {} in kinding context", - KindedIdentNotFound(Ident), + KindedIdentNotFound(Ident<'a>), // "Typing Context is missing the provenance value {}", PrvValueNotFound(String), // format!("{} is not declared", prv_rel.longer)); - PrvIdentNotFound(Ident), - // format!("{} is not defined as outliving {}.", l, s) - OutlRelNotDefined(Ident, Ident), + PrvIdentNotFound(Ident<'a>), + // format!("{} is not de<'a>ined as outliving {}.", l, s) + OutlRelNotDefined(Ident<'a>, Ident<'a>), // TODO move to TyError IllegalProjection, } -impl From for SubTyError { - fn from(err: CtxError) -> Self { +impl<'a> From> for SubTyError<'a> { + fn from(err: CtxError<'a>) -> Self { SubTyError::CtxError(err) } } #[must_use] #[derive(Debug)] -pub enum BorrowingError { +pub enum BorrowingError<'a> { Conflict { - checked: PlaceExpr, - existing: PlaceExpr, + checked: PlaceExpr<'a>, + existing: PlaceExpr<'a>, }, - CtxError(CtxError), + CtxError(CtxError<'a>), // "Trying to use place expression with {} capability while it refers to a \ // loan with {} capability.", // checked_own, ref_own ConflictingOwnership, ConflictingAccess, // The borrowing place is not in the reborrow list - BorrowNotInReborrowList(Place), + BorrowNotInReborrowList(Place<'a>), TemporaryConflictingBorrow(String), - WrongDevice(BaseExec, BaseExec), + WrongDevice(BaseExec<'a>, BaseExec<'a>), MultipleDistribs, CannotNarrow, DivergingExec, - TyError(Box), - NatEvalError(NatEvalError), + TyError(Box>), + NatEvalError(NatEvalError<'a>), } -impl From for BorrowingError { - fn from(err: TyError) -> Self { +impl<'a> From> for BorrowingError<'a> { + fn from(err: TyError<'a>) -> Self { BorrowingError::TyError(Box::new(err)) } } -impl From for BorrowingError { - fn from(err: CtxError) -> Self { +impl<'a> From> for BorrowingError<'a> { + fn from(err: CtxError<'a>) -> Self { BorrowingError::CtxError(err) } } -impl From for BorrowingError { - fn from(err: NatEvalError) -> Self { +impl<'a> From> for BorrowingError<'a> { + fn from(err: NatEvalError<'a>) -> Self { BorrowingError::NatEvalError(err) } } diff --git a/src/ty_check/exec.rs b/src/ty_check/exec.rs index ff8db715..10d01857 100644 --- a/src/ty_check/exec.rs +++ b/src/ty_check/exec.rs @@ -4,12 +4,12 @@ use super::{ }; use crate::arena_ast::{LeftOrRight, NatCtx}; -pub(super) fn ty_check( +pub(super) fn ty_check<'a>( nat_ctx: &NatCtx, ty_ctx: &TyCtx, ident_exec: Option<&IdentExec>, exec_expr: &mut ExecExpr, -) -> TyResult<()> { +) -> TyResult<'a, ()> { let mut exec_ty = match &exec_expr.exec.base { BaseExec::Ident(ident) => { if let Some(ie) = ident_exec { @@ -50,7 +50,7 @@ pub(super) fn ty_check( Ok(()) } -fn ty_check_exec_to_threads(d: DimCompo, exec_ty: &ExecTyKind) -> TyResult { +fn ty_check_exec_to_threads<'a>(d: DimCompo, exec_ty: &ExecTyKind) -> TyResult { if let ExecTyKind::GpuGrid(gdim, bdim) = exec_ty { let (rest_gdim, rem_gdim) = remove_dim(gdim, d)?; let (rest_bdim, rem_bdim) = remove_dim(bdim, d)?; @@ -89,7 +89,10 @@ fn ty_check_exec_to_threads(d: DimCompo, exec_ty: &ExecTyKind) -> TyResult TyResult { +fn ty_check_exec_to_warps<'a>( + nat_ctx: &NatCtx, + exec_ty: &'a ExecTyKind<'a>, +) -> TyResult<'a, ExecTyKind<'a>> { match exec_ty { ExecTyKind::GpuBlock(dim) => match dim.clone() { Dim::X(d) => { @@ -118,7 +121,10 @@ fn ty_check_exec_to_warps(nat_ctx: &NatCtx, exec_ty: &ExecTyKind) -> TyResult TyResult { +fn ty_check_exec_forall<'a>( + d: DimCompo, + exec_ty: &'a ExecTyKind<'a>, +) -> TyResult<'a, ExecTyKind<'a>> { let res_ty = match exec_ty { ExecTyKind::GpuGrid(gdim, bdim) => { let inner_dim = remove_dim(gdim, d)?.0; @@ -165,7 +171,10 @@ fn ty_check_exec_forall(d: DimCompo, exec_ty: &ExecTyKind) -> TyResult TyResult<(Option, Dim)> { +pub fn remove_dim<'a>( + dim: &'a Dim<'a>, + dim_compo: DimCompo, +) -> TyResult<'a, (Option>, Dim<'a>)> { match (dim, dim_compo) { (Dim::XYZ(dim3d), DimCompo::X) => Ok(( Some(Dim::YZ(Box::new(Dim2d( @@ -219,12 +228,12 @@ pub fn remove_dim(dim: &Dim, dim_compo: DimCompo) -> TyResult<(Option, Dim) } } -fn ty_check_exec_take_range( +fn ty_check_exec_take_range<'a>( d: DimCompo, - n: &Nat, + n: &'a Nat<'a>, proj: LeftOrRight, - exec_ty: &ExecTyKind, -) -> TyResult { + exec_ty: &'a ExecTyKind<'a>, +) -> TyResult<'a, ExecTyKind<'a>> { // TODO check well-formedness of Nats let (lexec_ty, rexec_ty) = match exec_ty { ExecTyKind::GpuGrid(gdim, bdim) | ExecTyKind::GpuBlockGrp(gdim, bdim) => { @@ -278,13 +287,17 @@ fn ty_check_exec_take_range( }) } -fn dim_compo_matches_dim(d: DimCompo, dim: &Dim) -> bool { +fn dim_compo_matches_dim<'a>(d: DimCompo, dim: &'a Dim<'a>) -> bool { (matches!(dim, Dim::X(_)) && d == DimCompo::X) | (matches!(dim, Dim::Y(_)) && d == DimCompo::Y) | (matches!(dim, Dim::Z(_)) && d == DimCompo::Z) } -fn split_dim(split_dim: DimCompo, pos: Nat, dim: Dim) -> TyResult<(Dim, Dim)> { +fn split_dim<'a>( + split_dim: DimCompo, + pos: Nat<'a>, + dim: Dim<'a>, +) -> TyResult<'a, (Dim<'a>, Dim<'a>)> { Ok(match dim { Dim::XYZ(d) => match split_dim { DimCompo::X => ( @@ -411,7 +424,7 @@ fn split_dim(split_dim: DimCompo, pos: Nat, dim: Dim) -> TyResult<(Dim, Dim)> { }) } -pub(super) fn normalize(mut exec: ExecExpr) -> ExecExpr { +pub(super) fn normalize<'a>(mut exec: ExecExpr<'a>) -> ExecExpr<'a> { assert!(exec.ty.is_some()); let mut exec_path = exec.exec.path; if !exec_path.is_empty() { @@ -424,7 +437,7 @@ pub(super) fn normalize(mut exec: ExecExpr) -> ExecExpr { // FIXME: not correct if first take_range on dimension of lower level followed by forall on different dimension in upper level // for fix: see formalism -fn level_boundaries(exec_path: &[ExecPathElem]) -> Vec { +fn level_boundaries<'a>(exec_path: &'a [ExecPathElem<'a>]) -> Vec { let mut forall_dims_encountered = Vec::with_capacity(3); let mut boundaries = Vec::with_capacity(3); for (i, elem) in exec_path.iter().enumerate() { @@ -454,7 +467,7 @@ fn level_boundaries(exec_path: &[ExecPathElem]) -> Vec { boundaries } -fn sort_within_boundaries(exec_path: &mut Vec, boundaries: &[usize]) { +fn sort_within_boundaries<'a>(exec_path: &'a mut Vec>, boundaries: &[usize]) { let mut lower_bound = 0; for b in boundaries { for i in lower_bound..*b { @@ -468,7 +481,7 @@ fn sort_within_boundaries(exec_path: &mut Vec, boundaries: &[usize } } -fn swappable_exec_path_elems(lhs: &ExecPathElem, rhs: &ExecPathElem) -> bool { +fn swappable_exec_path_elems<'a>(lhs: &'a ExecPathElem<'a>, rhs: &'a ExecPathElem<'a>) -> bool { match (lhs, rhs) { (ExecPathElem::ForAll(dl), ExecPathElem::ForAll(dr)) => dl > dr, (ExecPathElem::ForAll(_), ExecPathElem::TakeRange(_)) => true, diff --git a/src/ty_check/infer_kinded_args.rs b/src/ty_check/infer_kinded_args.rs index ce526556..b4d102b8 100644 --- a/src/ty_check/infer_kinded_args.rs +++ b/src/ty_check/infer_kinded_args.rs @@ -10,7 +10,10 @@ use std::collections::HashMap; // introduced by the polymorphic function, therefore finding an identifier on the poly type // means that it was introduced by the polymorphic function (even though the identifier may be an // instantiation of a bound identifier -pub fn infer_kinded_args(poly_fn_ty: &FnTy, mono_fn_ty: &FnTy) -> TyResult> { +pub fn infer_kinded_args<'a>( + poly_fn_ty: &'a FnTy<'a>, + mono_fn_ty: &'a FnTy<'a>, +) -> TyResult<'a, Vec>> { if poly_fn_ty.param_sigs.len() != mono_fn_ty.param_sigs.len() { panic!("Unexpected difference in amount of paramters.") } @@ -71,7 +74,11 @@ macro_rules! panic_if_neq { }; } -fn infer_kargs_tys(map: &mut HashMap, poly_ty: &Ty, mono_ty: &Ty) { +fn infer_kargs_tys<'a>( + map: &mut HashMap, ArgKinded<'a>>, + poly_ty: &'a Ty<'a>, + mono_ty: &'a Ty<'a>, +) { match (&poly_ty.ty, &mono_ty.ty) { (TyKind::Data(dty1), TyKind::Data(dty2)) => infer_kargs_dtys(map, dty1, dty2), (TyKind::FnTy(fn_ty1), TyKind::FnTy(fn_ty2)) => { @@ -94,19 +101,19 @@ fn infer_kargs_tys(map: &mut HashMap, poly_ty: &Ty, mono_ty: & } } -fn infer_kargs_param_sig( - map: &mut HashMap, - poly_param_sig: &ParamSig, - mono_param_sig: &ParamSig, +fn infer_kargs_param_sig<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_param_sig: &'a ParamSig<'a>, + mono_param_sig: &'a ParamSig<'a>, ) { infer_kargs_exec_expr(map, &poly_param_sig.exec_expr, &mono_param_sig.exec_expr); infer_kargs_tys(map, &poly_param_sig.ty, &mono_param_sig.ty); } -fn infer_kargs_exec_expr( - map: &mut HashMap, - poly_exec_expr: &ExecExpr, - mono_exec_expr: &ExecExpr, +fn infer_kargs_exec_expr<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_exec_expr: &'a ExecExpr<'a>, + mono_exec_expr: &'a ExecExpr<'a>, ) { match (&poly_exec_expr.exec.base, &mono_exec_expr.exec.base) { (BaseExec::Ident(i1), BaseExec::Ident(i2)) if i1 == i2 => (), @@ -119,10 +126,10 @@ fn infer_kargs_exec_expr( } } -fn infer_kargs_exec_level( - map: &mut HashMap, - poly_exec_level: &ExecTy, - mono_exec_level: &ExecTy, +fn infer_kargs_exec_level<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_exec_level: &'a ExecTy<'a>, + mono_exec_level: &'a ExecTy<'a>, ) { match (&poly_exec_level.ty, &mono_exec_level.ty) { (ExecTyKind::GpuGrid(gdim1, bdim1), ExecTyKind::GpuGrid(gdim2, bdim2)) @@ -141,7 +148,11 @@ fn infer_kargs_exec_level( } } -fn infer_kargs_dims(map: &mut HashMap, poly_dim: &Dim, mono_dim: &Dim) { +fn infer_kargs_dims<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_dim: &'a Dim<'a>, + mono_dim: &'a Dim<'a>, +) { match (poly_dim, mono_dim) { (Dim::XYZ(d3d1), Dim::XYZ(d3d2)) => { infer_kargs_nats(map, &d3d1.0, &d3d2.0); @@ -163,15 +174,19 @@ fn infer_kargs_dims(map: &mut HashMap, poly_dim: &Dim, mono_di } } -fn infer_kargs_field( - map: &mut HashMap, - poly_field: &(Ident, DataTy), - mono_field: &(Ident, DataTy), +fn infer_kargs_field<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_field: &'a (Ident<'a>, DataTy<'a>), + mono_field: &'a (Ident<'a>, DataTy<'a>), ) { infer_kargs_dtys(map, &poly_field.1, &mono_field.1) } -fn infer_kargs_dtys(map: &mut HashMap, poly_dty: &DataTy, mono_dty: &DataTy) { +fn infer_kargs_dtys<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_dty: &'a DataTy<'a>, + mono_dty: &'a DataTy<'a>, +) { match (&poly_dty.dty, &mono_dty.dty) { (DataTyKind::Ident(id), _) => insert_checked!(map, ArgKinded::DataTy, id, mono_dty), (DataTyKind::Scalar(sty1), DataTyKind::Scalar(sty2)) => { @@ -215,7 +230,11 @@ fn infer_kargs_dtys(map: &mut HashMap, poly_dty: &DataTy, mono } } -fn infer_kargs_nats(map: &mut HashMap, poly_nat: &Nat, mono_nat: &Nat) { +fn infer_kargs_nats<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_nat: &'a Nat<'a>, + mono_nat: &'a Nat<'a>, +) { match (poly_nat, mono_nat) { (Nat::Ident(id), _) => { if let Some(ArgKinded::Nat(old)) = @@ -243,17 +262,21 @@ fn infer_kargs_nats(map: &mut HashMap, poly_nat: &Nat, mono_na } } -fn infer_kargs_mems(map: &mut HashMap, poly_mem: &Memory, mono_mem: &Memory) { +fn infer_kargs_mems<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_mem: &'a Memory<'a>, + mono_mem: &'a Memory<'a>, +) { match (poly_mem, mono_mem) { (Memory::Ident(id), _) => insert_checked!(map, ArgKinded::Memory, id, mono_mem), _ => panic_if_neq!(poly_mem, mono_mem), } } -fn infer_kargs_prvs( - map: &mut HashMap, - poly_prv: &Provenance, - mono_prv: &Provenance, +fn infer_kargs_prvs<'a>( + map: &'a mut HashMap, ArgKinded<'a>>, + poly_prv: &'a Provenance<'a>, + mono_prv: &'a Provenance<'a>, ) { match (poly_prv, mono_prv) { (Provenance::Ident(id), _) => insert_checked!(map, ArgKinded::Provenance, id, mono_prv), diff --git a/src/ty_check/mod.rs b/src/ty_check/mod.rs index 3e2bc564..8714851d 100644 --- a/src/ty_check/mod.rs +++ b/src/ty_check/mod.rs @@ -18,11 +18,11 @@ use ctxs::{AccessCtx, GlobalCtx, KindCtx, TyCtx}; use error::*; use std::collections::HashSet; -type TyResult = Result; +type TyResult<'a, T> = Result>; macro_rules! matches_dty { ($ty: expr, $dty_pat: pat_param) => { - if let crate::ast::TyKind::Data(d) = &$ty.ty { + if let crate::arena_ast::TyKind::Data(d) = &$ty.ty { matches!(d.as_ref(), $dty_pat) } else { false @@ -37,14 +37,12 @@ pub(crate) use matches_dty; // ∀ε ∈ Σ. Σ ⊢ ε // -------------- // ⊢ Σ -pub fn ty_check(compil_unit: &mut CompilUnit) -> Result<(), ErrorReported> { - let ty_arena = Bump::new(); - +pub fn ty_check<'a>(compil_unit: &mut CompilUnit, arena: &'a Bump) -> Result<(), ErrorReported> { let mut gl_ctx = GlobalCtx::new( compil_unit, pre_decl::fun_decls() .into_iter() - .map(|(fname, fty)| GlobalDecl::FnDecl(Box::from(fname), ty_arena.alloc(fty))) + .map(|(fname, fty)| GlobalDecl::FnDecl(Box::from(fname), arena.alloc(fty))) .collect(), ); let mut nat_ctx = NatCtx::new(); @@ -63,24 +61,24 @@ pub fn ty_check(compil_unit: &mut CompilUnit) -> Result<(), ErrorReported> { } } -struct ExprTyCtx<'src, 'compil, 'ctxt> { +struct ExprTyCtx<'a, 'src, 'compil, 'ctxt> { gl_ctx: &'ctxt mut GlobalCtx<'src, 'compil>, nat_ctx: &'ctxt mut NatCtx, - ident_exec: Option<&'ctxt IdentExec>, - kind_ctx: &'ctxt mut KindCtx, - exec: ExecExpr, - ty_ctx: &'ctxt mut TyCtx, + ident_exec: Option<&'ctxt IdentExec<'a>>, + kind_ctx: &'ctxt mut KindCtx<'a>, + exec: ExecExpr<'a>, + ty_ctx: &'ctxt mut TyCtx<'a>, access_ctx: &'ctxt mut AccessCtx, unsafe_flag: bool, } // Σ ⊢ fn f (x1: τ1, ..., xn: τn) → τr where List[ρ1:ρ2] { e } fn ty_check_global_fun_def<'a>( - gl_ctx: &mut GlobalCtx<'a>, + gl_ctx: &mut GlobalCtx, nat_ctx: &mut NatCtx, gf: &mut FunDef<'a>, arena: &'a Bump, -) -> TyResult<()> { +) -> TyResult<'a, ()> { // TODO check that every prv_rel only uses provenance variables bound in generic_params let mut kind_ctx = KindCtx::gl_fun_kind_ctx(gf.generic_params.clone(), gf.prv_rels.clone())?; let mut ty_ctx = TyCtx::new(); @@ -167,7 +165,11 @@ fn ty_check_global_fun_def<'a>( // type τ is well-formed under well-formed GlFunCtxt, kinding ctx, output context Γ'. // Σ; Δ; Γ ⊢ e :^exec τ ⇒ Γ′, side conditions: ⊢ Σ;Δ;Γ and Σ;Δ;Γ′ ⊢ τ // This never returns a dead type, because typing an expression with a dead type is not possible. -fn ty_check_expr(ctx: &mut ExprTyCtx, expr: &mut Expr, arena) -> TyResult<()> { +fn ty_check_expr<'a>( + ctx: &'a mut ExprTyCtx, + expr: &'a mut Expr<'a>, + arena: &'a Bump, +) -> TyResult<'a, ()> { let ty = match &mut expr.expr { ExprKind::PlaceExpr(pl_expr) => { if pl_expr.is_place() { @@ -234,7 +236,7 @@ fn ty_check_expr(ctx: &mut ExprTyCtx, expr: &mut Expr, arena) -> TyResult<()> { Ok(()) } -fn ty_check_hole(ctx: &ExprTyCtx) -> TyResult { +fn ty_check_hole<'a>(ctx: &ExprTyCtx, arena: &'a Bump) -> TyResult<'a, Ty<'a>> { if ctx.unsafe_flag { Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( DataTyKind::Ident(Ident::new_impli(&utils::fresh_name("hole"))), @@ -244,7 +246,10 @@ fn ty_check_hole(ctx: &ExprTyCtx) -> TyResult { } } -fn ty_check_sync(ctx: &mut ExprTyCtx, exec: &mut Option) -> TyResult { +fn ty_check_sync<'a>( + ctx: &mut ExprTyCtx, + exec: &'a mut Option>, +) -> TyResult<'a, Ty<'a>> { let synced = match exec { Some(exec) => { exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, exec)?; @@ -260,7 +265,7 @@ fn ty_check_sync(ctx: &mut ExprTyCtx, exec: &mut Option) -> TyResult TyResult<()> { +fn syncable_under_exec<'a>(synced: &'a ExecExpr<'a>, under: &'a ExecExpr<'a>) -> TyResult<'a, ()> { if !syncable_exec_ty(synced.ty.as_ref().unwrap()) { return Err(TyError::String( "trying to synchronize non-synchronizable execution resource".to_string(), @@ -282,7 +287,7 @@ fn syncable_under_exec(synced: &ExecExpr, under: &ExecExpr) -> TyResult<()> { } } -fn syncable_exec_ty(exec_ty: &ExecTy) -> bool { +fn syncable_exec_ty<'a>(exec_ty: &'a ExecTy<'a>) -> bool { match &exec_ty.ty { ExecTyKind::GpuBlock(_) | ExecTyKind::GpuWarp => true, ExecTyKind::CpuThread @@ -296,7 +301,7 @@ fn syncable_exec_ty(exec_ty: &ExecTy) -> bool { } } -fn infer_and_append_prv(ty_ctx: &mut TyCtx, prv_name: &Option) -> String { +fn infer_and_append_prv<'a>(ty_ctx: &'a mut TyCtx<'a>, prv_name: &Option) -> String { if let Some(prv) = prv_name.as_ref() { prv.clone() } else { @@ -306,13 +311,13 @@ fn infer_and_append_prv(ty_ctx: &mut TyCtx, prv_name: &Option) -> String } } -fn ty_check_for_nat( +fn ty_check_for_nat<'a>( ctx: &mut ExprTyCtx, - ident: &Ident, - range: &NatRange, + ident: &Ident<'a>, + range: &NatRange<'a>, // TODO make this a block - body: &mut Expr, -) -> TyResult { + body: &mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { let compare_ty_ctx = ctx.ty_ctx.clone(); let lifted_range = range.lift(ctx.nat_ctx)?; @@ -340,12 +345,12 @@ fn ty_check_for_nat( ))) } -fn ty_check_for( +fn ty_check_for<'a>( ctx: &mut ExprTyCtx, - ident: &Ident, - collec: &mut Expr, - body: &mut Expr, -) -> TyResult { + ident: &Ident<'a>, + collec: &mut Expr<'a>, + body: &mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { ty_check_expr(ctx, collec)?; let collec_dty = if let TyKind::Data(collec_dty) = &collec.ty.as_ref().unwrap().ty { collec_dty.as_ref() @@ -408,7 +413,11 @@ fn ty_check_for( ))) } -fn ty_check_while(ctx: &mut ExprTyCtx, cond: &mut Expr, body: &mut Expr) -> TyResult { +fn ty_check_while<'a>( + ctx: &mut ExprTyCtx, + cond: &'a mut Expr<'a>, + body: &'a mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { ty_check_expr(&mut *ctx, cond)?; ctx.ty_ctx.push_empty_frame(); ty_check_expr(ctx, body)?; @@ -462,12 +471,12 @@ fn ty_check_while(ctx: &mut ExprTyCtx, cond: &mut Expr, body: &mut Expr) -> TyRe ))) } -fn ty_check_if_else( +fn ty_check_if_else<'a>( ctx: &mut ExprTyCtx, - cond: &mut Expr, - case_true: &mut Expr, - case_false: &mut Expr, -) -> TyResult { + cond: &'a mut Expr<'a>, + case_true: &'a mut Expr<'a>, + case_false: &'a mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { // TODO deal with provenances in cases ty_check_expr(ctx, cond)?; // TODO acccess_ctx clone @@ -533,7 +542,11 @@ fn ty_check_if_else( ))) } -fn ty_check_if(ctx: &mut ExprTyCtx, cond: &mut Expr, case_true: &mut Expr) -> TyResult { +fn ty_check_if<'a>( + ctx: &mut ExprTyCtx, + cond: &'a mut Expr<'a>, + case_true: &'a mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { // TODO deal with provenances in cases ty_check_expr(ctx, cond)?; ctx.ty_ctx.push_empty_frame(); @@ -573,7 +586,7 @@ fn ty_check_if(ctx: &mut ExprTyCtx, cond: &mut Expr, case_true: &mut Expr) -> Ty ))) } -fn ty_check_split(ctx: &mut ExprTyCtx, indep: &mut Split) -> TyResult { +fn ty_check_split<'a>(ctx: &mut ExprTyCtx, indep: &mut Split<'a>) -> TyResult<'a, Ty<'a>> { // exec::ty_check( // ctx.kind_ctx, // ctx.ty_ctx, @@ -645,7 +658,7 @@ fn ty_check_split(ctx: &mut ExprTyCtx, indep: &mut Split) -> TyResult { ))) } -fn ty_check_sched(ctx: &mut ExprTyCtx, sched: &mut Sched) -> TyResult { +fn ty_check_sched<'a>(ctx: &mut ExprTyCtx, sched: &'a mut Sched<'a>) -> TyResult<'a, Ty<'a>> { exec::ty_check( ctx.nat_ctx, ctx.ty_ctx, @@ -684,7 +697,7 @@ fn ty_check_sched(ctx: &mut ExprTyCtx, sched: &mut Sched) -> TyResult { ))) } -fn ty_check_block(ctx: &mut ExprTyCtx, block: &mut Block) -> TyResult { +fn ty_check_block<'a>(ctx: &mut ExprTyCtx, block: &'a mut Block<'a>) -> TyResult<'a, Ty<'a>> { ctx.ty_ctx.push_empty_frame(); for prv in &block.prvs { ctx.ty_ctx.append_prv_mapping(PrvMapping::new(prv)); @@ -695,7 +708,7 @@ fn ty_check_block(ctx: &mut ExprTyCtx, block: &mut Block) -> TyResult { Ok(block.body.ty.as_ref().unwrap().as_ref().clone()) } -fn collect_valid_loans(ty_ctx: &TyCtx, mut loans: HashSet) -> HashSet { +fn collect_valid_loans<'a>(ty_ctx: &TyCtx, mut loans: HashSet>) -> HashSet> { // FIXME this implementations assumes unique names which is not the case loans.retain(|l| { let root_ident = &l.place_expr.to_pl_ctx_and_most_specif_pl().1.ident; @@ -704,7 +717,7 @@ fn collect_valid_loans(ty_ctx: &TyCtx, mut loans: HashSet) -> HashSet TyResult<()> { +fn check_mutable<'a>(ty_ctx: &TyCtx, pl: &'a Place<'a>) -> TyResult<'a, ()> { let ident_ty = ty_ctx.ident_ty(&pl.ident)?; if ident_ty.mutbl != Mutability::Mut { return Err(TyError::AssignToConst(pl.to_place_expr())); @@ -712,11 +725,11 @@ fn check_mutable(ty_ctx: &TyCtx, pl: &Place) -> TyResult<()> { Ok(()) } -fn ty_check_assign_place( +fn ty_check_assign_place<'a>( ctx: &mut ExprTyCtx, - pl_expr: &mut PlaceExpr, - e: &mut Expr, -) -> TyResult { + pl_expr: &'a mut PlaceExpr<'a>, + e: &'a mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { ty_check_expr(ctx, e)?; let pl = pl_expr.to_place().unwrap(); let mut place_ty = ctx.ty_ctx.place_dty(&pl)?; @@ -766,11 +779,11 @@ fn ty_check_assign_place( ))) } -fn ty_check_assign_non_place( +fn ty_check_assign_non_place<'a>( ctx: &mut ExprTyCtx, - deref_expr: &mut PlaceExpr, - e: &mut Expr, -) -> TyResult { + deref_expr: &'a mut PlaceExpr<'a>, + e: &'a mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { ty_check_expr(ctx, e)?; pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), deref_expr)?; let potential_accesses = borrow_check::access_safety_check( @@ -805,12 +818,12 @@ fn ty_check_assign_non_place( } } -fn ty_check_idx_assign( +fn ty_check_idx_assign<'a>( ctx: &mut ExprTyCtx, - pl_expr: &mut PlaceExpr, - idx: &Nat, - e: &mut Expr, -) -> TyResult { + pl_expr: &'a mut PlaceExpr<'a>, + idx: &'a Nat<'a>, + e: &'a mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { ty_check_expr(ctx, e)?; pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr)?; let pl_expr_dty = if let TyKind::Data(dty) = &pl_expr.ty.as_ref().unwrap().ty { @@ -886,12 +899,12 @@ fn ty_check_idx_assign( // FIXME currently assumes that binary operators exist only for f32 and i32 and that both // arguments have to be of the same type -fn ty_check_binary_op( +fn ty_check_binary_op<'a>( ctx: &mut ExprTyCtx, bin_op: &BinOp, - lhs: &mut Expr, - rhs: &mut Expr, -) -> TyResult { + lhs: &mut Expr<'a>, + rhs: &mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { // FIXME certain operations should only be allowed for certain data types // true > false is currently valid ty_check_expr(ctx, lhs)?; @@ -988,7 +1001,11 @@ fn ty_check_binary_op( } } -fn ty_check_unary_op(ctx: &mut ExprTyCtx, un_op: &UnOp, e: &mut Expr) -> TyResult { +fn ty_check_unary_op<'a>( + ctx: &mut ExprTyCtx, + un_op: &UnOp, + e: &'a mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { ty_check_expr(ctx, e)?; let e_ty = e.ty.as_ref().unwrap(); let e_dty = if let TyKind::Data(dty) = &e_ty.ty { @@ -1010,7 +1027,11 @@ fn ty_check_unary_op(ctx: &mut ExprTyCtx, un_op: &UnOp, e: &mut Expr) -> TyResul } } -fn ty_check_cast(ctx: &mut ExprTyCtx, e: &mut Expr, dty: &DataTy) -> TyResult { +fn ty_check_cast<'a>( + ctx: &mut ExprTyCtx, + e: &mut Expr<'a>, + dty: &'a DataTy<'a>, +) -> TyResult<'a, Ty<'a>> { ty_check_expr(ctx, e)?; let e_ty = e.ty.as_ref().unwrap(); match &e_ty.dty().dty { @@ -1050,12 +1071,12 @@ fn ty_check_cast(ctx: &mut ExprTyCtx, e: &mut Expr, dty: &DataTy) -> TyResult( ctx: &mut ExprTyCtx, - fn_ident: &mut Ident, - gen_args: &mut Vec, - args: &mut [Expr], -) -> TyResult { + fn_ident: &'a mut Ident<'a>, + gen_args: &'a mut Vec>, + args: &'a mut [Expr<'a>], +) -> TyResult<'a, Ty<'a>> { // TODO check well-kinded: FrameTyping, Prv, Ty let partially_applied_dep_fn_ty = ty_check_dep_app(ctx, fn_ident, gen_args)?; for arg in args.iter_mut() { @@ -1128,11 +1149,11 @@ fn ty_check_app( // } // } -fn ty_check_dep_app( +fn ty_check_dep_app<'a>( ctx: &mut ExprTyCtx, - fn_ident: &Ident, - gen_args: &[ArgKinded], -) -> TyResult { + fn_ident: &'a Ident<'a>, + gen_args: &'a [ArgKinded<'a>], +) -> TyResult<'a, FnTy<'a>> { //ty_check_expr(ctx, ef)?; let fn_ty = ctx.gl_ctx.fn_ty_by_ident(fn_ident)?; apply_gen_args_to_fn_ty_checked(ctx.kind_ctx, &ctx.exec, &fn_ty, gen_args) @@ -1144,23 +1165,23 @@ fn ty_check_dep_app( // } } -fn apply_gen_args_to_fn_ty_checked( - kind_ctx: &KindCtx, - exec: &ExecExpr, - fn_ty: &FnTy, - gen_args: &[ArgKinded], -) -> TyResult { +fn apply_gen_args_to_fn_ty_checked<'a>( + kind_ctx: &'a KindCtx<'a>, + exec: &'a ExecExpr<'a>, + fn_ty: &'a FnTy<'a>, + gen_args: &'a [ArgKinded<'a>], +) -> TyResult<'a, FnTy<'a>> { let mut subst_fn_ty = fn_ty.clone(); apply_gen_args_checked(kind_ctx, &mut subst_fn_ty, gen_args)?; apply_exec_checked(&mut subst_fn_ty, exec)?; Ok(subst_fn_ty) } -fn apply_gen_args_checked( - kind_ctx: &KindCtx, - fn_ty: &mut FnTy, - gen_args: &[ArgKinded], -) -> TyResult<()> { +fn apply_gen_args_checked<'a>( + kind_ctx: &'a KindCtx<'a>, + fn_ty: &mut FnTy<'a>, + gen_args: &'a [ArgKinded<'a>], +) -> TyResult<'a, ()> { if fn_ty.generics.len() < gen_args.len() { return Err(TyError::String(format!( "Wrong amount of generic arguments. Expected {}, found {}", @@ -1176,7 +1197,11 @@ fn apply_gen_args_checked( Ok(()) } -fn check_arg_has_correct_kind(kind_ctx: &KindCtx, expected: &Kind, kv: &ArgKinded) -> TyResult<()> { +fn check_arg_has_correct_kind<'a>( + kind_ctx: &'a KindCtx<'a>, + expected: &'a Kind, + kv: &'a ArgKinded<'a>, +) -> TyResult<'a, ()> { if expected == &kv.kind() { Ok(()) } else { @@ -1189,7 +1214,7 @@ fn check_arg_has_correct_kind(kind_ctx: &KindCtx, expected: &Kind, kv: &ArgKinde // FIXME the correct way to do this is to unify execs and to unify an identifier with an exec_expr // only if the types match (i.e., the exec expr type check must happen within unify) -fn apply_exec_checked(fn_ty: &mut FnTy, exec: &ExecExpr) -> TyResult<()> { +fn apply_exec_checked<'a>(fn_ty: &'a mut FnTy<'a>, exec: &'a ExecExpr<'a>) -> TyResult<'a, ()> { // TODO reintroduce // exec::ty_check( // ctx.kind_ctx, @@ -1212,7 +1237,10 @@ fn apply_exec_checked(fn_ty: &mut FnTy, exec: &ExecExpr) -> TyResult<()> { Ok(()) } -fn ty_check_app_kernel(ctx: &mut ExprTyCtx, app_kernel: &mut AppKernel) -> TyResult { +fn ty_check_app_kernel<'a>( + ctx: &mut ExprTyCtx, + app_kernel: &'a mut AppKernel<'a>, +) -> TyResult<'a, Ty<'a>> { // current exec = cpu.thread if !matches!(ctx.exec.ty.as_ref().unwrap().ty, ExecTyKind::CpuThread) { return Err(TyError::String( @@ -1354,7 +1382,7 @@ fn ty_check_app_kernel(ctx: &mut ExprTyCtx, app_kernel: &mut AppKernel) -> TyRes Ok(unit_ty) } -fn exec_distrib_over_blocks(exec_expr: &ExecExpr) -> ExecExpr { +fn exec_distrib_over_blocks<'a>(exec_expr: &'a ExecExpr<'a>) -> ExecExpr<'a> { let base_clone = ExecExprKind::new(exec_expr.exec.base.clone()); let distrib_over_blocks = if let BaseExec::GpuGrid(gdim, _) = &exec_expr.exec.base { match gdim { @@ -1375,7 +1403,7 @@ fn exec_distrib_over_blocks(exec_expr: &ExecExpr) -> ExecExpr { ExecExpr::new(distrib_over_blocks) } -fn ty_check_tuple(ctx: &mut ExprTyCtx, elems: &mut [Expr]) -> TyResult { +fn ty_check_tuple<'a>(ctx: &mut ExprTyCtx, elems: &'a mut [Expr<'a>]) -> TyResult<'a, Ty<'a>> { for elem in elems.iter_mut() { ty_check_expr(ctx, elem)?; } @@ -1393,7 +1421,7 @@ fn ty_check_tuple(ctx: &mut ExprTyCtx, elems: &mut [Expr]) -> TyResult { ))) } -fn ty_check_proj(ctx: &mut ExprTyCtx, e: &mut Expr, i: usize) -> TyResult { +fn ty_check_proj<'a>(ctx: &mut ExprTyCtx, e: &'a mut Expr<'a>, i: usize) -> TyResult<'a, Ty<'a>> { if let ExprKind::PlaceExpr(_) = e.expr { panic!("Place expression should have been typechecked by a different rule.") } @@ -1407,7 +1435,7 @@ fn ty_check_proj(ctx: &mut ExprTyCtx, e: &mut Expr, i: usize) -> TyResult { Ok(Ty::new(TyKind::Data(arena.alloc(elem_ty?)))) } -fn ty_check_array(ctx: &mut ExprTyCtx, elems: &mut Vec) -> TyResult { +fn ty_check_array<'a>(ctx: &mut ExprTyCtx, elems: &'a mut Vec>) -> TyResult<'a, Ty<'a>> { assert!(!elems.is_empty()); for elem in elems.iter_mut() { ty_check_expr(ctx, elem)?; @@ -1432,7 +1460,7 @@ fn ty_check_array(ctx: &mut ExprTyCtx, elems: &mut Vec) -> TyResult { } } -fn ty_check_literal(l: &mut Lit) -> Ty { +fn ty_check_literal<'a>(l: &mut Lit) -> Ty<'a> { let scalar_data = match l { Lit::Unit => ScalarTy::Unit, Lit::Bool(_) => ScalarTy::Bool, @@ -1448,11 +1476,11 @@ fn ty_check_literal(l: &mut Lit) -> Ty { )) } -fn infer_pattern_ident_tys( +fn infer_pattern_ident_tys<'a>( ctx: &mut ExprTyCtx, - pattern: &Pattern, - pattern_ty: &Ty, -) -> TyResult<()> { + pattern: &'a Pattern<'a>, + pattern_ty: &'a Ty<'a>, +) -> TyResult<'a, ()> { let pattern_dty = if let TyKind::Data(dty) = &pattern_ty.ty { dty.as_ref() } else { @@ -1480,12 +1508,12 @@ fn infer_pattern_ident_tys( } } -fn infer_tys_and_append_idents( +fn infer_tys_and_append_idents<'a>( ctx: &mut ExprTyCtx, - pattern: &Pattern, - pattern_ty: &mut Option>, - assign_ty: &mut Ty, -) -> TyResult<()> { + pattern: &'a Pattern<'a>, + pattern_ty: &'a mut Option>>, + assign_ty: &'a mut Ty<'a>, +) -> TyResult<'a, ()> { let pattern_ty = if let Some(pty) = pattern_ty { unify::sub_unify(ctx.kind_ctx, ctx.ty_ctx, assign_ty, pty)?; pty.as_ref().clone() @@ -1495,12 +1523,12 @@ fn infer_tys_and_append_idents( infer_pattern_ident_tys(ctx, pattern, &pattern_ty) } -fn ty_check_let( +fn ty_check_let<'a>( ctx: &mut ExprTyCtx, - pattern: &Pattern, - pattern_ty: &mut Option>, - expr: &mut Expr, -) -> TyResult { + pattern: &'a Pattern<'a>, + pattern_ty: &'a mut Option>>, + expr: &'a mut Expr<'a>, +) -> TyResult<'a, Ty<'a>> { ty_check_expr(ctx, expr)?; let e_ty = expr.ty.as_mut().unwrap(); infer_tys_and_append_idents(ctx, pattern, pattern_ty, e_ty)?; @@ -1510,12 +1538,12 @@ fn ty_check_let( } // TODO respect exec? -fn ty_check_let_uninit( +fn ty_check_let_uninit<'a>( ctx: &mut ExprTyCtx, - annot_exec: &Option>, - ident: &Ident, - ty: &Ty, -) -> TyResult { + annot_exec: &'a Option>>, + ident: &'a Ident<'a>, + ty: &'a Ty<'a>, +) -> TyResult<'a, Ty<'a>> { // TODO is the type well-formed? if let TyKind::Data(dty) = &ty.ty { let mut exec_expr = if let Some(ex) = annot_exec { @@ -1541,7 +1569,7 @@ fn ty_check_let_uninit( } } -fn ty_check_seq(ctx: &mut ExprTyCtx, es: &mut [Expr]) -> TyResult { +fn ty_check_seq<'a>(ctx: &mut ExprTyCtx, es: &'a mut [Expr<'a>]) -> TyResult<'a, Ty<'a>> { for e in &mut *es { ty_check_expr(ctx, e)?; ctx.ty_ctx.garbage_collect_loans(); @@ -1549,7 +1577,10 @@ fn ty_check_seq(ctx: &mut ExprTyCtx, es: &mut [Expr]) -> TyResult { Ok(es.last().unwrap().ty.as_ref().unwrap().as_ref().clone()) } -fn ty_check_non_place(ctx: &mut ExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult { +fn ty_check_non_place<'a>( + ctx: &mut ExprTyCtx, + pl_expr: &'a mut PlaceExpr<'a>, +) -> TyResult<'a, Ty<'a>> { pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Shrd), pl_expr)?; if !pl_expr.ty.as_ref().unwrap().is_fully_alive() { return Err(TyError::String(format!( @@ -1579,7 +1610,7 @@ fn ty_check_non_place(ctx: &mut ExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult< } } -fn ty_check_place(ctx: &mut ExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult { +fn ty_check_place<'a>(ctx: &mut ExprTyCtx, pl_expr: &'a mut PlaceExpr<'a>) -> TyResult<'a, Ty<'a>> { pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr)?; let place = pl_expr.clone().to_place().unwrap(); let pl_ty = ctx.ty_ctx.place_dty(&place)?; @@ -1611,12 +1642,12 @@ fn ty_check_place(ctx: &mut ExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult Ok(Ty::new(TyKind::Data(arena.alloc(pl_ty)))) } -fn ty_check_borrow( +fn ty_check_borrow<'a>( ctx: &mut ExprTyCtx, prv_val_name: &Option, own: Ownership, - pl_expr: &mut PlaceExpr, -) -> TyResult { + pl_expr: &'a mut PlaceExpr<'a>, +) -> TyResult<'a, Ty<'a>> { // If borrowing a place uniquely, is it mutable? if let Some(place) = pl_expr.to_place() { if own == Ownership::Uniq && ctx.ty_ctx.ident_ty(&place.ident)?.mutbl == Mutability::Const { @@ -1673,7 +1704,7 @@ fn ty_check_borrow( Ok(Ty::new(TyKind::Data(arena.alloc(res_dty)))) } -fn allowed_mem_for_exec(exec_ty: &ExecTyKind) -> Vec { +fn allowed_mem_for_exec<'a>(exec_ty: &'a ExecTyKind<'a>) -> Vec> { match exec_ty { ExecTyKind::CpuThread => vec![Memory::CpuMem], ExecTyKind::GpuThread @@ -1690,7 +1721,7 @@ fn allowed_mem_for_exec(exec_ty: &ExecTyKind) -> Vec { } } -pub fn accessible_memory(exec_ty: &ExecTy, mem: &Memory) -> TyResult<()> { +pub fn accessible_memory(exec_ty: &'a ExecTy<'a>, mem: &'a Memory<'a>) -> TyResult<'a, ()> { if allowed_mem_for_exec(&exec_ty.ty).contains(mem) { Ok(()) } else { @@ -1702,7 +1733,12 @@ pub fn accessible_memory(exec_ty: &ExecTy, mem: &Memory) -> TyResult<()> { } // TODO respect memory -fn ty_well_formed(kind_ctx: &KindCtx, ty_ctx: &TyCtx, exec_ty: &ExecTy, ty: &Ty) -> TyResult<()> { +fn ty_well_formed<'a>( + kind_ctx: &'a KindCtx<'a>, + ty_ctx: &'a TyCtx<'a>, + exec_ty: &'a ExecTy<'a>, + ty: &'a Ty<'a>, +) -> TyResult<'a, ()> { match &ty.ty { TyKind::Data(dty) => match &dty.dty { // TODO variables of Dead types can be reassigned. So why do we not have to check @@ -1845,7 +1881,7 @@ fn ty_well_formed(kind_ctx: &KindCtx, ty_ctx: &TyCtx, exec_ty: &ExecTy, ty: &Ty) Ok(()) } -pub fn callable_in(callee_exec_ty: &ExecTy, caller_exec_ty: &ExecTy) -> bool { +pub fn callable_in<'a>(callee_exec_ty: &'a ExecTy<'a>, caller_exec_ty: &'a ExecTy<'a>) -> bool { if &callee_exec_ty.ty == &ExecTyKind::Any { true } else { @@ -1854,7 +1890,10 @@ pub fn callable_in(callee_exec_ty: &ExecTy, caller_exec_ty: &ExecTy) -> bool { } } -fn expand_exec_expr(ctx: &ExprTyCtx, exec_expr: &ExecExpr) -> TyResult { +fn expand_exec_expr<'a>( + ctx: &ExprTyCtx, + exec_expr: &'a ExecExpr<'a>, +) -> TyResult<'a, ExecExpr<'a>> { match &exec_expr.exec.base { BaseExec::CpuThread | BaseExec::GpuGrid(_, _) => Ok(exec_expr.clone()), BaseExec::Ident(ident) => { @@ -1875,7 +1914,7 @@ fn expand_exec_expr(ctx: &ExprTyCtx, exec_expr: &ExecExpr) -> TyResult } } -fn legal_exec_under_current(ctx: &ExprTyCtx, exec: &ExecExpr) -> TyResult<()> { +fn legal_exec_under_current<'a>(ctx: &ExprTyCtx, exec: &'a ExecExpr<'a>) -> TyResult<'a, ()> { let expanded_exec_expr = expand_exec_expr(ctx, exec)?; if ctx.exec != expanded_exec_expr { let current_exec_ty = &ctx.exec.ty.as_ref().unwrap().ty; @@ -1897,7 +1936,7 @@ fn legal_exec_under_current(ctx: &ExprTyCtx, exec: &ExecExpr) -> TyResult<()> { } // TODO move into utility module (also used in codegen) -pub fn proj_elem_dty(dty: &DataTy, i: usize) -> TyResult { +pub fn proj_elem_dty<'a>(dty: &'a DataTy<'a>, i: usize) -> TyResult<'a, DataTy<'a>> { match &dty.dty { DataTyKind::Tuple(dtys) => match dtys.get(i) { Some(dty) => Ok(dty.clone()), diff --git a/src/ty_check/pre_decl.rs b/src/ty_check/pre_decl.rs index 14b816bf..0131132b 100644 --- a/src/ty_check/pre_decl.rs +++ b/src/ty_check/pre_decl.rs @@ -41,7 +41,7 @@ pub static TAKE_RIGHT: &str = "take_right"; pub static SELECT_RANGE: &str = "select_range"; pub static MAP: &str = "map"; -pub fn fun_decls() -> Vec<(&'static str, FnTy)> { +pub fn fun_decls<'a>() -> Vec<(&'static str, FnTy<'a>)> { let decls = [ // Built-in functions (GPU_DEVICE, gpu_device_ty()), @@ -81,7 +81,7 @@ pub fn fun_decls() -> Vec<(&'static str, FnTy)> { decls.to_vec() } -fn create_array_ty() -> FnTy { +fn create_array_ty<'a>() -> FnTy<'a> { let n = Ident::new("n"); let d = Ident::new("d"); let n_nat = IdentKinded { @@ -116,7 +116,7 @@ fn create_array_ty() -> FnTy { // ( // &r gpu.thread uniq m t // ) -[gpu.thread]-> RawPtr -fn to_raw_ptr_ty() -> FnTy { +fn to_raw_ptr_ty<'a>() -> FnTy<'a> { let r = Ident::new("r"); let m = Ident::new("m"); let d = Ident::new("d"); @@ -161,7 +161,7 @@ fn to_raw_ptr_ty() -> FnTy { // ( // RawPtr, i32 // ) -[gpu.thread]-> RawPtr -fn offset_raw_ptr_ty() -> FnTy { +fn offset_raw_ptr_ty<'a>() -> FnTy<'a> { let d = Ident::new("d"); let d_dty = IdentKinded { ident: d.clone(), @@ -196,7 +196,7 @@ fn offset_raw_ptr_ty() -> FnTy { // ballot_sync: // <>(bool) -[w: gpu.warp]-> u32 -fn ballot_sync_ty() -> FnTy { +fn ballot_sync_ty<'a>() -> FnTy<'a> { let ident_exec = IdentExec::new(Ident::new("w"), ExecTy::new(ExecTyKind::GpuWarp)); let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); let param_exec = ExecExpr::new(exec_expr.exec.clone().forall(DimCompo::X)); @@ -221,7 +221,7 @@ fn ballot_sync_ty() -> FnTy { // FIXME warp should have the type given in the comment below // shfl_sync: // (u32, u32) -[w.forall]-> u32 -fn shfl_sync_ty() -> FnTy { +fn shfl_sync_ty<'a>() -> FnTy<'a> { let ident_exec = IdentExec::new(Ident::new("w"), ExecTy::new(ExecTyKind::GpuWarp)); let exec_expr_lane = ExecExpr::new( ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone())).forall(DimCompo::X), @@ -255,7 +255,7 @@ fn shfl_sync_ty() -> FnTy { // shfl_up: // <>(u32, i32) -[gpu.warp]-> u32 -fn shfl_up_ty() -> FnTy { +fn shfl_up_ty<'a>() -> FnTy<'a> { let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuWarp)); let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); @@ -286,7 +286,7 @@ fn shfl_up_ty() -> FnTy { // nat_as_u64: // () -[view]-> u64 -fn nat_as_u64_ty() -> FnTy { +fn nat_as_u64_ty<'a>() -> FnTy<'a> { let n = Ident::new("n"); let n_nat = IdentKinded { ident: n, @@ -308,7 +308,7 @@ fn nat_as_u64_ty() -> FnTy { } // get_warp_id: <>() -[w: gpu.Warp]-> u32 -fn get_warp_id_ty() -> FnTy { +fn get_warp_id_ty<'a>() -> FnTy<'a> { let ident_exec = IdentExec::new(Ident::new("w"), ExecTy::new(ExecTyKind::GpuWarp)); let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); @@ -325,7 +325,7 @@ fn get_warp_id_ty() -> FnTy { } // get_lane_id: <>() -[w: gpu.Thread]-> u32 -fn get_lane_id_ty() -> FnTy { +fn get_lane_id_ty<'a>() -> FnTy<'a> { let ident_exec = IdentExec::new(Ident::new("t"), ExecTy::new(ExecTyKind::GpuThread)); let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); @@ -343,7 +343,7 @@ fn get_lane_id_ty() -> FnTy { // thread_id_x: // <>() -[gpu.thread]-> u32 -fn thread_id_x_ty() -> FnTy { +fn thread_id_x_ty<'a>() -> FnTy<'a> { let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuThread)); let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); @@ -361,7 +361,7 @@ fn thread_id_x_ty() -> FnTy { // gpu: // <>(i32) -[cpu.thread]-> Gpu -fn gpu_device_ty() -> FnTy { +fn gpu_device_ty<'a>() -> FnTy<'a> { let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::CpuThread)); let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); @@ -384,7 +384,7 @@ fn gpu_device_ty() -> FnTy { // to_atomic_array: // (ex: &r uniq m [u32; n]) -[x: Any]-> &r uniq m [AtomicU32; n] -fn to_atomic_array_ty() -> FnTy { +fn to_atomic_array_ty<'a>() -> FnTy<'a> { let r = Ident::new("r"); let m = Ident::new("m"); let n = Ident::new("n"); @@ -438,7 +438,7 @@ fn to_atomic_array_ty() -> FnTy { // to_atomic: // (&r uniq x m u32) -[x: Any]-> &r uniq x m AtomicU32 -fn to_atomic_ty() -> FnTy { +fn to_atomic_ty<'a>() -> FnTy<'a> { let r = Ident::new("r"); let m = Ident::new("m"); let r_prv = IdentKinded { @@ -481,7 +481,7 @@ fn to_atomic_ty() -> FnTy { // atomic_store: // (&r shrd m AtomicU32, u32) -[gpu.thread]-> () -fn atomic_store_ty() -> FnTy { +fn atomic_store_ty<'a>() -> FnTy<'a> { let r = Ident::new("r"); let m = Ident::new("m"); let r_prv = IdentKinded { @@ -527,7 +527,7 @@ fn atomic_store_ty() -> FnTy { // atomic_fetch_or: // (&r shrd m AtomicU32, u32) -[gpu.thread]-> u32 -fn atomic_fetch_or_ty() -> FnTy { +fn atomic_fetch_or_ty<'a>() -> FnTy<'a> { let r = Ident::new("r"); let m = Ident::new("m"); let r_prv = IdentKinded { @@ -573,7 +573,7 @@ fn atomic_fetch_or_ty() -> FnTy { // atomic_min: // (&r shrd m AtomicI32, i32) -[gpu.thread]-> i32 -fn atomic_min_ty() -> FnTy { +fn atomic_min_ty<'a>() -> FnTy<'a> { let r = Ident::new("r"); let m = Ident::new("m"); let r_prv = IdentKinded { @@ -619,7 +619,7 @@ fn atomic_min_ty() -> FnTy { // atomic_fetch_add: // (&r shrd m AtomicU32, u32) -[gpu.thread]-> u32 -fn atomic_fetch_add_ty() -> FnTy { +fn atomic_fetch_add_ty<'a>() -> FnTy<'a> { let r = Ident::new("r"); let m = Ident::new("m"); let r_prv = IdentKinded { @@ -665,7 +665,7 @@ fn atomic_fetch_add_ty() -> FnTy { // atomic_load: // (&r shrd m AtomicU32) -[gpu.thread]-> u32 -fn atomic_load_ty() -> FnTy { +fn atomic_load_ty<'a>() -> FnTy<'a> { let r = Ident::new("r"); let m = Ident::new("m"); let r_prv = IdentKinded { @@ -705,7 +705,7 @@ fn atomic_load_ty() -> FnTy { // ( // &r1 uniq cpu.mem Gpu, &r2 shrd cpu.mem t // ) -[cpu.thread]-> t @ gpu.global -fn gpu_alloc_copy_ty() -> FnTy { +fn gpu_alloc_copy_ty<'a>() -> FnTy<'a> { let r1 = Ident::new("r1"); let r2 = Ident::new("r2"); let d = Ident::new("d"); @@ -762,7 +762,7 @@ fn gpu_alloc_copy_ty() -> FnTy { // copy_to_host: // (&r1 shrd gpu.global d, &r2 uniq cpu.mem d) // -[cpu.thread]-> () -fn copy_to_host_ty() -> FnTy { +fn copy_to_host_ty<'a>() -> FnTy<'a> { let r1 = Ident::new("r1"); let r2 = Ident::new("r2"); let d = Ident::new("d"); @@ -818,7 +818,7 @@ fn copy_to_host_ty() -> FnTy { // copy_to_gpu: // (& r1 uniq gpu.global d, // & r2 shrd cpu.mem d) -[cpu.thread]-> () -fn copy_to_gpu_ty() -> FnTy { +fn copy_to_gpu_ty<'a>() -> FnTy<'a> { let r1 = Ident::new("r1"); let r2 = Ident::new("r2"); let d = Ident::new("d"); @@ -873,7 +873,7 @@ fn copy_to_gpu_ty() -> FnTy { // to_view: // ([d; n]) -[view]-> [[d; n]] -fn to_view_ty() -> FnTy { +fn to_view_ty<'a>() -> FnTy<'a> { let n = Ident::new("n"); let d = Ident::new("d"); let n_nat = IdentKinded { @@ -908,7 +908,7 @@ fn to_view_ty() -> FnTy { // rev/rev_mut: // (&r W m [[d; n]]) -> &r W m [[d; n]] -fn reverse_ty() -> FnTy { +fn reverse_ty<'a>() -> FnTy<'a> { let n = Ident::new("n"); let d = Ident::new("d"); let n_nat = IdentKinded { @@ -942,7 +942,7 @@ fn reverse_ty() -> FnTy { } //map_mut:(|d| -[ex]-> d2, [[d;n]]) -[ex: Any]-> [[d2; n]] -fn map_ty() -> FnTy { +fn map_ty<'a>() -> FnTy<'a> { let d = Ident::new("d"); let d2 = Ident::new("d2"); let n = Ident::new("n"); @@ -1002,7 +1002,7 @@ fn map_ty() -> FnTy { // group/group_mut: // ([[d; n]]) -> [[ [[d; size]]; n/size ]] -fn group_ty() -> FnTy { +fn group_ty<'a>() -> FnTy<'a> { let s = Ident::new("s"); let n = Ident::new("n"); let d = Ident::new("d"); @@ -1112,7 +1112,7 @@ pub enum TakeSide { // } // select: ([[ d; n ]]) -[a: any]-> [[ d; u-l ]] -fn select_range_ty() -> FnTy { +fn select_range_ty<'a>() -> FnTy<'a> { let l = Ident::new("l"); let u = Ident::new("u"); let n = Ident::new("n"); @@ -1193,7 +1193,7 @@ fn select_range_ty() -> FnTy { // join/join_mut: // (&r W m [[ [[d; n]]; o]]) -> [[d; n*o]] -fn join_ty() -> FnTy { +fn join_ty<'a>() -> FnTy<'a> { let n = Ident::new("n"); let o = Ident::new("o"); let d = Ident::new("d"); @@ -1240,7 +1240,7 @@ fn join_ty() -> FnTy { // transpose: // (&r W m [[ [[d; n]]; o]]) -> &r W m [[ [[d; o]]; n]] -fn transpose_ty() -> FnTy { +fn transpose_ty<'a>() -> FnTy<'a> { let n = Ident::new("n"); let o = Ident::new("o"); let d = Ident::new("d"); diff --git a/src/ty_check/subty.rs b/src/ty_check/subty.rs index 99fe6155..7ea16937 100644 --- a/src/ty_check/subty.rs +++ b/src/ty_check/subty.rs @@ -9,17 +9,17 @@ use super::error::{CtxError, SubTyError}; use crate::arena_ast::*; use std::collections::HashSet; -type SubTyResult = Result; +type SubTyResult<'a, T> = Result>; // FIXME respect memory alaways, somehow provenances can be different is this correct? // τ1 is subtype of τ2 under Δ and Γ, producing Γ′ // Δ; Γ ⊢ τ1 ≲ τ2 ⇒ Γ′ -pub(super) fn check( - kind_ctx: &KindCtx, - ty_ctx: &mut TyCtx, - sub_dty: &DataTy, - super_dty: &DataTy, -) -> SubTyResult<()> { +pub(super) fn check<'a>( + kind_ctx: &'a KindCtx<'a>, + ty_ctx: &'a mut TyCtx<'a>, + sub_dty: &'a DataTy<'a>, + super_dty: &'a DataTy<'a>, +) -> SubTyResult<'a, ()> { use super::Ownership::*; use DataTyKind::*; @@ -70,12 +70,12 @@ pub(super) fn check( // ρ1 outlives ρ2 under Δ and Γ, producing Γ′ // Δ; Γ ⊢ ρ1 :> ρ2 ⇒ Γ′ -fn outlives( - kind_ctx: &KindCtx, - ty_ctx: &mut TyCtx, - longer_prv: &Provenance, - shorter_prv: &Provenance, -) -> SubTyResult<()> { +fn outlives<'a>( + kind_ctx: &'a KindCtx<'a>, + ty_ctx: &'a mut TyCtx<'a>, + longer_prv: &'a Provenance<'a>, + shorter_prv: &'a Provenance<'a>, +) -> SubTyResult<'a, ()> { use Provenance::*; match (longer_prv, shorter_prv) { @@ -109,7 +109,11 @@ fn outlives( // OL-LocalProvenances // Δ; Γ ⊢ r1 :> r2 ⇒ Γ[r2 ↦→ { Γ(r1) ∪ Γ(r2) }] -fn outl_check_val_prvs(ty_ctx: &mut TyCtx, longer: &str, shorter: &str) -> SubTyResult<()> { +fn outl_check_val_prvs<'a>( + ty_ctx: &mut TyCtx<'a>, + longer: &str, + shorter: &str, +) -> SubTyResult<'a, ()> { // CHECK: // NOT CLEAR WHY a. IS NECESSARY // a. for every variable of reference type with r1 in ty_ctx: there must not exist a loan @@ -134,7 +138,7 @@ fn outl_check_val_prvs(ty_ctx: &mut TyCtx, longer: &str, shorter: &str) -> SubTy Ok(()) } -fn longer_occurs_before_shorter(ty_ctx: &TyCtx, longer: &str, shorter: &str) -> bool { +fn longer_occurs_before_shorter<'a>(ty_ctx: &'a TyCtx<'a>, longer: &str, shorter: &str) -> bool { for prv in ty_ctx .prv_mappings() .map(|prv_mappings| prv_mappings.prv.clone()) @@ -148,7 +152,7 @@ fn longer_occurs_before_shorter(ty_ctx: &TyCtx, longer: &str, shorter: &str) -> panic!("Neither provenance found in typing context") } -fn exists_deref_loan_with_prv(ty_ctx: &TyCtx, prv: &str) -> bool { +fn exists_deref_loan_with_prv<'a>(ty_ctx: &'a TyCtx<'a>, prv: &str) -> bool { ty_ctx .all_places() .into_iter() @@ -171,7 +175,7 @@ fn exists_deref_loan_with_prv(ty_ctx: &TyCtx, prv: &str) -> bool { }) } -fn outl_check_val_ident_prv(ty_ctx: &TyCtx, longer_val: &str) -> SubTyResult<()> { +fn outl_check_val_ident_prv<'a>(ty_ctx: &'a TyCtx<'a>, longer_val: &str) -> SubTyResult<'a, ()> { // TODO how could the set ever be empty? let loan_set = ty_ctx.loans_in_prv(longer_val)?; if loan_set.is_empty() { @@ -183,19 +187,22 @@ fn outl_check_val_ident_prv(ty_ctx: &TyCtx, longer_val: &str) -> SubTyResult<()> } // FIXME Makes no sense! -fn borrowed_pl_expr_no_ref_to_existing_pl(ty_ctx: &TyCtx, loan_set: &HashSet) -> bool { +fn borrowed_pl_expr_no_ref_to_existing_pl<'a>( + ty_ctx: &'a TyCtx<'a>, + loan_set: &HashSet>, +) -> bool { ty_ctx .all_places() .iter() .any(|(pl, _)| loan_set.iter().any(|loan| loan.place_expr.equiv(pl))) } -fn outl_check_ident_val_prv( - kind_ctx: &KindCtx, - ty_ctx: &TyCtx, - longer_ident: &Ident, +fn outl_check_ident_val_prv<'a>( + kind_ctx: &'a KindCtx<'a>, + ty_ctx: &'a TyCtx<'a>, + longer_ident: &'a Ident<'a>, shorter_val: &str, -) -> SubTyResult<()> { +) -> SubTyResult<'a, ()> { if !kind_ctx.ident_of_kind_exists(longer_ident, Kind::Provenance) { return Err(SubTyError::CtxError(CtxError::PrvIdentNotFound( longer_ident.clone(), @@ -211,12 +218,12 @@ fn outl_check_ident_val_prv( // Δ; Γ ⊢ List[ρ1 :> ρ2] ⇒ Γ′ pub(super) fn multiple_outlives<'a, I>( - kind_ctx: &KindCtx, - ty_ctx: &mut TyCtx, + kind_ctx: &'a KindCtx<'a>, + ty_ctx: &'a mut TyCtx<'a>, prv_rels: I, -) -> SubTyResult<()> +) -> SubTyResult<'a, ()> where - I: IntoIterator, + I: IntoIterator, &'a Provenance<'a>)>, { for prv_rel in prv_rels { let (longer, shorter) = prv_rel; diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index b625d196..d8116dc1 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -7,19 +7,19 @@ use crate::ty_check::error::UnifyError; use crate::ty_check::subty; use std::collections::HashMap; -type UnifyResult = Result; +type UnifyResult<'a, T> = Result>; -pub(super) fn unify(t1: &mut C, t2: &mut C) -> UnifyResult<()> { +pub(super) fn unify<'a, C: Constrainable<'a>>(t1: &mut C, t2: &mut C) -> UnifyResult<'a, ()> { let (_, _) = constrain(t1, t2)?; Ok(()) } -pub(super) fn sub_unify( +pub(super) fn sub_unify<'a, C: Constrainable<'a>>( kind_ctx: &KindCtx, ty_ctx: &mut TyCtx, sub: &mut C, sup: &mut C, -) -> UnifyResult<()> { +) -> UnifyResult<'a, ()> { let (_, prv_rels) = constrain(sub, sup)?; subty::multiple_outlives( kind_ctx, @@ -29,17 +29,17 @@ pub(super) fn sub_unify( Ok(()) } -pub(super) fn constrain( +pub(super) fn constrain<'a, S: Constrainable<'a>>( t1: &mut S, t2: &mut S, -) -> UnifyResult<(ConstrainMap, Vec)> { +) -> UnifyResult<'a, (ConstrainMap<'a>, Vec>)> { let mut constr_map = ConstrainMap::new(); let mut prv_rels = Vec::new(); t1.constrain(t2, &mut constr_map, &mut prv_rels)?; Ok((constr_map, prv_rels)) } -pub(super) fn inst_fn_ty_scheme(fn_ty: &FnTy) -> FnTy { +pub(super) fn inst_fn_ty_scheme<'a>(fn_ty: &'a FnTy<'a>) -> FnTy<'a> { assert!( fn_ty.generic_exec.is_none(), "exec must be substituted before instantiation to make sure that it has the correct type" @@ -66,19 +66,19 @@ pub(super) fn inst_fn_ty_scheme(fn_ty: &FnTy) -> FnTy { } #[derive(Debug, PartialEq, Eq, Clone)] -pub(super) struct PrvConstr(pub Provenance, pub Provenance); +pub(super) struct PrvConstr<'a>(pub Provenance<'a>, pub Provenance<'a>); #[derive(Debug)] -pub(super) struct ConstrainMap { +pub(super) struct ConstrainMap<'a> { // TODO swap Box for something more abstract, like Symbol or Identifier - pub dty_unifier: HashMap, DataTy>, - pub nat_unifier: HashMap, Nat>, - pub mem_unifier: HashMap, Memory>, - pub prv_unifier: HashMap, Provenance>, - pub exec_unifier: HashMap, ExecExpr>, + pub dty_unifier: HashMap, DataTy<'a>>, + pub nat_unifier: HashMap, Nat<'a>>, + pub mem_unifier: HashMap, Memory<'a>>, + pub prv_unifier: HashMap, Provenance<'a>>, + pub exec_unifier: HashMap, ExecExpr<'a>>, } -impl ConstrainMap { +impl<'a> ConstrainMap<'a> { fn new() -> Self { ConstrainMap { dty_unifier: HashMap::new(), @@ -90,8 +90,12 @@ impl ConstrainMap { } } -impl DataTy { - fn bind_to(&self, ident: &Ident, constr_map: &mut ConstrainMap) -> UnifyResult<()> { +impl<'a> DataTy<'a> { + fn bind_to( + &self, + ident: &'a Ident<'a>, + constr_map: &'a mut ConstrainMap<'a>, + ) -> UnifyResult<'a, ()> { if let DataTyKind::Ident(ty_id) = &self.dty { if ty_id == ident { return Ok(()); @@ -121,29 +125,29 @@ impl DataTy { } } -pub(super) trait Substitutable { - fn substitute(&mut self, subst: &ConstrainMap); +pub(super) trait Substitutable<'a> { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>); } -pub(super) trait Constrainable: Visitable + Substitutable { +pub(super) trait Constrainable<'a>: Visitable<'a> + Substitutable<'a> { fn constrain( &mut self, other: &mut Self, constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, + prv_rels: &mut Vec>, ) -> UnifyResult<()>; - fn occurs_check(ident_kinded: &IdentKinded, s: &S) -> bool { + fn occurs_check>(ident_kinded: &'a IdentKinded<'a>, s: &S) -> bool { utils::free_kinded_idents(s).contains(ident_kinded) } } -impl Constrainable for FnTy { +impl<'a> Constrainable<'a> for FnTy<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, - ) -> UnifyResult<()> { + constr_map: &mut ConstrainMap<'a>, + prv_rels: &mut Vec>, + ) -> UnifyResult<'a, ()> { assert!(self.generics.is_empty()); assert!(other.generics.is_empty()); assert!(self.generic_exec.is_none()); @@ -180,20 +184,20 @@ impl Constrainable for FnTy { } } -impl Substitutable for FnTy { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for FnTy<'a> { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_fn_ty(self); } } -impl Constrainable for ParamSig { +impl<'a> Constrainable<'a> for ParamSig<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, - ) -> UnifyResult<()> { + constr_map: &'a mut ConstrainMap<'a>, + prv_rels: &'a mut Vec>, + ) -> UnifyResult<'a, ()> { self.exec_expr .constrain(&mut other.exec_expr, constr_map, prv_rels)?; substitute(constr_map, self); @@ -205,8 +209,8 @@ impl Constrainable for ParamSig { } } -impl Substitutable for ParamSig { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for ParamSig<'a> { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_param_sig(self); } @@ -214,12 +218,12 @@ impl Substitutable for ParamSig { // TODO unification for exec expressions necessary for Nats? Can this be moved into a separate // equality check? -impl Constrainable for ExecExpr { +impl<'a> Constrainable<'a> for ExecExpr<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, + constr_map: &mut ConstrainMap<'a>, + prv_rels: &mut Vec>, ) -> UnifyResult<()> { match (&mut self.exec.base, &mut other.exec.base) { (BaseExec::Ident(i1), BaseExec::Ident(i2)) => { @@ -288,19 +292,19 @@ impl Constrainable for ExecExpr { } } -impl Substitutable for ExecExpr { +impl<'a> Substitutable<'a> for ExecExpr<'a> { fn substitute(&mut self, subst: &ConstrainMap) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_exec_expr(self); } } -impl Constrainable for Ty { +impl<'a> Constrainable<'a> for Ty<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, + constr_map: &'a mut ConstrainMap<'a>, + prv_rels: &'a mut Vec>, ) -> UnifyResult<()> { match (&mut self.ty, &mut other.ty) { (TyKind::FnTy(fn_ty1), TyKind::FnTy(fn_ty2)) => { @@ -312,19 +316,19 @@ impl Constrainable for Ty { } } -impl Substitutable for Ty { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for Ty<'a> { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_ty(self); } } -impl Constrainable for DataTy { +impl<'a> Constrainable<'a> for DataTy<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, + constr_map: &'a mut ConstrainMap<'a>, + prv_rels: &'a mut Vec>, ) -> UnifyResult<()> { match (&mut self.dty, &mut other.dty) { (DataTyKind::Ident(i1), DataTyKind::Ident(i2)) => { @@ -472,19 +476,19 @@ impl Constrainable for DataTy { } } -impl Substitutable for DataTy { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for DataTy<'a> { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_dty(self); } } -impl Constrainable for ExecTy { +impl<'a> Constrainable<'a> for ExecTy<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, + constr_map: &'a mut ConstrainMap<'a>, + prv_rels: &'a mut Vec>, ) -> UnifyResult<()> { match (&mut self.ty, &mut other.ty) { (ExecTyKind::CpuThread, ExecTyKind::CpuThread) @@ -517,19 +521,19 @@ impl Constrainable for ExecTy { } } -impl Substitutable for ExecTy { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for ExecTy<'a> { + fn substitute(&mut self, subst: &#a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_exec_ty(self); } } -impl Constrainable for Dim { +impl<'a> Constrainable<'a> for Dim<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, + constr_map: &'a mut ConstrainMap<'a>, + prv_rels: &'a mut Vec>, ) -> UnifyResult<()> { match (self, other) { (Dim::XYZ(ldim), Dim::XYZ(rdim)) => { @@ -551,20 +555,20 @@ impl Constrainable for Dim { } } -impl Substitutable for Dim { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for Dim<'a> { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_dim(self); } } -impl Nat { +impl<'a> Nat<'a> { fn bind_to( &self, - ident: &Ident, - constr_map: &mut ConstrainMap, - _: &mut Vec, - ) -> UnifyResult<()> { + ident: &'a Ident<'a>, + constr_map: &'a mut ConstrainMap<'a>, + _: &'a mut Vec>, + ) -> UnifyResult<'a, ()> { // No occurs check. // Nats can be equal to an expression in which the nat appears again. E.g., a = a * 1 if let Some(old) = constr_map @@ -594,12 +598,12 @@ impl Nat { } } -impl Constrainable for Nat { - fn constrain( +impl<'a> Constrainable<'a> for Nat<'a> { + fn constrain<'a>( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, + constr_map: &'a mut ConstrainMap<'a>, + prv_rels: &'a mut Vec>, ) -> UnifyResult<()> { match (&mut *self, &mut *other) { (Nat::Ident(n1i), Nat::Ident(n2i)) if n1i.is_implicit || n2i.is_implicit => { @@ -625,15 +629,15 @@ impl Constrainable for Nat { } } -impl Substitutable for Nat { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for Nat<'a> { + fn substitute<'a>(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_nat(self); } } -impl Memory { - fn bind_to(&self, ident: &Ident, constr_map: &mut ConstrainMap) -> UnifyResult<()> { +impl<'a> Memory<'a> { + fn bind_to<'a>(&self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>) -> UnifyResult<'a, ()> { if Self::occurs_check(&IdentKinded::new(ident, Kind::Memory), self) { return Err(UnifyError::InfiniteType); } @@ -663,12 +667,12 @@ impl Memory { } } -impl Constrainable for Memory { - fn constrain( +impl<'a> Constrainable<'a> for Memory<'a> { + fn constrain<'a>( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - _prv_rels: &mut Vec, + constr_map: &'a mut ConstrainMap<'a>, + _prv_rels: &'a mut Vec>, ) -> UnifyResult<()> { match (&*self, &*other) { (Memory::Ident(i1), Memory::Ident(i2)) if i1 == i2 => Ok(()), @@ -684,15 +688,15 @@ impl Constrainable for Memory { } } -impl Substitutable for Memory { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for Memory<'a> { + fn substitute<'a>(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_mem(self); } } -impl Provenance { - fn bind_to(&self, ident: &Ident, constr_map: &mut ConstrainMap) -> UnifyResult<()> { +impl<'a> Provenance<'a> { + fn bind_to(&self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>) -> UnifyResult<'a, ()> { // TODO not necessary, since no recursion possible if Self::occurs_check(&IdentKinded::new(ident, Kind::Provenance), self) { return Err(UnifyError::InfiniteType); @@ -723,12 +727,12 @@ impl Provenance { } } -impl Constrainable for Provenance { +impl<'a> Constrainable<'a> for Provenance<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec, + constr_map: &'a mut ConstrainMap<'a>, + prv_rels: &'a mut Vec>, ) -> UnifyResult<()> { // TODO restructure cases for less? match (&*self, &*other) { @@ -748,36 +752,36 @@ impl Constrainable for Provenance { } } -impl Substitutable for Provenance { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for Provenance<'a> { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_prv(self); } } -impl Substitutable for View { - fn substitute(&mut self, subst: &ConstrainMap) { +impl<'a> Substitutable<'a> for View<'a> { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_view(self); } } -pub(super) fn substitute(subst: &ConstrainMap, s: &mut S) { +pub(super) fn substitute<'a, S: Substitutable<'a>>(subst: &'a ConstrainMap<'a>, s: &mut S) { s.substitute(subst) } pub(super) struct ApplySubst<'a> { - subst: &'a ConstrainMap, + subst: &'a ConstrainMap<'a>, } impl<'a> ApplySubst<'a> { - pub(super) fn new(subst: &'a ConstrainMap) -> Self { + pub(super) fn new(subst: &'a ConstrainMap<'a>) -> Self { ApplySubst { subst } } } -impl<'a> VisitMut for ApplySubst<'a> { - fn visit_nat(&mut self, nat: &mut Nat) { +impl<'a> VisitMut<'a> for ApplySubst<'a> { + fn visit_nat(&mut self, nat: &'a mut Nat<'a>) { match nat { Nat::Ident(ident) if self.subst.nat_unifier.contains_key(&ident.name) => { *nat = self.subst.nat_unifier.get(&ident.name).unwrap().clone(); @@ -786,7 +790,7 @@ impl<'a> VisitMut for ApplySubst<'a> { } } - fn visit_mem(&mut self, mem: &mut Memory) { + fn visit_mem(&mut self, mem: &'a mut Memory<'a>) { match mem { Memory::Ident(ident) if self.subst.mem_unifier.contains_key(&ident.name) => { *mem = self.subst.mem_unifier.get(&ident.name).unwrap().clone(); @@ -795,7 +799,7 @@ impl<'a> VisitMut for ApplySubst<'a> { } } - fn visit_prv(&mut self, prv: &mut Provenance) { + fn visit_prv(&mut self, prv: &'a mut Provenance<'a>) { match prv { Provenance::Ident(ident) if self.subst.prv_unifier.contains_key(&ident.name) => { *prv = self.subst.prv_unifier.get(&ident.name).unwrap().clone() @@ -804,7 +808,7 @@ impl<'a> VisitMut for ApplySubst<'a> { } } - fn visit_dty(&mut self, dty: &mut DataTy) { + fn visit_dty(&mut self, dty: &'a mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) if self.subst.dty_unifier.contains_key(&ident.name) => { *dty = self.subst.dty_unifier.get(&ident.name).unwrap().clone() @@ -814,19 +818,19 @@ impl<'a> VisitMut for ApplySubst<'a> { } } -struct SubstIdent<'a, S: Constrainable> { - ident: &'a Ident, +struct SubstIdent<'a, S: Constrainable<'a>> { + ident: &'a Ident<'a>, term: &'a S, } -impl<'a, S: Constrainable> SubstIdent<'a, S> { +impl<'a, S: Constrainable<'a>> SubstIdent<'a, S> { fn new(ident: &'a Ident, term: &'a S) -> Self { SubstIdent { ident, term } } } -impl<'a> VisitMut for SubstIdent<'a, Nat> { - fn visit_nat(&mut self, nat: &mut Nat) { +impl<'a> VisitMut<'a> for SubstIdent<'a, Nat<'a>> { + fn visit_nat(&mut self, nat: &'a mut Nat<'a>) { match nat { Nat::Ident(ident) if ident.name == self.ident.name => *nat = self.term.clone(), _ => visit_mut::walk_nat(self, nat), @@ -834,8 +838,8 @@ impl<'a> VisitMut for SubstIdent<'a, Nat> { } } -impl<'a> VisitMut for SubstIdent<'a, Memory> { - fn visit_mem(&mut self, mem: &mut Memory) { +impl<'a> VisitMut<'a> for SubstIdent<'a, Memory<'a>> { + fn visit_mem(&mut self, mem: &'a mut Memory<'a>) { match mem { Memory::Ident(ident) if ident.name == self.ident.name => *mem = self.term.clone(), _ => visit_mut::walk_mem(self, mem), @@ -843,8 +847,8 @@ impl<'a> VisitMut for SubstIdent<'a, Memory> { } } -impl<'a> VisitMut for SubstIdent<'a, Provenance> { - fn visit_prv(&mut self, prv: &mut Provenance) { +impl<'a> VisitMut<'a> for SubstIdent<'a, Provenance<'a>> { + fn visit_prv(&mut self, prv: &'a mut Provenance) { match prv { Provenance::Ident(ident) if ident.name == self.ident.name => *prv = self.term.clone(), _ => visit_mut::walk_prv(self, prv), @@ -852,8 +856,8 @@ impl<'a> VisitMut for SubstIdent<'a, Provenance> { } } -impl<'a> VisitMut for SubstIdent<'a, DataTy> { - fn visit_dty(&mut self, dty: &mut DataTy) { +impl<'a> VisitMut<'a> for SubstIdent<'a, DataTy<'a>> { + fn visit_dty(&mut self, dty: &'a mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) if ident.name == self.ident.name => *dty = self.term.clone(), _ => visit_mut::walk_dty(self, dty), @@ -861,8 +865,8 @@ impl<'a> VisitMut for SubstIdent<'a, DataTy> { } } -impl<'a> VisitMut for SubstIdent<'a, ExecExpr> { - fn visit_exec_expr(&mut self, exec: &mut ExecExpr) { +impl<'a> VisitMut<'a> for SubstIdent<'a, ExecExpr<'a>> { + fn visit_exec_expr(&mut self, exec: &'a mut ExecExpr<'a>) { if let BaseExec::Ident(i) = &exec.exec.base { if i.name == self.ident.name { let mut subst_exec = self.term.clone(); From 0484edc49a4643c6246e01a48b75883f71e2509c Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 24 Jul 2025 12:58:27 +0200 Subject: [PATCH 33/57] codegen simple changes to integrate lifetimes --- src/codegen/cu_ast.rs | 170 ++++++++++----------- src/codegen/mod.rs | 332 ++++++++++++++++++++++++----------------- src/codegen/printer.rs | 20 +-- 3 files changed, 287 insertions(+), 235 deletions(-) diff --git a/src/codegen/cu_ast.rs b/src/codegen/cu_ast.rs index eda2f46e..2e0a4ada 100644 --- a/src/codegen/cu_ast.rs +++ b/src/codegen/cu_ast.rs @@ -2,26 +2,26 @@ use crate::arena_ast::Nat; pub(super) enum Item<'a> { Include(String), - FunDecl(&'a FnSig), - FnDef(Box), + FunDecl(&'a FnSig<'a>), + FnDef(Box>), MultiLineComment(String), } #[derive(Clone)] -pub(super) struct FnSig { +pub(super) struct FnSig<'a> { pub(super) name: String, - pub(super) templ_params: Vec, - pub(super) params: Vec, - pub(super) ret_ty: Ty, + pub(super) templ_params: Vec>, + pub(super) params: Vec>, + pub(super) ret_ty: Ty<'a>, pub(super) exec_kind: ExecKind, } -impl FnSig { +impl<'a> FnSig<'a> { pub(super) fn new( name: String, - templ_params: Vec, - params: Vec, - ret_ty: Ty, + templ_params: Vec>, + params: Vec>, + ret_ty: Ty<'a>, exec_kind: ExecKind, ) -> Self { FnSig { @@ -42,135 +42,135 @@ pub(super) enum ExecKind { } #[derive(Clone)] -pub(super) struct FnDef { - pub(super) fn_sig: FnSig, - pub(super) body: Stmt, +pub(super) struct FnDef<'a> { + pub(super) fn_sig: FnSig<'a>, + pub(super) body: Stmt<'a>, } -impl FnDef { - pub(super) fn new(fn_sig: FnSig, body: Stmt) -> Self { +impl<'a> FnDef<'a> { + pub(super) fn new(fn_sig: FnSig<'a>, body: Stmt<'a>) -> Self { FnDef { fn_sig, body } } } #[derive(Clone, Debug)] -pub(super) struct ParamDecl { +pub(super) struct ParamDecl<'a> { pub(super) name: String, - pub(super) ty: Ty, + pub(super) ty: Ty<'a>, } #[derive(Clone, Debug)] -pub(super) enum Stmt { +pub(super) enum Stmt<'a> { Skip, VarDecl { name: String, - ty: Ty, + ty: Ty<'a>, addr_space: Option, - expr: Option, + expr: Option>, is_extern: bool, }, - Block(Box), - Seq(Vec), - Expr(Expr), + Block(Box>), + Seq(Vec>), + Expr(Expr<'a>), If { - cond: Expr, - body: Box, + cond: Expr<'a>, + body: Box>, }, IfElse { - cond: Expr, - true_body: Box, - false_body: Box, + cond: Expr<'a>, + true_body: Box>, + false_body: Box>, }, While { - cond: Expr, - stmt: Box, + cond: Expr<'a>, + stmt: Box>, }, ForLoop { - init: Box, - cond: Expr, - iter: Expr, - stmt: Box, + init: Box>, + cond: Expr<'a>, + iter: Expr<'a>, + stmt: Box>, }, - Return(Option), - ExecKernel(Box), + Return(Option>), + ExecKernel(Box>), } #[derive(Clone, Debug)] -pub(super) struct ExecKernel { +pub(super) struct ExecKernel<'a> { pub fun_name: String, - pub template_args: Vec, - pub grid_dim: Box, - pub block_dim: Box, - pub shared_mem_bytes: Box, - pub args: Vec, + pub template_args: Vec>, + pub grid_dim: Box>, + pub block_dim: Box>, + pub shared_mem_bytes: Box>, + pub args: Vec>, } #[derive(Clone, Debug)] -pub(super) enum Expr { +pub(super) enum Expr<'a> { Empty, Ident(String), Lit(Lit), Assign { - lhs: Box, - rhs: Box, + lhs: Box>, + rhs: Box>, }, Lambda { - captures: Vec, - params: Vec, - body: Box, - ret_ty: Ty, + captures: Vec>, + params: Vec>, + body: Box>, + ret_ty: Ty<'a>, is_dev_fun: bool, }, - FnCall(FnCall), + FnCall(FnCall<'a>), UnOp { op: UnOp, - arg: Box, + arg: Box>, }, BinOp { op: BinOp, - lhs: Box, - rhs: Box, + lhs: Box>, + rhs: Box>, }, Cast { - expr: Box, - ty: Ty, + expr: Box>, + ty: Ty<'a>, }, ArraySubscript { - array: Box, - index: Nat, + array: Box>, + index: Nat<'a>, }, Proj { - tuple: Box, + tuple: Box>, n: usize, }, FieldProj { - struct_expr: Box, + struct_expr: Box>, field_name: String, }, InitializerList { - elems: Vec, + elems: Vec>, }, AtomicRef { - expr: Box, - base_ty: Ty, + expr: Box>, + base_ty: Ty<'a>, }, - Ref(Box), - Deref(Box), - Tuple(Vec), + Ref(Box>), + Deref(Box>), + Tuple(Vec>), // The current plan for Nats is to simply print them with C syntax. // Instead generate a C/Cuda expression? - Nat(Nat), + Nat(Nat<'a>), } #[derive(Clone, Debug)] -pub(super) struct FnCall { - pub fun: Box, - pub template_args: Vec, - pub args: Vec, +pub(super) struct FnCall<'a> { + pub fun: Box>, + pub template_args: Vec>, + pub args: Vec>, } -impl FnCall { - pub fn new(fun: Expr, template_args: Vec, args: Vec) -> Self { +impl<'a> FnCall<'a> { + pub fn new(fun: Expr<'a>, template_args: Vec>, args: Vec>) -> Self { FnCall { fun: Box::new(fun), template_args, @@ -218,15 +218,15 @@ pub(super) enum BinOp { } #[derive(Clone)] -pub(super) enum TemplParam { - Value { param_name: String, ty: Ty }, +pub(super) enum TemplParam<'a> { + Value { param_name: String, ty: Ty<'a> }, TyName { name: String }, } #[derive(Clone, Debug)] -pub(super) enum TemplateArg { - Expr(Expr), - Ty(Ty), +pub(super) enum TemplateArg<'a> { + Expr(Expr<'a>), + Ty(Ty<'a>), } #[derive(Clone, Debug)] @@ -237,21 +237,21 @@ pub(super) enum GpuAddrSpace { } #[derive(Clone, Debug)] -pub(super) enum Ty { +pub(super) enum Ty<'a> { Scalar(ScalarTy), - Tuple(Vec), - Array(Box, Nat), - CArray(Box, Option), - Buffer(Box, BufferKind), + Tuple(Vec>), + Array(Box>, Nat<'a>), + CArray(Box>, Option>), + Buffer(Box>, BufferKind), // for now assume every pointer to be __restrict__ qualified // http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf#page=122&zoom=auto,-205,535 - Ptr(Box), + Ptr(Box>), // The pointer itself is mutable, but the underlying data is not. - PtrConst(Box), + PtrConst(Box>), // const in a parameter declaration changes the parameter type in a definition but not // "necessarily" the function signature ... https://abseil.io/tips/109 // Top-level const - Const(Box), + Const(Box>), // Template parameter identifer Ident(String), } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 1628aa55..766db7c0 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -14,7 +14,7 @@ pub(crate) static WARP_IDENT: &str = "$warp"; // Precondition. all function definitions are successfully typechecked and // therefore every subexpression stores a type -pub fn gen(comp_unit: &desc::CompilUnit, idx_checks: bool) -> String { +pub fn gen<'a>(comp_unit: &'a desc::CompilUnit<'a>, idx_checks: bool) -> String { let mut initial_fns_to_generate = collect_initial_fns_to_generate(comp_unit); let mut codegen_ctx = CodegenCtx::new( // CpuThread is only a dummy and will be set according to the generated function. @@ -74,7 +74,9 @@ pub fn gen(comp_unit: &desc::CompilUnit, idx_checks: bool) -> String { printer::print(&cu_program) } -fn collect_initial_fns_to_generate(comp_unit: &desc::CompilUnit) -> Vec { +fn collect_initial_fns_to_generate<'a>( + comp_unit: &'a desc::CompilUnit<'a>, +) -> Vec> { comp_unit .items .iter() @@ -142,11 +144,11 @@ fn collect_initial_fns_to_generate(comp_unit: &desc::CompilUnit) -> Vec cu::Stmt, +fn mv_shrd_mem_params_into_decls<'a>( + mut f: cu::FnDef<'a>, + unnamed_shrd_mem_decls: &dyn Fn(&[String]) -> cu::Stmt<'a>, num_shared_mem_decls: usize, -) -> cu::FnDef { +) -> cu::FnDef<'a> { if let cu::Stmt::Block(stmt) = f.body { let shrd_mem_params = f .fn_sig @@ -179,16 +181,16 @@ fn collect_fn_decls<'a>(items: &'a [cu::Item<'a>]) -> Vec> { } struct CodegenCtx<'a> { - view_ctx: ViewCtx, - inst_fn_ctx: HashMap, - exec_mapping: ExecMapping, - exec: desc::ExecExpr, - comp_unit: &'a [desc::Item], + view_ctx: ViewCtx<'a>, + inst_fn_ctx: HashMap>, + exec_mapping: ExecMapping<'a>, + exec: desc::ExecExpr<'a>, + comp_unit: &'a [desc::Item<'a>], kernel_infos: Vec, } impl<'a> CodegenCtx<'a> { - fn new(exec: desc::ExecExpr, comp_unit: &'a [desc::Item]) -> Self { + fn new(exec: desc::ExecExpr<'a>, comp_unit: &'a [desc::Item<'a>]) -> Self { CodegenCtx { view_ctx: ViewCtx::new(), inst_fn_ctx: HashMap::new(), @@ -216,8 +218,8 @@ struct KernelInfo { num_shrd_mem_decls: usize, } -type ViewCtx = ScopeCtx; -type ExecMapping = ScopeCtx; +type ViewCtx<'a> = ScopeCtx>; +type ExecMapping<'a> = ScopeCtx>; #[derive(Default, Clone, Debug)] struct ScopeCtx { @@ -269,7 +271,10 @@ impl ScopeCtx { } } -fn gen_fun_def(gl_fun: &desc::FunDef, codegen_ctx: &mut CodegenCtx) -> cu::FnDef { +fn gen_fun_def<'a>( + gl_fun: &'a desc::FunDef<'a>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::FnDef<'a> { let desc::FunDef { ident: name, generic_params: ty_idents, @@ -312,7 +317,11 @@ fn gen_fun_def(gl_fun: &desc::FunDef, codegen_ctx: &mut CodegenCtx) -> cu::FnDef } // Generate CUDA code for Descend syntax that allows sequencing. -fn gen_stmt(expr: &desc::Expr, return_value: bool, codegen_ctx: &mut CodegenCtx) -> cu::Stmt { +fn gen_stmt<'a>( + expr: &'a desc::Expr<'a>, + return_value: bool, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Stmt<'a> { use desc::ExprKind::*; match &expr.expr { Let(pattern, _, e) => { @@ -498,7 +507,11 @@ fn gen_stmt(expr: &desc::Expr, return_value: bool, codegen_ctx: &mut CodegenCtx) } } -fn gen_let(pattern: &desc::Pattern, e: &desc::Expr, codegen_ctx: &mut CodegenCtx) -> cu::Stmt { +fn gen_let<'a>( + pattern: &'a desc::Pattern<'a>, + e: &'a desc::Expr<'a>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Stmt<'a> { match pattern { desc::Pattern::Tuple(tuple_elems) => { let tuple_ident = desc::Ident::new(&desc::utils::fresh_name("tuple")); @@ -550,12 +563,12 @@ fn gen_let(pattern: &desc::Pattern, e: &desc::Expr, codegen_ctx: &mut CodegenCtx } } -fn gen_decl_init( - ident: &desc::Ident, +fn gen_decl_init<'a>( + ident: &'a desc::Ident<'a>, mutbl: desc::Mutability, - e: &desc::Expr, - codegen_ctx: &mut CodegenCtx, -) -> cu::Stmt { + e: &'a desc::Expr<'a>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Stmt<'a> { //let gened_ty = gen_ty(&e.ty.as_ref().unwrap().ty, mutbl); let (init_expr, cu_ty) = if let desc::ExprKind::Ref(_, _, pl_expr) = &e.expr { match &pl_expr.ty.as_ref().unwrap().dty().dty { @@ -618,12 +631,12 @@ fn gen_decl_init( } } -fn gen_if_else( - cond: cu_ast::Expr, - e_tt: &desc::Expr, - e_ff: &desc::Expr, - codegen_ctx: &mut CodegenCtx, -) -> cu::Stmt { +fn gen_if_else<'a>( + cond: cu_ast::Expr<'a>, + e_tt: &'a desc::Expr<'a>, + e_ff: &'a desc::Expr<'a>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Stmt<'a> { cu::Stmt::IfElse { cond: cond, true_body: Box::new(gen_stmt(e_tt, false, codegen_ctx)), @@ -631,19 +644,23 @@ fn gen_if_else( } } -fn gen_if(cond: cu_ast::Expr, e_tt: &desc::Expr, codegen_ctx: &mut CodegenCtx) -> cu::Stmt { +fn gen_if<'a>( + cond: cu_ast::Expr<'a>, + e_tt: &'a desc::Expr<'a>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Stmt<'a> { cu::Stmt::If { cond: cond, body: Box::new(gen_stmt(e_tt, false, codegen_ctx)), } } -fn gen_for_each( - ident: &desc::Ident, - coll_expr: &desc::Expr, - body: &desc::Block, - codegen_ctx: &mut CodegenCtx, -) -> cu::Stmt { +fn gen_for_each<'a>( + ident: &'a desc::Ident<'a>, + coll_expr: &'a desc::Expr<'a>, + body: &'a desc::Block<'a>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Stmt<'a> { todo!(); let i_name = crate::arena_ast::utils::fresh_name("i__"); let i_decl = cu::Stmt::VarDecl { @@ -691,12 +708,12 @@ fn gen_for_each( // for_loop } -fn gen_for_range( - ident: &desc::Ident, - range: &desc::Expr, - body: &desc::Expr, - codegen_ctx: &mut CodegenCtx, -) -> cu::Stmt { +fn gen_for_range<'a>( + ident: &'a desc::Ident<'a>, + range: &'a desc::Expr<'a>, + body: &'a desc::Expr<'a>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Stmt<'a> { if let desc::ExprKind::Range(l, u) = &range.expr { let lower = gen_expr(l, codegen_ctx); let upper = gen_expr(u, codegen_ctx); @@ -733,7 +750,10 @@ fn gen_for_range( } } -fn gen_app_kernel(app_kernel: &desc::AppKernel, codegen_ctx: &mut CodegenCtx) -> cu::Stmt { +fn gen_app_kernel( + app_kernel: &'a desc::AppKernel<'a>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Stmt<'a> { let tmp_global_fn_call = gen_global_fn_call( &app_kernel.fun_ident, &app_kernel.gen_args, @@ -759,14 +779,16 @@ fn gen_app_kernel(app_kernel: &desc::AppKernel, codegen_ctx: &mut CodegenCtx) -> })) } -fn convert_to_fn_name(f_expr: &cu::Expr) -> String { +fn convert_to_fn_name<'a>(f_expr: &'a cu::Expr<'a>) -> String { match f_expr { cu::Expr::Ident(f_name) => f_name.clone(), _ => panic!("The expression does not refer to a function by its identifier."), } } -fn unnamed_shared_mem_decls(dtys: Vec) -> Box cu::Stmt> { +fn unnamed_shared_mem_decls<'a>( + dtys: Vec>, +) -> Box cu::Stmt<'a>> { // Multiple shared memory arrays and Alignments: // Memory accesses require that the address be aligned to a multiple of the access size. // The access size of a memory instruction is the total number of bytes accessed in memory. @@ -841,7 +863,7 @@ fn unnamed_shared_mem_decls(dtys: Vec) -> Box }) } -fn size_of_dty(dty: &desc::DataTy) -> usize { +fn size_of_dty<'a>(dty: &'a desc::DataTy<'a>) -> usize { match &dty.dty { desc::DataTyKind::Scalar(desc::ScalarTy::Bool) => 1, desc::DataTyKind::Scalar(desc::ScalarTy::U32) @@ -855,7 +877,7 @@ fn size_of_dty(dty: &desc::DataTy) -> usize { } } -fn get_elem_ty_and_amount(dty: &desc::DataTy) -> (desc::Ty, desc::Nat) { +fn get_elem_ty_and_amount<'a>(dty: &'a desc::DataTy<'a>) -> (desc::Ty<'a>, desc::Nat<'a>) { let nat_1 = desc::Nat::Lit(1); match &dty.dty { desc::DataTyKind::Scalar(desc::ScalarTy::Bool) @@ -882,7 +904,7 @@ fn get_elem_ty_and_amount(dty: &desc::DataTy) -> (desc::Ty, desc::Nat) { } } -fn count_bytes(dtys: &[desc::DataTy]) -> desc::Nat { +fn count_bytes(dtys: &'a [desc::DataTy<'a>]) -> desc::Nat<'a> { let mut bytes = desc::Nat::Lit(0); for dty in dtys { let (elem_ty, amount) = get_elem_ty_and_amount(dty); @@ -896,7 +918,7 @@ fn count_bytes(dtys: &[desc::DataTy]) -> desc::Nat { bytes } -fn gen_indep(indep: &desc::Split, codegen_ctx: &mut CodegenCtx) -> cu::Stmt { +fn gen_indep<'a>(indep: &'a desc::Split<'a>, codegen_ctx: &'a mut CodegenCtx<'a>) -> cu::Stmt<'a> { let outer_exec = codegen_ctx.exec.clone(); let expanded_outer_exec = expand_exec_expr(codegen_ctx, &outer_exec); codegen_ctx.push_scope(); @@ -947,7 +969,7 @@ fn gen_indep(indep: &desc::Split, codegen_ctx: &mut CodegenCtx) -> cu::Stmt { } } -fn gen_sync_stmt(exec: &desc::ExecExpr) -> cu::Stmt { +fn gen_sync_stmt<'a>(exec: &'a desc::ExecExpr<'a>) -> cu::Stmt<'a> { let sync = cu::Stmt::Expr(cu::Expr::FnCall(cu::FnCall::new( cu::Expr::Ident("__syncthreads".to_string()), vec![], @@ -972,7 +994,7 @@ fn gen_sync_stmt(exec: &desc::ExecExpr) -> cu::Stmt { // } } -fn gen_sched(sched: &desc::Sched, codegen_ctx: &mut CodegenCtx) -> cu::Stmt { +fn gen_sched(sched: &'a desc::Sched<'a>, codegen_ctx: &'a mut CodegenCtx<'a>) -> cu::Stmt<'a> { codegen_ctx.push_scope(); let expanded_sched_exec_expr = expand_exec_expr(codegen_ctx, sched.sched_exec.as_ref()); let inner_exec = desc::ExecExpr::new(expanded_sched_exec_expr.exec.clone().forall(sched.dim)); @@ -1055,7 +1077,7 @@ fn gen_sched(sched: &desc::Sched, codegen_ctx: &mut CodegenCtx) -> cu::Stmt { // } // } -fn gen_expr(expr: &desc::Expr, codegen_ctx: &mut CodegenCtx) -> cu::Expr { +fn gen_expr<'a>(expr: &'a desc::Expr<'a>, codegen_ctx: &'a mut CodegenCtx<'a>) -> cu::Expr<'a> { use desc::ExprKind::*; match &expr.expr { Hole => cu::Expr::Empty, @@ -1235,10 +1257,10 @@ fn gen_expr(expr: &desc::Expr, codegen_ctx: &mut CodegenCtx) -> cu::Expr { } fn gen_lambda_call( - fun: &desc::Expr, - args: &[desc::Expr], - codegen_ctx: &mut CodegenCtx, -) -> cu::Expr { + fun: &'a desc::Expr<'a>, + args: &'a [desc::Expr<'a>], + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Expr<'a> { unimplemented!( "The only case for which this would have to be generated is, when a lambda is called right\ where it is created. There is no way to bind a lambda with let.\ @@ -1246,12 +1268,12 @@ fn gen_lambda_call( ) } -fn gen_global_fn_call( - fun_ident: &desc::Ident, - gen_args: &[desc::ArgKinded], - args: &[desc::Expr], - codegen_ctx: &mut CodegenCtx, -) -> cu::FnCall { +fn gen_global_fn_call<'a>( + fun_ident: &'a desc::Ident<'a>, + gen_args: &'a [desc::ArgKinded<'a>], + args: &'a [desc::Expr<'a>], + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::FnCall<'a> { // Make sure that we do not accidentally add views conflicting to fun, // because during type checking the order is: check fun first then do the arguments. codegen_ctx.push_scope(); @@ -1279,7 +1301,10 @@ fn gen_global_fn_call( } // TODO generate different arguments for views or inline -fn gen_fn_call_args(args: &[desc::Expr], codegen_ctx: &mut CodegenCtx) -> Vec { +fn gen_fn_call_args<'a>( + args: &'a [desc::Expr<'a>], + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> Vec> { args.iter() .map(|arg| gen_expr(arg, codegen_ctx)) // GenState::Gened(cu_expr) => cu_expr, @@ -1290,7 +1315,7 @@ fn gen_fn_call_args(args: &[desc::Expr], codegen_ctx: &mut CodegenCtx) -> Vec desc::PlaceExpr { +fn basis_ref<'a>(view_expr: &'a desc::PlaceExpr<'a>) -> desc::PlaceExpr<'a> { let mut bref = view_expr.clone(); let mut current = view_expr.clone(); while !matches!(¤t.pl_expr, desc::PlaceExprKind::Ident(_)) { @@ -1312,7 +1337,7 @@ fn basis_ref(view_expr: &desc::PlaceExpr) -> desc::PlaceExpr { bref } -fn view_exprs_in_args(args: &[desc::Expr]) -> Vec<&desc::Expr> { +fn view_exprs_in_args<'a>(args: &'a [desc::Expr<'a>]) -> Vec<&'a desc::Expr<'a>> { let (views, _): (Vec<_>, Vec<_>) = args .iter() .partition(|a| is_view_dty(a.ty.as_ref().unwrap())); @@ -1335,7 +1360,7 @@ fn view_exprs_in_args(args: &[desc::Expr]) -> Vec<&desc::Expr> { fn separate_view_params_with_args_from_rest<'a>( param_decls: &'a [desc::ParamDecl], args: &'a [desc::Expr], -) -> Vec<(&'a desc::ParamDecl, &'a desc::Expr)> { +) -> Vec<(&'a desc::ParamDecl<'a>, &'a desc::Expr<'a>)> { let (view_params_with_args, _): (Vec<_>, Vec<_>) = param_decls .iter() .zip(args.iter()) @@ -1356,7 +1381,7 @@ fn separate_view_params_with_args_from_rest<'a>( // } // } -fn stringify_exec(exec: &desc::ExecExpr) -> String { +fn stringify_exec<'a>(exec: &'a desc::ExecExpr<'a>) -> String { let mut str = String::with_capacity(10); for e in &exec.exec.path { match e { @@ -1442,19 +1467,19 @@ fn stringify_exec(exec: &desc::ExecExpr) -> String { // str // } -fn create_named_fn_call( +fn create_named_fn_call<'a>( name: String, - gen_args: Vec, - args: Vec, -) -> cu::FnCall { + gen_args: Vec>, + args: Vec>, +) -> cu::FnCall<'a> { create_fn_call(cu::Expr::Ident(name), gen_args, args) } -fn create_fn_call( - fun: cu::Expr, +fn create_fn_call<'a>( + fun: cu::Expr<'a>, gen_args: Vec, params: Vec, -) -> cu::FnCall { +) -> cu::FnCall<'a> { cu::FnCall { fun: Box::new(fun), template_args: gen_args, @@ -1462,12 +1487,12 @@ fn create_fn_call( } } -fn gen_bin_op_expr( +fn gen_bin_op_expr<'a>( op: &desc::BinOp, - lhs: &desc::Expr, - rhs: &desc::Expr, + lhs: &'a desc::Expr<'a>, + rhs: &'a desc::Expr<'a>, codegen_ctx: &mut CodegenCtx, -) -> cu::Expr { +) -> cu::Expr<'a> { let op = match op { desc::BinOp::Add => cu::BinOp::Add, desc::BinOp::Sub => cu::BinOp::Sub, @@ -1494,7 +1519,7 @@ fn gen_bin_op_expr( } } -fn extract_fn_ident(ident: &desc::Expr) -> desc::Ident { +fn extract_fn_ident<'a>(ident: &'a desc::Expr<'a>) -> desc::Ident<'a> { if let desc::ExprKind::PlaceExpr(pl_expr) = &ident.expr { if let desc::PlaceExprKind::Ident(ident) = &pl_expr.pl_expr { ident.clone() @@ -1506,7 +1531,7 @@ fn extract_fn_ident(ident: &desc::Expr) -> desc::Ident { } } -fn contains_shape_expr(pl_expr: &desc::PlaceExpr, shape_ctx: &ViewCtx) -> bool { +fn contains_shape_expr<'a>(pl_expr: &'a desc::PlaceExpr<'a>, shape_ctx: &ViewCtx) -> bool { let (_, pl) = pl_expr.to_pl_ctx_and_most_specif_pl(); shape_ctx.contains_key(&pl.ident.name) } @@ -1530,7 +1555,7 @@ fn contains_shape_expr(pl_expr: &desc::PlaceExpr, shape_ctx: &ViewCtx) -> bool { // ) // } -fn gen_lit(l: desc::Lit) -> cu::Expr { +fn gen_lit<'a>(l: desc::Lit) -> cu::Expr<'a> { match l { desc::Lit::Bool(b) => cu::Expr::Lit(cu::Lit::Bool(b)), desc::Lit::I32(i) => cu::Expr::Lit(cu::Lit::I32(i)), @@ -1543,15 +1568,15 @@ fn gen_lit(l: desc::Lit) -> cu::Expr { } } -enum IdxOrProj { - Idx(desc::Nat), +enum IdxOrProj<'a> { + Idx(desc::Nat<'a>), Proj(usize), } -fn flattened_elem_counts_per_dim( - dty: &desc::DataTy, - mut elem_counts: Vec, -) -> Vec { +fn flattened_elem_counts_per_dim<'a>( + dty: &'a desc::DataTy<'a>, + mut elem_counts: Vec>, +) -> Vec> { match &dty.dty { desc::DataTyKind::Array(d, n) | desc::DataTyKind::ArrayShape(d, n) => { for elem_count in &mut elem_counts { @@ -1568,16 +1593,16 @@ fn flattened_elem_counts_per_dim( } } -fn gen_pl_expr( - pl_expr: &desc::PlaceExpr, - path: &mut Vec, - codegen_ctx: &mut CodegenCtx, -) -> cu::Expr { - fn gen_flat_indexing( - expr: cu::Expr, - path: &[desc::Nat], - operand_dty: &desc::DataTy, - ) -> cu::Expr { +fn gen_pl_expr<'a>( + pl_expr: &'a desc::PlaceExpr<'a>, + path: &'a mut Vec>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Expr<'a> { + fn gen_flat_indexing<'a>( + expr: cu::Expr<'a>, + path: &'a [desc::Nat<'a>], + operand_dty: &'a desc::DataTy<'a>, + ) -> cu::Expr<'a> { let elem_counts = flattened_elem_counts_per_dim(operand_dty, vec![]); let mut elem_counts_iter = elem_counts.iter(); // skip outermost dimension @@ -1668,7 +1693,10 @@ fn gen_pl_expr( } } -fn inline_view_expr(pl_expr: &desc::PlaceExpr, codegen_ctx: &CodegenCtx) -> desc::PlaceExpr { +fn inline_view_expr<'a>( + pl_expr: &'a desc::PlaceExpr<'a>, + codegen_ctx: &'a CodegenCtx<'a>, +) -> desc::PlaceExpr<'a> { let (_, most_spec_pl) = pl_expr.to_pl_ctx_and_most_specif_pl(); if codegen_ctx.view_ctx.contains_key(&most_spec_pl.ident.name) { insert_into_pl_expr( @@ -1680,11 +1708,14 @@ fn inline_view_expr(pl_expr: &desc::PlaceExpr, codegen_ctx: &CodegenCtx) -> desc } } -fn insert_into_pl_expr(mut pl_expr: desc::PlaceExpr, insert: &desc::PlaceExpr) -> desc::PlaceExpr { +fn insert_into_pl_expr<'a>( + mut pl_expr: desc::PlaceExpr<'a>, + insert: &'a desc::PlaceExpr<'a>, +) -> desc::PlaceExpr<'a> { struct InsertIntoPlExpr<'a> { - insert: &'a desc::PlaceExpr, + insert: &'a desc::PlaceExpr<'a>, } - impl VisitMut for InsertIntoPlExpr<'_> { + impl<'a> VisitMut<'a> for InsertIntoPlExpr<'_> { fn visit_pl_expr(&mut self, pl_expr: &mut desc::PlaceExpr) { match &mut pl_expr.pl_expr { desc::PlaceExprKind::Deref(ple) => { @@ -1779,7 +1810,10 @@ fn transform_path_with_view(view: &desc::View, path: &mut Vec) -> boo true } -fn transform_path_with_group(grp_size: &desc::Nat, path: &mut Vec) -> bool { +fn transform_path_with_group<'a>( + grp_size: &'a desc::Nat<'a>, + path: &'a mut Vec>, +) -> bool { let i = path.pop(); let j = path.pop(); match (i, j) { @@ -1807,7 +1841,7 @@ fn transform_path_with_group(grp_size: &desc::Nat, path: &mut Vec) -> } } -fn transform_path_with_rev(len: &desc::Nat, path: &mut Vec) -> bool { +fn transform_path_with_rev<'a>(len: &'a desc::Nat<'a>, path: &'a mut Vec>) -> bool { let i = path.pop(); match i { Some(i) => { @@ -1826,7 +1860,7 @@ fn transform_path_with_rev(len: &desc::Nat, path: &mut Vec) -> bool { } } -fn transform_path_with_transpose(path: &mut Vec) -> bool { +fn transform_path_with_transpose<'a>(path: &'a mut Vec>) -> bool { let i = path.pop(); let j = path.pop(); match (i, j) { @@ -1839,7 +1873,10 @@ fn transform_path_with_transpose(path: &mut Vec) -> bool { } } -fn transform_path_with_join(row_size: &desc::Nat, path: &mut Vec) -> bool { +fn transform_path_with_join<'a>( + row_size: &'a desc::Nat<'a>, + path: &'a mut Vec>, +) -> bool { let i = path.pop(); match i { Some(idx) => { @@ -1859,7 +1896,10 @@ fn transform_path_with_join(row_size: &desc::Nat, path: &mut Vec) -> } } -fn transform_path_with_select_range(lower_bound: &desc::Nat, path: &mut Vec) -> bool { +fn transform_path_with_select_range<'a>( + lower_bound: &'a desc::Nat<'a>, + path: &'a mut Vec>, +) -> bool { let idx = path.pop(); match idx { Some(i) => { @@ -1875,9 +1915,9 @@ fn transform_path_with_select_range(lower_bound: &desc::Nat, path: &mut Vec, +fn transform_path_with_take<'a>( + split_pos: &'a desc::Nat<'a>, + path: &'a mut Vec>, take_side: ty_check::pre_decl::TakeSide, ) -> bool { let idx = path.pop(); @@ -1900,7 +1940,7 @@ fn transform_path_with_take( } } -fn transform_path_with_map(f: &desc::View, path: &mut Vec) -> bool { +fn transform_path_with_map<'a>(f: &'a desc::View<'a>, path: &'a mut Vec>) -> bool { let i = path.pop(); match i { Some(idx) => { @@ -1912,11 +1952,11 @@ fn transform_path_with_map(f: &desc::View, path: &mut Vec) -> bool { } } -fn gen_indep_branch_cond( +fn gen_indep_branch_cond<'a>( dim_compo: desc::DimCompo, - pos: &desc::Nat, - exec: &desc::ExecExprKind, -) -> cu::Expr { + pos: &'a desc::Nat<'a>, + exec: &'a desc::ExecExprKind<'a>, +) -> cu::Expr<'a> { cu::Expr::BinOp { op: cu::BinOp::Lt, lhs: Box::new(cu::Expr::Nat(parall_idx( @@ -1929,7 +1969,7 @@ fn gen_indep_branch_cond( } } -fn gen_templ_params(ty_idents: &[desc::IdentKinded]) -> Vec { +fn gen_templ_params<'a>(ty_idents: &'a [desc::IdentKinded<'a>]) -> Vec> { ty_idents .iter() .filter_map(|ty_ident| { @@ -1942,7 +1982,7 @@ fn gen_templ_params(ty_idents: &[desc::IdentKinded]) -> Vec { .collect() } -fn gen_templ_param(ty_ident: &desc::IdentKinded) -> cu::TemplParam { +fn gen_templ_param<'a>(ty_ident: &'a desc::IdentKinded<'a>) -> cu::TemplParam<'a> { let name = ty_ident.ident.name.clone(); match ty_ident.kind { desc::Kind::Nat => cu::TemplParam::Value { @@ -1963,11 +2003,11 @@ fn gen_templ_param(ty_ident: &desc::IdentKinded) -> cu::TemplParam { } } -fn gen_param_decls(param_decls: &[desc::ParamDecl]) -> Vec { +fn gen_param_decls<'a>(param_decls: &'a [desc::ParamDecl<'a>]) -> Vec> { param_decls.iter().map(gen_param_decl).collect() } -fn gen_param_decl(param_decl: &desc::ParamDecl) -> cu::ParamDecl { +fn gen_param_decl<'a>(param_decl: &'a desc::ParamDecl<'a>) -> cu::ParamDecl<'a> { let desc::ParamDecl { ident, ty, @@ -1980,11 +2020,11 @@ fn gen_param_decl(param_decl: &desc::ParamDecl) -> cu::ParamDecl { } } -fn gen_args_kinded(templ_args: &[desc::ArgKinded]) -> Vec { +fn gen_args_kinded<'a>(templ_args: &'a [desc::ArgKinded<'a>]) -> Vec> { templ_args.iter().filter_map(gen_arg_kinded).collect() } -fn gen_nat_as_u64(templ_args: &[desc::ArgKinded]) -> cu::Expr { +fn gen_nat_as_u64<'a>(templ_args: &'a [desc::ArgKinded<'a>]) -> cu::Expr<'a> { let generated_arg_expr = gen_arg_kinded(&templ_args[0]); if let Some(e) = generated_arg_expr { if let cu::TemplateArg::Expr(expr) = e { @@ -1997,15 +2037,18 @@ fn gen_nat_as_u64(templ_args: &[desc::ArgKinded]) -> cu::Expr { } } -fn gen_to_atomic_array(args: &Vec, codegen_ctx: &mut CodegenCtx) -> cu::Expr { +fn gen_to_atomic_array<'a>( + args: &'a Vec>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Expr<'a> { gen_fn_call_args(args, codegen_ctx)[0].clone() } -fn gen_shfl_up( - args: &Vec, - kinded_args: &Vec, - codegen_ctx: &mut CodegenCtx, -) -> cu::Expr { +fn gen_shfl_up<'a>( + args: &'a Vec>, + kinded_args: &'a Vec>, + codegen_ctx: &'a mut CodegenCtx<'a>, +) -> cu::Expr<'a> { cu::Expr::FnCall(create_fn_call( cu::Expr::Ident(format!("{}.shfl_up", WARP_IDENT)), gen_args_kinded(kinded_args), @@ -2013,7 +2056,7 @@ fn gen_shfl_up( )) } -fn gen_arg_kinded(templ_arg: &desc::ArgKinded) -> Option { +fn gen_arg_kinded<'a>(templ_arg: &'a desc::ArgKinded<'a>) -> Option> { match templ_arg { desc::ArgKinded::Nat(n) => Some(cu::TemplateArg::Expr(cu::Expr::Nat(n.clone()))), desc::ArgKinded::DataTy(dty) => Some(cu::TemplateArg::Ty(gen_ty( @@ -2030,7 +2073,7 @@ fn gen_arg_kinded(templ_arg: &desc::ArgKinded) -> Option { // in cu::Ty::Const. However, the formalism uses this, because it shows the generated code // as opposed to a Cuda-AST and there, the order of the const is different // when it comes to pointers (C things). -fn gen_ty(ty: &desc::TyKind, mutbl: desc::Mutability) -> cu::Ty { +fn gen_ty<'a>(ty: &'a desc::TyKind<'a>, mutbl: desc::Mutability) -> cu::Ty<'a> { use desc::DataTyKind as d; use desc::TyKind::*; @@ -2139,7 +2182,7 @@ fn gen_ty(ty: &desc::TyKind, mutbl: desc::Mutability) -> cu::Ty { } } -fn base_dty(dty: &desc::DataTy) -> desc::DataTy { +fn base_dty<'a>(dty: &desc::DataTy) -> desc::DataTy<'a> { if let desc::DataTyKind::Array(elem_dty, _) = &dty.dty { base_dty(elem_dty) } else { @@ -2161,7 +2204,10 @@ fn is_dev_fun(exec_ty: &desc::ExecTy) -> bool { } } -fn expand_exec_expr(codegen_ctx: &CodegenCtx, exec_expr: &desc::ExecExpr) -> desc::ExecExpr { +fn expand_exec_expr<'a>( + codegen_ctx: &CodegenCtx, + exec_expr: &desc::ExecExpr, +) -> desc::ExecExpr<'a> { match &exec_expr.exec.base { desc::BaseExec::CpuThread | desc::BaseExec::GpuGrid(_, _) => exec_expr.clone(), desc::BaseExec::Ident(ident) => { @@ -2176,7 +2222,9 @@ fn expand_exec_expr(codegen_ctx: &CodegenCtx, exec_expr: &desc::ExecExpr) -> des } } -fn to_parall_indices(exec: &desc::ExecExpr) -> (desc::Nat, desc::Nat, desc::Nat) { +fn to_parall_indices<'a>( + exec: &'a desc::ExecExpr<'a>, +) -> (desc::Nat<'a>, desc::Nat<'a>, desc::Nat<'a>) { let mut indices = match &exec.exec.base { desc::BaseExec::GpuGrid(_, _) => { (desc::Nat::GridIdx, desc::Nat::GridIdx, desc::Nat::GridIdx) @@ -2272,12 +2320,12 @@ fn to_parall_indices(exec: &desc::ExecExpr) -> (desc::Nat, desc::Nat, desc::Nat) indices } -fn contained_par_idx(n: &desc::Nat) -> Option { - struct ContainedParIdx { - par_idx: Option, +fn contained_par_idx<'a>(n: &'a desc::Nat<'a>) -> Option> { + struct ContainedParIdx<'a> { + par_idx: Option>, } - impl Visit for ContainedParIdx { - fn visit_nat(&mut self, n: &desc::Nat) { + impl<'a> Visit<'a> for ContainedParIdx<'a> { + fn visit_nat(&mut self, n: &desc::Nat<'a>) { match n { desc::Nat::GridIdx => self.par_idx = Some(n.clone()), desc::Nat::BlockIdx(_) => self.par_idx = Some(n.clone()), @@ -2292,16 +2340,20 @@ fn contained_par_idx(n: &desc::Nat) -> Option { contained.par_idx } -fn set_distrib_idx(idx: &mut desc::Nat, parall_idx: desc::Nat, shift: &mut desc::Nat) { +fn set_distrib_idx<'a>( + idx: &'a mut desc::Nat<'a>, + parall_idx: desc::Nat<'a>, + shift: &'a mut desc::Nat<'a>, +) { *idx = shift_idx_by(parall_idx, shift.clone()); *shift = desc::Nat::Lit(0); } -fn shift_idx_by(idx: desc::Nat, shift: desc::Nat) -> desc::Nat { +fn shift_idx_by<'a>(idx: desc::Nat<'a>, shift: desc::Nat<'a>) -> desc::Nat<'a> { desc::Nat::BinOp(desc::BinOpNat::Sub, Box::new(idx), Box::new(shift)) } -fn parall_idx(dim: desc::DimCompo, exec: &desc::ExecExpr) -> desc::Nat { +fn parall_idx<'a>(dim: desc::DimCompo, exec: &'a desc::ExecExpr<'a>) -> desc::Nat<'a> { match dim { desc::DimCompo::X => to_parall_indices(exec).0, desc::DimCompo::Y => to_parall_indices(exec).1, @@ -2309,7 +2361,7 @@ fn parall_idx(dim: desc::DimCompo, exec: &desc::ExecExpr) -> desc::Nat { } } -fn gen_dim3(dim: &desc::Dim) -> cu::Expr { +fn gen_dim3<'a>(dim: &'a desc::Dim<'a>) -> cu::Expr<'a> { let one = desc::Nat::Lit(1); let (nx, ny, nz) = match dim { desc::Dim::X(n) => (n.0.clone(), one.clone(), one), @@ -2328,7 +2380,7 @@ fn gen_dim3(dim: &desc::Dim) -> cu::Expr { }) } -fn is_view_dty(ty: &desc::Ty) -> bool { +fn is_view_dty<'a>(ty: &'a desc::Ty<'a>) -> bool { match &ty.ty { desc::TyKind::Data(dty) => match &dty.dty { desc::DataTyKind::Ref(reff) => { diff --git a/src/codegen/printer.rs b/src/codegen/printer.rs index c845b737..5d1560bd 100644 --- a/src/codegen/printer.rs +++ b/src/codegen/printer.rs @@ -60,7 +60,7 @@ impl<'a> std::fmt::Display for Item<'a> { } } -impl std::fmt::Display for FnSig { +impl<'a> std::fmt::Display for FnSig<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let FnSig { name, @@ -81,7 +81,7 @@ impl std::fmt::Display for FnSig { } } -impl std::fmt::Display for FnDef { +impl<'a> std::fmt::Display for FnDef<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let FnDef { fn_sig, body } = self; write!(f, "{}", fn_sig)?; @@ -89,7 +89,7 @@ impl std::fmt::Display for FnDef { } } -impl std::fmt::Display for Ident { +impl<'a> std::fmt::Display for Ident<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.name) } @@ -105,7 +105,7 @@ impl std::fmt::Display for ExecKind { } } -impl std::fmt::Display for Stmt { +impl<'a> std::fmt::Display for Stmt<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { use Stmt::*; match self { @@ -201,7 +201,7 @@ impl std::fmt::Display for Stmt { } } -impl std::fmt::Display for Expr { +impl<'a> std::fmt::Display for Expr<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { use Expr::*; match self { @@ -293,13 +293,13 @@ impl std::fmt::Display for Lit { } } -impl std::fmt::Display for ParamDecl { +impl<'a> std::fmt::Display for ParamDecl<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{} {}", self.ty, self.name) } } -impl std::fmt::Display for TemplateArg { +impl<'a> std::fmt::Display for TemplateArg<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { TemplateArg::Expr(expr) => write!(f, "{}", expr), @@ -308,7 +308,7 @@ impl std::fmt::Display for TemplateArg { } } -impl std::fmt::Display for TemplParam { +impl<'a> std::fmt::Display for TemplParam<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { TemplParam::Value { param_name, ty } => write!(f, "{} {}", ty, param_name), @@ -361,7 +361,7 @@ impl std::fmt::Display for GpuAddrSpace { } } -impl std::fmt::Display for Ty { +impl<'a> std::fmt::Display for Ty<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { use Ty::*; match self { @@ -415,7 +415,7 @@ impl std::fmt::Display for ScalarTy { } } -impl std::fmt::Display for Nat { +impl<'a> std::fmt::Display for Nat<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { Self::Ident(ident) => write!(f, "{}", ident), From b22763d025b1c22a04e8784997f247ee33c0aed1 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 24 Jul 2025 12:59:07 +0200 Subject: [PATCH 34/57] some more simple lifetime integration stuff for ty check --- src/ty_check/borrow_check.rs | 81 ++++++++++++++++++++---------------- src/ty_check/exec.rs | 5 ++- src/ty_check/pl_expr.rs | 12 +++--- src/ty_check/unify.rs | 10 ++--- 4 files changed, 59 insertions(+), 49 deletions(-) diff --git a/src/ty_check/borrow_check.rs b/src/ty_check/borrow_check.rs index 1954943b..c3b43588 100644 --- a/src/ty_check/borrow_check.rs +++ b/src/ty_check/borrow_check.rs @@ -9,15 +9,15 @@ use crate::ty_check::{exec, pre_decl, ExprTyCtx}; use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; use std::collections::HashSet; -type OwnResult = Result; +type OwnResult<'a, T> = Result>; -pub(super) struct BorrowCheckCtx<'gl, 'src, 'ctxt> { +pub(super) struct BorrowCheckCtx<'a, 'gl, 'src, 'ctxt> { // TODO refactor: move into ctx module and remove public pub gl_ctx: &'ctxt GlobalCtx<'gl, 'src>, pub nat_ctx: &'ctxt NatCtx, - pub kind_ctx: &'ctxt KindCtx, + pub kind_ctx: &'ctxt KindCtx<'a>, pub ident_exec: Option<&'ctxt IdentExec<'a>>, - pub ty_ctx: &'ctxt TyCtx, + pub ty_ctx: &'ctxt TyCtx<'a>, pub access_ctx: &'ctxt AccessCtx, pub exec: ExecExpr<'a>, pub reborrows: Vec>, @@ -25,10 +25,10 @@ pub(super) struct BorrowCheckCtx<'gl, 'src, 'ctxt> { pub unsafe_flag: bool, } -impl<'gl, 'src, 'ctxt> BorrowCheckCtx<'gl, 'src, 'ctxt> { +impl<'a, 'gl, 'src, 'ctxt> BorrowCheckCtx<'a, 'gl, 'src, 'ctxt> { pub(super) fn new( - expr_ty_ctx: &'ctxt ExprTyCtx<'gl, 'src, 'ctxt>, - reborrows: Vec, + expr_ty_ctx: &'ctxt ExprTyCtx<'a, 'gl, 'src, 'ctxt>, + reborrows: Vec>, own: Ownership, ) -> Self { BorrowCheckCtx { @@ -70,10 +70,10 @@ impl<'gl, 'src, 'ctxt> BorrowCheckCtx<'gl, 'src, 'ctxt> { // Ownership Safety // //p is ω-safe under δ and γ, with reborrow exclusion list π , and may point to any of the loans in ωp -pub(super) fn access_safety_check( +pub(super) fn access_safety_check<'a>( ctx: &BorrowCheckCtx, - p: &PlaceExpr, -) -> OwnResult>> { + p: &'a PlaceExpr<'a>, +) -> OwnResult<'a, HashSet>> { if !ctx.unsafe_flag { narrowing_check(ctx, p, &ctx.exec)?; access_conflict_check(ctx, p)?; @@ -81,7 +81,10 @@ pub(super) fn access_safety_check( borrow_check(ctx, p) } -pub(super) fn borrow_check(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult>> { +pub(super) fn borrow_check<'a>( + ctx: &'a BorrowCheckCtx, + p: &'a PlaceExpr<'a>, +) -> OwnResult<'a, HashSet>> { let (pl_ctx, most_spec_pl) = p.to_pl_ctx_and_most_specif_pl(); if p.is_place() { ownership_safe_place(ctx, p) @@ -109,11 +112,11 @@ pub(super) fn borrow_check(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult( ctx: &BorrowCheckCtx, - pl_ctx_no_deref: &PlaceCtx, - most_spec_pl: &internal::Place, -) -> OwnResult>> { + pl_ctx_no_deref: &'a PlaceCtx<'a>, + most_spec_pl: &'a internal::Place<'a>, +) -> OwnResult<'a, HashSet>> { // TODO is this correct? let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr(PlaceExpr::new( PlaceExprKind::Deref(Box::new(most_spec_pl.to_place_expr())), @@ -126,7 +129,10 @@ fn ownership_safe_deref_raw( Ok(passed_through_prvs) } -fn ownership_safe_place(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult>> { +fn ownership_safe_place<'a>( + ctx: &BorrowCheckCtx, + p: &PlaceExpr, +) -> OwnResult<'a, HashSet>> { ownership_safe_under_existing_borrows(ctx, p)?; let mut loan_set = HashSet::new(); loan_set.insert(Loan { @@ -136,13 +142,13 @@ fn ownership_safe_place(ctx: &BorrowCheckCtx, p: &PlaceExpr) -> OwnResult( ctx: &BorrowCheckCtx, pl_ctx_no_deref: &PlaceCtx, most_spec_pl: &internal::Place, prv_val_name: &str, ref_own: Ownership, -) -> OwnResult>> { +) -> OwnResult<'a, HashSet>> { // Γ(r) = { ω′pi } let loans_in_prv = ctx.ty_ctx.loans_in_prv(prv_val_name)?; // ω ≲ ωπ @@ -175,11 +181,11 @@ fn ownership_safe_deref( Ok(potential_prvs_after_subst) } -fn subst_pl_with_potential_prvs_ownership_safe( +fn subst_pl_with_potential_prvs_ownership_safe<'a>( ctx: &BorrowCheckCtx, - pl_ctx_no_deref: &PlaceCtx, + pl_ctx_no_deref: &'a PlaceCtx<'a>, loans_in_prv: &HashSet>, -) -> OwnResult>> { +) -> OwnResult<'a, HashSet>> { let mut loans: HashSet> = HashSet::new(); for pl_expr in loans_in_prv.iter().map(|loan| &loan.place_expr) { let insert_dereferenced_pl_expr = pl_ctx_no_deref.insert_pl_expr(pl_expr.clone()); @@ -190,12 +196,12 @@ fn subst_pl_with_potential_prvs_ownership_safe( Ok(loans) } -fn ownership_safe_deref_abs( +fn ownership_safe_deref_abs<'a>( ctx: &BorrowCheckCtx, - pl_ctx_no_deref: &PlaceCtx, - most_spec_pl: &internal::Place, + pl_ctx_no_deref: &'a PlaceCtx<'a>, + most_spec_pl: &'a internal::Place<'a>, ref_own: Ownership, -) -> OwnResult>> { +) -> OwnResult<'a, HashSet>> { let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr(PlaceExpr::new( PlaceExprKind::Deref(Box::new(most_spec_pl.to_place_expr())), )); @@ -212,11 +218,11 @@ fn ownership_safe_deref_abs( Ok(passed_through_prvs) } -fn narrowing_check( +fn narrowing_check<'a>( ctx: &BorrowCheckCtx, p: &'a PlaceExpr<'a>, active_ctx_exec: &'a ExecExpr<'a>, -) -> OwnResult<()> { +) -> OwnResult<'a, ()> { if ctx.own == Ownership::Shrd { return Ok(()); } @@ -238,14 +244,14 @@ fn narrowing_check( } } -fn narrowable(from: &'a ExecExpr<'a>, to: &'a ExecExpr<'a>) -> OwnResult<()> { +fn narrowable<'a>(from: &'a ExecExpr<'a>, to: &'a ExecExpr<'a>) -> OwnResult<'a, ()> { let normal_from = normalize(from.clone()); let normal_to = normalize(to.clone()); exec_is_prefix_of(&normal_from, &normal_to)?; no_forall_in_diff(&normal_from, &normal_to) } -fn exec_is_prefix_of(prefix: &&'a ExecExpr<'a>, of: &'a ExecExpr<'a>) -> OwnResult<()> { +fn exec_is_prefix_of<'a>(prefix: &'a ExecExpr<'a>, of: &'a ExecExpr<'a>) -> OwnResult<'a, ()> { if prefix.exec.base != of.exec.base { return Err(BorrowingError::WrongDevice( of.exec.base.clone(), @@ -263,7 +269,7 @@ fn exec_is_prefix_of(prefix: &&'a ExecExpr<'a>, of: &'a ExecExpr<'a>) -> OwnResu Ok(()) } -fn access_conflict_check(ctx: &BorrowCheckCtx, p: &'a PlaceExpr<'a>) -> OwnResult<()> { +fn access_conflict_check<'a>(ctx: &BorrowCheckCtx, p: &'a PlaceExpr<'a>) -> OwnResult<'a, ()> { for loan in ctx.access_ctx.hash_set() { if possible_conflict_with_previous_access(ctx.nat_ctx, ctx.own, p, loan)? { return Err(BorrowingError::Conflict { @@ -340,7 +346,7 @@ fn possible_conflict_with_previous_access<'a>( } fn range_intersects<'a>( - nat_ctx: &'a NatCtx<'a>, + nat_ctx: &NatCtx, lower_left: &'a Nat<'a>, upper_left: &'a Nat<'a>, lower_right: &'a Nat<'a>, @@ -352,7 +358,7 @@ fn range_intersects<'a>( && upper_left.eval(nat_ctx)? > upper_right.eval(nat_ctx)?)) } -fn no_forall_in_diff<'a>(from: &'a ExecExpr<'a>, under: &'a ExecExpr<'a>) -> OwnResult<()> { +fn no_forall_in_diff<'a>(from: &'a ExecExpr<'a>, under: &'a ExecExpr<'a>) -> OwnResult<'a, ()> { if from.exec.path.len() > under.exec.path.len() { return Err(BorrowingError::CannotNarrow); } @@ -366,14 +372,15 @@ fn no_forall_in_diff<'a>(from: &'a ExecExpr<'a>, under: &'a ExecExpr<'a>) -> Own fn pl_ctxs_and_places_in_loans<'a>( loans: &HashSet>, -) -> impl Iterator)> + '_ { +) -> impl Iterator, internal::Place<'a>)> + 'a { + // was '_ before, what does that mean loans .iter() .map(|loan| &loan.place_expr) .map(|pl_expr| pl_expr.to_pl_ctx_and_most_specif_pl()) } -fn new_own_weaker_equal(checked_own: Ownership, ref_own: Ownership) -> OwnResult<()> { +fn new_own_weaker_equal(checked_own: Ownership, ref_own: Ownership) -> OwnResult<'a, ()> { if ref_own < checked_own { Err(BorrowingError::ConflictingOwnership) } else { @@ -384,7 +391,7 @@ fn new_own_weaker_equal(checked_own: Ownership, ref_own: Ownership) -> OwnResult fn ownership_safe_under_existing_borrows<'a>( ctx: &BorrowCheckCtx, pl_expr: &'a PlaceExpr<'a>, -) -> OwnResult<()> { +) -> OwnResult<'a, ()> { if !ctx.unsafe_flag { for prv_mapping in ctx.ty_ctx.prv_mappings() { let PrvMapping { prv, loans } = prv_mapping; @@ -416,10 +423,10 @@ fn no_uniq_loan_overlap<'a>( } fn at_least_one_borrowing_place_and_all_in_reborrow<'a>( - ty_ctx: &TyCtx, + ty_ctx: &'a TyCtx<'a>, prv_name: &str, reborrows: &[internal::Place<'a>], -) -> OwnResult<()> { +) -> OwnResult<'a, ()> { let all_places = ty_ctx.all_places(); // check that a borrow with given provenance exists. // It could not exist for example in case it is used for a parameter diff --git a/src/ty_check/exec.rs b/src/ty_check/exec.rs index 10d01857..89073500 100644 --- a/src/ty_check/exec.rs +++ b/src/ty_check/exec.rs @@ -50,7 +50,10 @@ pub(super) fn ty_check<'a>( Ok(()) } -fn ty_check_exec_to_threads<'a>(d: DimCompo, exec_ty: &ExecTyKind) -> TyResult { +fn ty_check_exec_to_threads<'a>( + d: DimCompo, + exec_ty: &'a ExecTyKind<'a>, +) -> TyResult<'a, ExecTyKind<'a>> { if let ExecTyKind::GpuGrid(gdim, bdim) = exec_ty { let (rest_gdim, rem_gdim) = remove_dim(gdim, d)?; let (rest_bdim, rem_bdim) = remove_dim(bdim, d)?; diff --git a/src/ty_check/pl_expr.rs b/src/ty_check/pl_expr.rs index 062b54fc..884b947a 100644 --- a/src/ty_check/pl_expr.rs +++ b/src/ty_check/pl_expr.rs @@ -11,13 +11,13 @@ use crate::ty_check::unify; use crate::ty_check::unify::ConstrainMap; use crate::ty_check::{exec, ExprTyCtx}; -pub(super) struct PlExprTyCtx<'gl, 'src, 'ctxt> { +pub(super) struct PlExprTyCtx<'a, 'gl, 'src, 'ctxt> { gl_ctx: &'ctxt GlobalCtx<'gl, 'src>, nat_ctx: &'ctxt NatCtx, - kind_ctx: &'ctxt KindCtx, - ident_exec: Option<&'ctxt IdentExec>, - exec: ExecExpr, - ty_ctx: &'ctxt TyCtx, + kind_ctx: &'ctxt KindCtx<'a>, + ident_exec: Option<&'ctxt IdentExec<'a>>, + exec: ExecExpr<'a>, + ty_ctx: &'ctxt TyCtx<'a>, exec_borrow_ctx: &'ctxt AccessCtx, own: Ownership, } @@ -391,7 +391,7 @@ fn ty_check_index( ctx: &PlExprTyCtx, pl_expr: &mut PlaceExpr, idx: &mut Nat, -) -> TyResult<(Ty, Vec, Vec)> { +) -> TyResult<(Ty<'a>, Vec>, Vec>)> { let (mems, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr)?; let pl_expr_dty = if let TyKind::Data(dty) = &pl_expr.ty.as_ref().unwrap().ty { dty diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index d8116dc1..6ea4a743 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -881,7 +881,7 @@ impl<'a> VisitMut<'a> for SubstIdent<'a, ExecExpr<'a>> { mod tests { use super::*; - fn shrd_ref_ty() -> DataTy { + fn shrd_ref_ty<'a>() -> DataTy<'a> { Dim::X(Box::new(Dim1d(Nat::Lit(32)))); DataTy::new(DataTyKind::Ref(Box::new(RefDty::new( Provenance::Value("r".to_string()), @@ -895,7 +895,7 @@ mod tests { } #[test] - fn scalar() -> UnifyResult<()> { + fn scalar<'a>() -> UnifyResult<'a, ()> { let mut i32 = DataTy::new(DataTyKind::Scalar(ScalarTy::I32)); let mut t = DataTy::new(DataTyKind::Ident(Ident::new_impli("t"))); let (subst, _) = constrain(&mut i32, &mut t)?; @@ -906,7 +906,7 @@ mod tests { } #[test] - fn shrd_reft() -> UnifyResult<()> { + fn shrd_reft<'a>() -> UnifyResult<'a, ()> { let mut t = DataTy::new(DataTyKind::Ident(Ident::new_impli("t"))); let mut shrd_ref = shrd_ref_ty(); let (subst, _) = constrain(&mut shrd_ref, &mut t)?; @@ -917,7 +917,7 @@ mod tests { } #[test] - fn shrd_ref_inner_var() -> UnifyResult<()> { + fn shrd_ref_inner_var<'a>() -> UnifyResult<'a, ()> { let mut shrd_ref_t = DataTy::new(DataTyKind::Ref(Box::new(RefDty::new( Provenance::Value("r".to_string()), Ownership::Shrd, @@ -934,7 +934,7 @@ mod tests { } #[test] - fn prv_val_ident() -> UnifyResult<()> { + fn prv_val_ident<'a>() -> UnifyResult<'a, ()> { let mut shrd_ref_t = DataTy::new(DataTyKind::Ref(Box::new(RefDty::new( Provenance::Ident(Ident::new("a")), Ownership::Shrd, From 271d1766a03a1d21a520061efb54236a2ea4d7fb Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 24 Jul 2025 21:22:34 +0200 Subject: [PATCH 35/57] adding more lifetimes in ty check --- src/ty_check/ctxs.rs | 28 +++++++------- src/ty_check/mod.rs | 2 +- src/ty_check/pl_expr.rs | 81 +++++++++++++++++++++-------------------- src/ty_check/unify.rs | 38 +++++++++---------- 4 files changed, 76 insertions(+), 73 deletions(-) diff --git a/src/ty_check/ctxs.rs b/src/ty_check/ctxs.rs index 49de5b0c..7c830b93 100644 --- a/src/ty_check/ctxs.rs +++ b/src/ty_check/ctxs.rs @@ -408,26 +408,26 @@ impl<'a> TyCtx<'a> { } } -pub(super) struct AccessCtx { - ctx: HashSet, +pub(super) struct AccessCtx<'a> { + ctx: HashSet>, } -impl AccessCtx { +impl<'a> AccessCtx<'a> { pub fn new() -> Self { AccessCtx { ctx: HashSet::new(), } } - pub fn insert(&mut self, loans: HashSet) { + pub fn insert(&mut self, loans: HashSet>) { self.ctx.extend(loans.into_iter()) } - pub fn hash_set(&self) -> &HashSet { + pub fn hash_set(&self) -> &HashSet> { &self.ctx } - pub fn clear_sync_for(&mut self, ty_ctx: &TyCtx, exec: &ExecExpr) { + pub fn clear_sync_for(&mut self, ty_ctx: &'a TyCtx<'a>, exec: &'a ExecExpr<'a>) { self.ctx = self .ctx .iter() @@ -440,7 +440,7 @@ impl AccessCtx { .collect(); } - pub fn garbage_collect(&mut self, ty_ctx: &TyCtx) { + pub fn garbage_collect(&mut self, ty_ctx: &'a TyCtx<'a>) { // TODO make more efficient // drain is unstable for HashSet, use Vec anyway? let mut cleaned_up_set = HashSet::new(); @@ -454,7 +454,7 @@ impl AccessCtx { } } -fn trim_after_select_of(ty_ctx: &TyCtx, exec: &ExecExpr, pl_expr: PlaceExpr) -> Option { +fn trim_after_select_of<'a>(ty_ctx: &'a TyCtx<'a>, exec: &'a ExecExpr<'a>, pl_expr: PlaceExpr<'a>) -> Option> { match pl_expr.pl_expr { PlaceExprKind::Select(p, sel_exec) if sel_exec.as_ref() == exec => { Some(PlaceExpr::new(PlaceExprKind::Select(p, sel_exec))) @@ -488,7 +488,7 @@ enum KindingCtxEntry<'a> { PrvRel(PrvRel<'a>), } -pub(super) type CtxResult = Result; +pub(super) type CtxResult<'a, T> = Result>; #[derive(PartialEq, Eq, Debug, Clone)] pub(super) struct KindCtx<'a> { @@ -500,7 +500,7 @@ impl<'a> KindCtx<'a> { KindCtx { ctx: vec![vec![]] } } - pub fn gl_fun_kind_ctx(idents: Vec, prv_rels: Vec) -> CtxResult { + pub fn gl_fun_kind_ctx(idents: Vec>, prv_rels: Vec>) -> CtxResult<'a, Self> { let mut kind_ctx: Self = KindCtx::new(); kind_ctx.append_idents(idents); kind_ctx.append_prv_rels(prv_rels)?; @@ -554,7 +554,7 @@ impl<'a> KindCtx<'a> { Ok(()) } - pub fn get_idents(&self, kind: Kind) -> impl Iterator> { + pub fn get_idents(&self, kind: Kind) -> impl Iterator { self.ctx.iter().flatten().filter_map(move |entry| { if let KindingCtxEntry::Ident(IdentKinded { ident, kind: k }) = entry { if k == &kind { @@ -568,11 +568,11 @@ impl<'a> KindCtx<'a> { }) } - pub fn ident_of_kind_exists<'a>(&self, ident: &'a Ident<'a>, kind: Kind) -> bool { + pub fn ident_of_kind_exists(&self, ident: &'a Ident<'a>, kind: Kind) -> bool { self.get_idents(kind).any(|id| ident == id) } - pub fn outlives<'a>(&self, l: &'a Ident<'a>, s: &'a Ident<'a>) -> CtxResult<()> { + pub fn outlives(&self, l: &'a Ident<'a>, s: &'a Ident<'a>) -> CtxResult<'a, ()> { if self.ctx.iter().flatten().any(|entry| match entry { KindingCtxEntry::PrvRel(PrvRel { longer, shorter }) => longer == l && shorter == s, _ => false, @@ -594,7 +594,7 @@ pub(super) enum GlobalDecl<'a> { pub(super) struct GlobalCtx<'src, 'compil> { compil_unit: &'compil mut CompilUnit<'src>, checked_funs: Vec<(Box, Box<[usize]>)>, - decls: Vec, + decls: Vec>, //items: HashMap, GlobalItem>, } diff --git a/src/ty_check/mod.rs b/src/ty_check/mod.rs index 8714851d..8a19b0d9 100644 --- a/src/ty_check/mod.rs +++ b/src/ty_check/mod.rs @@ -23,7 +23,7 @@ type TyResult<'a, T> = Result>; macro_rules! matches_dty { ($ty: expr, $dty_pat: pat_param) => { if let crate::arena_ast::TyKind::Data(d) = &$ty.ty { - matches!(d.as_ref(), $dty_pat) + matches!(d, $dty_pat) } else { false } diff --git a/src/ty_check/pl_expr.rs b/src/ty_check/pl_expr.rs index 884b947a..c5e18b52 100644 --- a/src/ty_check/pl_expr.rs +++ b/src/ty_check/pl_expr.rs @@ -56,25 +56,25 @@ impl<'gl, 'src, 'ctxt> From<&'ctxt BorrowCheckCtx<'gl, 'src, 'ctxt>> // Δ; Γ ⊢ω p:τ // p in an ω context has type τ under Δ and Γ -pub(super) fn ty_check(ctx: &PlExprTyCtx, pl_expr: &mut PlaceExpr) -> TyResult<()> { +pub(super) fn ty_check<'a>(ctx: &PlExprTyCtx, pl_expr: &'a mut PlaceExpr<'a>) -> TyResult<'a, ()> { let _mem = ty_check_and_passed_mems(ctx, pl_expr)?; Ok(()) } -pub(super) fn ty_check_and_passed_mems( +pub(super) fn ty_check_and_passed_mems<'a>( ctx: &PlExprTyCtx, - pl_expr: &mut PlaceExpr, -) -> TyResult> { + pl_expr: &'a mut PlaceExpr<'a>, +) -> TyResult<'a, Vec>> { let (mem, _) = ty_check_and_passed_mems_prvs(ctx, pl_expr)?; Ok(mem) } // Δ; Γ ⊢ω p:τ,{ρ} // p in an ω context has type τ under Δ and Γ, passing through provenances in Vec<ρ> -fn ty_check_and_passed_mems_prvs( +fn ty_check_and_passed_mems_prvs<'a>( ctx: &PlExprTyCtx, - pl_expr: &mut PlaceExpr, -) -> TyResult<(Vec, Vec)> { + pl_expr: &'a mut PlaceExpr<'a>, +) -> TyResult<'a, (Vec>, Vec>)> { let (ty, mem, prvs) = match &mut pl_expr.pl_expr { // TC-Var PlaceExprKind::Ident(ident) => ty_check_ident(ctx, ident)?, @@ -95,11 +95,11 @@ fn ty_check_and_passed_mems_prvs( Ok((mem, prvs)) } -fn ty_check_view_pl_expr( +fn ty_check_view_pl_expr<'a>( ctx: &PlExprTyCtx, - pl_expr: &mut PlaceExpr, - view: &mut View, -) -> TyResult<(Ty, Vec, Vec)> { + pl_expr: &'a mut PlaceExpr<'a>, + view: &'a mut View<'a>, +) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mems, prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr)?; let view_fn_ty = ty_check_view(ctx, view)?; let in_dty = pl_expr.ty.as_ref().unwrap().dty().clone(); @@ -109,11 +109,11 @@ fn ty_check_view_pl_expr( Ok((Ty::new(TyKind::Data(Box::new(res_dty))), mems, prvs)) } -fn ty_check_app_view_fn_ty( +fn ty_check_app_view_fn_ty<'a>( ctx: &PlExprTyCtx, - in_dty: &DataTy, - mut view_fn_ty: FnTy, -) -> TyResult<(DataTy, ConstrainMap)> { + in_dty: &'a DataTy<'a>, + mut view_fn_ty: FnTy<'a>, +) -> TyResult<'a, (DataTy<'a>, ConstrainMap<'a>)> { let mut arg_dty_fn_ty = FnTy::new( vec![], None, @@ -132,7 +132,7 @@ fn ty_check_app_view_fn_ty( Ok((res_dty, constr_map)) } -fn ty_check_view(ctx: &PlExprTyCtx, view: &mut View) -> TyResult { +fn ty_check_view<'a>(ctx: &PlExprTyCtx, view: &'a mut View<'a>) -> TyResult<'a, FnTy<'a>> { let arg_tys = view .args .iter_mut() @@ -164,7 +164,10 @@ fn ty_check_view(ctx: &PlExprTyCtx, view: &mut View) -> TyResult { Ok(res_view_ty) } -fn create_view_ty_with_input_view_and_free_ret(exec: &ExecExpr, mut arg_tys: Vec) -> FnTy { +fn create_view_ty_with_input_view_and_free_ret<'a>( + exec: &ExecExpr, + mut arg_tys: Vec>, +) -> FnTy<'a> { arg_tys.push(Ty::new(TyKind::Data(Box::new(DataTy::new( utils::fresh_ident("in_view_dty", DataTyKind::Ident), ))))); @@ -184,10 +187,10 @@ fn create_view_ty_with_input_view_and_free_ret(exec: &ExecExpr, mut arg_tys: Vec ) } -fn ty_check_ident( +fn ty_check_ident<'a>( ctx: &PlExprTyCtx, - ident: &Ident, -) -> TyResult<(Ty, Vec, Vec)> { + ident: &'a Ident<'a>, +) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { // if let Ok(tty) = ctx.ty_ctx.ty_of_ident(ident) { let tty = ctx.ty_ctx.ty_of_ident(ident)?; if !&tty.is_fully_alive() { @@ -214,7 +217,7 @@ fn ty_check_ident( // } } -fn default_mem_by_exec(exec_ty: &ExecTyKind) -> Option { +fn default_mem_by_exec<'a>(exec_ty: &'a ExecTyKind<'a>) -> Option> { match exec_ty { ExecTyKind::CpuThread => Some(Memory::CpuMem), ExecTyKind::GpuThread => Some(Memory::GpuLocal), @@ -230,11 +233,11 @@ fn default_mem_by_exec(exec_ty: &ExecTyKind) -> Option { } // TODO refactor by fusing with ty_check_field_proj -fn ty_check_proj( +fn ty_check_proj<'a>( ctx: &PlExprTyCtx, - tuple_expr: &mut PlaceExpr, + tuple_expr: &'a mut PlaceExpr<'a>, n: usize, -) -> TyResult<(Ty, Vec, Vec)> { +) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mem, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, tuple_expr)?; let tuple_dty = match &tuple_expr.ty.as_ref().unwrap().ty { TyKind::Data(dty) => dty, @@ -266,11 +269,11 @@ fn ty_check_proj( } } -fn ty_check_field_proj( +fn ty_check_field_proj<'a>( ctx: &PlExprTyCtx, - struct_expr: &mut PlaceExpr, - ident: &Ident, -) -> TyResult<(Ty, Vec, Vec)> { + struct_expr: &'a mut PlaceExpr<'a>, + ident: &'a Ident<'a>, +) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mem, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, struct_expr)?; let struct_dty = match &struct_expr.ty.as_ref().unwrap().ty { TyKind::Data(dty) => dty, @@ -303,10 +306,10 @@ fn ty_check_field_proj( } } -fn ty_check_deref( +fn ty_check_deref<'a>( ctx: &PlExprTyCtx, - borr_expr: &mut PlaceExpr, -) -> TyResult<(Ty, Vec, Vec)> { + borr_expr: &'a mut PlaceExpr<'a>, +) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mut inner_mem, mut passed_prvs) = ty_check_and_passed_mems_prvs(ctx, borr_expr)?; let borr_dty = if let TyKind::Data(dty) = &borr_expr.ty.as_ref().unwrap().ty { dty @@ -344,11 +347,11 @@ fn ty_check_deref( } } -fn ty_check_select( +fn ty_check_select<'a>( ctx: &PlExprTyCtx, - p: &mut PlaceExpr, - select_exec: &mut ExecExpr, -) -> TyResult<(Ty, Vec, Vec)> { + p: &'a mut PlaceExpr<'a>, + select_exec: &'a mut ExecExpr<'a>, +) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, select_exec)?; // FIXME this check is required for uniq accesses, but not for shared accesses because there // the duplication of accesses is fine. Move this check into ownership/borrow checking? @@ -387,11 +390,11 @@ fn ty_check_select( Ok((Ty::new(TyKind::Data(Box::new(p_dty))), mems, prvs)) } -fn ty_check_index( +fn ty_check_index<'a>( ctx: &PlExprTyCtx, - pl_expr: &mut PlaceExpr, - idx: &mut Nat, -) -> TyResult<(Ty<'a>, Vec>, Vec>)> { + pl_expr: &'a mut PlaceExpr<'a>, + idx: &'a mut Nat<'a>, +) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mems, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr)?; let pl_expr_dty = if let TyKind::Data(dty) = &pl_expr.ty.as_ref().unwrap().ty { dty diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index 6ea4a743..091b6ca1 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -133,8 +133,8 @@ pub(super) trait Constrainable<'a>: Visitable<'a> + Substitutable<'a> { fn constrain( &mut self, other: &mut Self, - constr_map: &mut ConstrainMap, - prv_rels: &mut Vec>, + constr_map: &'a mut ConstrainMap<'a>, + prv_rels: &'a mut Vec>, ) -> UnifyResult<()>; fn occurs_check>(ident_kinded: &'a IdentKinded<'a>, s: &S) -> bool { utils::free_kinded_idents(s).contains(ident_kinded) @@ -589,7 +589,7 @@ impl<'a> Nat<'a> { Ok(()) } - fn unify(n1: &Nat, n2: &Nat, _constr_map: &mut ConstrainMap) -> UnifyResult<()> { + fn unify<'a>(n1: &'a Nat<'a>, n2: &'a Nat<'a>, _constr_map: &'a mut ConstrainMap<'a>) -> UnifyResult<'a, ()> { if n1 == n2 { Ok(()) } else { @@ -599,12 +599,12 @@ impl<'a> Nat<'a> { } impl<'a> Constrainable<'a> for Nat<'a> { - fn constrain<'a>( + fn constrain( &mut self, other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - prv_rels: &'a mut Vec>, - ) -> UnifyResult<()> { + constr_map: &mut ConstrainMap<'a>, + prv_rels: &mut Vec>, + ) -> UnifyResult<'a, ()> { match (&mut *self, &mut *other) { (Nat::Ident(n1i), Nat::Ident(n2i)) if n1i.is_implicit || n2i.is_implicit => { match (n1i.is_implicit, n2i.is_implicit) { @@ -630,14 +630,14 @@ impl<'a> Constrainable<'a> for Nat<'a> { } impl<'a> Substitutable<'a> for Nat<'a> { - fn substitute<'a>(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_nat(self); } } impl<'a> Memory<'a> { - fn bind_to<'a>(&self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>) -> UnifyResult<'a, ()> { + fn bind_to(&self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>) -> UnifyResult<'a, ()> { if Self::occurs_check(&IdentKinded::new(ident, Kind::Memory), self) { return Err(UnifyError::InfiniteType); } @@ -668,7 +668,7 @@ impl<'a> Memory<'a> { } impl<'a> Constrainable<'a> for Memory<'a> { - fn constrain<'a>( + fn constrain( &mut self, other: &mut Self, constr_map: &'a mut ConstrainMap<'a>, @@ -781,7 +781,7 @@ impl<'a> ApplySubst<'a> { } impl<'a> VisitMut<'a> for ApplySubst<'a> { - fn visit_nat(&mut self, nat: &'a mut Nat<'a>) { + fn visit_nat(&mut self, nat: &mut Nat<'a>) { match nat { Nat::Ident(ident) if self.subst.nat_unifier.contains_key(&ident.name) => { *nat = self.subst.nat_unifier.get(&ident.name).unwrap().clone(); @@ -790,7 +790,7 @@ impl<'a> VisitMut<'a> for ApplySubst<'a> { } } - fn visit_mem(&mut self, mem: &'a mut Memory<'a>) { + fn visit_mem(&mut self, mem: & mut Memory<'a>) { match mem { Memory::Ident(ident) if self.subst.mem_unifier.contains_key(&ident.name) => { *mem = self.subst.mem_unifier.get(&ident.name).unwrap().clone(); @@ -799,7 +799,7 @@ impl<'a> VisitMut<'a> for ApplySubst<'a> { } } - fn visit_prv(&mut self, prv: &'a mut Provenance<'a>) { + fn visit_prv(&mut self, prv: &mut Provenance<'a>) { match prv { Provenance::Ident(ident) if self.subst.prv_unifier.contains_key(&ident.name) => { *prv = self.subst.prv_unifier.get(&ident.name).unwrap().clone() @@ -808,7 +808,7 @@ impl<'a> VisitMut<'a> for ApplySubst<'a> { } } - fn visit_dty(&mut self, dty: &'a mut DataTy<'a>) { + fn visit_dty(&mut self, dty: &mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) if self.subst.dty_unifier.contains_key(&ident.name) => { *dty = self.subst.dty_unifier.get(&ident.name).unwrap().clone() @@ -830,7 +830,7 @@ impl<'a, S: Constrainable<'a>> SubstIdent<'a, S> { } impl<'a> VisitMut<'a> for SubstIdent<'a, Nat<'a>> { - fn visit_nat(&mut self, nat: &'a mut Nat<'a>) { + fn visit_nat(&mut self, nat: &mut Nat<'a>) { match nat { Nat::Ident(ident) if ident.name == self.ident.name => *nat = self.term.clone(), _ => visit_mut::walk_nat(self, nat), @@ -839,7 +839,7 @@ impl<'a> VisitMut<'a> for SubstIdent<'a, Nat<'a>> { } impl<'a> VisitMut<'a> for SubstIdent<'a, Memory<'a>> { - fn visit_mem(&mut self, mem: &'a mut Memory<'a>) { + fn visit_mem(&mut self, mem: &mut Memory<'a>) { match mem { Memory::Ident(ident) if ident.name == self.ident.name => *mem = self.term.clone(), _ => visit_mut::walk_mem(self, mem), @@ -848,7 +848,7 @@ impl<'a> VisitMut<'a> for SubstIdent<'a, Memory<'a>> { } impl<'a> VisitMut<'a> for SubstIdent<'a, Provenance<'a>> { - fn visit_prv(&mut self, prv: &'a mut Provenance) { + fn visit_prv(&mut self, prv: &mut Provenance<'a>) { match prv { Provenance::Ident(ident) if ident.name == self.ident.name => *prv = self.term.clone(), _ => visit_mut::walk_prv(self, prv), @@ -857,7 +857,7 @@ impl<'a> VisitMut<'a> for SubstIdent<'a, Provenance<'a>> { } impl<'a> VisitMut<'a> for SubstIdent<'a, DataTy<'a>> { - fn visit_dty(&mut self, dty: &'a mut DataTy<'a>) { + fn visit_dty(&mut self, dty: &mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) if ident.name == self.ident.name => *dty = self.term.clone(), _ => visit_mut::walk_dty(self, dty), @@ -866,7 +866,7 @@ impl<'a> VisitMut<'a> for SubstIdent<'a, DataTy<'a>> { } impl<'a> VisitMut<'a> for SubstIdent<'a, ExecExpr<'a>> { - fn visit_exec_expr(&mut self, exec: &'a mut ExecExpr<'a>) { + fn visit_exec_expr(&mut self, exec: &mut ExecExpr<'a>) { if let BaseExec::Ident(i) = &exec.exec.base { if i.name == self.ident.name { let mut subst_exec = self.term.clone(); From 0fd8d5c5cde6dd98ecf10f4b8a9850b3b0e4bed5 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 5 Aug 2025 16:42:49 +0200 Subject: [PATCH 36/57] worked on the ctxts for ty_check --- src/ty_check/ctxs.rs | 383 +++++++++++++++++++++++++++---------------- 1 file changed, 242 insertions(+), 141 deletions(-) diff --git a/src/ty_check/ctxs.rs b/src/ty_check/ctxs.rs index 7c830b93..815c1e0e 100644 --- a/src/ty_check/ctxs.rs +++ b/src/ty_check/ctxs.rs @@ -3,8 +3,9 @@ use crate::arena_ast::internal::{ }; use crate::arena_ast::*; use crate::ty_check::error::CtxError; -use std::collections::HashSet; +use bumpalo::collections::CollectIn; use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; +use std::collections::HashSet; // TODO introduce proper struct pub(super) type TypedPlace<'a> = (internal::Place<'a>, DataTy<'a>); @@ -16,12 +17,12 @@ pub(super) struct TyCtx<'a> { impl<'a> TyCtx<'a> { pub fn new(arena: &'a Bump) -> Self { - let mut frames = BumpVec::new_in(arena); - frames.push(Frame::new_in(arena)); - TyCtx { frames } - } - - pub fn get_exec_expr_for_exec_ident(&self, ident: &Ident) -> CtxResult<&ExecExpr> { + let mut frames = BumpVec::new_in(arena); + frames.push(Frame::new_in(arena)); + TyCtx { frames } + } + + pub fn get_exec_expr_for_exec_ident(&self, ident: &Ident<'a>) -> CtxResult<'a, &ExecExpr<'a>> { let exec_expr = self.flat_bindings().rev().find_map(|entry| match entry { FrameEntry::ExecMapping(em) if &em.ident == ident => Some(&em.exec_expr), _ => None, @@ -31,59 +32,55 @@ impl<'a> TyCtx<'a> { None => Err(CtxError::IdentNotFound(ident.clone())), } } - // - // pub fn last_frame(&self) -> &Frame { - // self.frames.last().unwrap() - // } - pub fn last_frame_mut(&mut self) -> &mut Frame { + pub fn last_frame_mut(&mut self) -> &mut Frame<'a> { self.frames.last_mut().unwrap() } - pub fn flat_bindings_mut(&mut self) -> impl DoubleEndedIterator { - self.frames.iter_mut().flat_map(|frm| &mut frm.bindings) + fn flat_bindings(&self) -> impl DoubleEndedIterator> { + self.frames.iter().flat_map(|f| &f.bindings) } - - pub fn flat_bindings(&self) -> impl DoubleEndedIterator { - self.frames.iter().flat_map(|frm| &frm.bindings) + fn flat_bindings_mut(&mut self) -> impl DoubleEndedIterator> { + self.frames.iter_mut().flat_map(|f| &mut f.bindings) } - pub fn push_empty_frame(&mut self) -> &mut Self { - self.frames.push(Frame<'a>::new()); + pub fn push_empty_frame(&mut self, arena: &'a Bump) -> &mut Self { + self.frames.push(Frame::new_in(arena)); self } - pub fn push_frame(&mut self, frame: Frame) -> &mut Self { + pub fn push_frame(&mut self, frame: Frame<'a>) -> &mut Self { self.frames.push(frame); self } - pub fn pop_frame(&mut self) -> Frame { - self.frames.pop().expect("There must always be a scope.") + pub fn pop_frame(&mut self) -> Frame<'a> { + assert!(self.frames.len() > 1, "Cannot pop the last frame"); + self.frames.pop().unwrap() } - pub fn append_ident_typed(&mut self, id_typed: IdentTyped) -> &mut Self { + pub fn append_ident_typed(&mut self, id_typed: IdentTyped<'a>) -> &mut Self { self.last_frame_mut() .bindings .push(FrameEntry::Var(id_typed)); self } - pub fn append_exec_mapping(&mut self, ident: Ident, exec: ExecExpr) -> &mut Self { + pub fn append_exec_mapping(&mut self, ident: Ident<'a>, exec: ExecExpr<'a>) -> &mut Self { self.last_frame_mut() .bindings .push(FrameEntry::ExecMapping(ExecMapping::new(ident, exec))); self } - pub fn append_prv_mapping(&mut self, prv_mapping: PrvMapping) -> &mut Self { + pub fn append_prv_mapping(&mut self, prv_mapping: PrvMapping<'a>) -> &mut Self { self.last_frame_mut() .bindings .push(FrameEntry::PrvMapping(prv_mapping)); self } - fn idents_typed(&self) -> impl DoubleEndedIterator { + fn idents_typed(&self) -> impl DoubleEndedIterator> { self.flat_bindings().filter_map(|fe| { if let FrameEntry::Var(ident_typed) = fe { Some(ident_typed) @@ -93,7 +90,7 @@ impl<'a> TyCtx<'a> { }) } - fn idents_typed_mut(&mut self) -> impl DoubleEndedIterator { + fn idents_typed_mut(&mut self) -> impl DoubleEndedIterator> { self.flat_bindings_mut().filter_map(|fe| { if let FrameEntry::Var(ident_typed) = fe { Some(ident_typed) @@ -103,7 +100,7 @@ impl<'a> TyCtx<'a> { }) } - pub(crate) fn prv_mappings(&self) -> impl DoubleEndedIterator { + pub(crate) fn prv_mappings(&self) -> impl DoubleEndedIterator> { self.flat_bindings().filter_map(|fe| { if let FrameEntry::PrvMapping(prv_mapping) = fe { Some(prv_mapping) @@ -113,7 +110,7 @@ impl<'a> TyCtx<'a> { }) } - fn prv_mappings_mut(&mut self) -> impl DoubleEndedIterator { + fn prv_mappings_mut(&mut self) -> impl DoubleEndedIterator> { self.flat_bindings_mut().filter_map(|fe| { if let FrameEntry::PrvMapping(prv_mapping) = fe { Some(prv_mapping) @@ -126,7 +123,7 @@ impl<'a> TyCtx<'a> { pub fn update_loan_set( &mut self, prv_val_name: &str, - loan_set: HashSet, + loan_set: HashSet>, ) -> CtxResult<&mut Self> { let mut found = false; for prv_mapping in self.prv_mappings_mut().rev() { @@ -143,7 +140,11 @@ impl<'a> TyCtx<'a> { } } - pub fn extend_loans_for_prv(&mut self, base: &str, extension: I) -> CtxResult<&mut TyCtx> + pub fn extend_loans_for_prv( + &mut self, + base: &str, + extension: I, + ) -> CtxResult<'a, &mut TyCtx<'a>> where I: IntoIterator>, { @@ -152,7 +153,7 @@ impl<'a> TyCtx<'a> { Ok(self) } - pub fn loans_in_prv(&self, prv_val_name: &str) -> CtxResult<&HashSet> { + pub fn loans_in_prv(&self, prv_val_name: &str) -> CtxResult<'a, &HashSet>> { match self .prv_mappings() .rev() @@ -163,7 +164,10 @@ impl<'a> TyCtx<'a> { } } - pub fn loans_for_prv_mut(&mut self, prv_val_name: &str) -> CtxResult<&mut HashSet> { + pub fn loans_for_prv_mut( + &mut self, + prv_val_name: &str, + ) -> CtxResult<'a, &mut HashSet>> { match self .prv_mappings_mut() .rev() @@ -188,26 +192,34 @@ impl<'a> TyCtx<'a> { } // ∀π:τ ∈ Γ - pub fn all_places(&self) -> Vec { + pub fn all_places(&self, arena: &'a Bump) -> BumpVec<'a, TypedPlace<'a>> { self.idents_typed() .filter_map(|IdentTyped { ident, ty, .. }| { if let TyKind::Data(dty) = &ty.ty { - Some(TyCtx::explode_places(ident, dty)) + Some(TyCtx::explode_places(ident, dty, arena)) } else { None } }) .flatten() - .collect() + .collect_in(arena) } - fn explode_places(ident: &Ident, dty: &DataTy) -> Vec> { - fn proj(mut pl: internal::Place, idx: PathElem) -> internal::Place<'a> { + fn explode_places( + ident: &Ident<'a>, + dty: &DataTy<'a>, + arena: &'a Bump, + ) -> BumpVec<'a, TypedPlace<'a>> { + fn proj<'a>(mut pl: internal::Place<'a>, idx: PathElem<'a>) -> internal::Place<'a> { pl.path.push(idx); pl } - fn explode(pl: internal::Place, dty: DataTy) -> Vec> { + fn explode<'a>( + pl: internal::Place<'a>, + dty: DataTy<'a>, + arena: &'a Bump, + ) -> BumpVec<'a, TypedPlace<'a>> { use DataTyKind as d; match &dty.dty { @@ -219,22 +231,29 @@ impl<'a> TyCtx<'a> { | d::Ref(_) | d::RawPtr(_) | d::Ident(_) - | d::Dead(_) => vec![(pl, dty.clone())], + | d::Dead(_) => BumpVec::from_iter_in([(pl.clone(), dty.clone())], arena), //vec![(pl, dty.clone())], d::Tuple(tys) => { - let mut place_frame = vec![(pl.clone(), dty.clone())]; + let mut place_frame = BumpVec::from_iter_in([(pl.clone(), dty.clone())], arena); for (index, proj_ty) in tys.iter().enumerate() { - let mut exploded_index = - explode(proj(pl.clone(), PathElem::Proj(index)), proj_ty.clone()); + let mut exploded_index = explode( + proj(pl.clone(), PathElem::Proj(index)), + proj_ty.clone(), + arena, + ); place_frame.append(&mut exploded_index); } place_frame } d::Struct(sdecl) => { - let mut place_frame = vec![(pl.clone(), dty.clone())]; + let mut place_frame = BumpVec::from_iter_in([(pl.clone(), dty.clone())], arena); for field in sdecl.fields.iter() { let mut exploded_field = explode( - proj(pl.clone(), PathElem::FieldProj(Box::new(field.0.clone()))), + proj( + pl.clone(), + PathElem::FieldProj(arena.alloc(field.0.clone())), + ), field.1.clone(), + arena, ); place_frame.append(&mut exploded_field); } @@ -243,14 +262,18 @@ impl<'a> TyCtx<'a> { } } - explode(internal::Place::new(ident.clone(), vec![]), dty.clone()) + explode( + internal::Place::new(ident.clone(), BumpVec::new_in(arena)), + dty.clone(), + arena, + ) } - pub fn ty_of_ident(&self, ident: &Ident) -> CtxResult<&Ty> { + pub fn ty_of_ident(&self, ident: &Ident<'a>) -> CtxResult<'a, &Ty<'a>> { Ok(&self.ident_ty(ident)?.ty) } - pub fn ident_ty(&self, ident: &Ident) -> CtxResult<&IdentTyped> { + pub fn ident_ty(&self, ident: &Ident<'a>) -> CtxResult<'a, &IdentTyped<'a>> { match self .idents_typed() .rev() @@ -261,12 +284,12 @@ impl<'a> TyCtx<'a> { } } - pub fn contains(&self, ident: &Ident) -> bool { + pub fn contains(&self, ident: &Ident<'a>) -> bool { self.idents_typed().any(|i| i.ident.name == ident.name) } - pub fn place_dty(&self, place: &internal::Place<'a>) -> CtxResult> { - fn proj_ty(dty: DataTy, path: &[PathElem<'a>]) -> CtxResult> { + pub fn place_dty(&self, place: &internal::Place<'a>) -> CtxResult<'a, DataTy<'a>> { + fn proj_ty<'a>(dty: DataTy<'a>, path: &[PathElem<'a>]) -> CtxResult<'a, DataTy<'a>> { let mut res_dty = dty; for pe in path { match (&res_dty.dty, pe) { @@ -278,7 +301,7 @@ impl<'a> TyCtx<'a> { } (DataTyKind::Struct(struct_decl), PathElem::FieldProj(ident)) => { res_dty = if let Some(field) = - struct_decl.fields.iter().find(|f| &f.0 == ident.as_ref()) + struct_decl.fields.iter().find(|f| &f.0 == *ident) { field.1.clone() } else { @@ -298,18 +321,24 @@ impl<'a> TyCtx<'a> { } let ident_ty = self.ty_of_ident(&place.ident)?; if let TyKind::Data(dty) = &ident_ty.ty { - proj_ty(dty.as_ref().clone(), &place.path) + proj_ty((**dty).clone(), &place.path) } else { panic!("This place is not of a data type.") } } - pub fn set_place_dty(&mut self, pl: &internal::Place, pl_ty: DataTy) -> &mut Self { - fn set_dty_for_path_in_dty( - orig_dty: DataTy, - path: &[PathElem], - part_dty: DataTy, - ) -> DataTy { + pub fn set_place_dty( + &mut self, + pl: &internal::Place<'a>, + pl_ty: DataTy<'a>, + arena: &'a Bump, + ) -> &mut Self { + fn set_dty_for_path_in_dty<'a>( + arena: &'a Bump, + orig_dty: DataTy<'a>, + path: &[PathElem<'a>], + part_dty: DataTy<'a>, + ) -> DataTy<'a> { if path.is_empty() { return part_dty; } @@ -318,17 +347,15 @@ impl<'a> TyCtx<'a> { match (orig_dty.dty, pe) { (DataTyKind::Tuple(mut elem_tys), PathElem::Proj(n)) => { elem_tys[*n] = - set_dty_for_path_in_dty(elem_tys[*n].clone(), &path[1..], part_dty); - DataTy::new(DataTyKind::Tuple(elem_tys)) + set_dty_for_path_in_dty(arena, elem_tys[*n].clone(), &path[1..], part_dty); + DataTy::new(arena, DataTyKind::Tuple(elem_tys)) } - (DataTyKind::Struct(mut struct_decl), PathElem::FieldProj(ident)) => { - if let Some(field) = struct_decl - .fields - .iter_mut() - .find(|f| &f.0 == ident.as_ref()) - { - field.1 = set_dty_for_path_in_dty(field.1.clone(), &path[1..], part_dty); - DataTy::new(DataTyKind::Struct(struct_decl)) + (DataTyKind::Struct(struct_decl), PathElem::FieldProj(ident)) => { + let struct_decl = arena.alloc(struct_decl.clone()); + if let Some(field) = struct_decl.fields.iter_mut().find(|f| &f.0 == *ident) { + field.1 = + set_dty_for_path_in_dty(arena, field.1.clone(), &path[1..], part_dty); + DataTy::new(arena, DataTyKind::Struct(struct_decl)) } else { panic!("Struct field with name `{}` does not exist.", ident.name) } @@ -337,23 +364,28 @@ impl<'a> TyCtx<'a> { } } - let mut ident_typed = self + let ident_typed = self .idents_typed_mut() .rev() .find(|ident_typed| ident_typed.ident == pl.ident) .unwrap(); if let TyKind::Data(dty) = &ident_typed.ty.ty { - let updated_dty = set_dty_for_path_in_dty(*dty.clone(), pl.path.as_slice(), pl_ty); - ident_typed.ty = Ty::new(TyKind::Data(Box::new(updated_dty))); + let updated_dty = + set_dty_for_path_in_dty(arena, (**dty).clone(), pl.path.as_slice(), pl_ty); + ident_typed.ty = Ty::new(TyKind::Data(arena.alloc(updated_dty))); self } else { panic!("Trying to set data type for identifier without data type.") } } - pub fn kill_place(&mut self, pl: &internal::Place) -> &mut Self { + pub fn kill_place(&mut self, pl: &internal::Place<'a>, arena: &'a Bump) -> &mut Self { if let Ok(pl_dty) = self.place_dty(pl) { - self.set_place_dty(pl, DataTy::new(DataTyKind::Dead(Box::new(pl_dty)))) + self.set_place_dty( + pl, + DataTy::new(arena, DataTyKind::Dead(arena.alloc(pl_dty))), + arena, + ) } else { panic!("Trying to kill the type of a place that doesn't exist.") } @@ -383,7 +415,7 @@ impl<'a> TyCtx<'a> { } // Γ ▷- p = Γ′ - pub(super) fn without_reborrow_loans(&mut self, pl_expr: &PlaceExpr) -> &mut Self { + pub(super) fn without_reborrow_loans(&mut self, pl_expr: &PlaceExpr<'a>) -> &mut Self { for frame_entry in self.flat_bindings_mut() { if let FrameEntry::PrvMapping(PrvMapping { prv: _, loans }) = frame_entry { // FIXME not prefix_of but *x within p? @@ -409,25 +441,30 @@ impl<'a> TyCtx<'a> { } pub(super) struct AccessCtx<'a> { - ctx: HashSet>, + ctx: BumpVec<'a, Loan<'a>>, } impl<'a> AccessCtx<'a> { - pub fn new() -> Self { + pub fn new(arena: &'a Bump) -> Self { AccessCtx { - ctx: HashSet::new(), + ctx: BumpVec::new_in(arena), } } - pub fn insert(&mut self, loans: HashSet>) { + pub fn insert(&mut self, loans: BumpVec>) { self.ctx.extend(loans.into_iter()) } - pub fn hash_set(&self) -> &HashSet> { + pub fn hash_set(&self) -> &BumpVec> { &self.ctx } - pub fn clear_sync_for(&mut self, ty_ctx: &'a TyCtx<'a>, exec: &'a ExecExpr<'a>) { + pub fn clear_sync_for( + &mut self, + ty_ctx: &'a TyCtx<'a>, + exec: &'a ExecExpr<'a>, + arena: &'a Bump, + ) { self.ctx = self .ctx .iter() @@ -437,26 +474,53 @@ impl<'a> AccessCtx<'a> { place_expr, }) }) - .collect(); + .collect_in(arena); + } + + // a tiny helper that drills down a PlaceExpr to its `Ident` + // and returns it by value (i.e. clones the Box inside Ident) + // maybe move this one out ? + fn root_ident_of_expr(pe: &PlaceExpr<'a>) -> Ident<'a> { + match &pe.pl_expr { + PlaceExprKind::Ident(id) => id.clone(), + PlaceExprKind::Select(inner, _) + | PlaceExprKind::View(inner, _) + | PlaceExprKind::Proj(inner, _) + | PlaceExprKind::FieldProj(inner, _) + | PlaceExprKind::Idx(inner, _) + | PlaceExprKind::Deref(inner) => { + // recursive descent + Self::root_ident_of_expr(inner) + } + } } - pub fn garbage_collect(&mut self, ty_ctx: &'a TyCtx<'a>) { - // TODO make more efficient - // drain is unstable for HashSet, use Vec anyway? - let mut cleaned_up_set = HashSet::new(); - for l in &self.ctx { - let ident = &l.place_expr.as_ident_and_path().0; - if ty_ctx.contains(ident) { - cleaned_up_set.insert(l.clone()); + pub fn garbage_collect(&mut self, ty_ctx: &TyCtx<'a>, arena: &'a Bump) { + // 1) take ownership of the old loans + let old_loans = std::mem::replace(&mut self.ctx, BumpVec::new_in(arena)); + + // 2) build a fresh vec of only the “alive” loans + let mut new_loans = BumpVec::new_in(arena); + for loan in old_loans.into_iter() { + // extract root ident by *value* (no long‐lived borrow) + let ident = Self::root_ident_of_expr(&loan.place_expr); + if ty_ctx.contains(&ident) { + new_loans.push(loan); } } - self.ctx = cleaned_up_set; + + // 3) store it back + self.ctx = new_loans; } } -fn trim_after_select_of<'a>(ty_ctx: &'a TyCtx<'a>, exec: &'a ExecExpr<'a>, pl_expr: PlaceExpr<'a>) -> Option> { +fn trim_after_select_of<'a>( + ty_ctx: &'a TyCtx<'a>, + exec: &'a ExecExpr<'a>, + pl_expr: PlaceExpr<'a>, +) -> Option> { match pl_expr.pl_expr { - PlaceExprKind::Select(p, sel_exec) if sel_exec.as_ref() == exec => { + PlaceExprKind::Select(p, sel_exec) if sel_exec == exec => { Some(PlaceExpr::new(PlaceExprKind::Select(p, sel_exec))) } PlaceExprKind::Select(ipl, _) @@ -464,7 +528,7 @@ fn trim_after_select_of<'a>(ty_ctx: &'a TyCtx<'a>, exec: &'a ExecExpr<'a>, pl_ex | PlaceExprKind::Proj(ipl, _) | PlaceExprKind::FieldProj(ipl, _) | PlaceExprKind::Idx(ipl, _) - | PlaceExprKind::Deref(ipl) => trim_after_select_of(ty_ctx, exec, *ipl), + | PlaceExprKind::Deref(ipl) => trim_after_select_of(ty_ctx, exec, ipl.clone()), PlaceExprKind::Ident(ident) => { let ident_exec = &ty_ctx .ident_ty(&ident) @@ -492,23 +556,29 @@ pub(super) type CtxResult<'a, T> = Result>; #[derive(PartialEq, Eq, Debug, Clone)] pub(super) struct KindCtx<'a> { - ctx: Vec>>, + ctx: BumpVec<'a, BumpVec<'a, KindingCtxEntry<'a>>>, } impl<'a> KindCtx<'a> { - pub fn new() -> Self { - KindCtx { ctx: vec![vec![]] } + pub fn new(arena: &'a Bump) -> Self { + let mut scopes = BumpVec::new_in(arena); + scopes.push(BumpVec::new_in(arena)); + KindCtx { ctx: scopes } } - pub fn gl_fun_kind_ctx(idents: Vec>, prv_rels: Vec>) -> CtxResult<'a, Self> { - let mut kind_ctx: Self = KindCtx::new(); + pub fn gl_fun_kind_ctx( + idents: BumpVec<'a, IdentKinded<'a>>, + prv_rels: BumpVec<'a, PrvRel<'a>>, + arena: &'a Bump, + ) -> CtxResult<'a, Self> { + let mut kind_ctx: Self = KindCtx::new(arena); kind_ctx.append_idents(idents); kind_ctx.append_prv_rels(prv_rels)?; Ok(kind_ctx) } - pub fn push_empty_scope(&mut self) -> &mut Self { - self.ctx.push(vec![]); + pub fn push_empty_scope(&mut self, arena: &'a Bump) -> &mut Self { + self.ctx.push(BumpVec::new_in(arena)); self } @@ -516,7 +586,10 @@ impl<'a> KindCtx<'a> { self.ctx.pop(); } - pub fn append_idents>>(&mut self, idents: I) -> &mut Self { + pub fn append_idents>>( + &mut self, + idents: I, + ) -> &mut Self { let entries = idents.into_iter().map(KindingCtxEntry::Ident); for e in entries { self.ctx.last_mut().unwrap().push(e); @@ -527,7 +600,7 @@ impl<'a> KindCtx<'a> { pub fn append_prv_rels> + Clone>( &mut self, prv_rels: I, - ) -> CtxResult<&mut Self> { + ) -> CtxResult<'a, &mut Self> { self.well_kinded_prv_rels(prv_rels.clone())?; for prv_rel in prv_rels { self.ctx @@ -541,7 +614,7 @@ impl<'a> KindCtx<'a> { pub fn well_kinded_prv_rels>>( &self, prv_rels: I, - ) -> CtxResult<()> { + ) -> CtxResult<'a, ()> { let mut prv_idents = self.get_idents(Kind::Provenance); for prv_rel in prv_rels.into_iter() { if !prv_idents.any(|prv_ident| &prv_rel.longer == prv_ident) { @@ -554,7 +627,7 @@ impl<'a> KindCtx<'a> { Ok(()) } - pub fn get_idents(&self, kind: Kind) -> impl Iterator { + pub fn get_idents(&'a self, kind: Kind) -> impl Iterator> + 'a { self.ctx.iter().flatten().filter_map(move |entry| { if let KindingCtxEntry::Ident(IdentKinded { ident, kind: k }) = entry { if k == &kind { @@ -586,57 +659,79 @@ impl<'a> KindCtx<'a> { #[derive(Debug, Clone)] pub(super) enum GlobalDecl<'a> { - FnDecl(Box, Box>), - StructDecl(Box>), + FnDecl(&'a str, &'a FnTy<'a>), + StructDecl(&'a StructDecl<'a>), } #[derive(Debug)] -pub(super) struct GlobalCtx<'src, 'compil> { - compil_unit: &'compil mut CompilUnit<'src>, - checked_funs: Vec<(Box, Box<[usize]>)>, - decls: Vec>, - //items: HashMap, GlobalItem>, +pub(super) struct GlobalCtx<'a> { + compil_unit: &'a mut CompilUnit<'a>, + checked_funs: BumpVec<'a, (&'a str, &'a [usize])>, + decls: BumpVec<'a, GlobalDecl<'a>>, } -impl<'src, 'compil> GlobalCtx<'src, 'compil> { - pub fn new(compil_unit: &'compil mut CompilUnit<'src>, mut decls: Vec) -> Self { - let mut compil_unit_decls = compil_unit - .items - .iter() - .map(|item| match item { +impl<'a> GlobalCtx<'a> { + pub fn new( + compil_unit: &'a mut CompilUnit<'a>, + mut decls: BumpVec<'a, GlobalDecl<'a>>, + arena: &'a Bump, + ) -> Self { + // 1) grab a raw pointer + length; this does NOT borrow. + let items_ptr = compil_unit.items.as_ptr(); + let len = compil_unit.items.len(); + + // 2) iterate by pointer offets + for i in 0..len { + // SAFETY: `i < len` so ptr.add(i) is in-bounds, and we never touch compil_unit.items mutably. + let item: &Item<'a> = unsafe { &*items_ptr.add(i) }; + match item { Item::FunDef(fun_def) => { - GlobalDecl::FnDecl(fun_def.ident.name.clone(), Box::new(fun_def.fn_ty())) + let name: &str = &fun_def.ident.name; + let ty_ref: &FnTy<'a> = arena.alloc(fun_def.fn_ty(arena)); + decls.push(GlobalDecl::FnDecl(name, ty_ref)); } Item::FunDecl(fun_decl) => { - GlobalDecl::FnDecl(fun_decl.ident.name.clone(), Box::new(fun_decl.fn_ty())) + let name: &str = &fun_decl.ident.name; + let ty_ref: &FnTy<'a> = arena.alloc(fun_decl.fn_ty(arena)); + decls.push(GlobalDecl::FnDecl(name, ty_ref)); } - Item::StructDecl(struct_decl) => GlobalDecl::StructDecl(struct_decl.clone()), - }) - .collect(); - decls.append(&mut compil_unit_decls); + Item::StructDecl(struct_decl) => { + // We can safely store the reference here, + // because `struct_decl` lives inside `compil_unit` for 'a. + decls.push(GlobalDecl::StructDecl(struct_decl)); + } + _ => {} + } + } + + // 3) now that we never held any &borrows of items, we can store the &mut GlobalCtx { compil_unit, - checked_funs: vec![], + checked_funs: BumpVec::new_in(arena), decls, } } - pub fn has_been_checked<'a>(&self, name: &str, nat_args: &[usize]) -> bool { + pub fn has_been_checked(&self, name: &str, nat_args: &[usize]) -> bool { self.checked_funs .iter() - .any(|(fun_name, nargs)| fun_name.as_ref() == name && nargs.as_ref() == nat_args) + .any(|(fun_name, nargs)| *fun_name == name && *nargs == nat_args) } - pub fn push_fun_checked_under_nats<'a>(&mut self, fun_def: Box, nat_vals: Box<[usize]>) { + pub fn push_fun_checked_under_nats( + &mut self, + fun_def: BumpBox<'a, FunDef<'a>>, + nat_vals: &'a [usize], + ) { let fun_name = fun_def.ident.name.clone(); self.compil_unit.items.push(Item::FunDef(fun_def)); self.checked_funs.push((fun_name, nat_vals)) } - pub fn pop_fun_def<'a>(&mut self, name: &str) -> Option> { + pub fn pop_fun_def(&mut self, name: &'a str) -> Option>> { let index = self.compil_unit.items.iter().position(|item| { if let Item::FunDef(fun_def) = item { - fun_def.ident.name.as_ref() == name + fun_def.ident.name == name } else { false } @@ -652,7 +747,7 @@ impl<'src, 'compil> GlobalCtx<'src, 'compil> { } } - pub fn fn_ty_by_ident<'a>(&self, ident: &'a Ident<'a>) -> CtxResult<&'a FnTy<'a>> { + pub fn fn_ty_by_ident(&self, ident: &'a Ident<'a>) -> CtxResult<'a, &'a FnTy<'a>> { if let Some(fn_ty) = self.decls.iter().find_map(|decl| match decl { GlobalDecl::FnDecl(name, fn_ty) if name == &ident.name => Some(fn_ty), GlobalDecl::FnDecl(_, _) | GlobalDecl::StructDecl(_) => None, @@ -666,17 +761,23 @@ impl<'src, 'compil> GlobalCtx<'src, 'compil> { #[test] fn test_kill_place_ident() { - let mut ty_ctx = TyCtx::new(); - let x = IdentTyped::new( - Ident::new("x"), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::I32, - ))))), - Mutability::Const, - ExecExpr::new(ExecExprKind::new(BaseExec::Ident(Ident::new("exec")))), + let arena = Bump::new(); + + let mut ty_ctx = TyCtx::new(&arena); + let x_ident = Ident::new(&arena, "x"); + let exec_ident = Ident::new(&arena, "exec"); + let exec_expr = ExecExpr::new( + &arena, + ExecExprKind::new(&arena, BaseExec::Ident(exec_ident.clone())), ); - let place = internal::Place::new(x.ident.clone(), vec![]); - ty_ctx.append_ident_typed(x).kill_place(&place); + let scalar_ty = arena.alloc(DataTy::new(&arena, DataTyKind::Scalar(ScalarTy::I32))); + let ty_kind = TyKind::Data(scalar_ty); + let x_typed = IdentTyped::new_in(&arena, "x", Ty::new(ty_kind), Mutability::Const, exec_expr); + + ty_ctx.append_ident_typed(x_typed); + let place = internal::Place::new(x_ident.clone(), BumpVec::new_in(&arena)); + ty_ctx.kill_place(&place, &arena); + assert!(matches!( ty_ctx.idents_typed().next().unwrap().ty.dty(), DataTy { From 87e25947f6324971a1fe78e5b31c9bfb02cf5889 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Fri, 8 Aug 2025 09:22:50 +0200 Subject: [PATCH 37/57] Borrow Checking done --- src/ty_check/borrow_check.rs | 375 ++++++++++++++++++++++++++--------- 1 file changed, 277 insertions(+), 98 deletions(-) diff --git a/src/ty_check/borrow_check.rs b/src/ty_check/borrow_check.rs index c3b43588..78e4e254 100644 --- a/src/ty_check/borrow_check.rs +++ b/src/ty_check/borrow_check.rs @@ -1,7 +1,6 @@ use super::ctxs::TyCtx; use crate::arena_ast::internal::{Loan, PlaceCtx, PrvMapping}; -use crate::arena_ast::{self, *}; -use crate::parser::descend::nat; +use crate::arena_ast::*; use crate::ty_check::ctxs::{AccessCtx, GlobalCtx, KindCtx}; use crate::ty_check::error::BorrowingError; use crate::ty_check::exec::normalize; @@ -11,23 +10,23 @@ use std::collections::HashSet; type OwnResult<'a, T> = Result>; -pub(super) struct BorrowCheckCtx<'a, 'gl, 'src, 'ctxt> { +pub(super) struct BorrowCheckCtx<'a> { // TODO refactor: move into ctx module and remove public - pub gl_ctx: &'ctxt GlobalCtx<'gl, 'src>, - pub nat_ctx: &'ctxt NatCtx, - pub kind_ctx: &'ctxt KindCtx<'a>, - pub ident_exec: Option<&'ctxt IdentExec<'a>>, - pub ty_ctx: &'ctxt TyCtx<'a>, - pub access_ctx: &'ctxt AccessCtx, + pub gl_ctx: &'a GlobalCtx<'a>, + pub nat_ctx: &'a NatCtx<'a>, + pub kind_ctx: &'a KindCtx<'a>, + pub ident_exec: Option<&'a IdentExec<'a>>, + pub ty_ctx: &'a TyCtx<'a>, + pub access_ctx: &'a AccessCtx<'a>, pub exec: ExecExpr<'a>, pub reborrows: Vec>, pub own: Ownership, pub unsafe_flag: bool, } -impl<'a, 'gl, 'src, 'ctxt> BorrowCheckCtx<'a, 'gl, 'src, 'ctxt> { +impl<'a> BorrowCheckCtx<'a> { pub(super) fn new( - expr_ty_ctx: &'ctxt ExprTyCtx<'a, 'gl, 'src, 'ctxt>, + expr_ty_ctx: &'a ExprTyCtx<'a>, reborrows: Vec>, own: Ownership, ) -> Self { @@ -71,56 +70,69 @@ impl<'a, 'gl, 'src, 'ctxt> BorrowCheckCtx<'a, 'gl, 'src, 'ctxt> { // //p is ω-safe under δ and γ, with reborrow exclusion list π , and may point to any of the loans in ωp pub(super) fn access_safety_check<'a>( - ctx: &BorrowCheckCtx, + ctx: &'a BorrowCheckCtx<'a>, p: &'a PlaceExpr<'a>, -) -> OwnResult<'a, HashSet>> { + arena: &'a Bump, +) -> OwnResult<'a, BumpVec<'a, Loan<'a>>> { if !ctx.unsafe_flag { - narrowing_check(ctx, p, &ctx.exec)?; - access_conflict_check(ctx, p)?; + narrowing_check(ctx, p, &ctx.exec, arena)?; + access_conflict_check(ctx, p, arena)?; } - borrow_check(ctx, p) + borrow_check(ctx, p, arena) } pub(super) fn borrow_check<'a>( - ctx: &'a BorrowCheckCtx, + ctx: &'a BorrowCheckCtx<'a>, p: &'a PlaceExpr<'a>, -) -> OwnResult<'a, HashSet>> { - let (pl_ctx, most_spec_pl) = p.to_pl_ctx_and_most_specif_pl(); + arena: &'a Bump, +) -> OwnResult<'a, BumpVec<'a, Loan<'a>>> { + let (pl_ctx, most_spec_pl) = p.to_pl_ctx_and_most_specif_pl(arena); + + let pl_ctx: &'a PlaceCtx<'a> = arena.alloc(pl_ctx); + let most_spec_pl = arena.alloc(most_spec_pl); + if p.is_place() { - ownership_safe_place(ctx, p) + ownership_safe_place(ctx, p, arena) } else { - let pl_ctx_no_deref = pl_ctx.without_innermost_deref(); + let pl_ctx_no_deref = pl_ctx.without_innermost_deref(arena); + // Γ(π) = &r ωπ τπ match &ctx.ty_ctx.place_dty(&most_spec_pl)?.dty { DataTyKind::Ref(reff) => match &reff.rgn { Provenance::Value(prv_val_name) => ownership_safe_deref( ctx, - &pl_ctx_no_deref, - &most_spec_pl, - prv_val_name.as_str(), + pl_ctx_no_deref, + most_spec_pl, + *prv_val_name, reff.own, + arena, ), Provenance::Ident(_) => { - ownership_safe_deref_abs(ctx, &pl_ctx_no_deref, &most_spec_pl, reff.own) + ownership_safe_deref_abs(ctx, pl_ctx_no_deref, most_spec_pl, reff.own, arena) } }, - DataTyKind::RawPtr(_) => ownership_safe_deref_raw(ctx, &pl_ctx_no_deref, &most_spec_pl), + DataTyKind::RawPtr(_) => { + ownership_safe_deref_raw(ctx, pl_ctx_no_deref, most_spec_pl, arena) + } // TODO improve error message - t => ownership_safe_place(ctx, p), //panic!("Is the type dead? `{:?}`\n {:?}", t, p), + t => ownership_safe_place(ctx, p, arena), //panic!("Is the type dead? `{:?}`\n {:?}", t, p), } } } // TODO remove? +/** fn ownership_safe_deref_raw<'a>( - ctx: &BorrowCheckCtx, + ctx: &'a BorrowCheckCtx<'a>, pl_ctx_no_deref: &'a PlaceCtx<'a>, most_spec_pl: &'a internal::Place<'a>, + arena: &'a Bump, ) -> OwnResult<'a, HashSet>> { // TODO is this correct? - let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr(PlaceExpr::new( - PlaceExprKind::Deref(Box::new(most_spec_pl.to_place_expr())), - )); + let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr( + arena, + PlaceExpr::new(PlaceExprKind::Deref(&most_spec_pl.to_place_expr(arena))), + ); let mut passed_through_prvs = HashSet::new(); passed_through_prvs.insert(Loan { place_expr: currently_checked_pl_expr, @@ -128,14 +140,42 @@ fn ownership_safe_deref_raw<'a>( }); Ok(passed_through_prvs) } +*/ + +fn ownership_safe_deref_raw<'a>( + ctx: &'a BorrowCheckCtx<'a>, + pl_ctx_no_deref: &'a PlaceCtx<'a>, + most_spec_pl: &'a internal::Place<'a>, + arena: &'a Bump, +) -> OwnResult<'a, BumpVec<'a, Loan<'a>>> { + // 1) Build the inner PlaceExpr and bump-allocate it + let inner_pe: PlaceExpr<'a> = most_spec_pl.to_place_expr(arena); + let inner_ref: &'a PlaceExpr<'a> = arena.alloc(inner_pe); + + // 2) Create the Deref node around that borrowed reference + let deref_pe = PlaceExpr::new(PlaceExprKind::Deref(inner_ref)); + + // 3) Insert into the context to get back an &'a PlaceExpr<'a> + let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr(arena, deref_pe); + + // 4) Build the result + let mut passed_through_prvs = BumpVec::new_in(arena); + passed_through_prvs.push(Loan { + place_expr: currently_checked_pl_expr, + own: ctx.own, + }); + + Ok(passed_through_prvs) +} fn ownership_safe_place<'a>( - ctx: &BorrowCheckCtx, - p: &PlaceExpr, -) -> OwnResult<'a, HashSet>> { - ownership_safe_under_existing_borrows(ctx, p)?; - let mut loan_set = HashSet::new(); - loan_set.insert(Loan { + ctx: &'a BorrowCheckCtx<'a>, + p: &'a PlaceExpr<'a>, + arena: &'a Bump, +) -> OwnResult<'a, BumpVec<'a, Loan<'a>>> { + ownership_safe_under_existing_borrows(ctx, p, arena)?; + let mut loan_set = BumpVec::new_in(arena); + loan_set.push(Loan { place_expr: p.clone(), own: ctx.own, }); @@ -143,18 +183,19 @@ fn ownership_safe_place<'a>( } fn ownership_safe_deref<'a>( - ctx: &BorrowCheckCtx, - pl_ctx_no_deref: &PlaceCtx, - most_spec_pl: &internal::Place, + ctx: &'a BorrowCheckCtx<'a>, + pl_ctx_no_deref: &'a PlaceCtx<'a>, + most_spec_pl: &'a internal::Place<'a>, prv_val_name: &str, ref_own: Ownership, -) -> OwnResult<'a, HashSet>> { + arena: &'a Bump, +) -> OwnResult<'a, BumpVec<'a, Loan<'a>>> { // Γ(r) = { ω′pi } let loans_in_prv = ctx.ty_ctx.loans_in_prv(prv_val_name)?; // ω ≲ ωπ new_own_weaker_equal(ctx.own, ref_own)?; // List - let pl_ctxs_and_places_in_loans = pl_ctxs_and_places_in_loans(loans_in_prv); + let pl_ctxs_and_places_in_loans = pl_ctxs_and_places_in_loans(loans_in_prv, arena); // List<πe>, List<πi>, π let ext_reborrow_ctx = ctx.extend_reborrows( pl_ctxs_and_places_in_loans @@ -162,93 +203,173 @@ fn ownership_safe_deref<'a>( .chain(std::iter::once(most_spec_pl.clone())), ); // ext_reborrow_ctx.exec = from_exec.clone(); + let ext_ctx: &'a BorrowCheckCtx<'a> = arena.alloc(ext_reborrow_ctx); // ∀i ∈ {1...n}.Δ;Γ ⊢ω List<πe>,List<πi>,π p□[pi] ⇒ {ω pi′} - let mut potential_prvs_after_subst = subst_pl_with_potential_prvs_ownership_safe( - &ext_reborrow_ctx, - pl_ctx_no_deref, - loans_in_prv, - )?; - - let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr(PlaceExpr::new( - PlaceExprKind::Deref(Box::new(most_spec_pl.to_place_expr())), - )); - ownership_safe_under_existing_borrows(&ext_reborrow_ctx, ¤tly_checked_pl_expr)?; - potential_prvs_after_subst.insert(Loan { - place_expr: currently_checked_pl_expr, + let mut potential_prvs_after_subst = + subst_pl_with_potential_prvs_ownership_safe(ext_ctx, pl_ctx_no_deref, loans_in_prv, arena)?; + + let inner_pe: PlaceExpr<'a> = most_spec_pl.to_place_expr(arena); + let inner_ref: &'a PlaceExpr<'a> = arena.alloc(inner_pe); + + // 2) Wrap in a Deref and bump‐allocate that too + let wrapper = PlaceExpr::new(PlaceExprKind::Deref(inner_ref)); + let stripped_ref: &'a PlaceExpr<'a> = arena.alloc(wrapper); + + ownership_safe_under_existing_borrows(ext_ctx, stripped_ref, arena)?; + potential_prvs_after_subst.push(Loan { + place_expr: stripped_ref.clone(), own: ctx.own, }); Ok(potential_prvs_after_subst) } +/** fn subst_pl_with_potential_prvs_ownership_safe<'a>( - ctx: &BorrowCheckCtx, + ctx: &'a BorrowCheckCtx<'a>, pl_ctx_no_deref: &'a PlaceCtx<'a>, loans_in_prv: &HashSet>, + arena: &'a Bump, ) -> OwnResult<'a, HashSet>> { let mut loans: HashSet> = HashSet::new(); + for pl_expr in loans_in_prv.iter().map(|loan| &loan.place_expr) { - let insert_dereferenced_pl_expr = pl_ctx_no_deref.insert_pl_expr(pl_expr.clone()); + let insert_dereferenced_pl_expr = pl_ctx_no_deref.insert_pl_expr(arena, pl_expr.clone()); let loans_for_possible_prv_pl_expr = - access_safety_check(ctx, &insert_dereferenced_pl_expr)?; + access_safety_check(ctx, &insert_dereferenced_pl_expr, arena)?; loans.extend(loans_for_possible_prv_pl_expr); } + Ok(loans) } +*/ + +fn subst_pl_with_potential_prvs_ownership_safe<'a>( + ctx: &'a BorrowCheckCtx<'a>, + pl_ctx_no_deref: &'a PlaceCtx<'a>, + loans_in_prv: &HashSet>, + arena: &'a Bump, +) -> OwnResult<'a, BumpVec<'a, Loan<'a>>> { + // 1) collect into a bump-vector + let mut collected = BumpVec::new_in(arena); + for loan in loans_in_prv { + let base_pe: PlaceExpr<'a> = loan.place_expr.clone(); + let inserted_pe = pl_ctx_no_deref.insert_pl_expr(arena, base_pe); + let pe_ref: &'a PlaceExpr<'a> = arena.alloc(inserted_pe); + + let new_loans = access_safety_check(ctx, pe_ref, arena)?; + for l in new_loans { + collected.push(l); + } + } + + // 2) deduplicate in place + let mut seen = HashSet::new(); + collected.retain(|loan| seen.insert(loan.clone())); + + Ok(collected) +} +/** fn ownership_safe_deref_abs<'a>( - ctx: &BorrowCheckCtx, + ctx: &'a BorrowCheckCtx<'a>, pl_ctx_no_deref: &'a PlaceCtx<'a>, most_spec_pl: &'a internal::Place<'a>, ref_own: Ownership, -) -> OwnResult<'a, HashSet>> { - let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr(PlaceExpr::new( - PlaceExprKind::Deref(Box::new(most_spec_pl.to_place_expr())), - )); + arena: &'a Bump, +) -> OwnResult<'a, BumpVec<'a, Loan<'a>>> { + let currently_checked_pl_expr = pl_ctx_no_deref.insert_pl_expr( + arena, + PlaceExpr::new(PlaceExprKind::Deref(&most_spec_pl.to_place_expr(arena))), + ); // FIXME the type check should not have any effect, however guaranteeing that every place // expression even those which are formed recursively seem cleaner // pl_expr::ty_check(&PlExprTyCtx::from(ctx), &mut currently_checked_pl_expr)?; new_own_weaker_equal(ctx.own, ref_own)?; - ownership_safe_under_existing_borrows(ctx, ¤tly_checked_pl_expr)?; - let mut passed_through_prvs = HashSet::new(); - passed_through_prvs.insert(Loan { + ownership_safe_under_existing_borrows(ctx, ¤tly_checked_pl_expr, arena)?; + let mut passed_through_prvs = BumpVec::new_in(arena); + passed_through_prvs.push(Loan { place_expr: currently_checked_pl_expr, own: ctx.own, }); Ok(passed_through_prvs) } + */ + +fn ownership_safe_deref_abs<'a>( + ctx: &'a BorrowCheckCtx<'a>, + pl_ctx_no_deref: &'a PlaceCtx<'a>, + most_spec_pl: &'a internal::Place<'a>, + ref_own: Ownership, + arena: &'a Bump, +) -> OwnResult<'a, BumpVec<'a, Loan<'a>>> { + // 1) Build and bump-allocate the inner PlaceExpr for the raw place + let base_pe: PlaceExpr<'a> = most_spec_pl.to_place_expr(arena); + let base_ref: &'a PlaceExpr<'a> = arena.alloc(base_pe); + + // 2) Insert into the context (still an owned PlaceExpr), then bump-allocate + let inserted_pe: PlaceExpr<'a> = pl_ctx_no_deref.insert_pl_expr(arena, base_ref.clone()); + let inserted_ref: &'a PlaceExpr<'a> = arena.alloc(inserted_pe); + + // 3) Wrap that in a Deref, bump-allocate again + let deref_pe = PlaceExpr::new(PlaceExprKind::Deref(inserted_ref)); + let deref_ref: &'a PlaceExpr<'a> = arena.alloc(deref_pe); + + // 4) Check ownership ordering + new_own_weaker_equal(ctx.own, ref_own)?; + + // 5) Run the “under existing borrows” check + ownership_safe_under_existing_borrows(ctx, deref_ref, arena)?; + + // 6) Return a single‐element BumpVec of the resulting loan + let mut passed_through_prvs = BumpVec::new_in(arena); + passed_through_prvs.push(Loan { + place_expr: deref_ref.clone(), + own: ctx.own, + }); + + Ok(passed_through_prvs) +} fn narrowing_check<'a>( - ctx: &BorrowCheckCtx, + ctx: &'a BorrowCheckCtx<'a>, p: &'a PlaceExpr<'a>, active_ctx_exec: &'a ExecExpr<'a>, + arena: &'a Bump, ) -> OwnResult<'a, ()> { if ctx.own == Ownership::Shrd { return Ok(()); } match &p.pl_expr { PlaceExprKind::Ident(ident) => { - narrowable(&ctx.ty_ctx.ident_ty(ident)?.exec, active_ctx_exec) + narrowable(&ctx.ty_ctx.ident_ty(ident)?.exec, active_ctx_exec, arena) } PlaceExprKind::Select(pl_expr, select_exec) => { - narrowable(select_exec, active_ctx_exec)?; - let mut outer_exec = active_ctx_exec.remove_last_distrib(); - exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, &mut outer_exec)?; - narrowing_check(ctx, pl_expr, &outer_exec) + narrowable(select_exec, active_ctx_exec, arena)?; + + let local_outer = active_ctx_exec.remove_last_distrib(arena); + let outer_exec: &'a mut ExecExpr<'a> = arena.alloc(local_outer); + + exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, outer_exec, arena)?; + narrowing_check(ctx, pl_expr, outer_exec, arena) } PlaceExprKind::View(pl_expr, _) | PlaceExprKind::Deref(pl_expr) | PlaceExprKind::Proj(pl_expr, _) | PlaceExprKind::FieldProj(pl_expr, _) - | PlaceExprKind::Idx(pl_expr, _) => narrowing_check(ctx, pl_expr, active_ctx_exec), + | PlaceExprKind::Idx(pl_expr, _) => narrowing_check(ctx, pl_expr, active_ctx_exec, arena), } } -fn narrowable<'a>(from: &'a ExecExpr<'a>, to: &'a ExecExpr<'a>) -> OwnResult<'a, ()> { - let normal_from = normalize(from.clone()); - let normal_to = normalize(to.clone()); - exec_is_prefix_of(&normal_from, &normal_to)?; - no_forall_in_diff(&normal_from, &normal_to) +fn narrowable<'a>( + from: &'a ExecExpr<'a>, + to: &'a ExecExpr<'a>, + arena: &'a Bump, +) -> OwnResult<'a, ()> { + let normal_from = arena.alloc(normalize(from.clone())); + let normal_to = arena.alloc(normalize(to.clone())); + exec_is_prefix_of(normal_from, normal_to)?; + no_forall_in_diff(normal_from, normal_to) } fn exec_is_prefix_of<'a>(prefix: &'a ExecExpr<'a>, of: &'a ExecExpr<'a>) -> OwnResult<'a, ()> { @@ -269,9 +390,13 @@ fn exec_is_prefix_of<'a>(prefix: &'a ExecExpr<'a>, of: &'a ExecExpr<'a>) -> OwnR Ok(()) } -fn access_conflict_check<'a>(ctx: &BorrowCheckCtx, p: &'a PlaceExpr<'a>) -> OwnResult<'a, ()> { +fn access_conflict_check<'a>( + ctx: &'a BorrowCheckCtx<'a>, + p: &'a PlaceExpr<'a>, + arena: &'a Bump, +) -> OwnResult<'a, ()> { for loan in ctx.access_ctx.hash_set() { - if possible_conflict_with_previous_access(ctx.nat_ctx, ctx.own, p, loan)? { + if possible_conflict_with_previous_access(ctx.nat_ctx, ctx.own, p, loan, arena)? { return Err(BorrowingError::Conflict { checked: p.clone(), existing: loan.place_expr.clone(), @@ -282,21 +407,28 @@ fn access_conflict_check<'a>(ctx: &BorrowCheckCtx, p: &'a PlaceExpr<'a>) -> OwnR } fn possible_conflict_with_previous_access<'a>( - nat_ctx: &NatCtx, + nat_ctx: &'a NatCtx<'a>, own: Ownership, p: &'a PlaceExpr<'a>, previous: &'a Loan<'a>, + arena: &'a Bump, ) -> NatEvalResult<'a, bool> { if own == Ownership::Shrd && previous.own == Ownership::Shrd { return Ok(false); } - let (p_ident, p_path) = p.as_ident_and_path(); - let (l_ident, l_path) = previous.place_expr.as_ident_and_path(); + + let (p_ident, p_path_local) = p.as_ident_and_path(arena); + let (l_ident, l_path_local) = previous.place_expr.as_ident_and_path(arena); + + let p_path: &'a [PlExprPathElem<'a>] = arena.alloc_slice_clone(&p_path_local); + let l_path: &'a [PlExprPathElem<'a>] = arena.alloc_slice_clone(&l_path_local); + if p_ident != l_ident { return Ok(false); } - for path_elems in p_path.iter().zip(&l_path) { - match path_elems { + + for (pe_p, pe_l) in p_path.iter().zip(l_path.iter()) { + match (pe_p, pe_l) { (PlExprPathElem::Deref, PlExprPathElem::Deref) => {} (PlExprPathElem::Proj(kp), PlExprPathElem::Proj(kl)) => { if kp != kl { @@ -346,7 +478,7 @@ fn possible_conflict_with_previous_access<'a>( } fn range_intersects<'a>( - nat_ctx: &NatCtx, + nat_ctx: &'a NatCtx<'a>, lower_left: &'a Nat<'a>, upper_left: &'a Nat<'a>, lower_right: &'a Nat<'a>, @@ -370,17 +502,33 @@ fn no_forall_in_diff<'a>(from: &'a ExecExpr<'a>, under: &'a ExecExpr<'a>) -> Own Ok(()) } +/** fn pl_ctxs_and_places_in_loans<'a>( loans: &HashSet>, + arena: &'a Bump, ) -> impl Iterator, internal::Place<'a>)> + 'a { // was '_ before, what does that mean loans .iter() .map(|loan| &loan.place_expr) - .map(|pl_expr| pl_expr.to_pl_ctx_and_most_specif_pl()) + .map(|pl_expr| pl_expr.to_pl_ctx_and_most_specif_pl(arena)) } +*/ -fn new_own_weaker_equal(checked_own: Ownership, ref_own: Ownership) -> OwnResult<'a, ()> { +fn pl_ctxs_and_places_in_loans<'a, I>( + loans: I, + arena: &'a Bump, +) -> impl Iterator, internal::Place<'a>)> + 'a +where + I: IntoIterator> + 'a, + ::IntoIter: 'a, +{ + loans + .into_iter() + .map(move |loan| loan.place_expr.to_pl_ctx_and_most_specif_pl(arena)) +} + +fn new_own_weaker_equal<'a>(checked_own: Ownership, ref_own: Ownership) -> OwnResult<'a, ()> { if ref_own < checked_own { Err(BorrowingError::ConflictingOwnership) } else { @@ -389,18 +537,20 @@ fn new_own_weaker_equal(checked_own: Ownership, ref_own: Ownership) -> OwnResult } fn ownership_safe_under_existing_borrows<'a>( - ctx: &BorrowCheckCtx, + ctx: &'a BorrowCheckCtx<'a>, pl_expr: &'a PlaceExpr<'a>, + arena: &'a Bump, ) -> OwnResult<'a, ()> { if !ctx.unsafe_flag { for prv_mapping in ctx.ty_ctx.prv_mappings() { let PrvMapping { prv, loans } = prv_mapping; - let no_uniq_overlap = no_uniq_loan_overlap(ctx.own, pl_expr, loans).is_none(); + let no_uniq_overlap = no_uniq_loan_overlap(ctx.own, pl_expr, loans, arena).is_none(); if !no_uniq_overlap { return at_least_one_borrowing_place_and_all_in_reborrow( ctx.ty_ctx, prv, &ctx.reborrows, + arena, ); } } @@ -408,26 +558,55 @@ fn ownership_safe_under_existing_borrows<'a>( Ok(()) } +/** // returns None if there is no unique loan overlap or Some with the existing overlapping loan fn no_uniq_loan_overlap<'a>( own: Ownership, pl_expr: &'a PlaceExpr<'a>, loans: &HashSet>, + arena: &'a Bump, ) -> Option> { for l in loans { - if (own == Ownership::Uniq || l.own == Ownership::Uniq) && overlap(&l.place_expr, pl_expr) { + if (own == Ownership::Uniq || l.own == Ownership::Uniq) + && overlap(&l.place_expr, pl_expr, arena) + { return Some(l.clone()); } } None } +*/ + +/// Returns `Some(clashing_loan)` if there is any unique‐ownership overlap, +/// or `None` if none of the loans conflict. +fn no_uniq_loan_overlap<'a, I>( + own: Ownership, + pl_expr: &'a PlaceExpr<'a>, + loans: I, + arena: &'a Bump, +) -> Option> +where + I: IntoIterator>, +{ + loans.into_iter().find_map(|l| { + // must be at least one Unique side, and the places must overlap + if (own == Ownership::Uniq || l.own == Ownership::Uniq) + && overlap(&l.place_expr, pl_expr, arena) + { + Some(l.clone()) + } else { + None + } + }) +} fn at_least_one_borrowing_place_and_all_in_reborrow<'a>( ty_ctx: &'a TyCtx<'a>, prv_name: &str, reborrows: &[internal::Place<'a>], + arena: &'a Bump, ) -> OwnResult<'a, ()> { - let all_places = ty_ctx.all_places(); + let all_places = ty_ctx.all_places(arena); // check that a borrow with given provenance exists. // It could not exist for example in case it is used for a parameter // during function application. The second part of this function would succeed in this case @@ -455,14 +634,14 @@ fn conflicting_path<'a>(pathl: &[PlExprPathElem<'a>], pathr: &[PlExprPathElem<'a match lr { (PlExprPathElem::Idx(_), _) => return true, (v @ PlExprPathElem::View(iv), path_elem) - if v != path_elem && iv.name.name.as_ref() != pre_decl::SELECT_RANGE => + if v != path_elem && iv.name.name != pre_decl::SELECT_RANGE => { return true } (PlExprPathElem::View(ivl), PlExprPathElem::View(ivr)) if ivl != ivr - && ivl.name.name.as_ref() == pre_decl::SELECT_RANGE - && ivr.name.name.as_ref() == pre_decl::SELECT_RANGE => + && ivl.name.name == pre_decl::SELECT_RANGE + && ivr.name.name == pre_decl::SELECT_RANGE => { match ( &ivr.gen_args[0], @@ -471,10 +650,10 @@ fn conflicting_path<'a>(pathl: &[PlExprPathElem<'a>], pathr: &[PlExprPathElem<'a &ivr.gen_args[1], ) { ( - ArgKinded::Nat(lower_left), - ArgKinded::Nat(upper_left), - ArgKinded::Nat(lower_right), - ArgKinded::Nat(upper_right), + ArgKinded::Nat(_lower_left), + ArgKinded::Nat(_upper_left), + ArgKinded::Nat(_lower_right), + ArgKinded::Nat(_upper_right), ) => { // intersecting ranges // TAKE CARE: the comparisons are partial and return false in case the From a4ff0f8dadefac483ddf5c32b774993b2e8c955a Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Fri, 8 Aug 2025 15:57:31 +0200 Subject: [PATCH 38/57] did some work in the type checker --- src/codegen/mod.rs | 2 +- src/lib.rs | 2 +- src/ty_check/borrow_check.rs | 20 +- src/ty_check/exec.rs | 545 +++++++++++++++++++++++++----- src/ty_check/infer_kinded_args.rs | 1 + src/ty_check/mod.rs | 18 +- src/ty_check/pl_expr.rs | 24 +- src/ty_check/subty.rs | 49 +-- 8 files changed, 523 insertions(+), 138 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 766db7c0..4b4bf4d7 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -994,7 +994,7 @@ fn gen_sync_stmt<'a>(exec: &'a desc::ExecExpr<'a>) -> cu::Stmt<'a> { // } } -fn gen_sched(sched: &'a desc::Sched<'a>, codegen_ctx: &'a mut CodegenCtx<'a>) -> cu::Stmt<'a> { +fn gen_sched<'a>(sched: &'a desc::Sched<'a>, codegen_ctx: &'a mut CodegenCtx<'a>) -> cu::Stmt<'a> { codegen_ctx.push_scope(); let expanded_sched_exec_expr = expand_exec_expr(codegen_ctx, sched.sched_exec.as_ref()); let inner_exec = desc::ExecExpr::new(expanded_sched_exec_expr.exec.clone().forall(sched.dim)); diff --git a/src/lib.rs b/src/lib.rs index 2e681693..62c11265 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,6 @@ pub fn compile(file_path: &str) -> Result { let source = parser::SourceCode::from_file(file_path)?; let arena = Bump::new(); let mut compil_unit = parser::parse(&arena, &source); - ty_check::ty_check(&mut compil_unit)?; + ty_check::ty_check(&mut compil_unit, &arena)?; Ok(codegen::gen(&compil_unit, false)) } diff --git a/src/ty_check/borrow_check.rs b/src/ty_check/borrow_check.rs index 78e4e254..ba6cdb24 100644 --- a/src/ty_check/borrow_check.rs +++ b/src/ty_check/borrow_check.rs @@ -347,11 +347,19 @@ fn narrowing_check<'a>( PlaceExprKind::Select(pl_expr, select_exec) => { narrowable(select_exec, active_ctx_exec, arena)?; - let local_outer = active_ctx_exec.remove_last_distrib(arena); - let outer_exec: &'a mut ExecExpr<'a> = arena.alloc(local_outer); + let mut outer_exec: ExecExpr<'a> = active_ctx_exec.remove_last_distrib(arena); - exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, outer_exec, arena)?; - narrowing_check(ctx, pl_expr, outer_exec, arena) + exec::ty_check( + ctx.nat_ctx, + ctx.ty_ctx, + ctx.ident_exec, + &mut outer_exec, + arena, + )?; + + let outer_exec_ref: &'a ExecExpr<'a> = arena.alloc(outer_exec); + + narrowing_check(ctx, pl_expr, outer_exec_ref, arena) } PlaceExprKind::View(pl_expr, _) | PlaceExprKind::Deref(pl_expr) @@ -366,8 +374,8 @@ fn narrowable<'a>( to: &'a ExecExpr<'a>, arena: &'a Bump, ) -> OwnResult<'a, ()> { - let normal_from = arena.alloc(normalize(from.clone())); - let normal_to = arena.alloc(normalize(to.clone())); + let normal_from = arena.alloc(normalize(from.clone(), arena)); + let normal_to = arena.alloc(normalize(to.clone(), arena)); exec_is_prefix_of(normal_from, normal_to)?; no_forall_in_diff(normal_from, normal_to) } diff --git a/src/ty_check/exec.rs b/src/ty_check/exec.rs index 89073500..5298d4c4 100644 --- a/src/ty_check/exec.rs +++ b/src/ty_check/exec.rs @@ -2,22 +2,25 @@ use super::{ BaseExec, BinOpNat, Dim, Dim1d, Dim2d, DimCompo, ExecExpr, ExecPathElem, ExecTy, ExecTyKind, IdentExec, Nat, TyCtx, TyError, TyResult, }; -use crate::arena_ast::{LeftOrRight, NatCtx}; +use crate::arena_ast::{ExecExprKind, LeftOrRight, NatCtx}; +use bumpalo::{collections::Vec as BumpVec, Bump}; pub(super) fn ty_check<'a>( - nat_ctx: &NatCtx, - ty_ctx: &TyCtx, - ident_exec: Option<&IdentExec>, - exec_expr: &mut ExecExpr, + nat_ctx: &'a NatCtx<'a>, + ty_ctx: &'a TyCtx<'a>, + ident_exec: Option<&'a IdentExec<'a>>, + exec_expr: &mut ExecExpr<'a>, + arena: &'a Bump, ) -> TyResult<'a, ()> { - let mut exec_ty = match &exec_expr.exec.base { + // 1) compute the base kind + let exec_kind = match &exec_expr.exec.base { BaseExec::Ident(ident) => { if let Some(ie) = ident_exec { if ident == &ie.ident { ie.ty.ty.clone() } else { - let inline_exec = ty_ctx.get_exec_expr_for_exec_ident(ident)?; - inline_exec.ty.as_ref().unwrap().ty.clone() + let inline = ty_ctx.get_exec_expr_for_exec_ident(ident)?; + inline.ty.as_ref().unwrap().ty.clone() } } else { return Err(TyError::IllegalExec); @@ -27,71 +30,75 @@ pub(super) fn ty_check<'a>( BaseExec::GpuGrid(gdim, bdim) => ExecTyKind::GpuGrid(gdim.clone(), bdim.clone()), }; - for e in &exec_expr.exec.path { - match e { - ExecPathElem::ForAll(d) => { - exec_ty = ty_check_exec_forall(*d, &exec_ty)?; - } - ExecPathElem::TakeRange(exec_split) => { - exec_ty = ty_check_exec_take_range( - exec_split.split_dim, - &exec_split.pos, - exec_split.left_or_right, - &exec_ty, - )?; - } - ExecPathElem::ToThreads(d) => { - exec_ty = ty_check_exec_to_threads(*d, &exec_ty)?; + // 2) Bump‐allocate that base kind so we have &'a ExecTyKind + let mut kind_ref: &'a ExecTyKind = &arena.alloc(ExecTy::new(exec_kind.clone())).ty; + + // 3) For each step, work entirely with arena‐owned refs + for step in &exec_expr.exec.path { + // call the helper on an arena‐live reference + let next_kind: ExecTyKind = match step { + ExecPathElem::ForAll(d) => ty_check_exec_forall(*d, kind_ref, arena)?, + ExecPathElem::TakeRange(sp) => { + ty_check_exec_take_range(sp.split_dim, &sp.pos, sp.left_or_right, kind_ref, arena)? } - ExecPathElem::ToWarps => exec_ty = ty_check_exec_to_warps(nat_ctx, &exec_ty)?, - } + ExecPathElem::ToThreads(d) => ty_check_exec_to_threads(*d, kind_ref, arena)?, + ExecPathElem::ToWarps => ty_check_exec_to_warps(nat_ctx, kind_ref, arena)?, + }; + // Now bump‐allocate the returned kind, update our ref + let boxed = arena.alloc(ExecTy::new(next_kind)); + kind_ref = &boxed.ty; } - exec_expr.ty = Some(Box::new(ExecTy::new(exec_ty))); + + // 4) Finally write out the fully‐elaborated type + exec_expr.ty = Some(arena.alloc(ExecTy::new(kind_ref.clone()))); + Ok(()) } fn ty_check_exec_to_threads<'a>( d: DimCompo, exec_ty: &'a ExecTyKind<'a>, + arena: &'a Bump, ) -> TyResult<'a, ExecTyKind<'a>> { if let ExecTyKind::GpuGrid(gdim, bdim) = exec_ty { - let (rest_gdim, rem_gdim) = remove_dim(gdim, d)?; - let (rest_bdim, rem_bdim) = remove_dim(bdim, d)?; - let global_dim = match (rem_gdim, rem_bdim) { - (Dim::X(g), Dim::X(b)) => Dim::X(Box::new(Dim1d(Nat::BinOp( - BinOpNat::Mul, - Box::new(g.0), - Box::new(b.0), - )))), - (Dim::Y(g), Dim::Y(b)) => Dim::Y(Box::new(Dim1d(Nat::BinOp( - BinOpNat::Mul, - Box::new(g.0), - Box::new(b.0), - )))), - (Dim::Z(g), Dim::Z(b)) => Dim::Z(Box::new(Dim1d(Nat::BinOp( - BinOpNat::Mul, - Box::new(g.0), - Box::new(b.0), - )))), + let (rest_gdim, rem_gdim) = remove_dim(gdim, d, arena)?; + let (rest_bdim, rem_bdim) = remove_dim(bdim, d, arena)?; + + let global_dim: Dim<'a> = match (rem_gdim, rem_bdim) { + (Dim::X(g), Dim::X(b)) => { + let combined = Nat::new_binop_ref(arena, BinOpNat::Mul, g.0.clone(), b.0.clone()); + // use a zero-capture closure so that its inferred lifetime is `'a` + Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::X(d1), combined) + } + (Dim::Y(g), Dim::Y(b)) => { + let combined = Nat::new_binop_ref(arena, BinOpNat::Mul, g.0.clone(), b.0.clone()); + Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Y(d1), combined) + } + (Dim::Z(g), Dim::Z(b)) => { + let combined = Nat::new_binop_ref(arena, BinOpNat::Mul, g.0.clone(), b.0.clone()); + Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Z(d1), combined) + } _ => { return Err(TyError::String(format!( - "Provided dimension {} does not exist", - d + "Cannot thread-map dimension {:?} on {:?}/{:?}", + d, gdim, bdim ))) } }; - match (rest_gdim, rest_bdim) { - (Some(rest_gdim), Some(rest_bdim)) => Ok(ExecTyKind::GpuToThreads( - global_dim, - Box::new(ExecTy::new(ExecTyKind::GpuBlockGrp(rest_gdim, rest_bdim))), - )), - _ => unimplemented!(), + + if let (Some(rg), Some(rb)) = (rest_gdim, rest_bdim) { + let inner = ExecTyKind::GpuBlockGrp(rg, rb); + let inner_ty: &'a ExecTy<'a> = arena.alloc(ExecTy::new(inner)); + Ok(ExecTyKind::GpuToThreads(global_dim, inner_ty)) + } else { + Err(TyError::UnexpectedType) } } else { Err(TyError::UnexpectedType) } } +/** fn ty_check_exec_to_warps<'a>( nat_ctx: &NatCtx, exec_ty: &'a ExecTyKind<'a>, @@ -123,35 +130,72 @@ fn ty_check_exec_to_warps<'a>( ))), } } +*/ + +fn ty_check_exec_to_warps<'a>( + nat_ctx: &'a NatCtx<'a>, + exec_ty: &'a ExecTyKind<'a>, + arena: &'a Bump, +) -> TyResult<'a, ExecTyKind<'a>> { + // Only valid if we're looking at a single‐dimension block + if let ExecTyKind::GpuBlock(block_dim) = exec_ty { + match block_dim { + Dim::X(d1) | Dim::Y(d1) | Dim::Z(d1) => { + // d1: &Dim1d<'a>, so d1.0: Nat<'a> + let len = d1.0.eval(nat_ctx)?; + if len % 32 != 0 { + return Err(TyError::String(format!( + "Block size must be divisible by 32 to form warps, got {} in {:?}", + len, exec_ty + ))); + } + // compute len / 32 in the arena + let warp_nat: Nat<'a> = + Nat::new_binop_ref(arena, BinOpNat::Div, d1.0.clone(), Nat::Lit(32)); + Ok(ExecTyKind::GpuWarpGrp(warp_nat)) + } + _ => Err(TyError::String(format!( + "GpuBlock must be 1-D to form warps, got {:?}", + exec_ty + ))), + } + } else { + Err(TyError::String(format!( + "Cannot form warps from non-GpuBlock type {:?}", + exec_ty + ))) + } +} fn ty_check_exec_forall<'a>( d: DimCompo, exec_ty: &'a ExecTyKind<'a>, + arena: &'a Bump, ) -> TyResult<'a, ExecTyKind<'a>> { let res_ty = match exec_ty { ExecTyKind::GpuGrid(gdim, bdim) => { - let inner_dim = remove_dim(gdim, d)?.0; + let inner_dim = remove_dim(gdim, d, arena)?.0; match inner_dim { Some(dim) => ExecTyKind::GpuGrid(dim, bdim.clone()), None => ExecTyKind::GpuBlock(bdim.clone()), } } ExecTyKind::GpuBlockGrp(gdim, bdim) => { - let inner_dim = remove_dim(gdim, d)?.0; + let inner_dim = remove_dim(gdim, d, arena)?.0; match inner_dim { Some(dim) => ExecTyKind::GpuBlockGrp(dim, bdim.clone()), None => ExecTyKind::GpuBlock(bdim.clone()), } } ExecTyKind::GpuBlock(bdim) => { - let inner_dim = remove_dim(bdim, d)?.0; + let inner_dim = remove_dim(bdim, d, arena)?.0; match inner_dim { Some(dim) => ExecTyKind::GpuBlock(dim), None => ExecTyKind::GpuThread, } } ExecTyKind::GpuThreadGrp(tdim) => { - let inner_dim = remove_dim(tdim, d)?.0; + let inner_dim = remove_dim(tdim, d, arena)?.0; match inner_dim { Some(dim) => ExecTyKind::GpuThreadGrp(dim), None => ExecTyKind::GpuThread, @@ -163,8 +207,10 @@ fn ty_check_exec_forall<'a>( if dim_compo_matches_dim(d, dim) { inner_exec.ty.clone() } else { - let forall_inner = ty_check_exec_forall(d, &inner_exec.ty)?; - ExecTyKind::GpuToThreads(dim.clone(), Box::new(ExecTy::new(forall_inner))) + let forall_inner = ty_check_exec_forall(d, &inner_exec.ty, arena)?; + let new_ty: ExecTy<'a> = ExecTy::new(forall_inner); + let new_ref: &'a ExecTy<'a> = arena.alloc(new_ty); + ExecTyKind::GpuToThreads(dim.clone(), new_ref) } } ex @ ExecTyKind::CpuThread | ex @ ExecTyKind::GpuThread | ex @ ExecTyKind::Any => { @@ -174,6 +220,7 @@ fn ty_check_exec_forall<'a>( Ok(res_ty) } +/** pub fn remove_dim<'a>( dim: &'a Dim<'a>, dim_compo: DimCompo, @@ -230,63 +277,168 @@ pub fn remove_dim<'a>( _ => Err(TyError::IllegalDimension), } } +*/ + +pub fn remove_dim<'a>( + dim: &'a Dim<'a>, + dim_compo: DimCompo, + arena: &'a Bump, +) -> TyResult<'a, (Option>, Dim<'a>)> { + use DimCompo::*; + let result = match (dim, dim_compo) { + // 3D → leftover 2D + removed 1D + (Dim::XYZ(d3), X) => { + let rest = Dim::new_2d( + arena, + |d2: &'a Dim2d<'a>| Dim::YZ(d2), + d3.1.clone(), + d3.2.clone(), + ); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::X(d1), d3.0.clone()); + (Some(rest), rem) + } + (Dim::XYZ(d3), Y) => { + let rest = Dim::new_2d( + arena, + |d2: &'a Dim2d<'a>| Dim::XZ(d2), + d3.0.clone(), + d3.2.clone(), + ); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Y(d1), d3.1.clone()); + (Some(rest), rem) + } + (Dim::XYZ(d3), Z) => { + let rest = Dim::new_2d( + arena, + |d2: &'a Dim2d<'a>| Dim::XY(d2), + d3.0.clone(), + d3.1.clone(), + ); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Z(d1), d3.2.clone()); + (Some(rest), rem) + } + + // 2D → leftover 1D + removed 1D + (Dim::XY(d2), X) => { + let rest = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Y(d1), d2.1.clone()); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::X(d1), d2.0.clone()); + (Some(rest), rem) + } + (Dim::XY(d2), Y) => { + let rest = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::X(d1), d2.0.clone()); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Y(d1), d2.1.clone()); + (Some(rest), rem) + } + + (Dim::XZ(d2), X) => { + let rest = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Z(d1), d2.1.clone()); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::X(d1), d2.0.clone()); + (Some(rest), rem) + } + (Dim::XZ(d2), Z) => { + let rest = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::X(d1), d2.0.clone()); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Z(d1), d2.1.clone()); + (Some(rest), rem) + } + + (Dim::YZ(d2), Y) => { + let rest = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Z(d1), d2.1.clone()); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Y(d1), d2.0.clone()); + (Some(rest), rem) + } + (Dim::YZ(d2), Z) => { + let rest = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Y(d1), d2.0.clone()); + let rem = Dim::new_1d(arena, |d1: &'a Dim1d<'a>| Dim::Z(d1), d2.1.clone()); + (Some(rest), rem) + } + + // 1D → nothing + same 1D + (Dim::X(d1), X) => ( + None, + Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::X(d), d1.0.clone()), + ), + (Dim::Y(d1), Y) => ( + None, + Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::Y(d), d1.0.clone()), + ), + (Dim::Z(d1), Z) => ( + None, + Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::Z(d), d1.0.clone()), + ), + + // anything else is illegal + _ => return Err(TyError::IllegalDimension), + }; + + Ok(result) +} fn ty_check_exec_take_range<'a>( d: DimCompo, n: &'a Nat<'a>, proj: LeftOrRight, exec_ty: &'a ExecTyKind<'a>, + arena: &'a Bump, ) -> TyResult<'a, ExecTyKind<'a>> { - // TODO check well-formedness of Nats - let (lexec_ty, rexec_ty) = match exec_ty { + // split into two ExecTyKind variants, left & right + let (left_ty, right_ty) = match exec_ty { + // Grid or BlockGrp: we split the grid‐dim, keep block‐dim the same ExecTyKind::GpuGrid(gdim, bdim) | ExecTyKind::GpuBlockGrp(gdim, bdim) => { - let (ldim, rdim) = split_dim(d, n.clone(), gdim.clone())?; - ( - ExecTyKind::GpuBlockGrp(ldim, bdim.clone()), - ExecTyKind::GpuBlockGrp(rdim, bdim.clone()), - ) + let (ldim, rdim) = split_dim(d, n, gdim.clone(), arena)?; + let left = ExecTyKind::GpuBlockGrp(ldim, bdim.clone()); + let right = ExecTyKind::GpuBlockGrp(rdim, bdim.clone()); + (left, right) } + + // Block or ThreadGrp: split the single dim ExecTyKind::GpuBlock(dim) | ExecTyKind::GpuThreadGrp(dim) => { - let (ldim, rdim) = split_dim(d, n.clone(), dim.clone())?; - ( - ExecTyKind::GpuThreadGrp(ldim), - ExecTyKind::GpuThreadGrp(rdim), - ) + let (ldim, rdim) = split_dim(d, n, dim.clone(), arena)?; + let left = ExecTyKind::GpuThreadGrp(ldim); + let right = ExecTyKind::GpuThreadGrp(rdim); + (left, right) } - ExecTyKind::GpuToThreads(dim, inner) => { + + // ToThreads: either it splits on the ToThreads dim, or we descend into the inner ExecTy + ExecTyKind::GpuToThreads(dim, inner_ref) => { if dim_compo_matches_dim(d, dim) { - let (ldim, rdim) = split_dim(d, n.clone(), dim.clone())?; + // slice the ToThreads dimension itself + let (ldim, rdim) = split_dim(d, n, dim.clone(), arena)?; ( - ExecTyKind::GpuToThreads(ldim, inner.clone()), - ExecTyKind::GpuToThreads(rdim, inner.clone()), + ExecTyKind::GpuToThreads(ldim, inner_ref.clone()), + ExecTyKind::GpuToThreads(rdim, inner_ref.clone()), ) - } else if let ExecTyKind::GpuBlockGrp(gdim, bdim) = &inner.ty { - let (ldim, rdim) = split_dim(d, n.clone(), gdim.clone())?; + } else if let ExecTyKind::GpuBlockGrp(gdim2, bdim2) = &inner_ref.ty { + // otherwise split inside the inner block‐group + let (ldim, rdim) = split_dim(d, n, gdim2.clone(), arena)?; + + // bump‐allocate the two new inner ExecTy values + let left_inner = ExecTyKind::GpuBlockGrp(ldim, bdim2.clone()); + let right_inner = ExecTyKind::GpuBlockGrp(rdim, bdim2.clone()); + let left_ref: &'a ExecTy<'a> = arena.alloc(ExecTy::new(left_inner)); + let right_ref: &'a ExecTy<'a> = arena.alloc(ExecTy::new(right_inner)); + ( - ExecTyKind::GpuToThreads( - dim.clone(), - Box::new(ExecTy::new(ExecTyKind::GpuBlockGrp(ldim, bdim.clone()))), - ), - ExecTyKind::GpuToThreads( - dim.clone(), - Box::new(ExecTy::new(ExecTyKind::GpuBlockGrp(rdim, bdim.clone()))), - ), + ExecTyKind::GpuToThreads(dim.clone(), left_ref), + ExecTyKind::GpuToThreads(dim.clone(), right_ref), ) } else { panic!("GpuToThreads is not well-formed.") } } - ex => { + + other => { return Err(TyError::String(format!( "Trying to split non-splittable execution resource: {:?}", - ex + other ))) } }; + + // pick the left or right projection Ok(if proj == LeftOrRight::Left { - lexec_ty + left_ty } else { - rexec_ty + right_ty }) } @@ -296,6 +448,7 @@ fn dim_compo_matches_dim<'a>(d: DimCompo, dim: &'a Dim<'a>) -> bool { | (matches!(dim, Dim::Z(_)) && d == DimCompo::Z) } +/** fn split_dim<'a>( split_dim: DimCompo, pos: Nat<'a>, @@ -426,7 +579,175 @@ fn split_dim<'a>( } }) } +*/ +pub fn split_dim<'a>( + split_dim: DimCompo, + pos: &'a Nat<'a>, + dim: Dim<'a>, + arena: &'a Bump, +) -> TyResult<'a, (Dim<'a>, Dim<'a>)> { + use DimCompo::*; + + let result = match dim { + // 3D case: peel off one axis, leave a 3D on both sides + Dim::XYZ(d3) => match split_dim { + X => { + let left = Dim::new_3d(arena, d3.0.clone(), d3.1.clone(), d3.2.clone()); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d3.0.clone(), pos.clone()); + let right = Dim::new_3d(arena, right_nat, d3.1.clone(), d3.2.clone()); + (left, right) + } + Y => { + let left = Dim::new_3d(arena, d3.0.clone(), d3.1.clone(), d3.2.clone()); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d3.1.clone(), pos.clone()); + let right = Dim::new_3d(arena, d3.0.clone(), right_nat, d3.2.clone()); + (left, right) + } + Z => { + let left = Dim::new_3d(arena, d3.0.clone(), d3.1.clone(), d3.2.clone()); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d3.2.clone(), pos.clone()); + let right = Dim::new_3d(arena, d3.0.clone(), d3.1.clone(), right_nat); + (left, right) + } + }, + + // 2D cases: peel off one axis, leave a 2D on both sides + Dim::XY(d2) => match split_dim { + X => { + let left = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::XY(d), + pos.clone(), + d2.1.clone(), + ); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d2.0.clone(), pos.clone()); + let right = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::XY(d), + right_nat, + d2.1.clone(), + ); + (left, right) + } + Y => { + let left = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::XY(d), + d2.0.clone(), + pos.clone(), + ); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d2.1.clone(), pos.clone()); + let right = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::XY(d), + d2.0.clone(), + right_nat, + ); + (left, right) + } + Z => return Err(TyError::IllegalDimension), + }, + + Dim::XZ(d2) => match split_dim { + X => { + let left = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::XZ(d), + pos.clone(), + d2.1.clone(), + ); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d2.0.clone(), pos.clone()); + let right = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::XZ(d), + right_nat, + d2.1.clone(), + ); + (left, right) + } + Z => { + let left = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::XZ(d), + d2.0.clone(), + pos.clone(), + ); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d2.1.clone(), pos.clone()); + let right = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::XZ(d), + d2.0.clone(), + right_nat, + ); + (left, right) + } + Y => return Err(TyError::IllegalDimension), + }, + + Dim::YZ(d2) => match split_dim { + Y => { + let left = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::YZ(d), + pos.clone(), + d2.1.clone(), + ); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d2.0.clone(), pos.clone()); + let right = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::YZ(d), + right_nat, + d2.1.clone(), + ); + (left, right) + } + Z => { + let left = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::YZ(d), + d2.0.clone(), + pos.clone(), + ); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d2.1.clone(), pos.clone()); + let right = Dim::new_2d( + arena, + |d: &'a Dim2d<'a>| Dim::YZ(d), + d2.0.clone(), + right_nat, + ); + (left, right) + } + X => return Err(TyError::IllegalDimension), + }, + + // 1D cases: peel off the only axis + Dim::X(d1) if split_dim == X => { + let left = Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::X(d), pos.clone()); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d1.0.clone(), pos.clone()); + let right = Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::X(d), right_nat); + (left, right) + } + Dim::Y(d1) if split_dim == Y => { + let left = Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::Y(d), pos.clone()); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d1.0.clone(), pos.clone()); + let right = Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::Y(d), right_nat); + (left, right) + } + Dim::Z(d1) if split_dim == Z => { + let left = Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::Z(d), pos.clone()); + let right_nat = Nat::new_binop_ref(arena, BinOpNat::Sub, d1.0.clone(), pos.clone()); + let right = Dim::new_1d(arena, |d: &'a Dim1d<'a>| Dim::Z(d), right_nat); + (left, right) + } + + _ => return Err(TyError::IllegalDimension), + }; + + Ok(result) +} + +/** pub(super) fn normalize<'a>(mut exec: ExecExpr<'a>) -> ExecExpr<'a> { assert!(exec.ty.is_some()); let mut exec_path = exec.exec.path; @@ -437,7 +758,39 @@ pub(super) fn normalize<'a>(mut exec: ExecExpr<'a>) -> ExecExpr<'a> { exec.exec.path = exec_path; exec } +*/ + +pub(super) fn normalize<'a>(old: ExecExpr<'a>, arena: &'a bumpalo::Bump) -> ExecExpr<'a> { + assert!(old.ty.is_some()); + + // 1) Copy the old path into a fresh bump-Vec + let mut new_path: BumpVec<'a, ExecPathElem<'a>> = BumpVec::new_in(arena); + new_path.extend(old.exec.path.iter().cloned()); + + // 2) Sort if needed + if !new_path.is_empty() { + // We can still use the slice-based sorter: + let slice = new_path.as_mut_slice(); + let boundaries = level_boundaries(slice); + sort_within_boundaries(slice, &boundaries); + } + + // 3) Build a new ExecExprKind<'a> in the arena + let new_exec_kind = ExecExprKind { + base: old.exec.base.clone(), + path: new_path, + }; + let new_exec_ref: &'a ExecExprKind<'a> = arena.alloc(new_exec_kind); + + // 4) Return a fresh ExecExpr pointing at it, but re‐use the old ty/span + ExecExpr { + exec: new_exec_ref, + ty: old.ty, + span: old.span, + } +} +// Allocating a handful of usizes on the heap here is negligible // FIXME: not correct if first take_range on dimension of lower level followed by forall on different dimension in upper level // for fix: see formalism fn level_boundaries<'a>(exec_path: &'a [ExecPathElem<'a>]) -> Vec { @@ -470,6 +823,7 @@ fn level_boundaries<'a>(exec_path: &'a [ExecPathElem<'a>]) -> Vec { boundaries } +/** fn sort_within_boundaries<'a>(exec_path: &'a mut Vec>, boundaries: &[usize]) { let mut lower_bound = 0; for b in boundaries { @@ -483,6 +837,21 @@ fn sort_within_boundaries<'a>(exec_path: &'a mut Vec>, boundari lower_bound = *b; } } +*/ + +fn sort_within_boundaries<'a>(exec_path: &mut [ExecPathElem<'a>], boundaries: &[usize]) { + let mut lower = 0; + for &b in boundaries { + for i in lower..b { + for j in lower..(b - 1) { + if swappable_exec_path_elems(&exec_path[j], &exec_path[j + 1]) { + exec_path.swap(j, j + 1); + } + } + } + lower = b; + } +} fn swappable_exec_path_elems<'a>(lhs: &'a ExecPathElem<'a>, rhs: &'a ExecPathElem<'a>) -> bool { match (lhs, rhs) { diff --git a/src/ty_check/infer_kinded_args.rs b/src/ty_check/infer_kinded_args.rs index b4d102b8..a9bda6fa 100644 --- a/src/ty_check/infer_kinded_args.rs +++ b/src/ty_check/infer_kinded_args.rs @@ -66,6 +66,7 @@ macro_rules! panic_no_inst { panic!("Unexpected: mono type is not an instantiation of poly type") }; } + macro_rules! panic_if_neq { ($lhs: expr, $rhs: expr) => { if $lhs != $rhs { diff --git a/src/ty_check/mod.rs b/src/ty_check/mod.rs index 8a19b0d9..e0b15a9d 100644 --- a/src/ty_check/mod.rs +++ b/src/ty_check/mod.rs @@ -43,7 +43,7 @@ pub fn ty_check<'a>(compil_unit: &mut CompilUnit, arena: &'a Bump) -> Result<(), pre_decl::fun_decls() .into_iter() .map(|(fname, fty)| GlobalDecl::FnDecl(Box::from(fname), arena.alloc(fty))) - .collect(), + .collect_in(arena), ); let mut nat_ctx = NatCtx::new(); if let Some(mut main_fun) = gl_ctx.pop_fun_def("main") { @@ -61,14 +61,14 @@ pub fn ty_check<'a>(compil_unit: &mut CompilUnit, arena: &'a Bump) -> Result<(), } } -struct ExprTyCtx<'a, 'src, 'compil, 'ctxt> { - gl_ctx: &'ctxt mut GlobalCtx<'src, 'compil>, - nat_ctx: &'ctxt mut NatCtx, - ident_exec: Option<&'ctxt IdentExec<'a>>, - kind_ctx: &'ctxt mut KindCtx<'a>, +struct ExprTyCtx<'a> { + gl_ctx: &'a mut GlobalCtx<'a>, + nat_ctx: &'a mut NatCtx<'a>, + ident_exec: Option<&'a IdentExec<'a>>, + kind_ctx: &'a mut KindCtx<'a>, exec: ExecExpr<'a>, - ty_ctx: &'ctxt mut TyCtx<'a>, - access_ctx: &'ctxt mut AccessCtx, + ty_ctx: &'a mut TyCtx<'a>, + access_ctx: &'a mut AccessCtx<'a>, unsafe_flag: bool, } @@ -1721,7 +1721,7 @@ fn allowed_mem_for_exec<'a>(exec_ty: &'a ExecTyKind<'a>) -> Vec> { } } -pub fn accessible_memory(exec_ty: &'a ExecTy<'a>, mem: &'a Memory<'a>) -> TyResult<'a, ()> { +pub fn accessible_memory<'a>(exec_ty: &'a ExecTy<'a>, mem: &'a Memory<'a>) -> TyResult<'a, ()> { if allowed_mem_for_exec(&exec_ty.ty).contains(mem) { Ok(()) } else { diff --git a/src/ty_check/pl_expr.rs b/src/ty_check/pl_expr.rs index c5e18b52..eda66c57 100644 --- a/src/ty_check/pl_expr.rs +++ b/src/ty_check/pl_expr.rs @@ -11,19 +11,19 @@ use crate::ty_check::unify; use crate::ty_check::unify::ConstrainMap; use crate::ty_check::{exec, ExprTyCtx}; -pub(super) struct PlExprTyCtx<'a, 'gl, 'src, 'ctxt> { - gl_ctx: &'ctxt GlobalCtx<'gl, 'src>, - nat_ctx: &'ctxt NatCtx, - kind_ctx: &'ctxt KindCtx<'a>, - ident_exec: Option<&'ctxt IdentExec<'a>>, +pub(super) struct PlExprTyCtx<'a> { + gl_ctx: &'a GlobalCtx<'a>, + nat_ctx: &'a NatCtx<'a>, + kind_ctx: &'a KindCtx<'a>, + ident_exec: Option<&'a IdentExec<'a>>, exec: ExecExpr<'a>, - ty_ctx: &'ctxt TyCtx<'a>, - exec_borrow_ctx: &'ctxt AccessCtx, + ty_ctx: &'a TyCtx<'a>, + exec_borrow_ctx: &'a AccessCtx<'a>, own: Ownership, } -impl<'gl, 'src, 'ctxt> PlExprTyCtx<'gl, 'src, 'ctxt> { - pub(super) fn new(expr_ty_ctx: &'ctxt ExprTyCtx<'gl, 'src, 'ctxt>, own: Ownership) -> Self { +impl<'a> PlExprTyCtx<'a> { + pub(super) fn new(expr_ty_ctx: &'a ExprTyCtx<'a>, own: Ownership) -> Self { PlExprTyCtx { gl_ctx: &*expr_ty_ctx.gl_ctx, nat_ctx: &*expr_ty_ctx.nat_ctx, @@ -37,10 +37,8 @@ impl<'gl, 'src, 'ctxt> PlExprTyCtx<'gl, 'src, 'ctxt> { } } -impl<'gl, 'src, 'ctxt> From<&'ctxt BorrowCheckCtx<'gl, 'src, 'ctxt>> - for PlExprTyCtx<'gl, 'src, 'ctxt> -{ - fn from(ctx: &'ctxt BorrowCheckCtx<'gl, 'src, 'ctxt>) -> Self { +impl<'a> From<&'a BorrowCheckCtx<'a>> for PlExprTyCtx<'a> { + fn from(ctx: &'a BorrowCheckCtx<'a>) -> Self { PlExprTyCtx { gl_ctx: ctx.gl_ctx, nat_ctx: ctx.nat_ctx, diff --git a/src/ty_check/subty.rs b/src/ty_check/subty.rs index 7ea16937..b3eb6c07 100644 --- a/src/ty_check/subty.rs +++ b/src/ty_check/subty.rs @@ -1,5 +1,5 @@ use super::ctxs::{KindCtx, TyCtx}; -use crate::arena_ast::internal::Loan; +use crate::arena_ast::{self, internal::Loan}; // // Subtyping and Provenance Subtyping from Oxide @@ -7,6 +7,7 @@ use crate::arena_ast::internal::Loan; use super::error::{CtxError, SubTyError}; use crate::arena_ast::*; +use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; use std::collections::HashSet; type SubTyResult<'a, T> = Result>; @@ -19,6 +20,7 @@ pub(super) fn check<'a>( ty_ctx: &'a mut TyCtx<'a>, sub_dty: &'a DataTy<'a>, super_dty: &'a DataTy<'a>, + arena: &'a Bump, ) -> SubTyResult<'a, ()> { use super::Ownership::*; use DataTyKind::*; @@ -29,15 +31,15 @@ pub(super) fn check<'a>( // Δ; Γ ⊢ [τ 1 ; n] ≲ [τ2 ; n] ⇒ Γ′ (Array(sub_elem_ty, sub_size), Array(sup_elem_ty, sup_size)) | (ArrayShape(sub_elem_ty, sub_size), ArrayShape(sup_elem_ty, sup_size)) => { - check(kind_ctx, ty_ctx, sub_elem_ty, sup_elem_ty) + check(kind_ctx, ty_ctx, sub_elem_ty, sup_elem_ty, arena) } // Δ; Γ ⊢ &B ρ1 shrd τ1 ≲ &B ρ2 shrd τ2 ⇒ Γ′′ (Ref(lref), Ref(rref)) if lref.own == Shrd && rref.own == Shrd => { - outlives(kind_ctx, ty_ctx, &lref.rgn, &rref.rgn)?; + outlives(kind_ctx, ty_ctx, &lref.rgn, &rref.rgn, arena)?; if lref.mem != rref.mem { return Err(SubTyError::MemoryKindsNoMatch); } - check(kind_ctx, ty_ctx, lref.dty.as_ref(), rref.dty.as_ref()) + check(kind_ctx, ty_ctx, lref.dty, rref.dty, arena) } // Δ; Γ ⊢ &B ρ1 uniq τ1 ≲ &B ρ2 uniq τ2 ⇒ Γ'' (Ref(lref), Ref(rref)) => { @@ -47,18 +49,18 @@ pub(super) fn check<'a>( if lref.mem != rref.mem { return Err(SubTyError::MemoryKindsNoMatch); } - outlives(kind_ctx, ty_ctx, &lref.rgn, &rref.rgn)?; - check(kind_ctx, ty_ctx, lref.dty.as_ref(), rref.dty.as_ref()) + outlives(kind_ctx, ty_ctx, &lref.rgn, &rref.rgn, arena)?; + check(kind_ctx, ty_ctx, lref.dty, rref.dty, arena) } // Δ; Γ ⊢ (τ1, ..., τn) ≲ (τ1′, ..., τn′) ⇒ Γn (Tuple(sub_elems), Tuple(sup_elems)) => { for (sub, sup) in sub_elems.iter().zip(sup_elems) { - check(kind_ctx, ty_ctx, sub, sup)?; + check(kind_ctx, ty_ctx, sub, sup, arena)?; } Ok(()) } // Δ; Γ ⊢ \delta1 ≲ †\delta2 ⇒ Γ - (_, Dead(sup)) => check(kind_ctx, ty_ctx, sub_dty, sup), + (_, Dead(sup)) => check(kind_ctx, ty_ctx, sub_dty, sup, arena), //TODO add case for Transitiviy? // Δ; Γ ⊢ τ1 ≲ τ3 ⇒ Γ'' (sub, sup) => panic!( @@ -75,6 +77,7 @@ fn outlives<'a>( ty_ctx: &'a mut TyCtx<'a>, longer_prv: &'a Provenance<'a>, shorter_prv: &'a Provenance<'a>, + arena: &'a Bump, ) -> SubTyResult<'a, ()> { use Provenance::*; @@ -97,9 +100,9 @@ fn outlives<'a>( Ok(()) } // OL-LocalProvenances - (Value(longer), Value(shorter)) => outl_check_val_prvs(ty_ctx, longer, shorter), + (Value(longer), Value(shorter)) => outl_check_val_prvs(ty_ctx, longer, shorter, arena), // OL-LocalProvAbsProv - (Value(longer_val), Ident(_)) => outl_check_val_ident_prv(ty_ctx, longer_val), + (Value(longer_val), Ident(_)) => outl_check_val_ident_prv(ty_ctx, longer_val, arena), // OL-AbsProvLocalProv (Ident(longer_ident), Value(shorter_val)) => { outl_check_ident_val_prv(kind_ctx, ty_ctx, longer_ident, shorter_val) @@ -110,16 +113,17 @@ fn outlives<'a>( // OL-LocalProvenances // Δ; Γ ⊢ r1 :> r2 ⇒ Γ[r2 ↦→ { Γ(r1) ∪ Γ(r2) }] fn outl_check_val_prvs<'a>( - ty_ctx: &mut TyCtx<'a>, + ty_ctx: &'a mut TyCtx<'a>, longer: &str, shorter: &str, + arena: &'a Bump, ) -> SubTyResult<'a, ()> { // CHECK: // NOT CLEAR WHY a. IS NECESSARY // a. for every variable of reference type with r1 in ty_ctx: there must not exist a loan // dereferencing the variable for any provenance in ty_ctx. - if exists_deref_loan_with_prv(ty_ctx, longer) { + if exists_deref_loan_with_prv(ty_ctx, longer, arena) { // TODO better error msg return Err(SubTyError::Dummy); } @@ -152,13 +156,13 @@ fn longer_occurs_before_shorter<'a>(ty_ctx: &'a TyCtx<'a>, longer: &str, shorter panic!("Neither provenance found in typing context") } -fn exists_deref_loan_with_prv<'a>(ty_ctx: &'a TyCtx<'a>, prv: &str) -> bool { +fn exists_deref_loan_with_prv<'a>(ty_ctx: &'a TyCtx<'a>, prv: &str, arena: &'a Bump) -> bool { ty_ctx - .all_places() + .all_places(arena) .into_iter() .filter(|(_, dty)| match &dty.dty { DataTyKind::Ref(reff) => match &reff.rgn { - Provenance::Value(prv_name) => prv_name == prv, + Provenance::Value(prv_name) => *prv_name == prv, _ => false, }, _ => false, @@ -167,7 +171,7 @@ fn exists_deref_loan_with_prv<'a>(ty_ctx: &'a TyCtx<'a>, prv: &str) -> bool { ty_ctx.prv_mappings().into_iter().any(|prv_mapping| { for loan in prv_mapping.loans.iter() { if let PlaceExprKind::Deref(pl_expr) = &loan.place_expr.pl_expr { - return pl_expr.equiv(&place); + return pl_expr.equiv(arena, &place); } } false @@ -175,14 +179,18 @@ fn exists_deref_loan_with_prv<'a>(ty_ctx: &'a TyCtx<'a>, prv: &str) -> bool { }) } -fn outl_check_val_ident_prv<'a>(ty_ctx: &'a TyCtx<'a>, longer_val: &str) -> SubTyResult<'a, ()> { +fn outl_check_val_ident_prv<'a>( + ty_ctx: &'a TyCtx<'a>, + longer_val: &str, + arena: &'a Bump, +) -> SubTyResult<'a, ()> { // TODO how could the set ever be empty? let loan_set = ty_ctx.loans_in_prv(longer_val)?; if loan_set.is_empty() { return Err(SubTyError::PrvNotUsedInBorrow(longer_val.to_string())); } - borrowed_pl_expr_no_ref_to_existing_pl(ty_ctx, loan_set); + borrowed_pl_expr_no_ref_to_existing_pl(ty_ctx, loan_set, arena); panic!("Not yet implemented.") } @@ -190,11 +198,12 @@ fn outl_check_val_ident_prv<'a>(ty_ctx: &'a TyCtx<'a>, longer_val: &str) -> SubT fn borrowed_pl_expr_no_ref_to_existing_pl<'a>( ty_ctx: &'a TyCtx<'a>, loan_set: &HashSet>, + arena: &'a Bump, ) -> bool { ty_ctx - .all_places() + .all_places(arena) .iter() - .any(|(pl, _)| loan_set.iter().any(|loan| loan.place_expr.equiv(pl))) + .any(|(pl, _)| loan_set.iter().any(|loan| loan.place_expr.equiv(arena, pl))) } fn outl_check_ident_val_prv<'a>( From f476c02221d289822fdd14bef9c6cffab28bef95 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Mon, 11 Aug 2025 10:44:55 +0200 Subject: [PATCH 39/57] changes in the ast implementation --- src/arena_ast/mod.rs | 119 ++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 53 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index 3e9ed103..7cb82598 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -32,7 +32,7 @@ pub enum Item<'a> { StructDecl(BumpBox<'a, StructDecl<'a>>), } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, PartialEq)] pub struct FunDecl<'a> { pub ident: Ident<'a>, pub generic_params: BumpVec<'a, IdentKinded<'a>>, @@ -135,7 +135,7 @@ impl<'a> IdentExec<'a> { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] pub struct ParamDecl<'a> { pub ident: Ident<'a>, pub ty: Option<&'a Ty<'a>>, @@ -620,7 +620,7 @@ impl<'a> ArgKinded<'a> { } } - pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a Self) -> NatEvalResult<'a, bool> { + pub fn equal(&'a self, nat_ctx: &'a NatCtx<'a>, other: &'a Self) -> NatEvalResult<'a, bool> { match (self, other) { (ArgKinded::Ident(i), ArgKinded::Ident(o)) => Ok(i == o), (ArgKinded::Nat(n), ArgKinded::Nat(no)) => Ok(n.eval(nat_ctx)? == no.eval(nat_ctx)?), @@ -651,7 +651,11 @@ pub struct View<'a> { } impl<'a> View<'a> { - pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a View<'a>) -> NatEvalResult<'a, bool> { + pub fn equal( + &'a self, + nat_ctx: &'a NatCtx<'a>, + other: &'a View<'a>, + ) -> NatEvalResult<'a, bool> { if self.name.name != other.name.name { return Ok(false); } @@ -835,7 +839,7 @@ impl<'a> PlaceExpr<'a> { arena: &'a bumpalo::Bump, ) -> (Ident<'a>, BumpVec<'a, PlExprPathElem<'a>>) { fn as_ident_and_path_rec<'a>( - pl_expr: &'a PlaceExpr, + pl_expr: &'a PlaceExpr<'a>, mut path: BumpVec<'a, PlExprPathElem<'a>>, ) -> (Ident<'a>, BumpVec<'a, PlExprPathElem<'a>>) { match &pl_expr.pl_expr { @@ -923,7 +927,7 @@ impl<'a> ExecExpr<'a> { ) } - pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { + pub fn equal(&self, nat_ctx: &'a NatCtx<'a>, other: &Self) -> NatEvalResult { match (&self.exec.base, &other.exec.base) { (BaseExec::Ident(i), BaseExec::Ident(o)) => { if i != o { @@ -1164,7 +1168,7 @@ pub struct Ty<'a> { pub span: Option, } -#[derive(PartialEq, Eq, Hash, Debug, Clone)] +#[derive(PartialEq, Eq, Hash, Debug)] pub struct ParamSig<'a> { pub exec_expr: ExecExpr<'a>, pub ty: &'a Ty<'a>, @@ -1307,20 +1311,21 @@ impl<'a> Dim<'a> { Dim::XYZ(arena.alloc(Dim3d(n1, n2, n3))) } - pub fn new_2d Self>( - arena: &'a Bump, - constr: F, - n1: Nat<'a>, - n2: Nat<'a>, - ) -> Self { + pub fn new_2d(arena: &'a Bump, constr: F, n1: Nat<'a>, n2: Nat<'a>) -> Self + where + F: Fn(&'a Dim2d<'a>) -> Self + 'a, + { constr(arena.alloc(Dim2d(n1, n2))) } - pub fn new_1d Self>(arena: &'a Bump, constr: F, n: Nat<'a>) -> Self { + pub fn new_1d(arena: &'a Bump, constr: F, n: Nat<'a>) -> Self + where + F: Fn(&'a Dim1d<'a>) -> Self + 'a, + { constr(arena.alloc(Dim1d(n))) } - pub fn equal(&self, nat_ctx: &NatCtx, other: &Self) -> NatEvalResult { + pub fn equal(&self, nat_ctx: &'a NatCtx<'a>, other: &Self) -> NatEvalResult { match (self, other) { (Dim::XYZ(d), Dim::XYZ(o)) => Ok(d.0.eval(nat_ctx)? == o.0.eval(nat_ctx)? && d.1.eval(nat_ctx)? == o.1.eval(nat_ctx)? @@ -1488,7 +1493,7 @@ impl<'a> DataTy<'a> { } } - pub fn equal(&'a self, nat_ctx: &'a NatCtx, other: &'a Self) -> NatEvalResult<'a, bool> { + pub fn equal(&'a self, nat_ctx: &'a NatCtx<'a>, other: &'a Self) -> NatEvalResult<'a, bool> { match (&self.dty, &other.dty) { (DataTyKind::Ident(i), DataTyKind::Ident(o)) => Ok(i == o), (DataTyKind::Tuple(dtys), DataTyKind::Tuple(dtyos)) => { @@ -1628,7 +1633,7 @@ pub enum NatRange<'a> { } impl<'a> NatRange<'a> { - pub fn lift(&self, arena: &'a Bump, nat_ctx: &NatCtx) -> NatEvalResult { + pub fn lift(&self, arena: &'a Bump, nat_ctx: &'a NatCtx<'a>) -> NatEvalResult { let range_iter = match self { NatRange::Simple { lower, upper } => { let lower = lower.eval(nat_ctx)?; @@ -1700,51 +1705,53 @@ pub enum Nat<'a> { LaneIdx, // Dummy that is always 0, i.e. equivalent to Lit(0) GridIdx, - BinOp(BinOpNat, Box>, Box>), + BinOp(BinOpNat, &'a Nat<'a>, &'a Nat<'a>), // Use Box<[Nat]> to safe 8 bytes compared to Vec - App(Ident<'a>, Box<[Nat<'a>]>), + App(Ident<'a>, BumpVec<'a, Nat<'a>>), } -pub struct NatCtx { - frames: Vec, usize)>>, +pub struct NatCtx<'a> { + frames: BumpVec<'a, BumpVec<'a, (&'a str, usize)>>, } -impl NatCtx { - pub fn new() -> Self { - NatCtx { - frames: vec![vec![]], - } +impl<'a> NatCtx<'a> { + pub fn new(arena: &'a Bump) -> Self { + let mut frames = BumpVec::new_in(arena); + frames.push(BumpVec::new_in(arena)); + NatCtx { frames } } - pub fn with_frame(frame: Vec<(Box, usize)>) -> Self { - let mut ctx = NatCtx { frames: vec![] }; - ctx.push_frame(frame); - ctx + pub fn with_frame(arena: &'a Bump, frame: BumpVec<'a, (&'a str, usize)>) -> Self { + let mut frames = BumpVec::new_in(arena); + frames.push(frame); + NatCtx { frames } } - pub fn append(&mut self, nat_name: &str, val: usize) { - self.frames - .last_mut() - .unwrap() - .push((Box::from(nat_name), val)) + pub fn append(&mut self, nat_name: &str, val: usize, arena: &'a Bump) -> &mut Self { + let interned: &'a str = arena.alloc_str(nat_name); + let frame = self.frames.last_mut().unwrap(); + frame.push((interned, val)); + self } pub fn find(&self, name: &str) -> Option { - self.frames.iter().flatten().rev().find_map(|(i, n)| { - if i.as_ref() == name { - Some(*n) - } else { - None - } - }) + self.frames.iter().flatten().rev().find_map( + |(i, n)| { + if *i == name { + Some(*n) + } else { + None + } + }, + ) } - pub fn push_empty_frame(&mut self) -> &mut Self { - self.frames.push(vec![]); + pub fn push_empty_frame(&mut self, arena: &'a Bump) -> &mut Self { + self.frames.push(BumpVec::new_in(arena)); self } - fn push_frame(&mut self, frame: Vec<(Box, usize)>) -> &mut Self { + fn push_frame(&mut self, frame: BumpVec<'a, (&'a str, usize)>) -> &mut Self { self.frames.push(frame); self } @@ -1763,7 +1770,7 @@ pub struct NatEvalError<'a> { pub type NatEvalResult<'a, T> = Result>; impl<'a> Nat<'a> { - pub fn eval(&self, nat_ctx: &NatCtx) -> NatEvalResult { + pub fn eval(&self, nat_ctx: &'a NatCtx<'a>) -> NatEvalResult { match self { Nat::GridIdx | Nat::BlockIdx(_) @@ -1794,6 +1801,12 @@ impl<'a> Nat<'a> { Nat::App(_, _) => unimplemented!(), } } + + pub fn new_binop_ref(arena: &'a Bump, op: BinOpNat, lhs: Nat<'a>, rhs: Nat<'a>) -> Self { + let l_ref = arena.alloc(lhs); + let r_ref = arena.alloc(rhs); + Nat::BinOp(op, l_ref, r_ref) + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1820,21 +1833,21 @@ mod size_asserts { }; } static_assert_size!(Dim, 16); - static_assert_size!(DataTy, 112); - static_assert_size!(DataTyKind, 64); + static_assert_size!(DataTy, 128); + static_assert_size!(DataTyKind, 80); static_assert_size!(ExecExpr, 32); static_assert_size!(ExecExprKind, 72); static_assert_size!(ExecPathElem, 16); - static_assert_size!(ExecTy, 64); - static_assert_size!(ExecTyKind, 48); - static_assert_size!(Expr, 104); - static_assert_size!(ExprKind, 80); + static_assert_size!(ExecTy, 80); + static_assert_size!(ExecTyKind, 64); + static_assert_size!(Expr, 112); + static_assert_size!(ExprKind, 88); static_assert_size!(FunDef, 216); static_assert_size!(Ident, 32); // maybe too large? static_assert_size!(IdentExec, 40); static_assert_size!(Lit, 16); static_assert_size!(Memory, 32); - static_assert_size!(Nat, 48); + static_assert_size!(Nat, 64); static_assert_size!(ParamDecl, 80); static_assert_size!(Pattern, 40); static_assert_size!(PlaceExpr, 56); From 6ee8c18c14b1cd46db64d3a29d1e9ad47e65a501 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Mon, 11 Aug 2025 11:03:39 +0200 Subject: [PATCH 40/57] fixed Nat into arena method --- src/ast/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index ea9a9648..e6319197 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -2556,14 +2556,15 @@ impl Nat { BinOp(op, lhs, rhs) => arena_ast::Nat::BinOp( op.clone().into_arena(), - Box::new(lhs.into_arena(arena)), - Box::new(rhs.into_arena(arena)), + arena.alloc(lhs.into_arena(arena)), + arena.alloc(rhs.into_arena(arena)), ), App(ident, args) => { - let new_args: Vec<_> = args.iter().map(|n| n.into_arena(arena)).collect(); - let boxed_slice: Box<[arena_ast::Nat<'a>]> = new_args.into_boxed_slice(); - arena_ast::Nat::App(ident.clone().into_arena(arena), boxed_slice) + let arena_args: BumpVec<'a, arena_ast::Nat<'a>> = + BumpVec::from_iter_in(args.iter().map(|n| n.into_arena(arena)), arena); + + arena_ast::Nat::App(ident.clone().into_arena(arena), arena_args) } } } From 6f12d0c950dcedc662d1f7ae11b12757149bf5ad Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Mon, 11 Aug 2025 19:05:54 +0200 Subject: [PATCH 41/57] Some work in the visitor --- src/arena_ast/mod.rs | 21 +- src/arena_ast/utils.rs | 1 + src/arena_ast/visit.rs | 4 +- src/arena_ast/visit_mut.rs | 822 +++++++++++++++++++++++++------------ 4 files changed, 581 insertions(+), 267 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index 7cb82598..dda8e7db 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -144,7 +144,7 @@ pub struct ParamDecl<'a> { } #[span_derive(PartialEq)] -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Expr<'a> { pub expr: ExprKind<'a>, // FIXME misusing span_derive_ignore to ignore type on equality checks @@ -361,7 +361,7 @@ pub struct AppKernel<'a> { pub args: BumpVec<'a, Expr<'a>>, } -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, Clone)] pub enum ExprKind<'a> { Hole, Lit(Lit), @@ -397,7 +397,7 @@ pub enum ExprKind<'a> { ), DepApp(Ident<'a>, BumpVec<'a, ArgKinded<'a>>), //AppKernel(&'a AppKernel<'a>), - AppKernel(BumpBox<'a, AppKernel<'a>>), + AppKernel(&'a AppKernel<'a>), // TODO branches must be blocks IfElse(&'a Expr<'a>, &'a Expr<'a>, &'a Expr<'a>), // TODO branch must be block @@ -1168,7 +1168,7 @@ pub struct Ty<'a> { pub span: Option, } -#[derive(PartialEq, Eq, Hash, Debug)] +#[derive(PartialEq, Eq, Hash, Debug, Clone)] pub struct ParamSig<'a> { pub exec_expr: ExecExpr<'a>, pub ty: &'a Ty<'a>, @@ -1220,15 +1220,14 @@ impl<'a> FnTy<'a> { } } -#[derive(PartialEq, Eq, Hash, Debug)] +#[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum NatConstr<'a> { True, - Eq(BumpBox<'a, Nat<'a>>, BumpBox<'a, Nat<'a>>), - Lt(BumpBox<'a, Nat<'a>>, BumpBox<'a, Nat<'a>>), - And(BumpBox<'a, NatConstr<'a>>, BumpBox<'a, NatConstr<'a>>), - Or(BumpBox<'a, NatConstr<'a>>, BumpBox<'a, NatConstr<'a>>), + Eq(&'a Nat<'a>, &'a Nat<'a>), + Lt(&'a Nat<'a>, &'a Nat<'a>), + And(&'a NatConstr<'a>, &'a NatConstr<'a>), + Or(&'a NatConstr<'a>, &'a NatConstr<'a>), } - #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum TyKind<'a> { Data(&'a DataTy<'a>), @@ -1809,7 +1808,7 @@ impl<'a> Nat<'a> { } } -#[derive(PartialEq, Eq, Hash, Debug, Clone)] +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] pub enum BinOpNat { Add, Sub, diff --git a/src/arena_ast/utils.rs b/src/arena_ast/utils.rs index 5a0e1375..1ec6ff2c 100644 --- a/src/arena_ast/utils.rs +++ b/src/arena_ast/utils.rs @@ -264,6 +264,7 @@ impl<'a> SubstIdentExec<'a> { SubstIdentExec { ident, exec } } } + impl<'a> VisitMut<'a> for SubstIdentExec<'a> { fn visit_exec_expr(&mut self, bump: &'a bumpalo::Bump, exec_expr: &mut ExecExpr<'a>) { insert_for_ident(bump, self.exec, &self.ident, exec_expr) diff --git a/src/arena_ast/visit.rs b/src/arena_ast/visit.rs index 56198026..52c96f73 100644 --- a/src/arena_ast/visit.rs +++ b/src/arena_ast/visit.rs @@ -51,7 +51,7 @@ pub trait Visit<'a>: Sized { macro_rules! walk_list { ($visitor: expr, $method: ident, $list: expr) => { - for elem in $list.iter_mut() { + for elem in $list.iter() { $visitor.$method(elem) } }; @@ -76,7 +76,7 @@ pub fn walk_nat<'a, V: Visit<'a>>(visitor: &mut V, n: &Nat<'a>) { | Nat::Lit(_) => {} Nat::App(func, args) => { visitor.visit_ident(func); - walk_list!(visitor, visit_nat, args.as_ref()) + walk_list!(visitor, visit_nat, args) } } } diff --git a/src/arena_ast/visit_mut.rs b/src/arena_ast/visit_mut.rs index b82a9d3a..e441a278 100644 --- a/src/arena_ast/visit_mut.rs +++ b/src/arena_ast/visit_mut.rs @@ -3,70 +3,74 @@ use crate::arena_ast::*; #[rustfmt::skip] pub trait VisitMut<'a>: Sized { fn visit_binary_op_nat(&mut self, _op: &mut BinOpNat) {} - fn visit_nat(&mut self, n: &mut Nat<'a>) { walk_nat(self, n) } - fn visit_nat_range(&mut self, nr: &mut NatRange<'a>) { walk_nat_range(self, nr) } - fn visit_ident_kinded(&mut self, id_kind: &mut IdentKinded<'a>) { walk_ident_kinded(self, id_kind) } - fn visit_ident_exec(&mut self, id_exec: &mut IdentExec<'a>) { walk_ident_exec(self, id_exec) } - fn visit_prv_rel(&mut self, prv_rel: &mut PrvRel<'a>) { walk_prv_rel(self, prv_rel) } + fn visit_nat(&mut self, arena: &'a Bump, n: &mut Nat<'a>) { walk_nat(self, arena, n) } + fn visit_nat_ref(&mut self, arena: &'a Bump, slot: &mut &'a Nat<'a>) { + walk_nat_ref(self, arena, slot) + } + fn visit_nat_range(&mut self, arena: &'a Bump, nr: &mut NatRange<'a>) { walk_nat_range(self, arena, nr) } + fn visit_ident_kinded(&mut self, arena: &'a Bump, id_kind: &mut IdentKinded<'a>) { walk_ident_kinded(self, arena, id_kind) } + fn visit_ident_exec(&mut self, arena: &'a Bump, id_exec: &mut IdentExec<'a>) { walk_ident_exec(self, arena, id_exec) } + fn visit_prv_rel(&mut self, arena: &'a Bump, prv_rel: &mut PrvRel<'a>) { walk_prv_rel(self, arena, prv_rel) } fn visit_exec_ty(&mut self, _exec: &mut ExecTy<'a>) {} - fn visit_mem(&mut self, mem: &mut Memory<'a>) { walk_mem(self, mem) } - fn visit_prv(&mut self, prv: &mut Provenance<'a>) { walk_prv(self, prv) } + fn visit_exec_ty_ref(&mut self, _arena: &'a bumpalo::Bump, _slot: &mut &'a ExecTy<'a>) {} + fn visit_mem(&mut self, arena: &'a Bump, mem: &mut Memory<'a>) { walk_mem(self, arena, mem) } + fn visit_prv(&mut self, arena: &'a Bump, prv: &mut Provenance<'a>) { walk_prv(self, arena, prv) } fn visit_scalar_ty(&mut self, _sty: &mut ScalarTy) {} fn visit_atomic_ty(&mut self, _aty: &mut AtomicTy) {} fn visit_dim_compo(&mut self, _dim_compo: &mut DimCompo) {} - fn visit_dim(&mut self, dim: &mut Dim<'a>) { walk_dim(self, dim) } - fn visit_dim3d(&mut self, dim3d: &mut Dim3d<'a>) { walk_dim3d(self, dim3d) } - fn visit_dim2d(&mut self, dim2d: &mut Dim2d<'a>) { walk_dim2d(self, dim2d) } - fn visit_dim1d(&mut self, dim1d: &mut Dim1d<'a>) { walk_dim1d(self, dim1d) } - fn visit_ref(&mut self, reff: &mut RefDty<'a>) { walk_ref(self, reff) } - fn visit_dty(&mut self, dty: &mut DataTy<'a>) { walk_dty(self, dty) } - fn visit_fn_ty(&mut self, fn_ty: &mut FnTy<'a>) { walk_fn_ty(self, fn_ty) } - fn visit_nat_constr(&mut self, nat_constr: &mut NatConstr<'a>) { walk_nat_constr(self, nat_constr) } - fn visit_ty(&mut self, ty: &mut Ty<'a>) { walk_ty(self, ty) } - fn visit_view(&mut self, view: &mut View<'a>) { walk_view(self, view) } - fn visit_pl_expr(&mut self, pl_expr: &mut PlaceExpr<'a>) { walk_pl_expr(self, pl_expr) } - fn visit_arg_kinded(&mut self, arg_kinded: &mut ArgKinded<'a>) { walk_arg_kinded(self, arg_kinded) } + fn visit_dim(&mut self, arena: &'a Bump, dim: &mut Dim<'a>) { walk_dim(self, arena, dim) } + fn visit_dim3d(&mut self, arena: &'a Bump, dim3d: &mut Dim3d<'a>) { walk_dim3d(self, arena, dim3d) } + fn visit_dim2d(&mut self, arena: &'a Bump, dim2d: &mut Dim2d<'a>) { walk_dim2d(self, arena, dim2d) } + fn visit_dim1d(&mut self, arena: &'a Bump, dim1d: &mut Dim1d<'a>) { walk_dim1d(self, arena, dim1d) } + fn visit_ref(&mut self, arena: &'a Bump, reff: &mut RefDty<'a>) { walk_ref(self, arena, reff) } + fn visit_dty(&mut self, arena: &'a Bump, dty: &mut DataTy<'a>) { walk_dty(self, arena, dty) } + fn visit_fn_ty(&mut self, arena: &'a Bump, fn_ty: &mut FnTy<'a>) { walk_fn_ty(self, arena, fn_ty) } + fn visit_nat_constr(&mut self, arena: &'a Bump, nat_constr: &mut NatConstr<'a>) { walk_nat_constr(self, arena, nat_constr) } + fn visit_ty(&mut self, arena: &'a Bump, ty: &mut Ty<'a>) { walk_ty(self, arena, ty) } + fn visit_view(&mut self, arena: &'a Bump, view: &mut View<'a>) { walk_view(self, arena, view) } + fn visit_pl_expr(&mut self, arena: &'a Bump, pl_expr: &mut PlaceExpr<'a>) { walk_pl_expr(self, arena, pl_expr) } + fn visit_arg_kinded(&mut self, arena: &'a Bump, arg_kinded: &mut ArgKinded<'a>) { walk_arg_kinded(self, arena, arg_kinded) } fn visit_kind(&mut self, _kind: &mut Kind) {} fn visit_binary_op(&mut self, _op: &mut BinOp) {} fn visit_unary_op(&mut self, _op: &mut UnOp) {} fn visit_own(&mut self, _own: &mut Ownership) {} fn visit_mutability(&mut self, _mutbl: &mut Mutability) {} fn visit_lit(&mut self, _lit: &mut Lit) {} - fn visit_ident(&mut self, _ident: &mut Ident<'a>) {} - fn visit_pattern(&mut self, pattern: &mut Pattern<'a>) { walk_pattern(self, pattern) } - fn visit_split(&mut self, split: &mut Split<'a>) { walk_split(self, split) } - fn visit_sched(&mut self, sched: &mut Sched<'a>) { walk_sched(self, sched) } - fn visit_expr(&mut self, expr: &mut Expr<'a>) { walk_expr(self, expr) } - fn visit_app_kernel(&mut self, app_kernel: &mut AppKernel<'a>) { walk_app_kernel(self, app_kernel) } - fn visit_block(&mut self, block: &mut Block<'a>) { walk_block(self, block) } - fn visit_split_proj(&mut self, exec_split: &mut TakeRange<'a>) { walk_split_proj(self, exec_split) } - fn visit_exec_expr(&mut self, exec_expr: &mut ExecExpr<'a>) { walk_exec_expr(self, exec_expr) } - fn visit_exec(&mut self, exec: &mut ExecExprKind<'a>) { walk_exec(self, exec) } - fn visit_exec_path_elem(&mut self, exec_path_elem: &mut ExecPathElem<'a>) { walk_exec_path_elem(self, exec_path_elem) } - fn visit_param_decl(&mut self, param_decl: &mut ParamDecl<'a>) { walk_param_decl(self, param_decl) } - fn visit_fun_def(&mut self, fun_def: &mut FunDef<'a>) { walk_fun_def(self, fun_def) } - fn visit_fun_decl(&mut self, fun_decl: &mut FunDecl<'a>) { walk_fun_decl(self, fun_decl) } - fn visit_param_sig(&mut self, param_sig: &mut ParamSig<'a>) { walk_param_sig(self, param_sig) } - fn visit_field(&mut self, field: &mut (Ident<'a>, DataTy<'a>)) { walk_field(self, field) } + fn visit_ident(&mut self, arena: &'a Bump, _ident: &mut Ident<'a>) {} + fn visit_pattern(&mut self, arena: &'a Bump, pattern: &mut Pattern<'a>) { walk_pattern(self, arena, pattern) } + fn visit_split(&mut self, arena: &'a Bump, split: &mut Split<'a>) { walk_split(self, arena, split) } + fn visit_sched(&mut self, arena: &'a Bump, sched: &mut Sched<'a>) { walk_sched(self, arena, sched) } + fn visit_expr(&mut self, arena: &'a Bump, expr: &mut Expr<'a>) { walk_expr(self, arena, expr) } + fn visit_app_kernel(&mut self, arena: &'a Bump, app_kernel: &mut AppKernel<'a>) { walk_app_kernel(self, arena, app_kernel) } + fn visit_block(&mut self, arena: &'a Bump, block: &mut Block<'a>) { walk_block(self, arena, block) } + fn visit_split_proj(&mut self,arena: &'a Bump, exec_split: &mut TakeRange<'a>) { walk_split_proj(self, arena, exec_split) } + fn visit_exec_expr(&mut self, arena: &'a Bump, exec_expr: &mut ExecExpr<'a>) { walk_exec_expr(self, arena, exec_expr) } + fn visit_exec(&mut self, arena: &'a Bump, exec: &mut ExecExprKind<'a>) { walk_exec(self, arena, exec) } + fn visit_exec_path_elem(&mut self, arena: &'a Bump, exec_path_elem: &mut ExecPathElem<'a>) { walk_exec_path_elem(self, arena, exec_path_elem) } + fn visit_param_decl(&mut self, arena: &'a Bump, param_decl: &mut ParamDecl<'a>) { walk_param_decl(self, arena, param_decl) } + fn visit_fun_def(&mut self, arena: &'a Bump, fun_def: &mut FunDef<'a>) { walk_fun_def(self, arena, fun_def) } + fn visit_fun_decl(&mut self, arena: &'a Bump, fun_decl: &mut FunDecl<'a>) { walk_fun_decl(self, arena, fun_decl) } + fn visit_param_sig(&mut self, arena: &'a Bump, param_sig: &mut ParamSig<'a>) { walk_param_sig(self, arena, param_sig) } + fn visit_field(&mut self, arena: &'a Bump, field: &mut (Ident<'a>, DataTy<'a>)) { walk_field(self, arena, field) } } // Taken from the Rust compiler macro_rules! walk_list { - ($visitor: expr, $method: ident, $list: expr) => { + ($visitor:expr, $method:ident, $list:expr, $arena:expr) => { for elem in $list.iter_mut() { - $visitor.$method(elem) + $visitor.$method($arena, elem) } }; } pub(crate) use walk_list; -pub fn walk_nat<'a, V: VisitMut<'a>>(visitor: &mut V, n: &mut Nat<'a>) { +pub fn walk_nat<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, n: &mut Nat<'a>) { match n { - Nat::Ident(ident) => visitor.visit_ident(ident), - Nat::BinOp(op, l, r) => { + Nat::Ident(ident) => visitor.visit_ident(arena, ident), + Nat::BinOp(op, ref mut l, ref mut r) => { visitor.visit_binary_op_nat(op); - visitor.visit_nat(l); - visitor.visit_nat(r) + visitor.visit_nat_ref(arena, l); + visitor.visit_nat_ref(arena, r); } Nat::GridIdx | Nat::BlockIdx(_) @@ -77,122 +81,241 @@ pub fn walk_nat<'a, V: VisitMut<'a>>(visitor: &mut V, n: &mut Nat<'a>) { | Nat::LaneIdx | Nat::Lit(_) => {} Nat::App(func, args) => { - visitor.visit_ident(func); - walk_list!(visitor, visit_nat, args.as_mut()) + visitor.visit_ident(arena, func); + walk_list!(visitor, visit_nat, args.as_mut_slice(), arena) + } + } +} + +pub fn walk_nat_ref<'a, V: VisitMut<'a>>( + v: &mut V, + arena: &'a bumpalo::Bump, + slot: &mut &'a Nat<'a>, +) { + match &*(*slot) { + Nat::BinOp(op, l, r) => { + let mut l_slot: &'a Nat<'a> = *l; + let mut r_slot: &'a Nat<'a> = *r; + + v.visit_nat_ref(arena, &mut l_slot); + v.visit_nat_ref(arena, &mut r_slot); + + // Rebuild the parent node with possibly-updated children + let new = arena.alloc(Nat::BinOp(*op, l_slot, r_slot)); + *slot = new; + } + Nat::App(func, args) => { + // Owned children: visit in place + let mut rebuilt = bumpalo::collections::Vec::new_in(arena); + rebuilt.reserve(args.len()); + for a in args.iter() { + let mut owned = a.clone(); + v.visit_nat(arena, &mut owned); + rebuilt.push(owned); + } + *slot = arena.alloc(Nat::App(func.clone(), rebuilt)); } + _ => {} } } -pub fn walk_nat_range<'a, V: VisitMut<'a>>(visitor: &mut V, nr: &mut NatRange<'a>) { +pub fn walk_nat_range<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + nr: &mut NatRange<'a>, +) { match nr { NatRange::Simple { lower, upper } => { - visitor.visit_nat(lower); - visitor.visit_nat(upper); + visitor.visit_nat(arena, lower); + visitor.visit_nat(arena, upper); } - NatRange::Halved { upper } | NatRange::Doubled { upper } => visitor.visit_nat(upper), + NatRange::Halved { upper } | NatRange::Doubled { upper } => visitor.visit_nat(arena, upper), } } -pub fn walk_ident_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, id_kind: &mut IdentKinded<'a>) { +pub fn walk_ident_kinded<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + id_kind: &mut IdentKinded<'a>, +) { let IdentKinded { ident, kind } = id_kind; - visitor.visit_ident(ident); + visitor.visit_ident(arena, ident); visitor.visit_kind(kind) } -pub fn walk_ident_exec<'a, V: VisitMut<'a>>(visitor: &mut V, id_exec: &mut IdentExec<'a>) { +pub fn walk_ident_exec<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + id_exec: &mut IdentExec<'a>, +) { let IdentExec { ident, ty } = id_exec; - visitor.visit_ident(ident); - visitor.visit_exec_ty(ty) + visitor.visit_ident(arena, ident); + visitor.visit_exec_ty_ref(arena, ty) } -pub fn walk_prv_rel<'a, V: VisitMut<'a>>(visitor: &mut V, prv_rel: &mut PrvRel<'a>) { +pub fn walk_prv_rel<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + prv_rel: &mut PrvRel<'a>, +) { let PrvRel { longer, shorter } = prv_rel; - visitor.visit_ident(longer); - visitor.visit_ident(shorter) + visitor.visit_ident(arena, longer); + visitor.visit_ident(arena, shorter) } -pub fn walk_mem<'a, V: VisitMut<'a>>(visitor: &mut V, mem: &mut Memory<'a>) { +pub fn walk_mem<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, mem: &mut Memory<'a>) { if let Memory::Ident(ident) = mem { - visitor.visit_ident(ident) + visitor.visit_ident(arena, ident) } } -pub fn walk_prv<'a, V: VisitMut<'a>>(visitor: &mut V, prv: &mut Provenance<'a>) { +pub fn walk_prv<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, prv: &mut Provenance<'a>) { match prv { - Provenance::Ident(ident) => visitor.visit_ident(ident), + Provenance::Ident(ident) => visitor.visit_ident(arena, ident), Provenance::Value(_) => {} } } -pub fn walk_dim3d<'a, V: VisitMut<'a>>(visitor: &mut V, dim3d: &mut Dim3d<'a>) { +pub fn walk_dim3d<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, dim3d: &mut Dim3d<'a>) { let Dim3d(n1, n2, n3) = dim3d; - visitor.visit_nat(n1); - visitor.visit_nat(n2); - visitor.visit_nat(n3); + visitor.visit_nat(arena, n1); + visitor.visit_nat(arena, n2); + visitor.visit_nat(arena, n3); } -pub fn walk_dim2d<'a, V: VisitMut<'a>>(visitor: &mut V, dim2d: &mut Dim2d<'a>) { +pub fn walk_dim2d<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, dim2d: &mut Dim2d<'a>) { let Dim2d(n1, n2) = dim2d; - visitor.visit_nat(n1); - visitor.visit_nat(n2); + visitor.visit_nat(arena, n1); + visitor.visit_nat(arena, n2); } -pub fn walk_dim1d<'a, V: VisitMut<'a>>(visitor: &mut V, dim1d: &mut Dim1d<'a>) { +pub fn walk_dim1d<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, dim1d: &mut Dim1d<'a>) { let Dim1d(n) = dim1d; - visitor.visit_nat(n); + visitor.visit_nat(arena, n); } -pub fn walk_dim<'a, V: VisitMut<'a>>(visitor: &mut V, dim: &mut Dim<'a>) { +/** +pub fn walk_dim<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, dim: &mut Dim<'a>) { match dim { Dim::XYZ(dim3d) => { - visitor.visit_dim3d(dim3d); + visitor.visit_dim3d(arena, dim3d); } Dim::XY(dim2d) | Dim::XZ(dim2d) | Dim::YZ(dim2d) => { - visitor.visit_dim2d(dim2d); + visitor.visit_dim2d(arena, dim2d); } - Dim::X(dim1d) | Dim::Y(dim1d) | Dim::Z(dim1d) => visitor.visit_dim1d(dim1d), + Dim::X(dim1d) | Dim::Y(dim1d) | Dim::Z(dim1d) => visitor.visit_dim1d(arena, dim1d), } +}*/ + +pub fn walk_dim<'a, V: VisitMut<'a>>(v: &mut V, arena: &'a bumpalo::Bump, dim: &mut Dim<'a>) { + let new_dim = match dim { + Dim::XYZ(d3_ref) => { + let mut d3 = (*(*d3_ref)).clone(); // owned, mutable + v.visit_dim3d(arena, &mut d3); + Dim::new_3d(arena, d3.0.clone(), d3.1.clone(), d3.2.clone()) + } + Dim::XY(d2_ref) => { + let mut d2 = (*(*d2_ref)).clone(); + v.visit_dim2d(arena, &mut d2); + Dim::new_2d(arena, Dim::XY, d2.0.clone(), d2.1.clone()) + } + Dim::XZ(d2_ref) => { + let mut d2 = (*(*d2_ref)).clone(); + v.visit_dim2d(arena, &mut d2); + Dim::new_2d(arena, Dim::XZ, d2.0.clone(), d2.1.clone()) + } + Dim::YZ(d2_ref) => { + let mut d2 = (*(*d2_ref)).clone(); + v.visit_dim2d(arena, &mut d2); + Dim::new_2d(arena, Dim::YZ, d2.0.clone(), d2.1.clone()) + } + Dim::X(d1_ref) => { + let mut d1 = (*(*d1_ref)).clone(); + v.visit_dim1d(arena, &mut d1); + Dim::new_1d(arena, Dim::X, d1.0.clone()) + } + Dim::Y(d1_ref) => { + let mut d1 = (*(*d1_ref)).clone(); + v.visit_dim1d(arena, &mut d1); + Dim::new_1d(arena, Dim::Y, d1.0.clone()) + } + Dim::Z(d1_ref) => { + let mut d1 = (*(*d1_ref)).clone(); + v.visit_dim1d(arena, &mut d1); + Dim::new_1d(arena, Dim::Z, d1.0.clone()) + } + }; + *dim = new_dim; } -pub fn walk_ref<'a, V: VisitMut<'a>>(visitor: &mut V, reff: &mut RefDty<'a>) { +pub fn walk_ref<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, reff: &mut RefDty<'a>) { let RefDty { rgn, own, mem, dty } = reff; - visitor.visit_prv(rgn); + visitor.visit_prv(arena, rgn); visitor.visit_own(own); - visitor.visit_mem(mem); - visitor.visit_dty(dty); + visitor.visit_mem(arena, mem); + + let mut owned = (*reff.dty).clone(); + visitor.visit_dty(arena, &mut owned); + reff.dty = arena.alloc(owned); } -pub fn walk_dty<'a, V: VisitMut<'a>>(visitor: &mut V, dty: &mut DataTy<'a>) { +pub fn walk_dty<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, dty: &mut DataTy<'a>) { match &mut dty.dty { - DataTyKind::Ident(ident) => visitor.visit_ident(ident), + DataTyKind::Ident(ident) => visitor.visit_ident(arena, ident), DataTyKind::Scalar(sty) => visitor.visit_scalar_ty(sty), DataTyKind::Atomic(aty) => visitor.visit_atomic_ty(aty), - DataTyKind::Tuple(elem_dtys) => walk_list!(visitor, visit_dty, elem_dtys), - DataTyKind::Struct(struct_decl) => { - visitor.visit_ident(&mut struct_decl.ident); - walk_list!(visitor, visit_field, &mut struct_decl.fields) - } - DataTyKind::Array(dty, n) => { - visitor.visit_dty(dty); - visitor.visit_nat(n) - } - DataTyKind::ArrayShape(dty, n) => { - visitor.visit_dty(dty); - visitor.visit_nat(n); - } - DataTyKind::At(dty, mem) => { - visitor.visit_dty(dty); - visitor.visit_mem(mem) - } - DataTyKind::Ref(reff) => { - visitor.visit_ref(reff); + DataTyKind::Tuple(elem_dtys) => walk_list!(visitor, visit_dty, elem_dtys, arena), + DataTyKind::Struct(struct_decl_ref) => { + let mut owned = (**struct_decl_ref).clone(); + visitor.visit_ident(arena, &mut owned.ident); + walk_list!(visitor, visit_field, &mut owned.fields, arena); + *struct_decl_ref = arena.alloc(owned); + } + DataTyKind::Array(dty_ref, n_ref) => { + let mut elem = (**dty_ref).clone(); + visitor.visit_dty(arena, &mut elem); + *dty_ref = arena.alloc(elem); + + let mut n = (*n_ref).clone(); + visitor.visit_nat(arena, &mut n); + *n_ref = n; + } + DataTyKind::ArrayShape(dty_ref, n_ref) => { + let mut elem = (**dty_ref).clone(); + visitor.visit_dty(arena, &mut elem); + *dty_ref = arena.alloc(elem); + + let mut n = (*n_ref).clone(); + visitor.visit_nat(arena, &mut n); + *n_ref = n; + } + DataTyKind::At(dty_ref, mem) => { + let mut elem = (**dty_ref).clone(); + visitor.visit_dty(arena, &mut elem); + *dty_ref = arena.alloc(elem); + + visitor.visit_mem(arena, mem); + } + DataTyKind::Ref(reff_ref) => { + let mut r = (**reff_ref).clone(); + visitor.visit_ref(arena, &mut r); + *reff_ref = arena.alloc(r); + } + DataTyKind::RawPtr(datayt_ref) => { + let mut elem = (**datayt_ref).clone(); + visitor.visit_dty(arena, &mut elem); + *datayt_ref = arena.alloc(elem); + } + + DataTyKind::Dead(datayt_ref) => { + let mut elem = (**datayt_ref).clone(); + visitor.visit_dty(arena, &mut elem); + *datayt_ref = arena.alloc(elem); } - DataTyKind::RawPtr(dty) => visitor.visit_dty(dty), - DataTyKind::Dead(dty) => visitor.visit_dty(dty), } } -pub fn walk_fn_ty<'a, V: VisitMut<'a>>(visitor: &mut V, fn_ty: &mut FnTy<'a>) { +pub fn walk_fn_ty<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, fn_ty: &mut FnTy<'a>) { let FnTy { generics, generic_exec, @@ -201,105 +324,228 @@ pub fn walk_fn_ty<'a, V: VisitMut<'a>>(visitor: &mut V, fn_ty: &mut FnTy<'a>) { ret_ty, nat_constrs, } = fn_ty; - walk_list!(visitor, visit_ident_kinded, generics); + walk_list!(visitor, visit_ident_kinded, generics, arena); for exec_decl in generic_exec { - visitor.visit_ident_exec(exec_decl) + visitor.visit_ident_exec(arena, exec_decl) } - walk_list!(visitor, visit_param_sig, param_sigs); - visitor.visit_exec_expr(exec); - visitor.visit_ty(ret_ty); - walk_list!(visitor, visit_nat_constr, nat_constrs); + walk_list!(visitor, visit_param_sig, param_sigs, arena); + visitor.visit_exec_expr(arena, exec); + let mut ret_ty_owned = (**ret_ty).clone(); + visitor.visit_ty(arena, &mut ret_ty_owned); + *ret_ty = arena.alloc(ret_ty_owned); + walk_list!(visitor, visit_nat_constr, nat_constrs, arena); } -pub fn walk_nat_constr<'a, V: VisitMut<'a>>(visitor: &mut V, nat_constr: &mut NatConstr<'a>) { +pub fn walk_nat_constr<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + nat_constr: &mut NatConstr<'a>, +) { match nat_constr { NatConstr::True => {} NatConstr::Eq(l, r) => { - visitor.visit_nat(l); - visitor.visit_nat(r); + visitor.visit_nat(arena, l); + visitor.visit_nat(arena, r); } NatConstr::Lt(l, r) => { - visitor.visit_nat(l); - visitor.visit_nat(r); + visitor.visit_nat(arena, l); + visitor.visit_nat(arena, r); } NatConstr::And(l, r) => { - visitor.visit_nat_constr(l); - visitor.visit_nat_constr(r); + visitor.visit_nat_constr(arena, l); + visitor.visit_nat_constr(arena, r); } NatConstr::Or(l, r) => { - visitor.visit_nat_constr(l); - visitor.visit_nat_constr(r); + visitor.visit_nat_constr(arena, l); + visitor.visit_nat_constr(arena, r); } } } -pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, ty: &mut Ty<'a>) { +pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a bumpalo::Bump, ty: &mut Ty<'a>) { match &mut ty.ty { - TyKind::Data(dty) => visitor.visit_dty(dty), - TyKind::FnTy(fn_ty) => { - visitor.visit_fn_ty(fn_ty); + TyKind::Data(dty) => visitor.visit_dty(arena, dty), + + TyKind::FnTy(fn_slot) => { + // 1) Detach: copy fields out of the &'a FnTy<'a> + let src: &FnTy<'a> = *fn_slot; + + let mut owned = FnTy { + generics: src.generics.clone(), + generic_exec: src.generic_exec.clone(), + param_sigs: src.param_sigs.clone(), + exec: src.exec.clone(), + ret_ty: src.ret_ty, + nat_constrs: src.nat_constrs.clone(), + }; + + // 2) Visit children on the owned struct + walk_list!(visitor, visit_ident_kinded, &mut owned.generics, arena); + + if let Some(ref mut ie) = owned.generic_exec { + visitor.visit_ident_exec(arena, ie); + } + + walk_list!(visitor, visit_param_sig, &mut owned.param_sigs, arena); + visitor.visit_exec_expr(arena, &mut owned.exec); + + // ret_ty needs its own detach/reattach + let mut ret_owned = (*owned.ret_ty).clone(); + visitor.visit_ty(arena, &mut ret_owned); + owned.ret_ty = arena.alloc(ret_owned); + + walk_list!(visitor, visit_nat_constr, &mut owned.nat_constrs, arena); + + // 3) Reattach + *fn_slot = arena.alloc(owned); } } } -pub fn walk_view<'a, V: VisitMut<'a>>(visitor: &mut V, view: &mut View<'a>) { - visitor.visit_ident(&mut view.name); - walk_list!(visitor, visit_arg_kinded, &mut view.gen_args); +pub fn walk_view<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, view: &mut View<'a>) { + visitor.visit_ident(arena, &mut view.name); + walk_list!(visitor, visit_arg_kinded, &mut view.gen_args, arena); for v in &mut view.args { - visitor.visit_view(v) + visitor.visit_view(arena, v) } } -pub fn walk_pl_expr<'a, V: VisitMut<'a>>(visitor: &mut V, pl_expr: &mut PlaceExpr<'a>) { +/** +pub fn walk_pl_expr<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + pl_expr: &mut PlaceExpr<'a>, +) { match &mut pl_expr.pl_expr { - PlaceExprKind::Ident(ident) => visitor.visit_ident(ident), - PlaceExprKind::Deref(pl_expr) => visitor.visit_pl_expr(pl_expr), + PlaceExprKind::Ident(ident) => visitor.visit_ident(arena, ident), + PlaceExprKind::Deref(pl_expr) => visitor.visit_pl_expr(arena, pl_expr), PlaceExprKind::Select(p, distrib_exec) => { - visitor.visit_pl_expr(p); - visitor.visit_exec_expr(distrib_exec); + visitor.visit_pl_expr(arena, p); + visitor.visit_exec_expr(arena, distrib_exec); } PlaceExprKind::Proj(pl_expr, _) => { - visitor.visit_pl_expr(pl_expr); + visitor.visit_pl_expr(arena, pl_expr); } PlaceExprKind::FieldProj(pl_expr, field_name) => { - visitor.visit_pl_expr(pl_expr); - visitor.visit_ident(field_name); + visitor.visit_pl_expr(arena, pl_expr); + visitor.visit_ident(arena, field_name); } PlaceExprKind::View(pl_expr, view) => { - visitor.visit_pl_expr(pl_expr); - visitor.visit_view(view); + visitor.visit_pl_expr(arena, pl_expr); + visitor.visit_view(arena, view); } PlaceExprKind::Idx(pl_expr, n) => { - visitor.visit_pl_expr(pl_expr); - visitor.visit_nat(n) + visitor.visit_pl_expr(arena, pl_expr); + visitor.visit_nat(arena, n) + } + } +} +*/ + +pub fn walk_pl_expr<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a bumpalo::Bump, + pl_expr: &mut PlaceExpr<'a>, +) { + match &mut pl_expr.pl_expr { + PlaceExprKind::Ident(ident) => { + visitor.visit_ident(arena, ident); + } + + PlaceExprKind::Deref(inner_ref) => { + let mut owned = (**inner_ref).clone(); + visitor.visit_pl_expr(arena, &mut owned); + *inner_ref = arena.alloc(owned); + } + + PlaceExprKind::Select(p_ref, exec_ref) => { + // place + let mut p_owned = (**p_ref).clone(); + visitor.visit_pl_expr(arena, &mut p_owned); + *p_ref = arena.alloc(p_owned); + + // exec + let mut exec_owned = (**exec_ref).clone(); + visitor.visit_exec_expr(arena, &mut exec_owned); + *exec_ref = arena.alloc(exec_owned); + } + + PlaceExprKind::Proj(p_ref, _k) => { + let mut p_owned = (**p_ref).clone(); + visitor.visit_pl_expr(arena, &mut p_owned); + *p_ref = arena.alloc(p_owned); + } + + PlaceExprKind::FieldProj(p_ref, field_ref) => { + // place + let mut p_owned = (**p_ref).clone(); + visitor.visit_pl_expr(arena, &mut p_owned); + *p_ref = arena.alloc(p_owned); + + // field ident (held by reference) + let mut field_owned = (**field_ref).clone(); + visitor.visit_ident(arena, &mut field_owned); + *field_ref = arena.alloc(field_owned); + } + + PlaceExprKind::View(p_ref, view_ref) => { + // place + let mut p_owned = (**p_ref).clone(); + visitor.visit_pl_expr(arena, &mut p_owned); + *p_ref = arena.alloc(p_owned); + + // view (held by reference) + let mut view_owned = (**view_ref).clone(); + visitor.visit_view(arena, &mut view_owned); + *view_ref = arena.alloc(view_owned); + } + + PlaceExprKind::Idx(p_ref, n_ref) => { + // place + let mut p_owned = (**p_ref).clone(); + visitor.visit_pl_expr(arena, &mut p_owned); + *p_ref = arena.alloc(p_owned); + + // index nat (held by reference) + let mut n_owned = (**n_ref).clone(); + visitor.visit_nat(arena, &mut n_owned); + *n_ref = arena.alloc(n_owned); } } } -pub fn walk_arg_kinded<'a, V: VisitMut<'a>>(visitor: &mut V, arg_kinded: &mut ArgKinded<'a>) { +pub fn walk_arg_kinded<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + arg_kinded: &mut ArgKinded<'a>, +) { match arg_kinded { - ArgKinded::Ident(ident) => visitor.visit_ident(ident), - ArgKinded::Nat(n) => visitor.visit_nat(n), - ArgKinded::Memory(mem) => visitor.visit_mem(mem), - ArgKinded::DataTy(dty) => visitor.visit_dty(dty), - ArgKinded::Provenance(prv) => visitor.visit_prv(prv), + ArgKinded::Ident(ident) => visitor.visit_ident(arena, ident), + ArgKinded::Nat(n) => visitor.visit_nat(arena, n), + ArgKinded::Memory(mem) => visitor.visit_mem(arena, mem), + ArgKinded::DataTy(dty) => visitor.visit_dty(arena, dty), + ArgKinded::Provenance(prv) => visitor.visit_prv(arena, prv), } } -pub fn walk_pattern<'a, V: VisitMut<'a>>(visitor: &mut V, pattern: &mut Pattern<'a>) { +pub fn walk_pattern<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + pattern: &mut Pattern<'a>, +) { match pattern { Pattern::Ident(mutab, ident) => { visitor.visit_mutability(mutab); - visitor.visit_ident(ident); + visitor.visit_ident(arena, ident); } Pattern::Tuple(patterns) => { - walk_list!(visitor, visit_pattern, patterns) + walk_list!(visitor, visit_pattern, patterns, arena) } Pattern::Wildcard => {} } } -pub fn walk_split<'a, V: VisitMut<'a>>(visitor: &mut V, indep: &mut Split<'a>) { +pub fn walk_split<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, indep: &mut Split<'a>) { let Split { dim_compo, pos, @@ -308,13 +554,13 @@ pub fn walk_split<'a, V: VisitMut<'a>>(visitor: &mut V, indep: &mut Split<'a>) { branch_bodies, } = indep; visitor.visit_dim_compo(dim_compo); - visitor.visit_nat(pos); - visitor.visit_exec_expr(split_exec); - walk_list!(visitor, visit_ident, branch_idents); - walk_list!(visitor, visit_expr, branch_bodies); + visitor.visit_nat(arena, pos); + visitor.visit_exec_expr(arena, split_exec); + walk_list!(visitor, visit_ident, branch_idents, arena); + walk_list!(visitor, visit_expr, branch_bodies, arena); } -pub fn walk_sched<'a, V: VisitMut<'a>>(visitor: &mut V, sched: &mut Sched<'a>) { +pub fn walk_sched<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, sched: &mut Sched<'a>) { let Sched { dim, inner_exec_ident, @@ -323,49 +569,66 @@ pub fn walk_sched<'a, V: VisitMut<'a>>(visitor: &mut V, sched: &mut Sched<'a>) { } = sched; visitor.visit_dim_compo(dim); for ident in inner_exec_ident { - visitor.visit_ident(ident) + visitor.visit_ident(arena, ident) } - visitor.visit_exec_expr(sched_exec); - visitor.visit_block(body); + visitor.visit_exec_expr(arena, sched_exec); + visitor.visit_block(arena, body); } -pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, expr: &mut Expr<'a>) { +pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &mut Expr<'a>) { // For now, only visit ExprKind match &mut expr.expr { ExprKind::Lit(l) => visitor.visit_lit(l), - ExprKind::PlaceExpr(pl_expr) => visitor.visit_pl_expr(pl_expr), - - ExprKind::Ref(_, own, pl_expr) => { - visitor.visit_own(own); - visitor.visit_pl_expr(pl_expr); + ExprKind::PlaceExpr(pl_ref) => { + let mut owned = (**pl_ref).clone(); + visitor.visit_pl_expr(arena, &mut owned); + *pl_ref = arena.alloc(owned); } - ExprKind::Block(block) => visitor.visit_block(block), - ExprKind::LetUninit(maybe_exec_expr, ident, ty) => { - for e in maybe_exec_expr { - visitor.visit_exec_expr(e); + ExprKind::Ref(_, own, pl_ref) => { + visitor.visit_own(own); + let mut owned = (**pl_ref).clone(); + visitor.visit_pl_expr(arena, &mut owned); + *pl_ref = arena.alloc(owned); + } + ExprKind::Block(block_ref) => { + let mut owned = (**block_ref).clone(); + visitor.visit_block(arena, &mut owned); + *block_ref = arena.alloc(owned); + } + ExprKind::LetUninit(maybe_exec_expr, ident_ref, ty_ref) => { + if let Some(slot) = maybe_exec_expr.as_mut() { + let mut owned = (**slot).clone(); + visitor.visit_exec_expr(arena, &mut owned); + *slot = arena.alloc(owned); } - visitor.visit_ident(ident); - visitor.visit_ty(ty); + + visitor.visit_ident(arena, ident_ref); + + let mut ty_owned = (**ty_ref).clone(); + visitor.visit_ty(arena, &mut ty_owned); + *ty_ref = arena.alloc(ty_owned); } - ExprKind::Let(pattern, ty, e) => { - visitor.visit_pattern(pattern); - for ty in ty.as_mut() { - visitor.visit_ty(ty); + ExprKind::Let(pattern, ty_opt, e) => { + visitor.visit_pattern(arena, pattern); + if let Some(slot) = ty_opt.as_mut() { + let mut ty_owned = (**slot).clone(); + visitor.visit_ty(arena, &mut ty_owned); + *slot = arena.alloc(ty_owned); } - visitor.visit_expr(e); + visitor.visit_expr(arena, e); } ExprKind::Assign(pl_expr, expr) => { - visitor.visit_pl_expr(pl_expr); - visitor.visit_expr(expr) + visitor.visit_pl_expr(arena, pl_expr); + visitor.visit_expr(arena, expr) } ExprKind::IdxAssign(pl_expr, idx, expr) => { - visitor.visit_pl_expr(pl_expr); - visitor.visit_nat(idx); - visitor.visit_expr(expr); + visitor.visit_pl_expr(arena, pl_expr); + visitor.visit_nat(arena, idx); + visitor.visit_expr(arena, expr); } ExprKind::Seq(es) => { for e in es { - visitor.visit_expr(e) + visitor.visit_expr(arena, e) } } // ExprKind::Lambda(params, exec_decl, dty, expr) => { @@ -375,74 +638,88 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, expr: &mut Expr<'a>) { // visitor.visit_expr(expr) // } ExprKind::App(f, gen_args, args) => { - visitor.visit_ident(f); - walk_list!(visitor, visit_arg_kinded, gen_args); - walk_list!(visitor, visit_expr, args); + visitor.visit_ident(arena, f); + walk_list!(visitor, visit_arg_kinded, gen_args, arena); + walk_list!(visitor, visit_expr, args, arena); } ExprKind::DepApp(f, gen_args) => { - visitor.visit_ident(f); - walk_list!(visitor, visit_arg_kinded, gen_args); - } - ExprKind::AppKernel(app_kernel) => visitor.visit_app_kernel(app_kernel), - ExprKind::IfElse(cond, tt, ff) => { - visitor.visit_expr(cond); - visitor.visit_expr(tt); - visitor.visit_expr(ff) + visitor.visit_ident(arena, f); + walk_list!(visitor, visit_arg_kinded, gen_args, arena); + } + ExprKind::AppKernel(app_kernel) => visitor.visit_app_kernel(arena, app_kernel), + ExprKind::IfElse(cond_ref, tt_ref, ff_ref) => { + let mut cond = (**cond_ref).clone(); + let mut tt = (**tt_ref).clone(); + let mut ff = (**ff_ref).clone(); + visitor.visit_expr(arena, &mut cond); + visitor.visit_expr(arena, &mut tt); + visitor.visit_expr(arena, &mut ff); + *cond_ref = arena.alloc(cond); + *tt_ref = arena.alloc(tt); + *ff_ref = arena.alloc(ff) } ExprKind::If(cond, tt) => { - visitor.visit_expr(cond); - visitor.visit_expr(tt) + visitor.visit_expr(arena, cond); + visitor.visit_expr(arena, tt) } ExprKind::Array(elems) => { - walk_list!(visitor, visit_expr, elems); + walk_list!(visitor, visit_expr, elems, arena); } ExprKind::Tuple(elems) => { - walk_list!(visitor, visit_expr, elems); + walk_list!(visitor, visit_expr, elems, arena); } - ExprKind::For(ident, coll, body) => { - visitor.visit_ident(ident); - visitor.visit_expr(coll); - visitor.visit_expr(body); + ExprKind::For(ident, coll_ref, body_ref) => { + visitor.visit_ident(arena, ident); + let mut coll = (**coll_ref).clone(); + let mut body = (**body_ref).clone(); + visitor.visit_expr(arena, &mut coll); + visitor.visit_expr(arena, &mut body); + *coll_ref = arena.alloc(coll); + *body_ref = arena.alloc(body); } ExprKind::Split(par_branch) => { - visitor.visit_split(par_branch); + visitor.visit_split(arena, par_branch); } ExprKind::Sched(sched) => { - visitor.visit_sched(sched); + visitor.visit_sched(arena, sched); } ExprKind::ForNat(ident, range, body) => { - visitor.visit_ident(ident); - visitor.visit_nat_range(range); - visitor.visit_expr(body) + visitor.visit_ident(arena, ident); + visitor.visit_nat_range(arena, range); + visitor.visit_expr(arena, body) } ExprKind::While(cond, body) => { - visitor.visit_expr(cond); - visitor.visit_expr(body); + visitor.visit_expr(arena, cond); + visitor.visit_expr(arena, body); } ExprKind::BinOp(op, l, r) => { visitor.visit_binary_op(op); - visitor.visit_expr(l); - visitor.visit_expr(r) + visitor.visit_expr(arena, l); + visitor.visit_expr(arena, r) } ExprKind::UnOp(op, expr) => { visitor.visit_unary_op(op); - visitor.visit_expr(expr) + visitor.visit_expr(arena, expr) } ExprKind::Sync(exec) => { for e in exec { - visitor.visit_exec_expr(e) + visitor.visit_exec_expr(arena, e) } } - ExprKind::Unsafe(expr) => visitor.visit_expr(expr), + ExprKind::Unsafe(expr) => visitor.visit_expr(arena, expr), ExprKind::Cast(expr, dty) => { - visitor.visit_expr(expr); - visitor.visit_dty(dty) + visitor.visit_expr(arena, expr); + visitor.visit_dty(arena, dty) } ExprKind::Range(_, _) | ExprKind::Hole => (), } } -pub fn walk_app_kernel<'a, V: VisitMut<'a>>(visitor: &mut V, app_kernel: &mut AppKernel<'a>) { +pub fn walk_app_kernel<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + app_kernel: &mut AppKernel<'a>, +) { let AppKernel { grid_dim, block_dim, @@ -452,87 +729,108 @@ pub fn walk_app_kernel<'a, V: VisitMut<'a>>(visitor: &mut V, app_kernel: &mut Ap gen_args, args, } = app_kernel; - visitor.visit_dim(grid_dim); - visitor.visit_dim(block_dim); + visitor.visit_dim(arena, grid_dim); + visitor.visit_dim(arena, block_dim); for dty in shared_mem_dtys { - visitor.visit_dty(dty); + visitor.visit_dty(arena, dty); } - visitor.visit_ident(fun_ident); + visitor.visit_ident(arena, fun_ident); for garg in gen_args { - visitor.visit_arg_kinded(garg); + visitor.visit_arg_kinded(arena, garg); } for arg in args { - visitor.visit_expr(arg); + visitor.visit_expr(arena, arg); } } -pub fn walk_block<'a, V: VisitMut<'a>>(visitor: &mut V, block: &mut Block<'a>) { +pub fn walk_block<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, block: &mut Block<'a>) { let Block { body, .. } = block; - visitor.visit_expr(body); + visitor.visit_expr(arena, body); } -pub fn walk_split_proj<'a, V: VisitMut<'a>>(visitor: &mut V, split_proj: &mut TakeRange<'a>) { +pub fn walk_split_proj<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + split_proj: &mut TakeRange<'a>, +) { let TakeRange { split_dim, pos, left_or_right: _, } = split_proj; visitor.visit_dim_compo(split_dim); - visitor.visit_nat(pos); + visitor.visit_nat(arena, pos); } -pub fn walk_exec_expr<'a, V: VisitMut<'a>>(visitor: &mut V, exec_expr: &mut ExecExpr<'a>) { - visitor.visit_exec(&mut exec_expr.exec); +pub fn walk_exec_expr<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + exec_expr: &mut ExecExpr<'a>, +) { + visitor.visit_exec(arena, &mut exec_expr.exec); for t in &mut exec_expr.ty { visitor.visit_exec_ty(t); } } -pub fn walk_exec<'a, V: VisitMut<'a>>(visitor: &mut V, exec: &mut ExecExprKind<'a>) { +pub fn walk_exec<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + exec: &mut ExecExprKind<'a>, +) { let ExecExprKind { base, path } = exec; match base { BaseExec::CpuThread => (), - BaseExec::Ident(ident) => visitor.visit_ident(ident), + BaseExec::Ident(ident) => visitor.visit_ident(arena, ident), BaseExec::GpuGrid(gdim, bdim) => { - visitor.visit_dim(gdim); - visitor.visit_dim(bdim); + visitor.visit_dim(arena, gdim); + visitor.visit_dim(arena, bdim); } }; for e in path { - visitor.visit_exec_path_elem(e) + visitor.visit_exec_path_elem(arena, e) } } pub fn walk_exec_path_elem<'a, V: VisitMut<'a>>( visitor: &mut V, + arena: &'a Bump, exec_path_elem: &mut ExecPathElem<'a>, ) { match exec_path_elem { - ExecPathElem::TakeRange(split_proj) => visitor.visit_split_proj(split_proj), + ExecPathElem::TakeRange(split_proj) => visitor.visit_split_proj(arena, split_proj), ExecPathElem::ForAll(dim_compo) => visitor.visit_dim_compo(dim_compo), ExecPathElem::ToWarps => {} ExecPathElem::ToThreads(dim_compo) => visitor.visit_dim_compo(dim_compo), } } -pub fn walk_param_decl<'a, V: VisitMut<'a>>(visitor: &mut V, param_decl: &mut ParamDecl<'a>) { +pub fn walk_param_decl<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + param_decl: &mut ParamDecl<'a>, +) { let ParamDecl { ident, ty, mutbl, exec_expr, } = param_decl; - visitor.visit_ident(ident); + visitor.visit_ident(arena, ident); if let Some(tty) = ty { - visitor.visit_ty(tty); + visitor.visit_ty(arena, tty); } visitor.visit_mutability(mutbl); for ex in exec_expr { - visitor.visit_exec_expr(ex); + visitor.visit_exec_expr(arena, ex); } } -pub fn walk_fun_def<'a, V: VisitMut<'a>>(visitor: &mut V, fun_def: &mut FunDef<'a>) { +pub fn walk_fun_def<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + fun_def: &mut FunDef<'a>, +) { let FunDef { ident: _, generic_params, @@ -543,18 +841,22 @@ pub fn walk_fun_def<'a, V: VisitMut<'a>>(visitor: &mut V, fun_def: &mut FunDef<' prv_rels, body, } = fun_def; - walk_list!(visitor, visit_ident_kinded, generic_params); + walk_list!(visitor, visit_ident_kinded, generic_params, arena); for exec_decl in generic_exec { - visitor.visit_ident_exec(exec_decl); + visitor.visit_ident_exec(arena, exec_decl); } - walk_list!(visitor, visit_param_decl, params); - visitor.visit_dty(ret_dty); - visitor.visit_exec_expr(exec); - walk_list!(visitor, visit_prv_rel, prv_rels); - visitor.visit_block(body) + walk_list!(visitor, visit_param_decl, params, arena); + visitor.visit_dty(arena, ret_dty); + visitor.visit_exec_expr(arena, exec); + walk_list!(visitor, visit_prv_rel, prv_rels, arena); + visitor.visit_block(arena, body) } -pub fn walk_fun_decl<'a, V: VisitMut<'a>>(visitor: &mut V, fun_decl: &mut FunDecl<'a>) { +pub fn walk_fun_decl<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + fun_decl: &mut FunDecl<'a>, +) { let FunDecl { ident: _, generic_params, @@ -564,24 +866,36 @@ pub fn walk_fun_decl<'a, V: VisitMut<'a>>(visitor: &mut V, fun_decl: &mut FunDec exec, prv_rels, } = fun_decl; - walk_list!(visitor, visit_ident_kinded, generic_params); + walk_list!(visitor, visit_ident_kinded, generic_params, arena); for exec_decl in generic_exec { - visitor.visit_ident_exec(exec_decl); + visitor.visit_ident_exec(arena, exec_decl); } - walk_list!(visitor, visit_param_decl, params); - visitor.visit_dty(ret_dty); - visitor.visit_exec_expr(exec); - walk_list!(visitor, visit_prv_rel, prv_rels); + walk_list!(visitor, visit_param_decl, params, arena); + let mut ret_dty_owned = (**ret_dty).clone(); + visitor.visit_dty(arena, &mut ret_dty_owned); + *ret_dty = arena.alloc(ret_dty_owned); + visitor.visit_exec_expr(arena, exec); + walk_list!(visitor, visit_prv_rel, prv_rels, arena); } -pub fn walk_param_sig<'a, V: VisitMut<'a>>(visitor: &mut V, param_sig: &mut ParamSig<'a>) { +pub fn walk_param_sig<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + param_sig: &mut ParamSig<'a>, +) { let ParamSig { exec_expr, ty } = param_sig; - visitor.visit_exec_expr(exec_expr); - visitor.visit_ty(ty); + visitor.visit_exec_expr(arena, exec_expr); + let mut ty_owned = (**ty).clone(); + visitor.visit_ty(arena, &mut ty_owned); + *ty = arena.alloc(ty_owned); } -pub fn walk_field<'a, V: VisitMut<'a>>(visitor: &mut V, field: &mut (Ident<'a>, DataTy<'a>)) { +pub fn walk_field<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a Bump, + field: &mut (Ident<'a>, DataTy<'a>), +) { let (ident, dty) = field; - visitor.visit_ident(ident); - visitor.visit_dty(dty); + visitor.visit_ident(arena, ident); + visitor.visit_dty(arena, dty); } From 83e3c9ff6a97fff93f6c7e6ef0dec4f9fdde83c3 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Mon, 11 Aug 2025 19:25:39 +0200 Subject: [PATCH 42/57] last updates for today --- src/arena_ast/visit_mut.rs | 51 ++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/arena_ast/visit_mut.rs b/src/arena_ast/visit_mut.rs index e441a278..1dc40556 100644 --- a/src/arena_ast/visit_mut.rs +++ b/src/arena_ast/visit_mut.rs @@ -344,28 +344,47 @@ pub fn walk_nat_constr<'a, V: VisitMut<'a>>( match nat_constr { NatConstr::True => {} NatConstr::Eq(l, r) => { - visitor.visit_nat(arena, l); - visitor.visit_nat(arena, r); + let mut owned_l = (**l).clone(); + let mut owned_r = (**r).clone(); + visitor.visit_nat(arena, &mut owned_l); + visitor.visit_nat(arena, &mut owned_r); + *l = arena.alloc(owned_l); + *r = arena.alloc(owned_r); } NatConstr::Lt(l, r) => { - visitor.visit_nat(arena, l); - visitor.visit_nat(arena, r); + let mut owned_l = (**l).clone(); + let mut owned_r = (**r).clone(); + visitor.visit_nat(arena, &mut owned_l); + visitor.visit_nat(arena, &mut owned_r); + *l = arena.alloc(owned_l); + *r = arena.alloc(owned_r); } NatConstr::And(l, r) => { - visitor.visit_nat_constr(arena, l); - visitor.visit_nat_constr(arena, r); + let mut owned_l = (**l).clone(); + let mut owned_r = (**r).clone(); + visitor.visit_nat_constr(arena, &mut owned_l); + visitor.visit_nat_constr(arena, &mut owned_r); + *l = arena.alloc(owned_l); + *r = arena.alloc(owned_r); } NatConstr::Or(l, r) => { - visitor.visit_nat_constr(arena, l); - visitor.visit_nat_constr(arena, r); + let mut owned_l = (**l).clone(); + let mut owned_r = (**r).clone(); + visitor.visit_nat_constr(arena, &mut owned_l); + visitor.visit_nat_constr(arena, &mut owned_r); + *l = arena.alloc(owned_l); + *r = arena.alloc(owned_r); } } } pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a bumpalo::Bump, ty: &mut Ty<'a>) { match &mut ty.ty { - TyKind::Data(dty) => visitor.visit_dty(arena, dty), - + TyKind::Data(dty) => { + let mut dty_owned = (**dty).clone(); + visitor.visit_dty(arena, &mut dty_owned); + *dty = arena.alloc(dty_owned); + } TyKind::FnTy(fn_slot) => { // 1) Detach: copy fields out of the &'a FnTy<'a> let src: &FnTy<'a> = *fn_slot; @@ -618,8 +637,12 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &m visitor.visit_expr(arena, e); } ExprKind::Assign(pl_expr, expr) => { - visitor.visit_pl_expr(arena, pl_expr); - visitor.visit_expr(arena, expr) + let mut pl_expr_owned = (**pl_expr).clone(); + let mut expr_owned = (**expr).clone(); + visitor.visit_pl_expr(arena, &mut pl_expr_owned); + visitor.visit_expr(arena, &mut expr_owned); + *pl_expr = arena.alloc(pl_expr_owned); + *expr = arena.alloc(expr_owned); } ExprKind::IdxAssign(pl_expr, idx, expr) => { visitor.visit_pl_expr(arena, pl_expr); @@ -818,7 +841,9 @@ pub fn walk_param_decl<'a, V: VisitMut<'a>>( } = param_decl; visitor.visit_ident(arena, ident); if let Some(tty) = ty { - visitor.visit_ty(arena, tty); + let mut tty_owned = (**tty).clone(); + visitor.visit_ty(arena, &mut tty_owned); + *tty = arena.alloc(tty_owned); } visitor.visit_mutability(mutbl); for ex in exec_expr { From 5c5002bf6ca31c63333ed17f1245847ab7650c92 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 12 Aug 2025 10:14:45 +0200 Subject: [PATCH 43/57] visitor update --- src/arena_ast/mod.rs | 14 +-- src/arena_ast/visit_mut.rs | 210 +++++++++++++++++++++++++++++-------- 2 files changed, 175 insertions(+), 49 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index dda8e7db..e089a25f 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -261,17 +261,17 @@ impl<'a> Expr<'a> { // } } -#[derive(PartialEq, Debug)] // Apparently you cannot clone BumpBoxes. If needed again, just make them mutable references? +#[derive(PartialEq, Debug, Clone)] pub struct Sched<'a> { pub dim: DimCompo, pub inner_exec_ident: Option>, - pub sched_exec: BumpBox<'a, ExecExpr<'a>>, - pub body: BumpBox<'a, Block<'a>>, + pub sched_exec: &'a ExecExpr<'a>, + pub body: &'a Block<'a>, } impl<'a> Sched<'a> { pub fn new_in( - bump: &'a bumpalo::Bump, + arena: &'a bumpalo::Bump, dim: DimCompo, inner_exec_ident: Option>, sched_exec: ExecExpr<'a>, @@ -280,8 +280,8 @@ impl<'a> Sched<'a> { Sched { dim, inner_exec_ident, - sched_exec: BumpBox::new_in(sched_exec, bump), - body: BumpBox::new_in(body, bump), + sched_exec: arena.alloc(sched_exec), + body: arena.alloc(body), } } } @@ -356,7 +356,7 @@ pub struct AppKernel<'a> { pub block_dim: Dim<'a>, pub shared_mem_dtys: BumpVec<'a, DataTy<'a>>, pub shared_mem_prvs: BumpVec<'a, String>, - pub fun_ident: BumpBox<'a, Ident<'a>>, + pub fun_ident: &'a Ident<'a>, pub gen_args: BumpVec<'a, ArgKinded<'a>>, pub args: BumpVec<'a, Expr<'a>>, } diff --git a/src/arena_ast/visit_mut.rs b/src/arena_ast/visit_mut.rs index 1dc40556..4c1e6d2f 100644 --- a/src/arena_ast/visit_mut.rs +++ b/src/arena_ast/visit_mut.rs @@ -100,12 +100,10 @@ pub fn walk_nat_ref<'a, V: VisitMut<'a>>( v.visit_nat_ref(arena, &mut l_slot); v.visit_nat_ref(arena, &mut r_slot); - // Rebuild the parent node with possibly-updated children let new = arena.alloc(Nat::BinOp(*op, l_slot, r_slot)); *slot = new; } Nat::App(func, args) => { - // Owned children: visit in place let mut rebuilt = bumpalo::collections::Vec::new_in(arena); rebuilt.reserve(args.len()); for a in args.iter() { @@ -386,7 +384,6 @@ pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a bumpalo::Bump, t *dty = arena.alloc(dty_owned); } TyKind::FnTy(fn_slot) => { - // 1) Detach: copy fields out of the &'a FnTy<'a> let src: &FnTy<'a> = *fn_slot; let mut owned = FnTy { @@ -398,7 +395,6 @@ pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a bumpalo::Bump, t nat_constrs: src.nat_constrs.clone(), }; - // 2) Visit children on the owned struct walk_list!(visitor, visit_ident_kinded, &mut owned.generics, arena); if let Some(ref mut ie) = owned.generic_exec { @@ -408,14 +404,12 @@ pub fn walk_ty<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a bumpalo::Bump, t walk_list!(visitor, visit_param_sig, &mut owned.param_sigs, arena); visitor.visit_exec_expr(arena, &mut owned.exec); - // ret_ty needs its own detach/reattach let mut ret_owned = (*owned.ret_ty).clone(); visitor.visit_ty(arena, &mut ret_owned); owned.ret_ty = arena.alloc(ret_owned); walk_list!(visitor, visit_nat_constr, &mut owned.nat_constrs, arena); - // 3) Reattach *fn_slot = arena.alloc(owned); } } @@ -478,12 +472,10 @@ pub fn walk_pl_expr<'a, V: VisitMut<'a>>( } PlaceExprKind::Select(p_ref, exec_ref) => { - // place let mut p_owned = (**p_ref).clone(); visitor.visit_pl_expr(arena, &mut p_owned); *p_ref = arena.alloc(p_owned); - // exec let mut exec_owned = (**exec_ref).clone(); visitor.visit_exec_expr(arena, &mut exec_owned); *exec_ref = arena.alloc(exec_owned); @@ -496,36 +488,30 @@ pub fn walk_pl_expr<'a, V: VisitMut<'a>>( } PlaceExprKind::FieldProj(p_ref, field_ref) => { - // place let mut p_owned = (**p_ref).clone(); visitor.visit_pl_expr(arena, &mut p_owned); *p_ref = arena.alloc(p_owned); - // field ident (held by reference) let mut field_owned = (**field_ref).clone(); visitor.visit_ident(arena, &mut field_owned); *field_ref = arena.alloc(field_owned); } PlaceExprKind::View(p_ref, view_ref) => { - // place let mut p_owned = (**p_ref).clone(); visitor.visit_pl_expr(arena, &mut p_owned); *p_ref = arena.alloc(p_owned); - // view (held by reference) let mut view_owned = (**view_ref).clone(); visitor.visit_view(arena, &mut view_owned); *view_ref = arena.alloc(view_owned); } PlaceExprKind::Idx(p_ref, n_ref) => { - // place let mut p_owned = (**p_ref).clone(); visitor.visit_pl_expr(arena, &mut p_owned); *p_ref = arena.alloc(p_owned); - // index nat (held by reference) let mut n_owned = (**n_ref).clone(); visitor.visit_nat(arena, &mut n_owned); *n_ref = arena.alloc(n_owned); @@ -574,7 +560,9 @@ pub fn walk_split<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, indep: } = indep; visitor.visit_dim_compo(dim_compo); visitor.visit_nat(arena, pos); - visitor.visit_exec_expr(arena, split_exec); + let mut split_exec_owned = (**split_exec).clone(); + visitor.visit_exec_expr(arena, &mut split_exec_owned); + *split_exec = arena.alloc(split_exec_owned); walk_list!(visitor, visit_ident, branch_idents, arena); walk_list!(visitor, visit_expr, branch_bodies, arena); } @@ -590,8 +578,13 @@ pub fn walk_sched<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, sched: for ident in inner_exec_ident { visitor.visit_ident(arena, ident) } - visitor.visit_exec_expr(arena, sched_exec); - visitor.visit_block(arena, body); + let mut sched_exec_owned = (**sched_exec).clone(); + visitor.visit_exec_expr(arena, &mut sched_exec_owned); + *sched_exec = arena.alloc(sched_exec_owned); + + let mut body_owned = (**body).clone(); + visitor.visit_block(arena, &mut body_owned); + *body = arena.alloc(body_owned); } pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &mut Expr<'a>) { @@ -634,7 +627,9 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &m visitor.visit_ty(arena, &mut ty_owned); *slot = arena.alloc(ty_owned); } - visitor.visit_expr(arena, e); + let mut e_owned = (**e).clone(); + visitor.visit_expr(arena, &mut e_owned); + *e = arena.alloc(e_owned); } ExprKind::Assign(pl_expr, expr) => { let mut pl_expr_owned = (**pl_expr).clone(); @@ -645,9 +640,13 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &m *expr = arena.alloc(expr_owned); } ExprKind::IdxAssign(pl_expr, idx, expr) => { - visitor.visit_pl_expr(arena, pl_expr); + let mut pl_expr_owned = (**pl_expr).clone(); + let mut expr_owned = (**expr).clone(); + visitor.visit_pl_expr(arena, &mut pl_expr_owned); visitor.visit_nat(arena, idx); - visitor.visit_expr(arena, expr); + visitor.visit_expr(arena, &mut expr_owned); + *pl_expr = arena.alloc(pl_expr_owned); + *expr = arena.alloc(expr_owned); } ExprKind::Seq(es) => { for e in es { @@ -661,7 +660,9 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &m // visitor.visit_expr(expr) // } ExprKind::App(f, gen_args, args) => { - visitor.visit_ident(arena, f); + let mut f_owned = (**f).clone(); + visitor.visit_ident(arena, &mut f_owned); + *f = arena.alloc(f_owned); walk_list!(visitor, visit_arg_kinded, gen_args, arena); walk_list!(visitor, visit_expr, args, arena); } @@ -669,7 +670,43 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &m visitor.visit_ident(arena, f); walk_list!(visitor, visit_arg_kinded, gen_args, arena); } - ExprKind::AppKernel(app_kernel) => visitor.visit_app_kernel(arena, app_kernel), + ExprKind::AppKernel(app_kernel_ref) => { + let src: &AppKernel<'a> = *app_kernel_ref; + + let mut tmp = AppKernel { + grid_dim: src.grid_dim.clone(), + block_dim: src.block_dim.clone(), + shared_mem_dtys: src.shared_mem_dtys.clone(), + shared_mem_prvs: src.shared_mem_prvs.clone(), + fun_ident: { + let mut id = (*src.fun_ident).clone(); + visitor.visit_ident(arena, &mut id); + arena.alloc(id) + }, + gen_args: { + let mut v = src.gen_args.clone(); + for a in v.iter_mut() { + visitor.visit_arg_kinded(arena, a); + } + v + }, + args: { + let mut v = src.args.clone(); + for e in v.iter_mut() { + visitor.visit_expr(arena, e); + } + v + }, + }; + + visitor.visit_dim(arena, &mut tmp.grid_dim); + visitor.visit_dim(arena, &mut tmp.block_dim); + for d in tmp.shared_mem_dtys.iter_mut() { + visitor.visit_dty(arena, d); + } + + *app_kernel_ref = arena.alloc(tmp); + } ExprKind::IfElse(cond_ref, tt_ref, ff_ref) => { let mut cond = (**cond_ref).clone(); let mut tt = (**tt_ref).clone(); @@ -682,8 +719,12 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &m *ff_ref = arena.alloc(ff) } ExprKind::If(cond, tt) => { - visitor.visit_expr(arena, cond); - visitor.visit_expr(arena, tt) + let mut cond_owned = (**cond).clone(); + let mut tt_owned = (**tt).clone(); + visitor.visit_expr(arena, &mut cond_owned); + visitor.visit_expr(arena, &mut tt_owned); + *cond = arena.alloc(cond_owned); + *tt = arena.alloc(tt_owned); } ExprKind::Array(elems) => { walk_list!(visitor, visit_expr, elems, arena); @@ -700,39 +741,92 @@ pub fn walk_expr<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, expr: &m *coll_ref = arena.alloc(coll); *body_ref = arena.alloc(body); } - ExprKind::Split(par_branch) => { - visitor.visit_split(arena, par_branch); + ExprKind::Split(split_ref) => { + let src: &Split<'a> = *split_ref; + + let mut dim = src.dim_compo; + visitor.visit_dim_compo(&mut dim); + + let mut pos = src.pos.clone(); + visitor.visit_nat(arena, &mut pos); + + let mut exec_owned = (*src.split_exec).clone(); + visitor.visit_exec_expr(arena, &mut exec_owned); + let exec_ref: &'a ExecExpr<'a> = arena.alloc(exec_owned); + + let mut branch_idents = src.branch_idents.clone(); + for id in branch_idents.iter_mut() { + visitor.visit_ident(arena, id); + } + + let mut branch_bodies = src.branch_bodies.clone(); + for body in branch_bodies.iter_mut() { + visitor.visit_expr(arena, body); + } + + let new_split = Split { + dim_compo: dim, + pos, + split_exec: exec_ref, + branch_idents, + branch_bodies, + }; + *split_ref = arena.alloc(new_split); } ExprKind::Sched(sched) => { - visitor.visit_sched(arena, sched); + let mut sched_owned = (**sched).clone(); + visitor.visit_sched(arena, &mut sched_owned); + *sched = arena.alloc(sched_owned); } ExprKind::ForNat(ident, range, body) => { visitor.visit_ident(arena, ident); - visitor.visit_nat_range(arena, range); - visitor.visit_expr(arena, body) + let mut range_owned = (**range).clone(); + let mut body_owned = (**body).clone(); + visitor.visit_nat_range(arena, &mut range_owned); + visitor.visit_expr(arena, &mut body_owned); + *range = arena.alloc(range_owned); + *body = arena.alloc(body_owned); } ExprKind::While(cond, body) => { - visitor.visit_expr(arena, cond); - visitor.visit_expr(arena, body); + let mut cond_owned = (**cond).clone(); + let mut body_owned = (**body).clone(); + visitor.visit_expr(arena, &mut cond_owned); + visitor.visit_expr(arena, &mut body_owned); + *cond = arena.alloc(cond_owned); + *body = arena.alloc(body_owned); } ExprKind::BinOp(op, l, r) => { visitor.visit_binary_op(op); - visitor.visit_expr(arena, l); - visitor.visit_expr(arena, r) + let mut l_owned = (**l).clone(); + let mut r_owned = (**r).clone(); + visitor.visit_expr(arena, &mut l_owned); + visitor.visit_expr(arena, &mut r_owned); + *l = arena.alloc(l_owned); + *r = arena.alloc(r_owned); } ExprKind::UnOp(op, expr) => { visitor.visit_unary_op(op); - visitor.visit_expr(arena, expr) + let mut expr_owned = (**expr).clone(); + visitor.visit_expr(arena, &mut expr_owned); + *expr = arena.alloc(expr_owned); } ExprKind::Sync(exec) => { for e in exec { visitor.visit_exec_expr(arena, e) } } - ExprKind::Unsafe(expr) => visitor.visit_expr(arena, expr), + ExprKind::Unsafe(expr) => { + let mut expr_owned = (**expr).clone(); + visitor.visit_expr(arena, &mut expr_owned); + *expr = arena.alloc(expr_owned); + } ExprKind::Cast(expr, dty) => { - visitor.visit_expr(arena, expr); - visitor.visit_dty(arena, dty) + let mut expr_owned = (**expr).clone(); + let mut dty_owned = (**dty).clone(); + visitor.visit_expr(arena, &mut expr_owned); + visitor.visit_dty(arena, &mut dty_owned); + *expr = arena.alloc(expr_owned); + *dty = arena.alloc(dty_owned); } ExprKind::Range(_, _) | ExprKind::Hole => (), } @@ -757,7 +851,9 @@ pub fn walk_app_kernel<'a, V: VisitMut<'a>>( for dty in shared_mem_dtys { visitor.visit_dty(arena, dty); } - visitor.visit_ident(arena, fun_ident); + let mut fun_owned = (**fun_ident).clone(); + visitor.visit_ident(arena, &mut fun_owned); + *fun_ident = arena.alloc(fun_owned); for garg in gen_args { visitor.visit_arg_kinded(arena, garg); } @@ -768,7 +864,9 @@ pub fn walk_app_kernel<'a, V: VisitMut<'a>>( pub fn walk_block<'a, V: VisitMut<'a>>(visitor: &mut V, arena: &'a Bump, block: &mut Block<'a>) { let Block { body, .. } = block; - visitor.visit_expr(arena, body); + let mut body_owned = (**body).clone(); + visitor.visit_expr(arena, &mut body_owned); + *body = arena.alloc(body_owned); } pub fn walk_split_proj<'a, V: VisitMut<'a>>( @@ -785,6 +883,7 @@ pub fn walk_split_proj<'a, V: VisitMut<'a>>( visitor.visit_nat(arena, pos); } +/** pub fn walk_exec_expr<'a, V: VisitMut<'a>>( visitor: &mut V, arena: &'a Bump, @@ -795,6 +894,23 @@ pub fn walk_exec_expr<'a, V: VisitMut<'a>>( visitor.visit_exec_ty(t); } } +*/ + +pub fn walk_exec_expr<'a, V: VisitMut<'a>>( + visitor: &mut V, + arena: &'a bumpalo::Bump, + exec_expr: &mut ExecExpr<'a>, +) { + let mut exec_owned = (*exec_expr.exec).clone(); + visitor.visit_exec(arena, &mut exec_owned); + exec_expr.exec = arena.alloc(exec_owned); + + if let Some(ty_ref) = &mut exec_expr.ty { + let mut ty_owned = (**ty_ref).clone(); + visitor.visit_exec_ty(&mut ty_owned); + *ty_ref = arena.alloc(ty_owned); + } +} pub fn walk_exec<'a, V: VisitMut<'a>>( visitor: &mut V, @@ -821,7 +937,11 @@ pub fn walk_exec_path_elem<'a, V: VisitMut<'a>>( exec_path_elem: &mut ExecPathElem<'a>, ) { match exec_path_elem { - ExecPathElem::TakeRange(split_proj) => visitor.visit_split_proj(arena, split_proj), + ExecPathElem::TakeRange(split_proj) => { + let mut split_proj_owned = (**split_proj).clone(); + visitor.visit_split_proj(arena, &mut split_proj_owned); + *split_proj = arena.alloc(split_proj_owned); + } ExecPathElem::ForAll(dim_compo) => visitor.visit_dim_compo(dim_compo), ExecPathElem::ToWarps => {} ExecPathElem::ToThreads(dim_compo) => visitor.visit_dim_compo(dim_compo), @@ -871,10 +991,16 @@ pub fn walk_fun_def<'a, V: VisitMut<'a>>( visitor.visit_ident_exec(arena, exec_decl); } walk_list!(visitor, visit_param_decl, params, arena); - visitor.visit_dty(arena, ret_dty); + let mut ret_dty_owned = (**ret_dty).clone(); + visitor.visit_dty(arena, &mut ret_dty_owned); + *ret_dty = arena.alloc(ret_dty_owned); + visitor.visit_exec_expr(arena, exec); walk_list!(visitor, visit_prv_rel, prv_rels, arena); - visitor.visit_block(arena, body) + + let mut body_owned = (**body).clone(); + visitor.visit_block(arena, &mut body_owned); + *body = arena.alloc(body_owned); } pub fn walk_fun_decl<'a, V: VisitMut<'a>>( From a3eb9d6275df8a9e46c4968fc9d349502c921386 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 12 Aug 2025 11:21:13 +0200 Subject: [PATCH 44/57] repaired visitor implementation --- src/arena_ast/utils.rs | 176 ++++++++++++++++++++++------------------- src/ast/mod.rs | 28 +++---- 2 files changed, 110 insertions(+), 94 deletions(-) diff --git a/src/arena_ast/utils.rs b/src/arena_ast/utils.rs index 1ec6ff2c..c95fdf28 100644 --- a/src/arena_ast/utils.rs +++ b/src/arena_ast/utils.rs @@ -1,5 +1,6 @@ use crate::arena_ast::visit::walk_list; use crate::arena_ast::visit::Visit; +use crate::arena_ast::visit_mut::walk_list as walk_list_mut; use crate::arena_ast::visit_mut::VisitMut; use crate::arena_ast::{ visit, visit_mut, ArgKinded, BaseExec, DataTy, DataTyKind, Dim, ExecExpr, ExecExprKind, ExecTy, @@ -46,18 +47,21 @@ pub fn implicit_idents<'a>(f: &FunDef<'a>) -> Option>> { } } +// utils.rs (or wherever you define this trait) pub trait VisitableMut<'a> { - fn visit_mut>(&mut self, visitor: &mut V); + fn visit_mut>(&mut self, visitor: &mut V, arena: &'a bumpalo::Bump); } + macro_rules! visitable_mut { ($t:ident, $f:ident) => { impl<'a> VisitableMut<'a> for $t<'a> { - fn visit_mut>(&mut self, visitor: &mut V) { - visitor.$f(self); + fn visit_mut>(&mut self, visitor: &mut V, arena: &'a bumpalo::Bump) { + visitor.$f(arena, self); } } }; } + visitable_mut!(Ty, visit_ty); visitable_mut!(Expr, visit_expr); visitable_mut!(ExecExpr, visit_exec_expr); @@ -71,29 +75,35 @@ visitable_mut!(FnTy, visit_fn_ty); * gen_args: the kinded expressions that are substituting the generic identifiers * t: the term to substitute in */ -pub fn subst_idents_kinded<'a, I, J, T: VisitableMut<'a>>(gen_idents: I, gen_args: J, t: &mut T) -where +pub fn subst_idents_kinded<'a, I, J, T: VisitableMut<'a>>( + arena: &'a bumpalo::Bump, + gen_idents: I, + gen_args: J, + t: &mut T, +) where I: IntoIterator>, J: IntoIterator>, { - let subst_map = HashMap::from_iter( - gen_idents - .into_iter() - .map(|p| p.ident.name.as_ref()) - .zip(gen_args), - ); - let mut subst_idents_kinded = SubstIdentsKinded::new(subst_map); - t.visit_mut(&mut subst_idents_kinded); + let subst_map: HashMap<&'a str, &'a ArgKinded<'a>> = gen_idents + .into_iter() + .map(|p| p.ident.name.as_ref()) + .zip(gen_args) + .collect(); + + let mut v = SubstIdentsKinded::new(&subst_map); + t.visit_mut(&mut v, arena); } pub fn subst_ident_exec<'a, T: VisitableMut<'a>>( + arena: &'a bumpalo::Bump, ident: &'a Ident<'a>, exec: &'a ExecExpr<'a>, t: &mut T, ) { let mut subst_ident_exec = SubstIdentExec::new(ident, exec); - t.visit_mut(&mut subst_ident_exec); + t.visit_mut(&mut subst_ident_exec, arena); } + /* * substitute kinded arguments for free identifiers * @@ -101,32 +111,29 @@ pub fn subst_ident_exec<'a, T: VisitableMut<'a>>( * bound. In order to substitute generic identifiers with their arguments, the relevant generic * identifiers must be removed from the list, first. */ -struct SubstIdentsKinded<'a> { - pub subst_map: HashMap<&'a str, &'a ArgKinded<'a>>, +struct SubstIdentsKinded<'a, 'm> { + pub subst_map: &'m HashMap<&'a str, &'a ArgKinded<'a>>, pub bound_idents: HashSet>, } -impl<'a> SubstIdentsKinded<'a> { - fn new(subst_map: HashMap<&'a str, &'a ArgKinded<'a>>) -> Self { - SubstIdentsKinded { +impl<'a, 'm> SubstIdentsKinded<'a, 'm> { + fn new(subst_map: &'m HashMap<&'a str, &'a ArgKinded<'a>>) -> Self { + Self { subst_map, bound_idents: HashSet::new(), } } - fn with_bound_idents( - subst_map: HashMap<&'a str, &'a ArgKinded<'a>>, - bound_idents: HashSet>, - ) -> Self { - SubstIdentsKinded { - subst_map, + fn with_bound_idents(&self, bound_idents: HashSet>) -> Self { + Self { + subst_map: self.subst_map, bound_idents, } } } -impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { - fn visit_nat(&mut self, nat: &mut Nat<'a>) { +impl<'a, 'm> VisitMut<'a> for SubstIdentsKinded<'a, 'm> { + fn visit_nat(&mut self, arena: &'a bumpalo::Bump, nat: &mut Nat<'a>) { match nat { Nat::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Nat); @@ -138,11 +145,11 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } } } - _ => visit_mut::walk_nat(self, nat), + _ => visit_mut::walk_nat(self, arena, nat), } } - fn visit_mem(&mut self, mem: &mut Memory<'a>) { + fn visit_mem(&mut self, arena: &'a bumpalo::Bump, mem: &mut Memory<'a>) { match mem { Memory::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Memory); @@ -154,11 +161,11 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } } } - _ => visit_mut::walk_mem(self, mem), + _ => visit_mut::walk_mem(self, arena, mem), } } - fn visit_prv(&mut self, prv: &mut Provenance<'a>) { + fn visit_prv(&mut self, arena: &'a bumpalo::Bump, prv: &mut Provenance<'a>) { match prv { Provenance::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::Provenance); @@ -170,11 +177,11 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } } } - _ => visit_mut::walk_prv(self, prv), + _ => visit_mut::walk_prv(self, arena, prv), } } - fn visit_dty(&mut self, dty: &mut DataTy<'a>) { + fn visit_dty(&mut self, arena: &'a bumpalo::Bump, dty: &mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) => { let ident_kinded = IdentKinded::new(ident, Kind::DataTy); @@ -186,67 +193,83 @@ impl<'a> VisitMut<'a> for SubstIdentsKinded<'a> { } } } - _ => visit_mut::walk_dty(self, dty), + _ => visit_mut::walk_dty(self, arena, dty), } } // add generic paramters to list of bound identifiers - fn visit_fn_ty(&mut self, fn_ty: &mut FnTy<'a>) { + fn visit_fn_ty(&mut self, arena: &'a bumpalo::Bump, fn_ty: &mut FnTy<'a>) { let fun_bound_idents = fn_ty.generics.clone(); let mut all_bound_idents = self.bound_idents.clone(); all_bound_idents.extend(fun_bound_idents); let mut visitor_subst_generic_ident = - SubstIdentsKinded::with_bound_idents(self.subst_map, all_bound_idents); - walk_list!( + SubstIdentsKinded::with_bound_idents(self, all_bound_idents); + walk_list_mut!( &mut visitor_subst_generic_ident, visit_param_sig, - &mut fn_ty.param_sigs + &mut fn_ty.param_sigs.as_mut_slice(), + arena ); - for ident_exec in &mut fn_ty.generic_exec { - visitor_subst_generic_ident.visit_exec_ty(&mut ident_exec.ty); + if let Some(ident_exec) = &mut fn_ty.generic_exec { + let mut owned = (*ident_exec.ty).clone(); + self.visit_exec_ty(&mut owned); + ident_exec.ty = arena.alloc(owned); } - visitor_subst_generic_ident.visit_exec_expr(&mut fn_ty.exec); - visitor_subst_generic_ident.visit_ty(&mut fn_ty.ret_ty); + + visitor_subst_generic_ident.visit_exec_expr(arena, &mut fn_ty.exec); + let mut ret_owned = (*fn_ty.ret_ty).clone(); + self.visit_ty(arena, &mut ret_owned); + fn_ty.ret_ty = arena.alloc(ret_owned); } // only required to introduce a new scope of bound identifiers - fn visit_expr(&mut self, expr: &mut Expr<'a>) { + fn visit_expr(&mut self, arena: &'a bumpalo::Bump, expr: &mut Expr<'a>) { match &mut expr.expr { ExprKind::ForNat(ident, collec, body) => { - self.visit_nat_range(collec); + let mut range_owned = (**collec).clone(); + self.visit_nat_range(arena, &mut range_owned); + *collec = arena.alloc(range_owned); let mut scoped_bound_idents = self.bound_idents.clone(); scoped_bound_idents.extend(std::iter::once(IdentKinded::new(ident, Kind::Nat))); let mut subst_inner_kinded_idents = - SubstIdentsKinded::with_bound_idents(self.subst_map, scoped_bound_idents); - subst_inner_kinded_idents.visit_expr(body); + SubstIdentsKinded::with_bound_idents(self, scoped_bound_idents); + let mut body_owned = (**body).clone(); + subst_inner_kinded_idents.visit_expr(arena, &mut body_owned); + *body = arena.alloc(body_owned); } - _ => visit_mut::walk_expr(self, expr), + _ => visit_mut::walk_expr(self, arena, expr), } } // add generic paramters to list of bound identifiers - fn visit_fun_def(&mut self, fun_def: &mut FunDef<'a>) { + fn visit_fun_def(&mut self, arena: &'a bumpalo::Bump, fun_def: &mut FunDef<'a>) { let fun_bound_idents = fun_def.generic_params.clone(); let mut all_bound_idents = self.bound_idents.clone(); all_bound_idents.extend(fun_bound_idents); let mut subst_fun_free_kind_idents = - SubstIdentsKinded::with_bound_idents(self.subst_map, all_bound_idents); - walk_list!( + SubstIdentsKinded::with_bound_idents(self, all_bound_idents); + walk_list_mut!( &mut subst_fun_free_kind_idents, visit_param_decl, - &mut fun_def.param_decls + &mut fun_def.param_decls.as_mut_slice(), + arena ); - subst_fun_free_kind_idents.visit_dty(&mut fun_def.ret_dty); + let mut ret_owned = (*fun_def.ret_dty).clone(); + self.visit_dty(arena, &mut ret_owned); + fun_def.ret_dty = arena.alloc(ret_owned); for ident_exec in &mut fun_def.generic_exec { - subst_fun_free_kind_idents.visit_ident_exec(ident_exec); + subst_fun_free_kind_idents.visit_ident_exec(arena, ident_exec); } - subst_fun_free_kind_idents.visit_exec_expr(&mut fun_def.exec); - walk_list!( + subst_fun_free_kind_idents.visit_exec_expr(arena, &mut fun_def.exec); + walk_list_mut!( subst_fun_free_kind_idents, visit_prv_rel, - &mut fun_def.prv_rels + &mut fun_def.prv_rels.as_mut_slice(), + arena ); - subst_fun_free_kind_idents.visit_block(&mut fun_def.body) + let mut body_owned = (*fun_def.body).clone(); + self.visit_block(arena, &mut body_owned); + fun_def.body = arena.alloc(body_owned); } } @@ -266,22 +289,10 @@ impl<'a> SubstIdentExec<'a> { } impl<'a> VisitMut<'a> for SubstIdentExec<'a> { - fn visit_exec_expr(&mut self, bump: &'a bumpalo::Bump, exec_expr: &mut ExecExpr<'a>) { - insert_for_ident(bump, self.exec, &self.ident, exec_expr) - } -} - -/** -fn insert_for_ident<'a>(exec: &ExecExpr<'a>, ident: &Ident<'a>, in_exec: &mut ExecExpr<'a>) { - if let BaseExec::Ident(i) = &mut in_exec.exec.base { - if i == ident { - let mut subst_exec = exec.clone(); - subst_exec.exec.path.extend(in_exec.exec.path.clone()); - *in_exec = subst_exec; - } + fn visit_exec_expr(&mut self, arena: &'a bumpalo::Bump, exec_expr: &mut ExecExpr<'a>) { + insert_for_ident(arena, self.exec, self.ident, exec_expr) } } -*/ fn insert_for_ident<'a>( bump: &'a bumpalo::Bump, @@ -291,21 +302,26 @@ fn insert_for_ident<'a>( ) { if let BaseExec::Ident(i) = &in_exec.exec.base { if i == ident { - let mut merged_path = exec.exec.path.clone(); - merged_path.extend(in_exec.exec.path.iter().cloned()); + // Build merged path in this arena + let mut merged = bumpalo::collections::Vec::new_in(bump); + merged.extend(exec.exec.path.iter().cloned()); + merged.extend(in_exec.exec.path.iter().cloned()); - let new_exec = bump.alloc(ExecExprKind { + // New exec node allocated in arena + let new_kind = bump.alloc(ExecExprKind { base: exec.exec.base.clone(), - path: merged_path, + path: merged, }); - let new_exec_expr = ExecExpr { - exec: new_exec, - ty: in_exec.ty, + // Keep or drop the cached type (choose one) + // let new_ty = in_exec.ty; // keep it (may be stale) + let new_ty = None; // safer: force re-tycheck later + + *in_exec = ExecExpr { + exec: new_kind, + ty: new_ty, span: in_exec.span, }; - - *in_exec = new_exec_expr; } } } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index e6319197..43cd4307 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -419,8 +419,8 @@ impl Sched { arena_ast::Sched { dim: self.dim.into_arena(), inner_exec_ident: self.inner_exec_ident.map(|id| id.into_arena(arena)), - sched_exec: BumpBox::new_in(self.sched_exec.into_arena(arena), arena), - body: BumpBox::new_in(self.body.into_arena(arena), arena), + sched_exec: arena.alloc(self.sched_exec.into_arena(arena)), + body: arena.alloc(self.body.into_arena(arena)), } } } @@ -533,7 +533,7 @@ impl AppKernel { .iter() .map(|s| arena.alloc_str(s).to_string()) .collect_in(arena), - fun_ident: BumpBox::new_in(self.fun_ident.clone().into_arena(arena), arena), + fun_ident: arena.alloc(self.fun_ident.clone().into_arena(arena)), gen_args: self .gen_args .iter() @@ -675,9 +675,9 @@ impl ExprKind { .map(|a| a.into_arena(arena)) .collect_in(arena), ), - ExprKind::AppKernel(kern) => arena_ast::ExprKind::AppKernel( - bumpalo::boxed::Box::new_in(kern.into_arena(arena), arena), - ), + ExprKind::AppKernel(kern) => { + arena_ast::ExprKind::AppKernel(arena.alloc(kern.into_arena(arena))) + } IfElse(cond, then_, else_) => arena_ast::ExprKind::IfElse( arena.alloc(cond.into_arena(arena)), arena.alloc(then_.into_arena(arena)), @@ -1773,20 +1773,20 @@ impl NatConstr { match self { True => arena_ast::NatConstr::True, Eq(lhs, rhs) => arena_ast::NatConstr::Eq( - bumpalo::boxed::Box::new_in(lhs.into_arena(arena), arena), - bumpalo::boxed::Box::new_in(rhs.into_arena(arena), arena), + arena.alloc(lhs.into_arena(arena)), + arena.alloc(rhs.into_arena(arena)), ), Lt(lhs, rhs) => arena_ast::NatConstr::Lt( - bumpalo::boxed::Box::new_in(lhs.into_arena(arena), arena), - bumpalo::boxed::Box::new_in(rhs.into_arena(arena), arena), + arena.alloc(lhs.into_arena(arena)), + arena.alloc(rhs.into_arena(arena)), ), And(lhs, rhs) => arena_ast::NatConstr::And( - bumpalo::boxed::Box::new_in(lhs.into_arena(arena), arena), - bumpalo::boxed::Box::new_in(rhs.into_arena(arena), arena), + arena.alloc(lhs.into_arena(arena)), + arena.alloc(rhs.into_arena(arena)), ), Or(lhs, rhs) => arena_ast::NatConstr::Or( - bumpalo::boxed::Box::new_in(lhs.into_arena(arena), arena), - bumpalo::boxed::Box::new_in(rhs.into_arena(arena), arena), + arena.alloc(lhs.into_arena(arena)), + arena.alloc(rhs.into_arena(arena)), ), } } From d6af866003c5288924bb8b1c351e872a67626c5d Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 12 Aug 2025 14:06:39 +0200 Subject: [PATCH 45/57] fixed lifetime problems in the arena ast parser --- src/arena_ast/mod.rs | 29 +++++- src/ast/mod.rs | 96 +++++++++---------- src/parser/mod.rs | 215 ++++++++++++++++++++++++++++--------------- src/ty_check/ctxs.rs | 14 +-- 4 files changed, 224 insertions(+), 130 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index e089a25f..aebdc93d 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -27,9 +27,9 @@ impl<'a> CompilUnit<'a> { #[derive(Debug)] pub enum Item<'a> { - FunDef(BumpBox<'a, FunDef<'a>>), - FunDecl(BumpBox<'a, FunDecl<'a>>), - StructDecl(BumpBox<'a, StructDecl<'a>>), + FunDef(&'a FunDef<'a>), + FunDecl(&'a FunDecl<'a>), + StructDecl(&'a StructDecl<'a>), } #[derive(Debug, PartialEq)] @@ -68,6 +68,29 @@ impl<'a> FunDecl<'a> { [], ) } + + pub fn clone_in(&self, arena: &'a bumpalo::Bump) -> FunDecl<'a> { + let mut generic_params = BumpVec::new_in(arena); + generic_params.extend(self.generic_params.iter().cloned()); + + let generic_exec = self.generic_exec.clone(); + + let mut param_decls = BumpVec::new_in(arena); + param_decls.extend(self.param_decls.iter().cloned()); + + let mut prv_rels = BumpVec::new_in(arena); + prv_rels.extend(self.prv_rels.iter().cloned()); + + FunDecl { + ident: self.ident.clone(), + generic_params, + generic_exec, + param_decls, + ret_dty: self.ret_dty, // copy pointer; visitor will re-point if needed + exec: self.exec.clone(), + prv_rels, + } + } } #[derive(Debug, Clone, Eq, Hash, PartialEq)] diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 43cd4307..ae75dfdd 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -6,7 +6,7 @@ pub use span::*; use crate::arena_ast; use crate::parser::SourceCode; -use bumpalo::{boxed::Box as BumpBox, collections::CollectIn, collections::Vec as BumpVec, Bump}; +use bumpalo::{collections::CollectIn, collections::Vec as BumpVec, Bump}; pub mod internal; @@ -36,19 +36,19 @@ pub enum Item { } impl Item { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Item<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::Item<'a> { match self { Item::FunDef(f) => { let arena_f = f.into_arena(arena); - arena_ast::Item::FunDef(BumpBox::new_in(arena_f, arena)) + arena_ast::Item::FunDef(arena.alloc(arena_f)) } Item::FunDecl(f) => { let arena_fd = f.into_arena(arena); - arena_ast::Item::FunDecl(BumpBox::new_in(arena_fd, arena)) + arena_ast::Item::FunDecl(arena.alloc(arena_fd)) } Item::StructDecl(s) => { let arena_s = s.into_arena(arena); - arena_ast::Item::StructDecl(BumpBox::new_in(arena_s, arena)) + arena_ast::Item::StructDecl(arena.alloc(arena_s)) } } } @@ -87,7 +87,7 @@ impl FunDecl { } } - pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::FunDecl<'a> { + pub fn into_arena<'a>(self: Box, arena: &'a Bump) -> arena_ast::FunDecl<'a> { let generic_params = self .generic_params .into_iter() @@ -126,7 +126,7 @@ pub struct StructDecl { } impl StructDecl { - pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::StructDecl<'a> { + pub fn into_arena<'a>(self: Box, arena: &'a Bump) -> arena_ast::StructDecl<'a> { let generic_params = self .generic_params .into_iter() @@ -182,7 +182,7 @@ impl FunDef { } } - pub fn into_arena<'a>(self: Box, arena: &'a bumpalo::Bump) -> arena_ast::FunDef<'a> { + pub fn into_arena<'a>(self: Box, arena: &'a Bump) -> arena_ast::FunDef<'a> { let generic_params = self .generic_params .into_iter() @@ -234,7 +234,7 @@ impl IdentExec { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::IdentExec<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::IdentExec<'a> { arena_ast::IdentExec { ident: self.ident.into_arena(arena), ty: arena.alloc(self.ty.into_arena(arena)), @@ -251,7 +251,7 @@ pub struct ParamDecl { } impl ParamDecl { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ParamDecl<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::ParamDecl<'a> { let ty = self.ty.map(|t| &*arena.alloc(t.into_arena(arena))); let exec_expr = self .exec_expr @@ -302,7 +302,7 @@ impl Expr { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Expr<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::Expr<'a> { arena_ast::Expr { expr: self.expr.into_arena(arena), ty: self.ty.map(|t| &*arena.alloc(t.into_arena(arena))), @@ -415,7 +415,7 @@ impl Sched { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Sched<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::Sched<'a> { arena_ast::Sched { dim: self.dim.into_arena(), inner_exec_ident: self.inner_exec_ident.map(|id| id.into_arena(arena)), @@ -451,7 +451,7 @@ impl Split { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Split<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::Split<'a> { let mut branch_idents = bumpalo::collections::Vec::new_in(arena); branch_idents.extend( self.branch_idents @@ -490,7 +490,7 @@ impl Block { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Block<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::Block<'a> { let prvs: bumpalo::collections::Vec<'a, String> = self.prvs.into_iter().collect_in(arena); arena_ast::Block { @@ -519,7 +519,7 @@ pub struct AppKernel { } impl AppKernel { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::AppKernel<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::AppKernel<'a> { arena_ast::AppKernel { grid_dim: self.grid_dim.into_arena(arena), block_dim: self.block_dim.into_arena(arena), @@ -607,7 +607,7 @@ pub enum ExprKind { } impl ExprKind { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExprKind<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::ExprKind<'a> { use ExprKind::*; match self { Hole => arena_ast::ExprKind::Hole, @@ -761,7 +761,7 @@ impl Ident { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Ident<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::Ident<'a> { arena_ast::Ident { name: arena.alloc_str(&self.name), span: self.span, @@ -778,7 +778,7 @@ pub enum Pattern { } impl Pattern { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Pattern<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::Pattern<'a> { use Pattern::*; match self { Ident(mutability, ident) => { @@ -807,7 +807,7 @@ pub enum Lit { } impl Lit { - pub fn into_arena<'a>(&self, _arena: &'a bumpalo::Bump) -> arena_ast::Lit { + pub fn into_arena<'a>(&self, _arena: &'a Bump) -> arena_ast::Lit { use arena_ast::Lit as ALit; use Lit::*; @@ -996,7 +996,7 @@ pub enum Kind { } impl Kind { - pub fn into_arena(&self, _arena: &bumpalo::Bump) -> arena_ast::Kind { + pub fn into_arena(&self, _arena: &Bump) -> arena_ast::Kind { match self { Kind::Nat => arena_ast::Kind::Nat, Kind::Memory => arena_ast::Kind::Memory, @@ -1039,7 +1039,7 @@ impl ArgKinded { } } - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::ArgKinded<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::ArgKinded<'a> { use ArgKinded::*; match self { @@ -1064,7 +1064,7 @@ pub struct PlaceExpr { } impl PlaceExpr { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::PlaceExpr<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::PlaceExpr<'a> { arena_ast::PlaceExpr { pl_expr: self.pl_expr.into_arena(arena), ty: self.ty.map(|t| &*arena.alloc(t.into_arena(arena))), @@ -1104,7 +1104,7 @@ impl View { Ok(true) } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::View<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::View<'a> { let gen_args = self .gen_args .into_iter() @@ -1156,7 +1156,7 @@ pub enum PlaceExprKind { } impl PlaceExprKind { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::PlaceExprKind<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::PlaceExprKind<'a> { use PlaceExprKind::*; match self { @@ -1351,7 +1351,7 @@ impl ExecExpr { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExecExpr<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::ExecExpr<'a> { arena_ast::ExecExpr { exec: arena.alloc(self.exec.into_arena(arena)), ty: self.ty.map(|t| { @@ -1488,7 +1488,7 @@ impl TakeRange { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::TakeRange<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::TakeRange<'a> { arena_ast::TakeRange { split_dim: self.split_dim.into_arena(), pos: self.pos.into_arena(arena), @@ -1534,7 +1534,7 @@ impl ExecExprKind { None } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExecExprKind<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::ExecExprKind<'a> { let path = bumpalo::collections::Vec::from_iter_in( self.path.into_iter().map(|elem| elem.into_arena(arena)), arena, @@ -1555,7 +1555,7 @@ pub enum BaseExec { } impl BaseExec { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::BaseExec<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::BaseExec<'a> { use BaseExec::*; match self { Ident(ident) => arena_ast::BaseExec::Ident(ident.into_arena(arena)), @@ -1576,7 +1576,7 @@ pub enum ExecPathElem { } impl ExecPathElem { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExecPathElem<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::ExecPathElem<'a> { use ExecPathElem::*; match self { @@ -1611,7 +1611,7 @@ impl ExecTy { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ExecTy<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::ExecTy<'a> { arena_ast::ExecTy { ty: self.ty.into_arena(arena), span: self.span, @@ -1634,7 +1634,7 @@ pub enum ExecTyKind { } impl ExecTyKind { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::ExecTyKind<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::ExecTyKind<'a> { use ExecTyKind::*; match self { @@ -1668,7 +1668,7 @@ pub struct Ty { } impl Ty { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::Ty<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::Ty<'a> { arena_ast::Ty { ty: self.ty.into_arena(arena), span: self.span, @@ -1687,7 +1687,7 @@ impl ParamSig { ParamSig { exec_expr, ty } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::ParamSig<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::ParamSig<'a> { let ty = self.ty.into_arena(arena); arena_ast::ParamSig { exec_expr: self.exec_expr.into_arena(arena), @@ -1725,7 +1725,7 @@ impl FnTy { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::FnTy<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::FnTy<'a> { let generics = self .generics .into_iter() @@ -1767,7 +1767,7 @@ pub enum NatConstr { } impl NatConstr { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::NatConstr<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::NatConstr<'a> { use NatConstr::*; match self { @@ -1800,7 +1800,7 @@ pub enum TyKind { } impl TyKind { - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::TyKind<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::TyKind<'a> { match self { TyKind::Data(dty) => { let boxed = bumpalo::boxed::Box::new_in(dty.into_arena(arena), arena); @@ -1920,7 +1920,7 @@ impl Dim { } } - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Dim<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::Dim<'a> { use Dim::*; match self { @@ -1984,7 +1984,7 @@ impl DataTy { } } - pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::DataTy<'a> { + pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::DataTy<'a> { arena_ast::DataTy { dty: self.dty.into_arena(arena), constraints: self @@ -2166,7 +2166,7 @@ impl RefDty { } } - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::RefDty<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::RefDty<'a> { arena_ast::RefDty { rgn: self.rgn.into_arena(arena), own: self.own.into_arena(), @@ -2196,7 +2196,7 @@ pub enum DataTyKind { } impl DataTyKind { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::DataTyKind<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::DataTyKind<'a> { use DataTyKind::*; match self { @@ -2298,7 +2298,7 @@ pub enum Provenance { } impl Provenance { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Provenance<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::Provenance<'a> { match self { Provenance::Value(s) => arena_ast::Provenance::Value(arena.alloc_str(s)), Provenance::Ident(ident) => { @@ -2318,7 +2318,7 @@ pub enum Memory { } impl Memory { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Memory<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::Memory<'a> { match self { Memory::CpuMem => arena_ast::Memory::CpuMem, Memory::GpuGlobal => arena_ast::Memory::GpuGlobal, @@ -2336,7 +2336,7 @@ pub struct PrvRel { } impl PrvRel { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::PrvRel<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::PrvRel<'a> { arena_ast::PrvRel { longer: self.longer.clone().into_arena(arena), shorter: self.shorter.clone().into_arena(arena), @@ -2358,7 +2358,7 @@ impl IdentKinded { } } - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::IdentKinded<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::IdentKinded<'a> { arena_ast::IdentKinded { ident: self.ident.clone().into_arena(arena), kind: self.kind.into_arena(arena), @@ -2393,7 +2393,7 @@ impl NatRange { Ok(range_iter) } - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::NatRange<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::NatRange<'a> { use NatRange::*; match self { @@ -2520,7 +2520,7 @@ pub struct NatEvalError { } impl NatEvalError { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::NatEvalError<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::NatEvalError<'a> { arena_ast::NatEvalError { unevaluable: self.unevaluable.clone().into_arena(arena), } @@ -2531,13 +2531,13 @@ pub type NatEvalResult = Result; fn convert_result<'a>( result: NatEvalResult, - arena: &'a bumpalo::Bump, + arena: &'a Bump, ) -> arena_ast::NatEvalResult<'a, usize> { result.map_err(|e| e.into_arena(arena)) } impl Nat { - pub fn into_arena<'a>(&self, arena: &'a bumpalo::Bump) -> arena_ast::Nat<'a> { + pub fn into_arena<'a>(&self, arena: &'a Bump) -> arena_ast::Nat<'a> { use Nat::*; match self { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index b28fa9ed..bd892ccf 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7,6 +7,7 @@ use crate::arena_ast::visit_mut::VisitMut as ArenaVisitMut; use crate::arena_ast::AppKernel as ArenaAppKernel; use crate::arena_ast::ArgKinded as ArenaArgKinded; use crate::arena_ast::BaseExec as ArenaBaseExec; +use crate::arena_ast::Block as ArenaBlock; use crate::arena_ast::CompilUnit as ArenaCompilUnit; use crate::arena_ast::DataTy as ArenaDataTy; use crate::arena_ast::DataTyKind as ArenaDataTyKind; @@ -45,39 +46,36 @@ pub fn parse<'a>( let parser = Parser::new(source); let heap_items = parser.parse().map_err(|err| err.emit())?; - // Step 1: Convert heap AST -> arena AST - let mut arena_items = BumpVec::new_in(arena); - for heap_item in heap_items { - arena_items.push(heap_item.into_arena(arena)) // into arena will be the converter - } + // 1) heap -> arena, collect &'a StructDecl while we build the vec + let mut arena_items: bumpalo::collections::Vec<'a, ArenaItem<'a>> = + bumpalo::collections::Vec::new_in(arena); + let mut struct_refs: Vec<&'a ArenaStructDecl<'a>> = Vec::new(); - // Step 2: Postprocess - // TODO refactor to not require unnecessary copying out of items - let struct_copies = arena_items - .iter() - .filter_map(|i| { - if let ArenaItem::StructDecl(struct_dty) = i { - Some(struct_dty.as_ref()) - } else { - None + for heap_item in heap_items { + match heap_item.into_arena(arena) { + ArenaItem::StructDecl(sd_ref) => { + struct_refs.push(sd_ref); + arena_items.push(ArenaItem::StructDecl(sd_ref)); } - }) - .cloned() - .collect::>(); + other => { + arena_items.push(other); + } + } + } - for fun_def in arena_items.iter_mut().filter_map(|i| { - if let ArenaItem::FunDef(fun_def) = i { - Some(fun_def) - } else { - None + // 2) mutate fun defs (safe; we’re not holding borrows into arena_items) + for item in arena_items.iter_mut() { + if let ArenaItem::FunDef(fun_def) = item { + let mut fun_def_owned = (**fun_def).clone(); + replace_arg_kinded_idents(&mut fun_def_owned, arena); + replace_exec_idents_with_specific_execs(arena, &mut fun_def_owned); + *fun_def = arena.alloc(fun_def_owned); } - }) { - replace_arg_kinded_idents(fun_def); - replace_exec_idents_with_specific_execs(arena, fun_def); } - for i in &mut arena_items.iter_mut() { - replace_struct_idents_with_specific_struct_dtys(&struct_copies, i); + // 3) resolve struct idents using the collected &'a decls + for item in arena_items.iter_mut() { + replace_struct_idents_with_specific_struct_dtys(arena, &struct_refs, item); } Ok(ArenaCompilUnit::new(arena_items, source)) @@ -98,7 +96,7 @@ impl<'a> Parser<'a> { } } -fn replace_arg_kinded_idents<'a>(fun_def: &mut ArenaFunDef) { +fn replace_arg_kinded_idents<'a>(fun_def: &mut ArenaFunDef<'a>, arena: &'a Bump) { struct ReplaceArgKindedIdents { ident_names_to_kinds: HashMap, ArenaKind>, } @@ -135,56 +133,112 @@ fn replace_arg_kinded_idents<'a>(fun_def: &mut ArenaFunDef) { } impl<'a> ArenaVisitMut<'a> for ReplaceArgKindedIdents { - fn visit_expr(&mut self, arena: &'a Bump, expr: &mut ArenaExpr) { + fn visit_expr(&mut self, arena: &'a Bump, expr: &mut ArenaExpr<'a>) { match &mut expr.expr { - ArenaExprKind::Block(block) => { - self.ident_names_to_kinds.extend( - block - .prvs - .iter() - .map(|prv| (prv.clone().into_boxed_str(), ArenaKind::Provenance)), - ); - self.visit_expr(&mut block.body) + ArenaExprKind::Block(block_ref) => { + let src = *block_ref; + + let added_keys: Vec> = src + .prvs + .iter() + .map(|p| p.clone().into_boxed_str()) + .collect(); + for k in &added_keys { + self.ident_names_to_kinds + .insert(k.clone(), ArenaKind::Provenance); + } + + let mut body_owned = (*src.body).clone(); + self.visit_expr(arena, &mut body_owned); + let body_ref = arena.alloc(body_owned); + + let mut new_prvs = BumpVec::new_in(arena); + new_prvs.extend(src.prvs.iter().cloned()); + + let new_block = ArenaBlock { + prvs: new_prvs, + body: body_ref, + }; + + *block_ref = arena.alloc(new_block); + + for k in added_keys { + self.ident_names_to_kinds.remove(k.as_ref()); + } } ArenaExprKind::DepApp(fun_ident, gen_args) => { - self.visit_ident(fun_ident); + self.visit_ident(arena, fun_ident); self.subst_in_gen_args(arena, gen_args); } - ArenaExprKind::AppKernel(app_kernel) => { - let ArenaAppKernel { - fun_ident, + ArenaExprKind::AppKernel(app_kernel_ref) => { + let src = *app_kernel_ref; + let mut grid_dim = src.grid_dim.clone(); + let mut block_dim = src.block_dim.clone(); + self.visit_dim(arena, &mut grid_dim); + self.visit_dim(arena, &mut block_dim); + let mut fun_ident_owned = (*src.fun_ident).clone(); + self.visit_ident(arena, &mut fun_ident_owned); + let fun_ident_ref = arena.alloc(fun_ident_owned); + + let mut gen_args = BumpVec::new_in(arena); + gen_args.extend(src.gen_args.iter().cloned()); + self.subst_in_gen_args(arena, gen_args.as_mut_slice()); + + let mut args = BumpVec::new_in(arena); + for mut e in src.args.iter().cloned() { + self.visit_expr(arena, &mut e); + args.push(e); + } + + let mut shared_mem_dtys = BumpVec::new_in(arena); + for mut d in src.shared_mem_dtys.iter().cloned() { + self.visit_dty(arena, &mut d); + shared_mem_dtys.push(d); + } + + let mut shared_mem_prvs = BumpVec::new_in(arena); + shared_mem_prvs.extend(src.shared_mem_prvs.iter().cloned()); + + let new_node = ArenaAppKernel { + grid_dim, + block_dim, + shared_mem_dtys, + shared_mem_prvs, + fun_ident: fun_ident_ref, gen_args, args, - .. - } = app_kernel.as_mut(); - self.visit_ident(fun_ident); - self.subst_in_gen_args(arena, gen_args); - arena_visit_mut::walk_list!(self, visit_expr, args) + }; + *app_kernel_ref = arena.alloc(new_node); } + ArenaExprKind::App(fun_ident, gen_args, args) => { - self.visit_ident(fun_ident); + let mut fun_ident_owned = (**fun_ident).clone(); + self.visit_ident(arena, &mut fun_ident_owned); + *fun_ident = arena.alloc(fun_ident_owned); self.subst_in_gen_args(arena, gen_args); - arena_visit_mut::walk_list!(self, visit_expr, args) + arena_visit_mut::walk_list!(self, visit_expr, args, arena) } ArenaExprKind::ForNat(ident, _, body) => { self.ident_names_to_kinds.extend(iter::once(( ident.name.to_owned().into_boxed_str(), ArenaKind::Nat, ))); - self.visit_expr(body) + let mut body_owned = (**body).clone(); + self.visit_expr(arena, &mut body_owned); + *body = arena.alloc(body_owned); } - _ => arena_visit_mut::walk_expr(self, expr), + _ => arena_visit_mut::walk_expr(self, arena, expr), } } - fn visit_view(&mut self, arena: &'a Bump, view: &mut ArenaView) { + fn visit_view(&mut self, arena: &'a Bump, view: &mut ArenaView<'a>) { self.subst_in_gen_args(arena, &mut view.gen_args); for v in &mut view.args { - self.visit_view(v) + self.visit_view(arena, v) } } - fn visit_fun_def(&mut self, fun_def: &mut ArenaFunDef) { + fn visit_fun_def(&mut self, arena: &'a Bump, fun_def: &mut ArenaFunDef<'a>) { self.ident_names_to_kinds = fun_def .generic_params .iter() @@ -192,13 +246,13 @@ fn replace_arg_kinded_idents<'a>(fun_def: &mut ArenaFunDef) { (ident.name.to_owned().into_boxed_str(), *kind) }) .collect(); - arena_visit_mut::walk_fun_def(self, fun_def) + arena_visit_mut::walk_fun_def(self, arena, fun_def) } } let mut replace = ReplaceArgKindedIdents { ident_names_to_kinds: HashMap::new(), }; - replace.visit_fun_def(fun_def); + replace.visit_fun_def(arena, fun_def); } fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut ArenaFunDef<'a>) { @@ -233,7 +287,7 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Ar ); self.ident_names_to_exec_expr .push((ident.name.to_owned().into_boxed_str(), branch_exec_expr)); - self.visit_expr(branch); + self.visit_expr(arena, branch); self.ident_names_to_exec_expr.pop(); } } @@ -247,7 +301,7 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Ar self.ident_names_to_exec_expr .push((ident.name.to_owned().into_boxed_str(), body_exec)); } - arena_visit_mut::walk_sched(self, sched); + arena_visit_mut::walk_sched(self, arena, sched); self.ident_names_to_exec_expr.pop(); // self.visit_block(&mut sched.body); } @@ -285,7 +339,7 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Ar _ => {} } } - arena_visit_mut::walk_fun_def(self, fun_def) + arena_visit_mut::walk_fun_def(self, arena, fun_def) } } @@ -345,32 +399,47 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Ar let mut replace_exec_idents = ReplaceExecIdents { ident_names_to_exec_expr: vec![], }; - replace_exec_idents.visit_fun_def(fun_def); + replace_exec_idents.visit_fun_def(arena, fun_def); } -fn replace_struct_idents_with_specific_struct_dtys<'a>( - struct_dtys: &[ArenaStructDecl<'a>], - item: &mut ArenaItem, +fn replace_struct_idents_with_specific_struct_dtys<'a, 's>( + arena: &'a bumpalo::Bump, + struct_dtys: &'s [&'a ArenaStructDecl<'a>], // outer borrow 's, elements 'a + item: &mut ArenaItem<'a>, ) { - struct ReplaceStructIdents<'a> { - struct_dtys: &'a [ArenaStructDecl<'a>], + struct ReplaceStructIdents<'s, 'a> { + struct_dtys: &'s [&'a ArenaStructDecl<'a>], } - impl<'a> ArenaVisitMut<'a> for ReplaceStructIdents<'a> { - fn visit_dty(&mut self, dty: &mut ArenaDataTy<'a>) { + + impl<'s, 'a> ArenaVisitMut<'a> for ReplaceStructIdents<'s, 'a> { + fn visit_dty(&mut self, arena: &'a bumpalo::Bump, dty: &mut ArenaDataTy<'a>) { if let ArenaDataTyKind::Ident(ident) = &mut dty.dty { - if let Some(struct_decl) = self.struct_dtys.iter().find(|s| &s.ident == ident) { - dty.dty = ArenaDataTyKind::Struct(struct_decl) + if let Some(sd) = self + .struct_dtys + .iter() + .copied() // &&T -> &T + .find(|sd| &sd.ident == ident) + { + dty.dty = ArenaDataTyKind::Struct(sd); + return; } - } else { - arena_visit_mut::walk_dty(self, dty) } + arena_visit_mut::walk_dty(self, arena, dty) } } - let mut replace_struct_idents = ReplaceStructIdents { struct_dtys }; + let mut v = ReplaceStructIdents { struct_dtys }; match item { - ArenaItem::FunDef(fun_def) => replace_struct_idents.visit_fun_def(fun_def), - ArenaItem::FunDecl(fun_decl) => replace_struct_idents.visit_fun_decl(fun_decl), + ArenaItem::FunDef(fd) => { + let mut fd_owned = (**fd).clone(); + v.visit_fun_def(arena, &mut fd_owned); + *fd = arena.alloc(fd_owned); + } + ArenaItem::FunDecl(fd) => { + let mut fd_owned = (**fd).clone_in(arena); + v.visit_fun_decl(arena, &mut fd_owned); + *fd = arena.alloc(fd_owned); + } _ => {} } } diff --git a/src/ty_check/ctxs.rs b/src/ty_check/ctxs.rs index 815c1e0e..9689f9e0 100644 --- a/src/ty_check/ctxs.rs +++ b/src/ty_check/ctxs.rs @@ -4,7 +4,7 @@ use crate::arena_ast::internal::{ use crate::arena_ast::*; use crate::ty_check::error::CtxError; use bumpalo::collections::CollectIn; -use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; +use bumpalo::{collections::Vec as BumpVec, Bump}; use std::collections::HashSet; // TODO introduce proper struct @@ -720,15 +720,17 @@ impl<'a> GlobalCtx<'a> { pub fn push_fun_checked_under_nats( &mut self, - fun_def: BumpBox<'a, FunDef<'a>>, + arena: &'a bumpalo::Bump, + fun_def_owned: FunDef<'a>, // take by value nat_vals: &'a [usize], ) { - let fun_name = fun_def.ident.name.clone(); - self.compil_unit.items.push(Item::FunDef(fun_def)); - self.checked_funs.push((fun_name, nat_vals)) + let fun_name = fun_def_owned.ident.name.clone(); + let fd_ref: &'a FunDef<'a> = arena.alloc(fun_def_owned); + self.compil_unit.items.push(Item::FunDef(fd_ref)); + self.checked_funs.push((fun_name, nat_vals)); } - pub fn pop_fun_def(&mut self, name: &'a str) -> Option>> { + pub fn pop_fun_def(&mut self, name: &'a str) -> Option<&'a FunDef<'a>> { let index = self.compil_unit.items.iter().position(|item| { if let Item::FunDef(fun_def) = item { fun_def.ident.name == name From 733cf23648bb6009ce96c674bd799c1ece49dc2c Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 12 Aug 2025 14:22:14 +0200 Subject: [PATCH 46/57] fixed subtyping --- src/ty_check/subty.rs | 45 ++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/ty_check/subty.rs b/src/ty_check/subty.rs index b3eb6c07..94272a1a 100644 --- a/src/ty_check/subty.rs +++ b/src/ty_check/subty.rs @@ -1,5 +1,5 @@ use super::ctxs::{KindCtx, TyCtx}; -use crate::arena_ast::{self, internal::Loan}; +use crate::arena_ast::internal::Loan; // // Subtyping and Provenance Subtyping from Oxide @@ -7,17 +7,17 @@ use crate::arena_ast::{self, internal::Loan}; use super::error::{CtxError, SubTyError}; use crate::arena_ast::*; -use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; +use bumpalo::Bump; use std::collections::HashSet; type SubTyResult<'a, T> = Result>; -// FIXME respect memory alaways, somehow provenances can be different is this correct? +// FIXME respect memory always, somehow provenances can be different is this correct? // τ1 is subtype of τ2 under Δ and Γ, producing Γ′ // Δ; Γ ⊢ τ1 ≲ τ2 ⇒ Γ′ -pub(super) fn check<'a>( +pub(super) fn check<'m, 'a>( kind_ctx: &'a KindCtx<'a>, - ty_ctx: &'a mut TyCtx<'a>, + ty_ctx: &'m mut TyCtx<'a>, sub_dty: &'a DataTy<'a>, super_dty: &'a DataTy<'a>, arena: &'a Bump, @@ -72,9 +72,9 @@ pub(super) fn check<'a>( // ρ1 outlives ρ2 under Δ and Γ, producing Γ′ // Δ; Γ ⊢ ρ1 :> ρ2 ⇒ Γ′ -fn outlives<'a>( +pub(super) fn outlives<'m, 'a>( kind_ctx: &'a KindCtx<'a>, - ty_ctx: &'a mut TyCtx<'a>, + ty_ctx: &'m mut TyCtx<'a>, longer_prv: &'a Provenance<'a>, shorter_prv: &'a Provenance<'a>, arena: &'a Bump, @@ -112,8 +112,8 @@ fn outlives<'a>( // OL-LocalProvenances // Δ; Γ ⊢ r1 :> r2 ⇒ Γ[r2 ↦→ { Γ(r1) ∪ Γ(r2) }] -fn outl_check_val_prvs<'a>( - ty_ctx: &'a mut TyCtx<'a>, +fn outl_check_val_prvs<'m, 'a>( + ty_ctx: &'m mut TyCtx<'a>, longer: &str, shorter: &str, arena: &'a Bump, @@ -142,7 +142,11 @@ fn outl_check_val_prvs<'a>( Ok(()) } -fn longer_occurs_before_shorter<'a>(ty_ctx: &'a TyCtx<'a>, longer: &str, shorter: &str) -> bool { +fn longer_occurs_before_shorter<'m, 'a>( + ty_ctx: &'m TyCtx<'a>, + longer: &str, + shorter: &str, +) -> bool { for prv in ty_ctx .prv_mappings() .map(|prv_mappings| prv_mappings.prv.clone()) @@ -156,7 +160,7 @@ fn longer_occurs_before_shorter<'a>(ty_ctx: &'a TyCtx<'a>, longer: &str, shorter panic!("Neither provenance found in typing context") } -fn exists_deref_loan_with_prv<'a>(ty_ctx: &'a TyCtx<'a>, prv: &str, arena: &'a Bump) -> bool { +fn exists_deref_loan_with_prv<'m, 'a>(ty_ctx: &'m TyCtx<'a>, prv: &str, arena: &'a Bump) -> bool { ty_ctx .all_places(arena) .into_iter() @@ -179,8 +183,8 @@ fn exists_deref_loan_with_prv<'a>(ty_ctx: &'a TyCtx<'a>, prv: &str, arena: &'a B }) } -fn outl_check_val_ident_prv<'a>( - ty_ctx: &'a TyCtx<'a>, +fn outl_check_val_ident_prv<'m, 'a>( + ty_ctx: &'m TyCtx<'a>, longer_val: &str, arena: &'a Bump, ) -> SubTyResult<'a, ()> { @@ -195,8 +199,8 @@ fn outl_check_val_ident_prv<'a>( } // FIXME Makes no sense! -fn borrowed_pl_expr_no_ref_to_existing_pl<'a>( - ty_ctx: &'a TyCtx<'a>, +fn borrowed_pl_expr_no_ref_to_existing_pl<'m, 'a>( + ty_ctx: &'m TyCtx<'a>, loan_set: &HashSet>, arena: &'a Bump, ) -> bool { @@ -206,9 +210,9 @@ fn borrowed_pl_expr_no_ref_to_existing_pl<'a>( .any(|(pl, _)| loan_set.iter().any(|loan| loan.place_expr.equiv(arena, pl))) } -fn outl_check_ident_val_prv<'a>( +fn outl_check_ident_val_prv<'m, 'a>( kind_ctx: &'a KindCtx<'a>, - ty_ctx: &'a TyCtx<'a>, + ty_ctx: &'m TyCtx<'a>, longer_ident: &'a Ident<'a>, shorter_val: &str, ) -> SubTyResult<'a, ()> { @@ -226,17 +230,18 @@ fn outl_check_ident_val_prv<'a>( } // Δ; Γ ⊢ List[ρ1 :> ρ2] ⇒ Γ′ -pub(super) fn multiple_outlives<'a, I>( +pub(super) fn multiple_outlives<'m, 'a, I>( kind_ctx: &'a KindCtx<'a>, - ty_ctx: &'a mut TyCtx<'a>, + ty_ctx: &'m mut TyCtx<'a>, prv_rels: I, + arena: &'a Bump, ) -> SubTyResult<'a, ()> where I: IntoIterator, &'a Provenance<'a>)>, { for prv_rel in prv_rels { let (longer, shorter) = prv_rel; - outlives(kind_ctx, ty_ctx, longer, shorter)?; + outlives(kind_ctx, ty_ctx, longer, shorter, arena)?; } Ok(()) } From 1b60d766e23e9c24f5b31cd96e9a8873b303ad58 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 12 Aug 2025 14:57:23 +0200 Subject: [PATCH 47/57] fixed infer_kinded_args --- src/ty_check/infer_kinded_args.rs | 89 +++++++++++++++++-------------- 1 file changed, 49 insertions(+), 40 deletions(-) diff --git a/src/ty_check/infer_kinded_args.rs b/src/ty_check/infer_kinded_args.rs index a9bda6fa..03ee2bd1 100644 --- a/src/ty_check/infer_kinded_args.rs +++ b/src/ty_check/infer_kinded_args.rs @@ -15,28 +15,39 @@ pub fn infer_kinded_args<'a>( mono_fn_ty: &'a FnTy<'a>, ) -> TyResult<'a, Vec>> { if poly_fn_ty.param_sigs.len() != mono_fn_ty.param_sigs.len() { - panic!("Unexpected difference in amount of paramters.") + panic!("Unexpected difference in amount of parameters."); } - let mut res_map = HashMap::new(); - for (subst_ty, mono_ty) in poly_fn_ty.param_sigs.iter().zip(&mono_fn_ty.param_sigs) { - infer_kargs_param_sig(&mut res_map, subst_ty, mono_ty) + + // Map each generic Ident -> inferred ArgKinded + let mut res_map: HashMap<&'a Ident<'a>, ArgKinded<'a>> = HashMap::new(); + + // 1) from param sigs + for (subst_ps, mono_ps) in poly_fn_ty.param_sigs.iter().zip(&mono_fn_ty.param_sigs) { + infer_kargs_param_sig(&mut res_map, subst_ps, mono_ps); } + + // 2) from exec expr infer_kargs_exec_expr(&mut res_map, &poly_fn_ty.exec, &mono_fn_ty.exec); - infer_kargs_tys(&mut res_map, &poly_fn_ty.ret_ty, &mono_fn_ty.ret_ty); - let mut res_vec = Vec::new(); - for gen_arg in &poly_fn_ty.generics { - // FIXME unwrap leads to panic when the value for ident could not be inferred - // as does happen when the identifier is not used in the argument type or part of - // an expression in the case of nats - if let Some(res_karg) = res_map.get(&gen_arg.ident) { - if gen_arg.kind != res_karg.kind() { - panic!("Unexpected: Kinds of identifier and argument do not match.") + + // 3) from return type + infer_kargs_tys(&mut res_map, poly_fn_ty.ret_ty, mono_fn_ty.ret_ty); + + // 4) build result vector in the order of generics + let mut res_vec = Vec::with_capacity(poly_fn_ty.generics.len()); + for g in &poly_fn_ty.generics { + match res_map.remove(&g.ident) { + Some(arg) => { + if g.kind != arg.kind() { + panic!("Unexpected: Kinds of identifier and argument do not match."); + } + res_vec.push(arg); + } + None => { + return Err(TyError::CannotInferGenericArg(g.ident.clone())); } - res_vec.push(res_karg.clone()); - } else { - return Err(TyError::CannotInferGenericArg(gen_arg.ident.clone())); } } + Ok(res_vec) } @@ -51,7 +62,7 @@ macro_rules! infer_from_lists { macro_rules! insert_checked { ($map: expr, $constr: path, $id_ref: expr, $mono_ref: expr) => {{ let arg_kinded = $constr($mono_ref.clone()); - if let Some(old) = $map.insert($id_ref.clone(), arg_kinded.clone()) { + if let Some(old) = $map.insert($id_ref, arg_kinded.clone()) { if old != arg_kinded { println!("old: {:?}", old); println!("new: {:?}", arg_kinded); @@ -75,8 +86,8 @@ macro_rules! panic_if_neq { }; } -fn infer_kargs_tys<'a>( - map: &mut HashMap, ArgKinded<'a>>, +fn infer_kargs_tys<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_ty: &'a Ty<'a>, mono_ty: &'a Ty<'a>, ) { @@ -102,8 +113,8 @@ fn infer_kargs_tys<'a>( } } -fn infer_kargs_param_sig<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_param_sig<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_param_sig: &'a ParamSig<'a>, mono_param_sig: &'a ParamSig<'a>, ) { @@ -111,8 +122,8 @@ fn infer_kargs_param_sig<'a>( infer_kargs_tys(map, &poly_param_sig.ty, &mono_param_sig.ty); } -fn infer_kargs_exec_expr<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_exec_expr<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_exec_expr: &'a ExecExpr<'a>, mono_exec_expr: &'a ExecExpr<'a>, ) { @@ -127,8 +138,8 @@ fn infer_kargs_exec_expr<'a>( } } -fn infer_kargs_exec_level<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_exec_level<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_exec_level: &'a ExecTy<'a>, mono_exec_level: &'a ExecTy<'a>, ) { @@ -149,8 +160,8 @@ fn infer_kargs_exec_level<'a>( } } -fn infer_kargs_dims<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_dims<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_dim: &'a Dim<'a>, mono_dim: &'a Dim<'a>, ) { @@ -175,16 +186,16 @@ fn infer_kargs_dims<'a>( } } -fn infer_kargs_field<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_field<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_field: &'a (Ident<'a>, DataTy<'a>), mono_field: &'a (Ident<'a>, DataTy<'a>), ) { infer_kargs_dtys(map, &poly_field.1, &mono_field.1) } -fn infer_kargs_dtys<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_dtys<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_dty: &'a DataTy<'a>, mono_dty: &'a DataTy<'a>, ) { @@ -231,16 +242,14 @@ fn infer_kargs_dtys<'a>( } } -fn infer_kargs_nats<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_nats<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_nat: &'a Nat<'a>, mono_nat: &'a Nat<'a>, ) { match (poly_nat, mono_nat) { (Nat::Ident(id), _) => { - if let Some(ArgKinded::Nat(old)) = - map.insert(id.clone(), ArgKinded::Nat(mono_nat.clone())) - { + if let Some(ArgKinded::Nat(old)) = map.insert(id, ArgKinded::Nat(mono_nat.clone())) { if &old != mono_nat { panic!( "not able to check equality of Nats `{}` and `{}`", @@ -263,8 +272,8 @@ fn infer_kargs_nats<'a>( } } -fn infer_kargs_mems<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_mems<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_mem: &'a Memory<'a>, mono_mem: &'a Memory<'a>, ) { @@ -274,8 +283,8 @@ fn infer_kargs_mems<'a>( } } -fn infer_kargs_prvs<'a>( - map: &'a mut HashMap, ArgKinded<'a>>, +fn infer_kargs_prvs<'m, 'a>( + map: &'m mut HashMap<&'a Ident<'a>, ArgKinded<'a>>, poly_prv: &'a Provenance<'a>, mono_prv: &'a Provenance<'a>, ) { From 154b4716de3bb66f981e73a947922e4ca8a18f57 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 14 Aug 2025 11:59:06 +0200 Subject: [PATCH 48/57] fixed pre_decls.rs --- src/ty_check/pre_decl.rs | 1607 +++++++++++++++++++++----------------- 1 file changed, 889 insertions(+), 718 deletions(-) diff --git a/src/ty_check/pre_decl.rs b/src/ty_check/pre_decl.rs index 0131132b..d5ef6787 100644 --- a/src/ty_check/pre_decl.rs +++ b/src/ty_check/pre_decl.rs @@ -4,6 +4,8 @@ use crate::arena_ast::{ ParamSig, Provenance, RefDty, ScalarTy, Ty, TyKind, }; +use bumpalo::{collections::Vec as BumpVec, Bump}; + pub static GPU_DEVICE: &str = "gpu_device"; pub static GPU_ALLOC: &str = "gpu_alloc_copy"; pub static COPY_TO_HOST: &str = "copy_to_host"; @@ -41,49 +43,95 @@ pub static TAKE_RIGHT: &str = "take_right"; pub static SELECT_RANGE: &str = "select_range"; pub static MAP: &str = "map"; -pub fn fun_decls<'a>() -> Vec<(&'static str, FnTy<'a>)> { - let decls = [ - // Built-in functions - (GPU_DEVICE, gpu_device_ty()), - (GPU_ALLOC, gpu_alloc_copy_ty()), - (COPY_TO_HOST, copy_to_host_ty()), - (COPY_TO_GPU, copy_to_gpu_ty()), - (CREATE_ARRAY, create_array_ty()), - (TO_RAW_PTR, to_raw_ptr_ty()), - (OFFSET_RAW_PTR, offset_raw_ptr_ty()), - (SHFL_SYNC, shfl_sync_ty()), - (SHFL_UP, shfl_up_ty()), - (BALLOT_SYNC, ballot_sync_ty()), - (THREAD_ID_X, thread_id_x_ty()), - (GET_WARP_ID, get_warp_id_ty()), - (GET_LANE_ID, get_lane_id_ty()), - (NAT_AS_U64, nat_as_u64_ty()), - // Built-in atomic functions - (ATOMIC_STORE, atomic_store_ty()), - (ATOMIC_LOAD, atomic_load_ty()), - (ATOMIC_FETCH_OR, atomic_fetch_or_ty()), - (ATOMIC_FETCH_ADD, atomic_fetch_add_ty()), - (ATOMIC_MIN, atomic_min_ty()), - (TO_ATOMIC_ARRAY, to_atomic_array_ty()), - (TO_ATOMIC, to_atomic_ty()), - // View constructors - (TO_VIEW, to_view_ty()), - (REVERSE, reverse_ty()), - (MAP, map_ty()), - (GROUP, group_ty()), - (JOIN, join_ty()), - (TRANSPOSE, transpose_ty()), - // (TAKE_LEFT, take_ty(TakeSide::Left)), - // (TAKE_RIGHT, take_ty(TakeSide::Right)), - (SELECT_RANGE, select_range_ty()), - ]; - - decls.to_vec() +pub fn fun_decls<'a>(arena: &'a Bump) -> BumpVec<'a, (&'static str, FnTy<'a>)> { + let mut decls = BumpVec::new_in(arena); + + decls.push((GPU_DEVICE, gpu_device_ty(arena))); + decls.push((GPU_ALLOC, gpu_alloc_copy_ty(arena))); + decls.push((COPY_TO_HOST, copy_to_host_ty(arena))); + decls.push((COPY_TO_GPU, copy_to_gpu_ty(arena))); + decls.push((CREATE_ARRAY, create_array_ty(arena))); + decls.push((TO_RAW_PTR, to_raw_ptr_ty(arena))); + decls.push((OFFSET_RAW_PTR, offset_raw_ptr_ty(arena))); + decls.push((SHFL_SYNC, shfl_sync_ty(arena))); + decls.push((SHFL_UP, shfl_up_ty(arena))); + decls.push((BALLOT_SYNC, ballot_sync_ty(arena))); + decls.push((THREAD_ID_X, thread_id_x_ty(arena))); + decls.push((GET_WARP_ID, get_warp_id_ty(arena))); + decls.push((GET_LANE_ID, get_lane_id_ty(arena))); + decls.push((NAT_AS_U64, nat_as_u64_ty(arena))); + decls.push((ATOMIC_STORE, atomic_store_ty(arena))); + decls.push((ATOMIC_LOAD, atomic_load_ty(arena))); + decls.push((ATOMIC_FETCH_OR, atomic_fetch_or_ty(arena))); + decls.push((ATOMIC_FETCH_ADD, atomic_fetch_add_ty(arena))); + decls.push((ATOMIC_MIN, atomic_min_ty(arena))); + decls.push((TO_ATOMIC_ARRAY, to_atomic_array_ty(arena))); + decls.push((TO_ATOMIC, to_atomic_ty(arena))); + decls.push((TO_VIEW, to_view_ty(arena))); + decls.push((REVERSE, reverse_ty(arena))); + decls.push((MAP, map_ty(arena))); + decls.push((GROUP, group_ty(arena))); + decls.push((JOIN, join_ty(arena))); + decls.push((TRANSPOSE, transpose_ty(arena))); + decls.push((SELECT_RANGE, select_range_ty(arena))); + + decls +} + +// DataTy helpers +fn d_ident<'a>(id: Ident<'a>, arena: &'a Bump) -> DataTy<'a> { + DataTy::new(arena, DataTyKind::Ident(id)) +} +fn d_scalar<'a>(s: ScalarTy, arena: &'a Bump) -> DataTy<'a> { + DataTy::new(arena, DataTyKind::Scalar(s)) +} +fn d_atomic<'a>(a: AtomicTy, arena: &'a Bump) -> DataTy<'a> { + DataTy::new(arena, DataTyKind::Atomic(a)) +} + +fn d_array<'a>(arena: &'a Bump, elem: DataTy<'a>, n: Nat<'a>) -> DataTy<'a> { + let elem_ref = arena.alloc(elem); + DataTy::new(arena, DataTyKind::Array(elem_ref, n)) +} +fn d_array_shape<'a>(arena: &'a Bump, elem: DataTy<'a>, n: Nat<'a>) -> DataTy<'a> { + let elem_ref = arena.alloc(elem); + DataTy::new(arena, DataTyKind::ArrayShape(elem_ref, n)) +} +fn d_ref<'a>( + arena: &'a Bump, + prv: Provenance<'a>, + own: Ownership, + mem: Memory<'a>, + ty: DataTy<'a>, +) -> DataTy<'a> { + let reff = arena.alloc(RefDty::new(arena, prv, own, mem, ty)); + DataTy::new(arena, DataTyKind::Ref(reff)) +} + +// Ty helpers +fn ty_data_ref<'a>(arena: &'a Bump, d: DataTy<'a>) -> &'a Ty<'a> { + let data_ty = arena.alloc(d); + arena.alloc(Ty { + ty: TyKind::Data(data_ty), + span: None, + }) +} + +// Exec helpers +fn exec_ident<'a>(arena: &'a Bump, id: Ident<'a>) -> ExecExpr<'a> { + let kind = arena.alloc(ExecExprKind::new(arena, BaseExec::Ident(id))); + ExecExpr { + exec: kind, + ty: None, + span: None, + } } -fn create_array_ty<'a>() -> FnTy<'a> { - let n = Ident::new("n"); - let d = Ident::new("d"); +fn create_array_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // (d) -[Any]-> [d; n] + let n = Ident::new(arena, "n"); + let d = Ident::new(arena, "d"); + let n_nat = IdentKinded { ident: n.clone(), kind: Kind::Nat, @@ -92,23 +140,26 @@ fn create_array_ty<'a>() -> FnTy<'a> { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // param: d + let param_ty = ty_data_ref(arena, d_ident(d.clone(), arena)); + + // return: [d; n] + let ret_dt = d_array(arena, d_ident(d, arena), Nat::Ident(n)); + let ret_ty = ty_data_ref(arena, ret_dt); + FnTy::new( - vec![n_nat, d_dty], + arena, + [n_nat, d_dty], Some(ident_exec), - vec![ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ident( - d.clone(), - ))))), - )], + [ParamSig::new(exec_expr.clone(), param_ty)], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Array( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Nat::Ident(n), - ))))), - vec![], + ret_ty, + [], ) } @@ -116,10 +167,11 @@ fn create_array_ty<'a>() -> FnTy<'a> { // ( // &r gpu.thread uniq m t // ) -[gpu.thread]-> RawPtr -fn to_raw_ptr_ty<'a>() -> FnTy<'a> { - let r = Ident::new("r"); - let m = Ident::new("m"); - let d = Ident::new("d"); +fn to_raw_ptr_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // (&r uniq m d) -[gpu.thread]-> RawPtr + let r = Ident::new(arena, "r"); + let m = Ident::new(arena, "m"); + let d = Ident::new(arena, "d"); let r_prv = IdentKinded { ident: r.clone(), @@ -133,27 +185,37 @@ fn to_raw_ptr_ty<'a>() -> FnTy<'a> { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // param: &r uniq m d + let param_dt = d_ref( + arena, + Provenance::Ident(r.clone()), + Ownership::Uniq, + Memory::Ident(m.clone()), + d_ident(d.clone(), arena), + ); + let param_ty = ty_data_ref(arena, param_dt); + + // return: RawPtr + let ret_inner = d_ident(d, arena); + let ret_dt = DataTy::new(arena, DataTyKind::RawPtr(arena.alloc(ret_inner))); + let ret_ty = ty_data_ref(arena, ret_dt); + FnTy::new( - vec![r_prv, m_mem, d_dty], + arena, + [r_prv, m_mem, d_dty], Some(ident_exec), - vec![ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r), - Ownership::Uniq, - Memory::Ident(m), - DataTy::new(DataTyKind::Ident(d.clone())), - )), - ))))), - )], + [ParamSig::new(exec_expr.clone(), param_ty)], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::RawPtr( - Box::new(DataTy::new(DataTyKind::Ident(d))), - ))))), - vec![], + ret_ty, + [], ) } @@ -161,233 +223,275 @@ fn to_raw_ptr_ty<'a>() -> FnTy<'a> { // ( // RawPtr, i32 // ) -[gpu.thread]-> RawPtr -fn offset_raw_ptr_ty<'a>() -> FnTy<'a> { - let d = Ident::new("d"); +// (RawPtr, i32) -[gpu.thread]-> RawPtr +fn offset_raw_ptr_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let d = Ident::new(arena, "d"); let d_dty = IdentKinded { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // param 1: RawPtr + let p1_dt = DataTy::new( + arena, + DataTyKind::RawPtr(arena.alloc(d_ident(d.clone(), arena))), + ); + let p1_ty = ty_data_ref(arena, p1_dt); + + // param 2: i32 + let p2_ty = ty_data_ref(arena, d_scalar(ScalarTy::I32, arena)); + + // return: RawPtr + let ret_dt = DataTy::new(arena, DataTyKind::RawPtr(arena.alloc(d_ident(d, arena)))); + let ret_ty = ty_data_ref(arena, ret_dt); + FnTy::new( - vec![d_dty], + arena, + [d_dty], Some(ident_exec), - vec![ - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::RawPtr( - Box::new(DataTy::new(DataTyKind::Ident(d.clone()))), - ))))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::I32, - ))))), - ), + [ + ParamSig::new(exec_expr.clone(), p1_ty), + ParamSig::new(exec_expr.clone(), p2_ty), ], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::RawPtr( - Box::new(DataTy::new(DataTyKind::Ident(d))), - ))))), - vec![], + ret_ty, + [], ) } // ballot_sync: // <>(bool) -[w: gpu.warp]-> u32 -fn ballot_sync_ty<'a>() -> FnTy<'a> { - let ident_exec = IdentExec::new(Ident::new("w"), ExecTy::new(ExecTyKind::GpuWarp)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); - let param_exec = ExecExpr::new(exec_expr.exec.clone().forall(DimCompo::X)); +// <>(bool) -[w: gpu.warp]-> u32 +fn ballot_sync_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "w"), + ExecTy::new(ExecTyKind::GpuWarp), + ); + + // body exec: w + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // param exec: w.forall(x) + let lane_kind = + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())).forall(DimCompo::X); + let param_exec = ExecExpr { + exec: arena.alloc(lane_kind), + ty: None, + span: None, + }; + + // param: bool + let p_ty = ty_data_ref(arena, d_scalar(ScalarTy::Bool, arena)); + // return: u32 + let r_ty = ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)); FnTy::new( - vec![], + arena, + [], Some(ident_exec), - vec![ParamSig::new( - param_exec, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::Bool, - ))))), - )], + [ParamSig::new(param_exec, p_ty)], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + r_ty, + [], ) } // FIXME warp should have the type given in the comment below // shfl_sync: -// (u32, u32) -[w.forall]-> u32 -fn shfl_sync_ty<'a>() -> FnTy<'a> { - let ident_exec = IdentExec::new(Ident::new("w"), ExecTy::new(ExecTyKind::GpuWarp)); - let exec_expr_lane = ExecExpr::new( - ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone())).forall(DimCompo::X), +// (u32, u32) -[w.forall]-> u32 +fn shfl_sync_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // generic exec: w : gpu.warp + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "w"), + ExecTy::new(ExecTyKind::GpuWarp), ); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + // param exec = w.forall(X) + let lane_kind = + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())).forall(DimCompo::X); + let param_exec = ExecExpr { + exec: arena.alloc(lane_kind), + ty: None, + span: None, + }; + + // body exec = w + let body_exec = exec_ident(arena, ident_exec.ident.clone()); + + // types + let u32_ty = ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)); FnTy::new( - vec![], - Some(ident_exec), - vec![ - ParamSig::new( - exec_expr_lane.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - ), - ParamSig::new( - exec_expr_lane.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - ), + arena, + [], // generics (kinded Idents) + Some(ident_exec), // generic exec + [ + ParamSig::new(param_exec.clone(), u32_ty), + ParamSig::new(param_exec, u32_ty), ], - exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + body_exec, + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), + [], // nat constraints ) } // shfl_up: -// <>(u32, i32) -[gpu.warp]-> u32 -fn shfl_up_ty<'a>() -> FnTy<'a> { - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuWarp)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); +// <>(u32, i32) -[gpu.warp]-> u32 +fn shfl_up_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // generic exec: ex : gpu.warp + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::GpuWarp), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // types + let u32_ty = ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)); + let i32_ty = ty_data_ref(arena, d_scalar(ScalarTy::I32, arena)); FnTy::new( - vec![], + arena, + [], // no kinded generics Some(ident_exec), - vec![ - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::I32, - ))))), - ), + [ + ParamSig::new(exec_expr.clone(), u32_ty), + ParamSig::new(exec_expr.clone(), i32_ty), ], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), + [], // no nat constraints ) } // nat_as_u64: -// () -[view]-> u64 -fn nat_as_u64_ty<'a>() -> FnTy<'a> { - let n = Ident::new("n"); +// () -[Any]-> u64 +fn nat_as_u64_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // generic nat parameter + let n = Ident::new(arena, "n"); let n_nat = IdentKinded { ident: n, kind: Kind::Nat, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + // execution level: Any, carried via an exec identifier "ex" + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); FnTy::new( - vec![n_nat], - Some(ident_exec), - vec![], - exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U64, - ))))), - vec![], + arena, + [n_nat], // generics + Some(ident_exec), // generic exec + [], // params + exec_expr, // function exec + ty_data_ref(arena, d_scalar(ScalarTy::U64, arena)), // return type + [], // nat constraints ) } -// get_warp_id: <>() -[w: gpu.Warp]-> u32 -fn get_warp_id_ty<'a>() -> FnTy<'a> { - let ident_exec = IdentExec::new(Ident::new("w"), ExecTy::new(ExecTyKind::GpuWarp)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); +// get_warp_id: +// <>() -[w: gpu.warp]-> u32 +fn get_warp_id_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // generic exec: w : gpu.warp + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "w"), + ExecTy::new(ExecTyKind::GpuWarp), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); FnTy::new( - vec![], - Some(ident_exec), - vec![], - exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + arena, + [], // no kinded generics + Some(ident_exec), // generic exec + [], // params + exec_expr, // function exec + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), // return type + [], // nat constraints ) } -// get_lane_id: <>() -[w: gpu.Thread]-> u32 -fn get_lane_id_ty<'a>() -> FnTy<'a> { - let ident_exec = IdentExec::new(Ident::new("t"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); +// get_lane_id: <>() -[t: gpu.thread]-> u32 +fn get_lane_id_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "t"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); FnTy::new( - vec![], - Some(ident_exec), - vec![], - exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + arena, + [], // no kinded generics + Some(ident_exec), // generic exec + [], // no params + exec_expr, // function exec + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), // return type + [], // no nat constraints ) } -// thread_id_x: -// <>() -[gpu.thread]-> u32 -fn thread_id_x_ty<'a>() -> FnTy<'a> { - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); +// thread_id_x: <>() -[gpu.thread]-> u32 +fn thread_id_x_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); FnTy::new( - vec![], - Some(ident_exec), - vec![], - exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + arena, + [], // no kinded generics + Some(ident_exec), // generic exec + [], // no params + exec_expr, // function exec + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), // return type + [], // no nat constraints ) } // gpu: // <>(i32) -[cpu.thread]-> Gpu -fn gpu_device_ty<'a>() -> FnTy<'a> { - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::CpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); +fn gpu_device_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::CpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); FnTy::new( - vec![], + arena, + [], // no kinded generics Some(ident_exec), - vec![ParamSig::new( + [ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::I32, - ))))), + ty_data_ref(arena, d_scalar(ScalarTy::I32, arena)), )], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::Gpu, - ))))), - vec![], + ty_data_ref(arena, d_scalar(ScalarTy::Gpu, arena)), + [], // no nat constraints ) } // to_atomic_array: -// (ex: &r uniq m [u32; n]) -[x: Any]-> &r uniq m [AtomicU32; n] -fn to_atomic_array_ty<'a>() -> FnTy<'a> { - let r = Ident::new("r"); - let m = Ident::new("m"); - let n = Ident::new("n"); +// (ex: &r uniq m [u32; n]) -[ex: Any]-> &r uniq m [AtomicU32; n] +fn to_atomic_array_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r = Ident::new(arena, "r"); + let m = Ident::new(arena, "m"); + let n = Ident::new(arena, "n"); + let r_prv = IdentKinded { ident: r.clone(), kind: Kind::Provenance, @@ -400,47 +504,49 @@ fn to_atomic_array_ty<'a>() -> FnTy<'a> { ident: n.clone(), kind: Kind::Nat, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // &r uniq m [u32; n] + let param_dty = d_ref( + arena, + Provenance::Ident(r.clone()), + Ownership::Uniq, + Memory::Ident(m.clone()), + d_array(arena, d_scalar(ScalarTy::U32, arena), Nat::Ident(n.clone())), + ); + + // &r uniq m [AtomicU32; n] + let ret_dty = d_ref( + arena, + Provenance::Ident(r), + Ownership::Uniq, + Memory::Ident(m), + d_array(arena, d_atomic(AtomicTy::AtomicU32, arena), Nat::Ident(n)), + ); FnTy::new( - vec![r_prv, m_mem, n_nat], + arena, + [r_prv, m_mem, n_nat], Some(ident_exec), - vec![ParamSig::new( + [ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r.clone()), - Ownership::Uniq, - Memory::Ident(m.clone()), - DataTy::new(DataTyKind::Array( - Box::new(DataTy::new(DataTyKind::Scalar(ScalarTy::U32))), - Nat::Ident(n.clone()), - )), - )), - ))))), + ty_data_ref(arena, param_dty), )], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r), - Ownership::Uniq, - Memory::Ident(m), - DataTy::new(DataTyKind::Array( - Box::new(DataTy::new(DataTyKind::Atomic(AtomicTy::AtomicU32))), - Nat::Ident(n), - )), - )), - ))))), - vec![], + ty_data_ref(arena, ret_dty), + [], // no nat constraints ) } // to_atomic: -// (&r uniq x m u32) -[x: Any]-> &r uniq x m AtomicU32 -fn to_atomic_ty<'a>() -> FnTy<'a> { - let r = Ident::new("r"); - let m = Ident::new("m"); +// (&r uniq m u32) -[ex: Any]-> &r uniq m AtomicU32 +fn to_atomic_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r = Ident::new(arena, "r"); + let m = Ident::new(arena, "m"); + let r_prv = IdentKinded { ident: r.clone(), kind: Kind::Provenance, @@ -449,41 +555,49 @@ fn to_atomic_ty<'a>() -> FnTy<'a> { ident: m.clone(), kind: Kind::Memory, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // &r uniq m u32 + let param_dty = d_ref( + arena, + Provenance::Ident(r.clone()), + Ownership::Uniq, + Memory::Ident(m.clone()), + d_scalar(ScalarTy::U32, arena), + ); + + // &r uniq m AtomicU32 + let ret_dty = d_ref( + arena, + Provenance::Ident(r), + Ownership::Uniq, + Memory::Ident(m), + d_atomic(AtomicTy::AtomicU32, arena), + ); FnTy::new( - vec![r_prv, m_mem], + arena, + [r_prv, m_mem], Some(ident_exec), - vec![ParamSig::new( + [ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r.clone()), - Ownership::Uniq, - Memory::Ident(m.clone()), - DataTy::new(DataTyKind::Scalar(ScalarTy::U32)), - )), - ))))), + ty_data_ref(arena, param_dty), )], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r), - Ownership::Uniq, - Memory::Ident(m), - DataTy::new(DataTyKind::Atomic(AtomicTy::AtomicU32)), - )), - ))))), - vec![], + ty_data_ref(arena, ret_dty), + [], ) } // atomic_store: -// (&r shrd m AtomicU32, u32) -[gpu.thread]-> () -fn atomic_store_ty<'a>() -> FnTy<'a> { - let r = Ident::new("r"); - let m = Ident::new("m"); +// (&r shrd m AtomicU32, u32) -[gpu.thread]-> () +fn atomic_store_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r = Ident::new(arena, "r"); + let m = Ident::new(arena, "m"); + let r_prv = IdentKinded { ident: r.clone(), kind: Kind::Provenance, @@ -492,44 +606,46 @@ fn atomic_store_ty<'a>() -> FnTy<'a> { ident: m.clone(), kind: Kind::Memory, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // &r shrd m AtomicU32 + let ptr_arg = d_ref( + arena, + Provenance::Ident(r), + Ownership::Shrd, + Memory::Ident(m), + d_atomic(AtomicTy::AtomicU32, arena), + ); FnTy::new( - vec![r_prv, m_mem], + arena, + [r_prv, m_mem], Some(ident_exec), - vec![ + [ + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, ptr_arg)), ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r), - Ownership::Shrd, - Memory::Ident(m), - DataTy::new(DataTyKind::Atomic(AtomicTy::AtomicU32)), - )), - ))))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), ), ], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::Unit, - ))))), - vec![], + ty_data_ref(arena, d_scalar(ScalarTy::Unit, arena)), + [], ) } // atomic_fetch_or: // (&r shrd m AtomicU32, u32) -[gpu.thread]-> u32 -fn atomic_fetch_or_ty<'a>() -> FnTy<'a> { - let r = Ident::new("r"); - let m = Ident::new("m"); +fn atomic_fetch_or_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r = Ident::new(arena, "r"); + let m = Ident::new(arena, "m"); + let r_prv = IdentKinded { ident: r.clone(), kind: Kind::Provenance, @@ -538,44 +654,46 @@ fn atomic_fetch_or_ty<'a>() -> FnTy<'a> { ident: m.clone(), kind: Kind::Memory, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // &r shrd m AtomicU32 + let ptr_arg = d_ref( + arena, + Provenance::Ident(r), + Ownership::Shrd, + Memory::Ident(m), + d_atomic(AtomicTy::AtomicU32, arena), + ); FnTy::new( - vec![r_prv, m_mem], + arena, + [r_prv, m_mem], Some(ident_exec), - vec![ + [ + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, ptr_arg)), ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r), - Ownership::Shrd, - Memory::Ident(m), - DataTy::new(DataTyKind::Atomic(AtomicTy::AtomicU32)), - )), - ))))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), ), ], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), + [], ) } // atomic_min: // (&r shrd m AtomicI32, i32) -[gpu.thread]-> i32 -fn atomic_min_ty<'a>() -> FnTy<'a> { - let r = Ident::new("r"); - let m = Ident::new("m"); +fn atomic_min_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r = Ident::new(arena, "r"); + let m = Ident::new(arena, "m"); + let r_prv = IdentKinded { ident: r.clone(), kind: Kind::Provenance, @@ -584,44 +702,46 @@ fn atomic_min_ty<'a>() -> FnTy<'a> { ident: m.clone(), kind: Kind::Memory, }; - let ident_exec = IdentExec::new(Ident::new("t"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "t"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // &r shrd m AtomicI32 + let ptr_arg = d_ref( + arena, + Provenance::Ident(r), + Ownership::Shrd, + Memory::Ident(m), + d_atomic(AtomicTy::AtomicI32, arena), + ); FnTy::new( - vec![r_prv, m_mem], + arena, + [r_prv, m_mem], Some(ident_exec), - vec![ - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r), - Ownership::Shrd, - Memory::Ident(m), - DataTy::new(DataTyKind::Atomic(AtomicTy::AtomicI32)), - )), - ))))), - ), + [ + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, ptr_arg)), ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::I32, - ))))), + ty_data_ref(arena, d_scalar(ScalarTy::I32, arena)), ), ], - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::I32, - ))))), - vec![], + exec_expr, + ty_data_ref(arena, d_scalar(ScalarTy::I32, arena)), + [], ) } // atomic_fetch_add: // (&r shrd m AtomicU32, u32) -[gpu.thread]-> u32 -fn atomic_fetch_add_ty<'a>() -> FnTy<'a> { - let r = Ident::new("r"); - let m = Ident::new("m"); +fn atomic_fetch_add_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r = Ident::new(arena, "r"); + let m = Ident::new(arena, "m"); + let r_prv = IdentKinded { ident: r.clone(), kind: Kind::Provenance, @@ -630,44 +750,46 @@ fn atomic_fetch_add_ty<'a>() -> FnTy<'a> { ident: m.clone(), kind: Kind::Memory, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // &r shrd m AtomicU32 + let ptr_arg = d_ref( + arena, + Provenance::Ident(r), + Ownership::Shrd, + Memory::Ident(m), + d_atomic(AtomicTy::AtomicU32, arena), + ); FnTy::new( - vec![r_prv, m_mem], + arena, + [r_prv, m_mem], Some(ident_exec), - vec![ + [ + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, ptr_arg)), ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r), - Ownership::Shrd, - Memory::Ident(m), - DataTy::new(DataTyKind::Atomic(AtomicTy::AtomicU32)), - )), - ))))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), ), ], exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), + [], ) } // atomic_load: // (&r shrd m AtomicU32) -[gpu.thread]-> u32 -fn atomic_load_ty<'a>() -> FnTy<'a> { - let r = Ident::new("r"); - let m = Ident::new("m"); +fn atomic_load_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r = Ident::new(arena, "r"); + let m = Ident::new(arena, "m"); + let r_prv = IdentKinded { ident: r.clone(), kind: Kind::Provenance, @@ -676,39 +798,46 @@ fn atomic_load_ty<'a>() -> FnTy<'a> { ident: m.clone(), kind: Kind::Memory, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::GpuThread)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = IdentExec::new_in( + arena, + Ident::new(arena, "ex"), + ExecTy::new(ExecTyKind::GpuThread), + ); + let exec_expr = exec_ident(arena, ident_exec.ident.clone()); + + // &r shrd m AtomicU32 + let ptr_arg = d_ref( + arena, + Provenance::Ident(r), + Ownership::Shrd, + Memory::Ident(m), + d_atomic(AtomicTy::AtomicU32, arena), + ); FnTy::new( - vec![r_prv, m_mem], + arena, + [r_prv, m_mem], Some(ident_exec), - vec![ParamSig::new( + [ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r), - Ownership::Shrd, - Memory::Ident(m), - DataTy::new(DataTyKind::Atomic(AtomicTy::AtomicU32)), - )), - ))))), + ty_data_ref(arena, ptr_arg), )], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::U32, - ))))), - vec![], + ty_data_ref(arena, d_scalar(ScalarTy::U32, arena)), + [], ) } -// gpu_alloc: +// gpu_alloc_copy: // ( -// &r1 uniq cpu.mem Gpu, &r2 shrd cpu.mem t -// ) -[cpu.thread]-> t @ gpu.global -fn gpu_alloc_copy_ty<'a>() -> FnTy<'a> { - let r1 = Ident::new("r1"); - let r2 = Ident::new("r2"); - let d = Ident::new("d"); +// &r1 uniq cpu.mem Gpu, &r2 shrd cpu.mem d +// ) -[cpu.thread]-> d @ gpu.global +fn gpu_alloc_copy_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r1 = Ident::new(arena, "r1"); + let r2 = Ident::new(arena, "r2"); + let d = Ident::new(arena, "d"); + let r1_prv = IdentKinded { ident: r1.clone(), kind: Kind::Provenance, @@ -721,51 +850,55 @@ fn gpu_alloc_copy_ty<'a>() -> FnTy<'a> { ident: d.clone(), kind: Kind::DataTy, }; - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::CpuThread)); + + let exec_expr = ExecExpr::new(arena, ExecExprKind::new(arena, BaseExec::CpuThread)); + + // &r1 uniq cpu.mem Gpu + let arg0 = d_ref( + arena, + Provenance::Ident(r1), + Ownership::Uniq, + Memory::CpuMem, + d_scalar(ScalarTy::Gpu, arena), + ); + + // &r2 shrd cpu.mem d + let arg1 = d_ref( + arena, + Provenance::Ident(r2), + Ownership::Shrd, + Memory::CpuMem, + d_ident(d.clone(), arena), + ); + + // d @ gpu.global + let ret_inner = d_ident(d, arena); + let ret_dty_ref = arena.alloc(ret_inner); + let ret_at = DataTy::new(arena, DataTyKind::At(ret_dty_ref, Memory::GpuGlobal)); FnTy::new( - vec![r1_prv, r2_prv, d_dty], + arena, + [r1_prv, r2_prv, d_dty], None, - vec![ - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r1), - Ownership::Uniq, - Memory::CpuMem, - DataTy::new(DataTyKind::Scalar(ScalarTy::Gpu)), - )), - ))))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r2), - Ownership::Shrd, - Memory::CpuMem, - DataTy::new(DataTyKind::Ident(d.clone())), - )), - ))))), - ), + [ + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, arg0)), + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, arg1)), ], - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::At( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Memory::GpuGlobal, - ))))), - vec![], + exec_expr, + ty_data_ref(arena, ret_at), + [], ) } // copy_to_host: -// (&r1 shrd gpu.global d, &r2 uniq cpu.mem d) -// -[cpu.thread]-> () -fn copy_to_host_ty<'a>() -> FnTy<'a> { - let r1 = Ident::new("r1"); - let r2 = Ident::new("r2"); - let d = Ident::new("d"); +// ( +// &r1 shrd gpu.global d, &r2 uniq cpu.mem d +// ) -[cpu.thread]-> () +fn copy_to_host_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r1 = Ident::new(arena, "r1"); + let r2 = Ident::new(arena, "r2"); + let d = Ident::new(arena, "d"); + let r1_prv = IdentKinded { ident: r1.clone(), kind: Kind::Provenance, @@ -778,50 +911,49 @@ fn copy_to_host_ty<'a>() -> FnTy<'a> { ident: d.clone(), kind: Kind::DataTy, }; - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::CpuThread)); + + let exec_expr = ExecExpr::new(arena, ExecExprKind::new(arena, BaseExec::CpuThread)); + + // &r1 shrd gpu.global d + let arg0 = d_ref( + arena, + Provenance::Ident(r1), + Ownership::Shrd, + Memory::GpuGlobal, + d_ident(d.clone(), arena), + ); + + // &r2 uniq cpu.mem d + let arg1 = d_ref( + arena, + Provenance::Ident(r2), + Ownership::Uniq, + Memory::CpuMem, + d_ident(d, arena), + ); FnTy::new( - vec![r1_prv, r2_prv, d_dty], + arena, + [r1_prv, r2_prv, d_dty], None, - vec![ - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r1), - Ownership::Shrd, - Memory::GpuGlobal, - DataTy::new(DataTyKind::Ident(d.clone())), - )), - ))))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r2), - Ownership::Uniq, - Memory::CpuMem, - DataTy::new(DataTyKind::Ident(d)), - )), - ))))), - ), + [ + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, arg0)), + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, arg1)), ], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::Unit, - ))))), - vec![], + ty_data_ref(arena, d_scalar(ScalarTy::Unit, arena)), + [], ) } // copy_to_gpu: -// (& r1 uniq gpu.global d, -// & r2 shrd cpu.mem d) -[cpu.thread]-> () -fn copy_to_gpu_ty<'a>() -> FnTy<'a> { - let r1 = Ident::new("r1"); - let r2 = Ident::new("r2"); - let d = Ident::new("d"); +// (&r1 uniq gpu.global d, &r2 shrd cpu.mem d) +// -[cpu.thread]-> () +fn copy_to_gpu_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let r1 = Ident::new(arena, "r1"); + let r2 = Ident::new(arena, "r2"); + let d = Ident::new(arena, "d"); + let r1_prv = IdentKinded { ident: r1.clone(), kind: Kind::Provenance, @@ -834,48 +966,47 @@ fn copy_to_gpu_ty<'a>() -> FnTy<'a> { ident: d.clone(), kind: Kind::DataTy, }; - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::CpuThread)); + + let exec_expr = ExecExpr::new(arena, ExecExprKind::new(arena, BaseExec::CpuThread)); + + // &r1 uniq gpu.global d + let arg0 = d_ref( + arena, + Provenance::Ident(r1), + Ownership::Uniq, + Memory::GpuGlobal, + d_ident(d.clone(), arena), + ); + + // &r2 shrd cpu.mem d + let arg1 = d_ref( + arena, + Provenance::Ident(r2), + Ownership::Shrd, + Memory::CpuMem, + d_ident(d, arena), + ); FnTy::new( - vec![r1_prv, r2_prv, d_dty], + arena, + [r1_prv, r2_prv, d_dty], None, - vec![ - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r1), - Ownership::Uniq, - Memory::GpuGlobal, - DataTy::new(DataTyKind::Ident(d.clone())), - )), - ))))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ref( - Box::new(RefDty::new( - Provenance::Ident(r2), - Ownership::Shrd, - Memory::CpuMem, - DataTy::new(DataTyKind::Ident(d)), - )), - ))))), - ), + [ + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, arg0)), + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, arg1)), ], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Scalar( - ScalarTy::Unit, - ))))), - vec![], + ty_data_ref(arena, d_scalar(ScalarTy::Unit, arena)), + [], ) } // to_view: -// ([d; n]) -[view]-> [[d; n]] -fn to_view_ty<'a>() -> FnTy<'a> { - let n = Ident::new("n"); - let d = Ident::new("d"); +// ([d; n]) -[Any]-> [[d; n]] +fn to_view_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let n = Ident::new(arena, "n"); + let d = Ident::new(arena, "d"); + let n_nat = IdentKinded { ident: n.clone(), kind: Kind::Nat, @@ -884,68 +1015,79 @@ fn to_view_ty<'a>() -> FnTy<'a> { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = ExecExpr::new( + arena, + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())), + ); + + // param: [d; n] + let param_dty = d_array(arena, d_ident(d.clone(), arena), Nat::Ident(n.clone())); + + // return: [[d; n]] + let ret_dty = d_array_shape(arena, d_ident(d, arena), Nat::Ident(n)); FnTy::new( - vec![n_nat, d_dty], + arena, + [n_nat, d_dty], Some(ident_exec), - vec![ParamSig::new( + [ParamSig::new( exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Array( - Box::new(DataTy::new(DataTyKind::Ident(d.clone()))), - Nat::Ident(n.clone()), - ))))), + ty_data_ref(arena, param_dty), )], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Nat::Ident(n), - ))))), - vec![], + ty_data_ref(arena, ret_dty), + [], ) } -// rev/rev_mut: -// (&r W m [[d; n]]) -> &r W m [[d; n]] -fn reverse_ty<'a>() -> FnTy<'a> { - let n = Ident::new("n"); - let d = Ident::new("d"); +// rev / rev_mut +// ([[d; n]]) -[Any]-> [[d; n]] +fn reverse_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let n = Ident::new(arena, "n"); + let d = Ident::new(arena, "d"); + let n_nat = IdentKinded { ident: n.clone(), kind: Kind::Nat, }; - let d_ty = IdentKinded { + let d_dty = IdentKinded { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = ExecExpr::new( + arena, + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())), + ); + + // param: [[d; n]] + let param = d_array_shape(arena, d_ident(d.clone(), arena), Nat::Ident(n.clone())); + // return: [[d; n]] + let ret = d_array_shape(arena, d_ident(d, arena), Nat::Ident(n)); FnTy::new( - vec![n_nat, d_ty], + arena, + [n_nat, d_dty], Some(ident_exec), - vec![ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d.clone()))), - Nat::Ident(n.clone()), - ))))), - )], + [ParamSig::new(exec_expr.clone(), ty_data_ref(arena, param))], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Nat::Ident(n), - ))))), - vec![], + ty_data_ref(arena, ret), + [], ) } -//map_mut:(|d| -[ex]-> d2, [[d;n]]) -[ex: Any]-> [[d2; n]] -fn map_ty<'a>() -> FnTy<'a> { - let d = Ident::new("d"); - let d2 = Ident::new("d2"); - let n = Ident::new("n"); +// map_mut: +// (|d| -[ex]-> d2, [[d; n]]) -[ex: Any]-> [[d2; n]] +fn map_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + let d = Ident::new(arena, "d"); + let d2 = Ident::new(arena, "d2"); + let n = Ident::new(arena, "n"); + let d_dty = IdentKinded { ident: d.clone(), kind: Kind::DataTy, @@ -958,54 +1100,69 @@ fn map_ty<'a>() -> FnTy<'a> { ident: n.clone(), kind: Kind::Nat, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = ExecExpr::new( + arena, + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())), + ); + + // Build the inner function type: (d) -[ex]-> d2 + let inner_param_ty = ty_data_ref(arena, d_ident(d.clone(), arena)); + let inner_ret_ty = ty_data_ref(arena, d_ident(d2.clone(), arena)); + + let inner_fn = FnTy::new( + arena, + [], // no generics + None, // no generic exec + [ParamSig::new(exec_expr.clone(), inner_param_ty)], + exec_expr.clone(), + inner_ret_ty, + [], // no nat constraints + ); + let inner_fn_ref: &'a FnTy<'a> = arena.alloc(inner_fn); + let inner_fn_ty_ref: &'a Ty<'a> = arena.alloc(Ty { + ty: TyKind::FnTy(inner_fn_ref), + span: None, + }); + + // Second param: [[d; n]] + let arr_param = d_array_shape(arena, d_ident(d, arena), Nat::Ident(n.clone())); + + // Return type: [[d2; n]] + let ret = d_array_shape(arena, d_ident(d2, arena), Nat::Ident(n)); FnTy::new( - vec![d_dty, d2_dty, n_nat], + arena, + [d_dty, d2_dty, n_nat], Some(ident_exec), - vec![ - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::FnTy(Box::new(FnTy::new( - vec![], - None, - vec![ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ident( - d.clone(), - ))))), - )], - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ident( - d2.clone(), - ))))), - vec![], - )))), - ), - ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Nat::Ident(n.clone()), - ))))), - ), + [ + ParamSig::new(exec_expr.clone(), inner_fn_ty_ref), + ParamSig::new(exec_expr.clone(), ty_data_ref(arena, arr_param)), ], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d2))), - Nat::Ident(n), - ))))), - vec![], + ty_data_ref(arena, ret), + [], ) } +// Small Nat helper (arena-allocates both operands) +#[inline] +fn n_binop<'a>(arena: &'a Bump, op: BinOpNat, l: Nat<'a>, r: Nat<'a>) -> Nat<'a> { + let l_ref = arena.alloc(l); + let r_ref = arena.alloc(r); + Nat::BinOp(op, l_ref, r_ref) +} + // group/group_mut: -// ([[d; n]]) -> [[ [[d; size]]; n/size ]] -fn group_ty<'a>() -> FnTy<'a> { - let s = Ident::new("s"); - let n = Ident::new("n"); - let d = Ident::new("d"); +// ([[d; n]]) -[Any]-> [[ [[d; s]]; n/s ]] +fn group_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // generics + let s = Ident::new(arena, "s"); + let n = Ident::new(arena, "n"); + let d = Ident::new(arena, "d"); + let s_nat = IdentKinded { ident: s.clone(), kind: Kind::Nat, @@ -1014,43 +1171,48 @@ fn group_ty<'a>() -> FnTy<'a> { ident: n.clone(), kind: Kind::Nat, }; - let d_ty = IdentKinded { + let d_dty = IdentKinded { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + // exec + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = ExecExpr::new( + arena, + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())), + ); + + // param: [[d; n]] + let param = d_array_shape(arena, d_ident(d.clone(), arena), Nat::Ident(n.clone())); + + // inner element: [[d; s]] + let inner = d_array_shape(arena, d_ident(d, arena), Nat::Ident(s.clone())); + + // outer size: n / s (arena-allocated operands) + let n_div_s = n_binop( + arena, + BinOpNat::Div, + Nat::Ident(n.clone()), + Nat::Ident(s.clone()), + ); + + // return: [[ [[d; s]]; n/s ]] + let ret = d_array_shape(arena, inner, n_div_s); + + // constraint: (n % s) == 0 (all pieces arena-allocated) + let n_mod_s = n_binop(arena, BinOpNat::Mod, Nat::Ident(n), Nat::Ident(s)); + let constr = NatConstr::Eq(arena.alloc(n_mod_s), arena.alloc(Nat::Lit(0))); FnTy::new( - vec![s_nat, n_nat, d_ty], + arena, + [s_nat, n_nat, d_dty], Some(ident_exec), - vec![ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d.clone()))), - Nat::Ident(n.clone()), - ))))), - )], + [ParamSig::new(exec_expr.clone(), ty_data_ref(arena, param))], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Nat::Ident(s.clone()), - ))), - Nat::BinOp( - BinOpNat::Div, - Box::new(Nat::Ident(n.clone())), - Box::new(Nat::Ident(s.clone())), - ), - ))))), - vec![NatConstr::Eq( - Box::new(Nat::BinOp( - BinOpNat::Mod, - Box::new(Nat::Ident(n)), - Box::new(Nat::Ident(s)), - )), - Box::new(Nat::Lit(0)), - )], + ty_data_ref(arena, ret), + [constr], ) } @@ -1112,11 +1274,13 @@ pub enum TakeSide { // } // select: ([[ d; n ]]) -[a: any]-> [[ d; u-l ]] -fn select_range_ty<'a>() -> FnTy<'a> { - let l = Ident::new("l"); - let u = Ident::new("u"); - let n = Ident::new("n"); - let d = Ident::new("d"); +fn select_range_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // generics + let l = Ident::new(arena, "l"); + let u = Ident::new(arena, "u"); + let n = Ident::new(arena, "n"); + let d = Ident::new(arena, "d"); + let l_nat = IdentKinded { ident: l.clone(), kind: Kind::Nat, @@ -1129,48 +1293,52 @@ fn select_range_ty<'a>() -> FnTy<'a> { ident: n.clone(), kind: Kind::Nat, }; - let d_ty = IdentKinded { + let d_dty = IdentKinded { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + // exec + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = ExecExpr::new( + arena, + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())), + ); + + // param: [[d; n]] + let param = d_array_shape(arena, d_ident(d.clone(), arena), Nat::Ident(n.clone())); + + // return: [[d; u - l]] + let u_minus_l = n_binop( + arena, + BinOpNat::Sub, + Nat::Ident(u.clone()), + Nat::Ident(l.clone()), + ); + let ret = d_array_shape(arena, d_ident(d, arena), u_minus_l); + + // constraints: l < u AND (u < n OR u == n) + let c_lt_lu = NatConstr::Lt( + arena.alloc(Nat::Ident(l.clone())), + arena.alloc(Nat::Ident(u.clone())), + ); + let c_lt_un = NatConstr::Lt( + arena.alloc(Nat::Ident(u.clone())), + arena.alloc(Nat::Ident(n.clone())), + ); + let c_eq_un = NatConstr::Eq(arena.alloc(Nat::Ident(u)), arena.alloc(Nat::Ident(n))); + let c_or = NatConstr::Or(arena.alloc(c_lt_un), arena.alloc(c_eq_un)); + let constr = NatConstr::And(arena.alloc(c_lt_lu), arena.alloc(c_or)); FnTy::new( - vec![l_nat, u_nat, n_nat, d_ty], + arena, + [l_nat, u_nat, n_nat, d_dty], Some(ident_exec), - vec![ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d.clone()))), - Nat::Ident(n.clone()), - ))))), - )], + [ParamSig::new(exec_expr.clone(), ty_data_ref(arena, param))], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Nat::BinOp( - BinOpNat::Sub, - Box::new(Nat::Ident(u.clone())), - Box::new(Nat::Ident(l.clone())), - ), - ))))), - vec![NatConstr::And( - Box::new(NatConstr::Lt( - Box::new(Nat::Ident(l)), - Box::new(Nat::Ident(u.clone())), - )), - Box::new(NatConstr::Or( - Box::new(NatConstr::Lt( - Box::new(Nat::Ident(u.clone())), - Box::new(Nat::Ident(n.clone())), - )), - Box::new(NatConstr::Eq( - Box::new(Nat::Ident(u)), - Box::new(Nat::Ident(n)), - )), - )), - )], + ty_data_ref(arena, ret), + [constr], ) } @@ -1193,10 +1361,12 @@ fn select_range_ty<'a>() -> FnTy<'a> { // join/join_mut: // (&r W m [[ [[d; n]]; o]]) -> [[d; n*o]] -fn join_ty<'a>() -> FnTy<'a> { - let n = Ident::new("n"); - let o = Ident::new("o"); - let d = Ident::new("d"); +fn join_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // generics + let n = Ident::new(arena, "n"); + let o = Ident::new(arena, "o"); + let d = Ident::new(arena, "d"); + let n_nat = IdentKinded { ident: n.clone(), kind: Kind::Nat, @@ -1209,77 +1379,78 @@ fn join_ty<'a>() -> FnTy<'a> { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + // exec + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = ExecExpr::new( + arena, + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())), + ); + + // param: [[ [[d; n]]; o ]] + let inner = d_array_shape(arena, d_ident(d.clone(), arena), Nat::Ident(n.clone())); + let param = d_array_shape(arena, inner, Nat::Ident(o.clone())); + + // return: [[d; n * o]] + let n_mul_o = n_binop(arena, BinOpNat::Mul, Nat::Ident(n), Nat::Ident(o)); + let ret = d_array_shape(arena, d_ident(d, arena), n_mul_o); FnTy::new( - vec![o_nat, n_nat, d_dty], + arena, + [o_nat, n_nat, d_dty], Some(ident_exec), - vec![ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d.clone()))), - Nat::Ident(n.clone()), - ))), - Nat::Ident(o.clone()), - ))))), - )], + [ParamSig::new(exec_expr.clone(), ty_data_ref(arena, param))], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Nat::BinOp( - BinOpNat::Mul, - Box::new(Nat::Ident(n)), - Box::new(Nat::Ident(o)), - ), - ))))), - vec![], + ty_data_ref(arena, ret), + [], ) } // transpose: // (&r W m [[ [[d; n]]; o]]) -> &r W m [[ [[d; o]]; n]] -fn transpose_ty<'a>() -> FnTy<'a> { - let n = Ident::new("n"); - let o = Ident::new("o"); - let d = Ident::new("d"); - let o_nat = IdentKinded { - ident: o.clone(), - kind: Kind::Nat, - }; +fn transpose_ty<'a>(arena: &'a Bump) -> FnTy<'a> { + // generics + let n = Ident::new(arena, "n"); + let o = Ident::new(arena, "o"); + let d = Ident::new(arena, "d"); + let n_nat = IdentKinded { ident: n.clone(), kind: Kind::Nat, }; - let d_ty = IdentKinded { + let o_nat = IdentKinded { + ident: o.clone(), + kind: Kind::Nat, + }; + let d_dty = IdentKinded { ident: d.clone(), kind: Kind::DataTy, }; - let ident_exec = IdentExec::new(Ident::new("ex"), ExecTy::new(ExecTyKind::Any)); - let exec_expr = ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); + + // exec + let ident_exec = + IdentExec::new_in(arena, Ident::new(arena, "ex"), ExecTy::new(ExecTyKind::Any)); + let exec_expr = ExecExpr::new( + arena, + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())), + ); + + // param: [[ [[d; n]]; o ]] + let inner_param = d_array_shape(arena, d_ident(d.clone(), arena), Nat::Ident(n.clone())); + let param = d_array_shape(arena, inner_param, Nat::Ident(o.clone())); + + // return: [[ [[d; o]]; n ]] + let inner_ret = d_array_shape(arena, d_ident(d, arena), Nat::Ident(o)); + let ret = d_array_shape(arena, inner_ret, Nat::Ident(n)); FnTy::new( - vec![n_nat, o_nat, d_ty], + arena, + [n_nat, o_nat, d_dty], Some(ident_exec), - vec![ParamSig::new( - exec_expr.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d.clone()))), - Nat::Ident(n.clone()), - ))), - Nat::Ident(o.clone()), - ))))), - )], + [ParamSig::new(exec_expr.clone(), ty_data_ref(arena, param))], exec_expr, - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::ArrayShape( - Box::new(DataTy::new(DataTyKind::Ident(d))), - Nat::Ident(o), - ))), - Nat::Ident(n), - ))))), - vec![], + ty_data_ref(arena, ret), + [], ) } From 68023eaea35c5032833ce42a3cc19cfcd3df0dbb Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 14 Aug 2025 11:59:28 +0200 Subject: [PATCH 49/57] some small fixes --- src/ty_check/borrow_check.rs | 2 +- src/ty_check/ctxs.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ty_check/borrow_check.rs b/src/ty_check/borrow_check.rs index ba6cdb24..4a82c0cb 100644 --- a/src/ty_check/borrow_check.rs +++ b/src/ty_check/borrow_check.rs @@ -5,7 +5,7 @@ use crate::ty_check::ctxs::{AccessCtx, GlobalCtx, KindCtx}; use crate::ty_check::error::BorrowingError; use crate::ty_check::exec::normalize; use crate::ty_check::{exec, pre_decl, ExprTyCtx}; -use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; +use bumpalo::{collections::Vec as BumpVec, Bump}; use std::collections::HashSet; type OwnResult<'a, T> = Result>; diff --git a/src/ty_check/ctxs.rs b/src/ty_check/ctxs.rs index 9689f9e0..30b8a157 100644 --- a/src/ty_check/ctxs.rs +++ b/src/ty_check/ctxs.rs @@ -700,7 +700,6 @@ impl<'a> GlobalCtx<'a> { // because `struct_decl` lives inside `compil_unit` for 'a. decls.push(GlobalDecl::StructDecl(struct_decl)); } - _ => {} } } From 653da496167010289cbfc02341412e91113dfc8c Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 14 Aug 2025 18:28:27 +0200 Subject: [PATCH 50/57] some work one unify.rs --- src/ty_check/subty.rs | 9 +- src/ty_check/unify.rs | 517 +++++++++++++++++++++++------------------- 2 files changed, 287 insertions(+), 239 deletions(-) diff --git a/src/ty_check/subty.rs b/src/ty_check/subty.rs index 94272a1a..51c2b7c8 100644 --- a/src/ty_check/subty.rs +++ b/src/ty_check/subty.rs @@ -29,8 +29,8 @@ pub(super) fn check<'m, 'a>( // Δ; Γ ⊢ τ ≲ τ ⇒ Γ (sub, sup) if sub == sup => Ok(()), // Δ; Γ ⊢ [τ 1 ; n] ≲ [τ2 ; n] ⇒ Γ′ - (Array(sub_elem_ty, sub_size), Array(sup_elem_ty, sup_size)) - | (ArrayShape(sub_elem_ty, sub_size), ArrayShape(sup_elem_ty, sup_size)) => { + (Array(sub_elem_ty, _sub_size), Array(sup_elem_ty, _sup_size)) + | (ArrayShape(sub_elem_ty, _sub_size), ArrayShape(sup_elem_ty, _sup_size)) => { check(kind_ctx, ty_ctx, sub_elem_ty, sup_elem_ty, arena) } // Δ; Γ ⊢ &B ρ1 shrd τ1 ≲ &B ρ2 shrd τ2 ⇒ Γ′′ @@ -239,9 +239,8 @@ pub(super) fn multiple_outlives<'m, 'a, I>( where I: IntoIterator, &'a Provenance<'a>)>, { - for prv_rel in prv_rels { - let (longer, shorter) = prv_rel; - outlives(kind_ctx, ty_ctx, longer, shorter, arena)?; + for (p1, p2) in prv_rels { + outlives(kind_ctx, ty_ctx, p1, p2, arena)?; } Ok(()) } diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index 091b6ca1..b2a58f4b 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -5,41 +5,49 @@ use crate::arena_ast::*; use crate::ty_check::ctxs::{KindCtx, TyCtx}; use crate::ty_check::error::UnifyError; use crate::ty_check::subty; +use bumpalo::{collections::Vec as BumpVec, Bump}; use std::collections::HashMap; type UnifyResult<'a, T> = Result>; -pub(super) fn unify<'a, C: Constrainable<'a>>(t1: &mut C, t2: &mut C) -> UnifyResult<'a, ()> { - let (_, _) = constrain(t1, t2)?; +pub(super) fn unify<'a, C: Constrainable<'a>>( + t1: &'a mut C, + t2: &'a mut C, + arena: &'a Bump, +) -> UnifyResult<'a, ()> { + let (_, _) = constrain(t1, t2, arena)?; Ok(()) } pub(super) fn sub_unify<'a, C: Constrainable<'a>>( - kind_ctx: &KindCtx, - ty_ctx: &mut TyCtx, - sub: &mut C, - sup: &mut C, + kind_ctx: &'a KindCtx<'a>, + ty_ctx: &'a mut TyCtx<'a>, + sub: &'a mut C, + sup: &'a mut C, + arena: &'a Bump, ) -> UnifyResult<'a, ()> { - let (_, prv_rels) = constrain(sub, sup)?; + let (_map, prv) = constrain(sub, sup, arena)?; subty::multiple_outlives( kind_ctx, ty_ctx, - prv_rels.iter().map(|PrvConstr(p1, p2)| (p1, p2)), + prv.iter().map(|PrvConstr(p1, p2)| (*p1, *p2)), + arena, )?; Ok(()) } pub(super) fn constrain<'a, S: Constrainable<'a>>( - t1: &mut S, - t2: &mut S, -) -> UnifyResult<'a, (ConstrainMap<'a>, Vec>)> { + t1: &'a mut S, + t2: &'a mut S, + arena: &'a Bump, +) -> UnifyResult<'a, (ConstrainMap<'a>, BumpVec<'a, PrvConstr<'a>>)> { let mut constr_map = ConstrainMap::new(); - let mut prv_rels = Vec::new(); - t1.constrain(t2, &mut constr_map, &mut prv_rels)?; + let mut prv_rels = BumpVec::new_in(arena); + t1.constrain(t2, &mut constr_map, &mut prv_rels, arena)?; Ok((constr_map, prv_rels)) } -pub(super) fn inst_fn_ty_scheme<'a>(fn_ty: &'a FnTy<'a>) -> FnTy<'a> { +pub(super) fn inst_fn_ty_scheme<'a>(fn_ty: &'a FnTy<'a>, arena: &'a Bump) -> FnTy<'a> { assert!( fn_ty.generic_exec.is_none(), "exec must be substituted before instantiation to make sure that it has the correct type" @@ -48,39 +56,40 @@ pub(super) fn inst_fn_ty_scheme<'a>(fn_ty: &'a FnTy<'a>) -> FnTy<'a> { .generics .iter() .map(|i| match i.kind { - Kind::DataTy => ArgKinded::DataTy(DataTy::new(utils::fresh_ident( - &i.ident.name, - DataTyKind::Ident, - ))), - Kind::Nat => ArgKinded::Nat(utils::fresh_ident(&i.ident.name, Nat::Ident)), - Kind::Memory => ArgKinded::Memory(utils::fresh_ident(&i.ident.name, Memory::Ident)), + Kind::DataTy => ArgKinded::DataTy(DataTy::new( + arena, + utils::fresh_ident(arena, &i.ident.name, DataTyKind::Ident), + )), + Kind::Nat => ArgKinded::Nat(utils::fresh_ident(arena, &i.ident.name, Nat::Ident)), + Kind::Memory => { + ArgKinded::Memory(utils::fresh_ident(arena, &i.ident.name, Memory::Ident)) + } Kind::Provenance => { - ArgKinded::Provenance(utils::fresh_ident(&i.ident.name, Provenance::Ident)) + ArgKinded::Provenance(utils::fresh_ident(arena, &i.ident.name, Provenance::Ident)) } }) .collect(); let mut inst_fn_ty = fn_ty.clone(); let generics = inst_fn_ty.generics.drain(..).collect::>(); - utils::subst_idents_kinded(generics.iter(), mono_idents.iter(), &mut inst_fn_ty); + utils::subst_idents_kinded(arena, generics.iter(), mono_idents.iter(), &mut inst_fn_ty); inst_fn_ty } -#[derive(Debug, PartialEq, Eq, Clone)] -pub(super) struct PrvConstr<'a>(pub Provenance<'a>, pub Provenance<'a>); +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub(super) struct PrvConstr<'a>(pub &'a Provenance<'a>, pub &'a Provenance<'a>); #[derive(Debug)] pub(super) struct ConstrainMap<'a> { - // TODO swap Box for something more abstract, like Symbol or Identifier - pub dty_unifier: HashMap, DataTy<'a>>, - pub nat_unifier: HashMap, Nat<'a>>, - pub mem_unifier: HashMap, Memory<'a>>, - pub prv_unifier: HashMap, Provenance<'a>>, - pub exec_unifier: HashMap, ExecExpr<'a>>, + pub dty_unifier: HashMap<&'a str, DataTy<'a>>, + pub nat_unifier: HashMap<&'a str, Nat<'a>>, + pub mem_unifier: HashMap<&'a str, Memory<'a>>, + pub prv_unifier: HashMap<&'a str, Provenance<'a>>, + pub exec_unifier: HashMap<&'a str, ExecExpr<'a>>, } impl<'a> ConstrainMap<'a> { fn new() -> Self { - ConstrainMap { + Self { dty_unifier: HashMap::new(), nat_unifier: HashMap::new(), mem_unifier: HashMap::new(), @@ -95,6 +104,7 @@ impl<'a> DataTy<'a> { &self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>, + arena: &'a Bump, ) -> UnifyResult<'a, ()> { if let DataTyKind::Ident(ty_id) = &self.dty { if ty_id == ident { @@ -120,42 +130,46 @@ impl<'a> DataTy<'a> { constr_map .dty_unifier .values_mut() - .for_each(|dty| SubstIdent::new(ident, self).visit_dty(dty)); + .for_each(|dty| SubstIdent::new(ident, self).visit_dty(arena, dty)); Ok(()) } } pub(super) trait Substitutable<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>); + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump); } pub(super) trait Constrainable<'a>: Visitable<'a> + Substitutable<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - prv_rels: &'a mut Vec>, - ) -> UnifyResult<()>; - fn occurs_check>(ident_kinded: &'a IdentKinded<'a>, s: &S) -> bool { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()>; + + fn occurs_check>(ident_kinded: &IdentKinded<'a>, s: &S) -> bool { utils::free_kinded_idents(s).contains(ident_kinded) } } impl<'a> Constrainable<'a> for FnTy<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &mut ConstrainMap<'a>, - prv_rels: &mut Vec>, + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, ) -> UnifyResult<'a, ()> { assert!(self.generics.is_empty()); assert!(other.generics.is_empty()); assert!(self.generic_exec.is_none()); assert!(other.generic_exec.is_none()); - self.exec.constrain(&mut other.exec, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); + self.exec + .constrain(&mut other.exec, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); if self.param_sigs.len() != other.param_sigs.len() { return Err(UnifyError::CannotUnify); @@ -168,63 +182,66 @@ impl<'a> Constrainable<'a> for FnTy<'a> { while let (Some((next_lhs, _)), Some((next_rhs, _))) = (remain_lhs.split_first_mut(), remain_rhs.split_first_mut()) { - next_lhs.constrain(next_rhs, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); + next_lhs.constrain(next_rhs, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); i += 1; remain_lhs = &mut self.param_sigs[i..]; remain_rhs = &mut other.param_sigs[i..]; } self.ret_ty - .constrain(&mut other.ret_ty, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); + .constrain(&mut other.ret_ty, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); Ok(()) } } impl<'a> Substitutable<'a> for FnTy<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_fn_ty(self); + apply_subst.visit_fn_ty(arena, self); } } impl<'a> Constrainable<'a> for ParamSig<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - prv_rels: &'a mut Vec>, + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, ) -> UnifyResult<'a, ()> { self.exec_expr - .constrain(&mut other.exec_expr, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); - self.ty.constrain(&mut other.ty, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); + .constrain(&mut other.exec_expr, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); + self.ty + .constrain(&mut other.ty, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); Ok(()) } } impl<'a> Substitutable<'a> for ParamSig<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_param_sig(self); + apply_subst.visit_param_sig(arena, self); } } // TODO unification for exec expressions necessary for Nats? Can this be moved into a separate // equality check? impl<'a> Constrainable<'a> for ExecExpr<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &mut ConstrainMap<'a>, - prv_rels: &mut Vec>, - ) -> UnifyResult<()> { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { match (&mut self.exec.base, &mut other.exec.base) { (BaseExec::Ident(i1), BaseExec::Ident(i2)) => { assert!( @@ -243,8 +260,8 @@ impl<'a> Constrainable<'a> for ExecExpr<'a> { } (BaseExec::CpuThread, BaseExec::CpuThread) => {} (BaseExec::GpuGrid(gdim1, bdim1), BaseExec::GpuGrid(gdim2, bdim2)) => { - gdim1.constrain(gdim2, constr_map, prv_rels)?; - bdim1.constrain(bdim2, constr_map, prv_rels)?; + gdim1.constrain(gdim2, constr_map, prv_rels, arena)?; + bdim1.constrain(bdim2, constr_map, prv_rels, arena)?; } _ => return Err(UnifyError::CannotUnify), } @@ -257,11 +274,11 @@ impl<'a> Constrainable<'a> for ExecExpr<'a> { { tail_lhs.iter_mut().for_each(|ep| { let mut apply_subst = ApplySubst::new(constr_map); - apply_subst.visit_exec_path_elem(ep); + apply_subst.visit_exec_path_elem(arena, ep); }); tail_rhs.iter_mut().for_each(|ep| { let mut apply_subst = ApplySubst::new(constr_map); - apply_subst.visit_exec_path_elem(ep); + apply_subst.visit_exec_path_elem(arena, ep); }); match (next_lhs, next_rhs) { @@ -278,7 +295,7 @@ impl<'a> Constrainable<'a> for ExecExpr<'a> { if rl.left_or_right != rr.left_or_right { return Err(UnifyError::CannotUnify); } - rl.pos.constrain(&mut rr.pos, constr_map, prv_rels)? + rl.pos.constrain(&mut rr.pos, constr_map, prv_rels, arena)? } (ExecPathElem::ToWarps, ExecPathElem::ToWarps) => {} _ => return Err(UnifyError::CannotUnify), @@ -293,64 +310,68 @@ impl<'a> Constrainable<'a> for ExecExpr<'a> { } impl<'a> Substitutable<'a> for ExecExpr<'a> { - fn substitute(&mut self, subst: &ConstrainMap) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_exec_expr(self); + apply_subst.visit_exec_expr(arena, self); } } impl<'a> Constrainable<'a> for Ty<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - prv_rels: &'a mut Vec>, - ) -> UnifyResult<()> { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { match (&mut self.ty, &mut other.ty) { (TyKind::FnTy(fn_ty1), TyKind::FnTy(fn_ty2)) => { - fn_ty1.constrain(fn_ty2, constr_map, prv_rels) + fn_ty1.constrain(fn_ty2, constr_map, prv_rels, arena) + } + (TyKind::Data(dty1), TyKind::Data(dty2)) => { + dty1.constrain(dty2, constr_map, prv_rels, arena) } - (TyKind::Data(dty1), TyKind::Data(dty2)) => dty1.constrain(dty2, constr_map, prv_rels), _ => Err(UnifyError::CannotUnify), } } } impl<'a> Substitutable<'a> for Ty<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_ty(self); + apply_subst.visit_ty(arena, self); } } impl<'a> Constrainable<'a> for DataTy<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - prv_rels: &'a mut Vec>, - ) -> UnifyResult<()> { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { match (&mut self.dty, &mut other.dty) { (DataTyKind::Ident(i1), DataTyKind::Ident(i2)) => { if i1.is_implicit { - other.bind_to(i1, constr_map)? + other.bind_to(i1, constr_map, arena)? } else if i2.is_implicit { - self.bind_to(i2, constr_map)? + self.bind_to(i2, constr_map, arena)? } else if i1 == i2 { return Ok(()); } else { return Err(UnifyError::CannotUnify); } - substitute(constr_map, self); - substitute(constr_map, other); + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); } (DataTyKind::Ident(i), _) if i.is_implicit => { - other.bind_to(i, constr_map)?; - substitute(constr_map, other); + other.bind_to(i, constr_map, arena)?; + substitute(constr_map, other, arena); } (_, DataTyKind::Ident(i)) if i.is_implicit => { - self.bind_to(i, constr_map)?; - substitute(constr_map, self); + self.bind_to(i, constr_map, arena)?; + substitute(constr_map, self, arena); } (DataTyKind::Scalar(sty1), DataTyKind::Scalar(sty2)) => { if sty1 != sty2 { @@ -376,17 +397,17 @@ impl<'a> Constrainable<'a> for DataTy<'a> { if own1 != own2 { return Err(UnifyError::CannotUnify); } - rgn1.constrain(rgn2, constr_map, prv_rels)?; - substitute(constr_map, &mut **dty1); - substitute(constr_map, &mut **dty2); - mem1.constrain(mem2, constr_map, prv_rels)?; - substitute(constr_map, mem1); - substitute(constr_map, mem2); - substitute(constr_map, &mut **dty1); - substitute(constr_map, &mut **dty2); - dty1.constrain(dty2, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); + rgn1.constrain(rgn2, constr_map, prv_rels, arena)?; + substitute(constr_map, &mut **dty1, arena); + substitute(constr_map, &mut **dty2, arena); + mem1.constrain(mem2, constr_map, prv_rels, arena)?; + substitute(constr_map, mem1, arena); + substitute(constr_map, mem2, arena); + substitute(constr_map, &mut **dty1, arena); + substitute(constr_map, &mut **dty2, arena); + dty1.constrain(dty2, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); } (DataTyKind::Tuple(elem_dtys1), DataTyKind::Tuple(elem_dtys2)) => { // TODO figure out why the las three/two lines of the while loop enable borrowing @@ -397,10 +418,10 @@ impl<'a> Constrainable<'a> for DataTy<'a> { while let (Some((next_lhs, _)), Some((next_rhs, _))) = (remain_lhs.split_first_mut(), remain_rhs.split_first_mut()) { - next_lhs.constrain(next_rhs, constr_map, prv_rels)?; + next_lhs.constrain(next_rhs, constr_map, prv_rels, arena)?; for (dty1, dty2) in elem_dtys1.iter_mut().zip(elem_dtys2.iter_mut()) { - substitute(constr_map, dty1); - substitute(constr_map, dty2); + substitute(constr_map, dty1, arena); + substitute(constr_map, dty2, arena); } i += 1; @@ -420,14 +441,14 @@ impl<'a> Constrainable<'a> for DataTy<'a> { } next_lhs .1 - .constrain(&mut next_rhs.1, constr_map, prv_rels)?; + .constrain(&mut next_rhs.1, constr_map, prv_rels, arena)?; for ((_, dty1), (_, dty2)) in struct_decl1 .fields .iter_mut() .zip(struct_decl2.fields.iter_mut()) { - substitute(constr_map, dty1); - substitute(constr_map, dty2); + substitute(constr_map, dty1, arena); + substitute(constr_map, dty2, arena); } i += 1; @@ -437,20 +458,20 @@ impl<'a> Constrainable<'a> for DataTy<'a> { } (DataTyKind::Array(dty1, n1), DataTyKind::Array(dty2, n2)) | (DataTyKind::ArrayShape(dty1, n1), DataTyKind::ArrayShape(dty2, n2)) => { - dty1.constrain(dty2, constr_map, prv_rels)?; - substitute(constr_map, &mut **dty1); - substitute(constr_map, &mut **dty2); - n1.constrain(n2, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); + dty1.constrain(dty2, constr_map, prv_rels, arena)?; + substitute(constr_map, &mut **dty1, arena); + substitute(constr_map, &mut **dty2, arena); + n1.constrain(n2, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); } (DataTyKind::At(dty1, mem1), DataTyKind::At(dty2, mem2)) => { - dty1.constrain(dty2, constr_map, prv_rels)?; - substitute(constr_map, &mut **dty1); - substitute(constr_map, &mut **dty2); - mem1.constrain(mem2, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); + dty1.constrain(dty2, constr_map, prv_rels, arena)?; + substitute(constr_map, &mut **dty1, arena); + substitute(constr_map, &mut **dty2, arena); + mem1.constrain(mem2, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); } (DataTyKind::Atomic(sty1), DataTyKind::Atomic(sty2)) => { if sty1 != sty2 { @@ -466,9 +487,9 @@ impl<'a> Constrainable<'a> for DataTy<'a> { panic!() } (dty1, DataTyKind::Dead(dty2)) if !matches!(dty1, DataTyKind::Dead(_)) => { - self.constrain(dty2, constr_map, prv_rels)?; - substitute(constr_map, self); - substitute(constr_map, other); + self.constrain(dty2, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); } _ => return Err(UnifyError::CannotUnify), } @@ -477,31 +498,32 @@ impl<'a> Constrainable<'a> for DataTy<'a> { } impl<'a> Substitutable<'a> for DataTy<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_dty(self); + apply_subst.visit_dty(arena, self); } } impl<'a> Constrainable<'a> for ExecTy<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - prv_rels: &'a mut Vec>, - ) -> UnifyResult<()> { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { match (&mut self.ty, &mut other.ty) { (ExecTyKind::CpuThread, ExecTyKind::CpuThread) | (ExecTyKind::GpuThread, ExecTyKind::GpuThread) | (ExecTyKind::GpuWarp, ExecTyKind::GpuWarp) | (_, ExecTyKind::Any) => Ok(()), (ExecTyKind::GpuWarpGrp(nl), ExecTyKind::GpuWarpGrp(nr)) => { - nl.constrain(nr, constr_map, prv_rels) + nl.constrain(nr, constr_map, prv_rels, arena) } (ExecTyKind::GpuGrid(lgdim, lbdim), ExecTyKind::GpuGrid(rgdim, rbdim)) | (ExecTyKind::GpuBlockGrp(lgdim, lbdim), ExecTyKind::GpuBlockGrp(rgdim, rbdim)) => { - lgdim.constrain(rgdim, constr_map, prv_rels)?; - lbdim.constrain(rbdim, constr_map, prv_rels) + lgdim.constrain(rgdim, constr_map, prv_rels, arena)?; + lbdim.constrain(rbdim, constr_map, prv_rels, arena) } ( ExecTyKind::GpuToThreads(ldim_compo, l_inner), @@ -510,11 +532,11 @@ impl<'a> Constrainable<'a> for ExecTy<'a> { if ldim_compo != rdim_compo { return Err(UnifyError::CannotUnify); } - l_inner.constrain(r_inner, constr_map, prv_rels) + l_inner.constrain(r_inner, constr_map, prv_rels, arena) } (ExecTyKind::GpuBlock(ldim), ExecTyKind::GpuBlock(rdim)) | (ExecTyKind::GpuThreadGrp(ldim), ExecTyKind::GpuThreadGrp(rdim)) => { - ldim.constrain(rdim, constr_map, prv_rels) + ldim.constrain(rdim, constr_map, prv_rels, arena) } _ => Err(UnifyError::CannotUnify), } @@ -522,33 +544,34 @@ impl<'a> Constrainable<'a> for ExecTy<'a> { } impl<'a> Substitutable<'a> for ExecTy<'a> { - fn substitute(&mut self, subst: &#a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, _arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_exec_ty(self); } } impl<'a> Constrainable<'a> for Dim<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - prv_rels: &'a mut Vec>, - ) -> UnifyResult<()> { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { match (self, other) { (Dim::XYZ(ldim), Dim::XYZ(rdim)) => { - ldim.0.constrain(&mut rdim.0, constr_map, prv_rels)?; - ldim.1.constrain(&mut rdim.1, constr_map, prv_rels)?; - ldim.2.constrain(&mut rdim.2, constr_map, prv_rels) + ldim.0.constrain(&mut rdim.0, constr_map, prv_rels, arena)?; + ldim.1.constrain(&mut rdim.1, constr_map, prv_rels, arena)?; + ldim.2.constrain(&mut rdim.2, constr_map, prv_rels, arena) } (Dim::XY(ldim), Dim::XY(rdim)) | (Dim::XZ(ldim), Dim::XZ(rdim)) | (Dim::YZ(ldim), Dim::YZ(rdim)) => { - ldim.0.constrain(&mut rdim.0, constr_map, prv_rels)?; - ldim.1.constrain(&mut rdim.1, constr_map, prv_rels) + ldim.0.constrain(&mut rdim.0, constr_map, prv_rels, arena)?; + ldim.1.constrain(&mut rdim.1, constr_map, prv_rels, arena) } (Dim::X(ld), Dim::X(rd)) | (Dim::Y(ld), Dim::Y(rd)) | (Dim::Z(ld), Dim::Z(rd)) => { - ld.0.constrain(&mut rd.0, constr_map, prv_rels) + ld.0.constrain(&mut rd.0, constr_map, prv_rels, arena) } _ => Err(UnifyError::CannotUnify), } @@ -556,9 +579,9 @@ impl<'a> Constrainable<'a> for Dim<'a> { } impl<'a> Substitutable<'a> for Dim<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_dim(self); + apply_subst.visit_dim(arena, self); } } @@ -567,7 +590,8 @@ impl<'a> Nat<'a> { &self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>, - _: &'a mut Vec>, + _: &'a mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, ) -> UnifyResult<'a, ()> { // No occurs check. // Nats can be equal to an expression in which the nat appears again. E.g., a = a * 1 @@ -585,11 +609,15 @@ impl<'a> Nat<'a> { constr_map .nat_unifier .values_mut() - .for_each(|n| SubstIdent::new(ident, self).visit_nat(n)); + .for_each(|n| SubstIdent::new(ident, self).visit_nat(arena, n)); Ok(()) } - fn unify<'a>(n1: &'a Nat<'a>, n2: &'a Nat<'a>, _constr_map: &'a mut ConstrainMap<'a>) -> UnifyResult<'a, ()> { + fn unify( + n1: &'a Nat<'a>, + n2: &'a Nat<'a>, + _constr_map: &'a mut ConstrainMap<'a>, + ) -> UnifyResult<'a, ()> { if n1 == n2 { Ok(()) } else { @@ -599,28 +627,33 @@ impl<'a> Nat<'a> { } impl<'a> Constrainable<'a> for Nat<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &mut ConstrainMap<'a>, - prv_rels: &mut Vec>, + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, ) -> UnifyResult<'a, ()> { match (&mut *self, &mut *other) { (Nat::Ident(n1i), Nat::Ident(n2i)) if n1i.is_implicit || n2i.is_implicit => { match (n1i.is_implicit, n2i.is_implicit) { - (true, _) => other.bind_to(n1i, constr_map, prv_rels), - (false, _) => self.bind_to(n2i, constr_map, prv_rels), + (true, _) => other.bind_to(n1i, constr_map, prv_rels, arena), + (false, _) => self.bind_to(n2i, constr_map, prv_rels, arena), } } - (Nat::Ident(n1i), _) if n1i.is_implicit => other.bind_to(n1i, constr_map, prv_rels), - (_, Nat::Ident(n2i)) if n2i.is_implicit => self.bind_to(n2i, constr_map, prv_rels), + (Nat::Ident(n1i), _) if n1i.is_implicit => { + other.bind_to(n1i, constr_map, prv_rels, arena) + } + (_, Nat::Ident(n2i)) if n2i.is_implicit => { + self.bind_to(n2i, constr_map, prv_rels, arena) + } (Nat::BinOp(op1, n1l, n1r), Nat::BinOp(op2, n2l, n2r)) if op1 == op2 => { - n1l.constrain(n2l, constr_map, prv_rels)?; - n1r.constrain(n2r, constr_map, prv_rels) + n1l.constrain(n2l, constr_map, prv_rels, arena)?; + n1r.constrain(n2r, constr_map, prv_rels, arena) } (Nat::App(f1, ns1), Nat::App(f2, ns2)) if f1 == f2 => { for (n1, n2) in ns1.iter_mut().zip(ns2.iter_mut()) { - n1.constrain(n2, constr_map, prv_rels)?; + n1.constrain(n2, constr_map, prv_rels, arena)?; } Ok(()) } @@ -630,14 +663,19 @@ impl<'a> Constrainable<'a> for Nat<'a> { } impl<'a> Substitutable<'a> for Nat<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_nat(self); + apply_subst.visit_nat(arena, self); } } impl<'a> Memory<'a> { - fn bind_to(&self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>) -> UnifyResult<'a, ()> { + fn bind_to( + &self, + ident: &'a Ident<'a>, + constr_map: &'a mut ConstrainMap<'a>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { if Self::occurs_check(&IdentKinded::new(ident, Kind::Memory), self) { return Err(UnifyError::InfiniteType); } @@ -662,26 +700,27 @@ impl<'a> Memory<'a> { constr_map .mem_unifier .values_mut() - .for_each(|m| SubstIdent::new(ident, self).visit_mem(m)); + .for_each(|m| SubstIdent::new(ident, self).visit_mem(arena, m)); Ok(()) } } impl<'a> Constrainable<'a> for Memory<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - _prv_rels: &'a mut Vec>, - ) -> UnifyResult<()> { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + _prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { match (&*self, &*other) { (Memory::Ident(i1), Memory::Ident(i2)) if i1 == i2 => Ok(()), (Memory::Ident(i1), Memory::Ident(i2)) => match (i1.is_implicit, i2.is_implicit) { - (true, _) => other.bind_to(i1, constr_map), - (false, _) => self.bind_to(i2, constr_map), + (true, _) => other.bind_to(i1, constr_map, arena), + (false, _) => self.bind_to(i2, constr_map, arena), }, - (Memory::Ident(i), o) => o.bind_to(i, constr_map), - (s, Memory::Ident(i)) => s.bind_to(i, constr_map), + (Memory::Ident(i), o) => o.bind_to(i, constr_map, arena), + (s, Memory::Ident(i)) => s.bind_to(i, constr_map, arena), (mem1, mem2) if mem1 == mem2 => Ok(()), _ => Err(UnifyError::CannotUnify), } @@ -689,14 +728,19 @@ impl<'a> Constrainable<'a> for Memory<'a> { } impl<'a> Substitutable<'a> for Memory<'a> { - fn substitute<'a>(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_mem(self); + apply_subst.visit_mem(arena, self); } } impl<'a> Provenance<'a> { - fn bind_to(&self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>) -> UnifyResult<'a, ()> { + fn bind_to( + &self, + ident: &'a Ident<'a>, + constr_map: &'a mut ConstrainMap<'a>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { // TODO not necessary, since no recursion possible if Self::occurs_check(&IdentKinded::new(ident, Kind::Provenance), self) { return Err(UnifyError::InfiniteType); @@ -722,23 +766,24 @@ impl<'a> Provenance<'a> { constr_map .prv_unifier .values_mut() - .for_each(|m| SubstIdent::new(ident, self).visit_prv(m)); + .for_each(|m| SubstIdent::new(ident, self).visit_prv(arena, m)); Ok(()) } } impl<'a> Constrainable<'a> for Provenance<'a> { - fn constrain( - &mut self, - other: &mut Self, - constr_map: &'a mut ConstrainMap<'a>, - prv_rels: &'a mut Vec>, - ) -> UnifyResult<()> { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { // TODO restructure cases for less? match (&*self, &*other) { (Provenance::Ident(i1), Provenance::Ident(i2)) if i1 == i2 => Ok(()), (Provenance::Ident(i), r) | (r, Provenance::Ident(i)) if i.is_implicit => { - r.bind_to(i, constr_map) + r.bind_to(i, constr_map, arena) } (Provenance::Ident(_), _) | (_, Provenance::Ident(_)) => { prv_rels.push(PrvConstr(self.clone(), other.clone())); @@ -753,67 +798,71 @@ impl<'a> Constrainable<'a> for Provenance<'a> { } impl<'a> Substitutable<'a> for Provenance<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_prv(self); + apply_subst.visit_prv(arena, self); } } impl<'a> Substitutable<'a> for View<'a> { - fn substitute(&mut self, subst: &'a ConstrainMap<'a>) { + fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); - apply_subst.visit_view(self); + apply_subst.visit_view(arena, self); } } -pub(super) fn substitute<'a, S: Substitutable<'a>>(subst: &'a ConstrainMap<'a>, s: &mut S) { - s.substitute(subst) +pub(super) fn substitute<'a, S: Substitutable<'a>>( + subst: &'a ConstrainMap<'a>, + s: &mut S, + arena: &'a Bump, +) { + s.substitute(subst, arena) } -pub(super) struct ApplySubst<'a> { - subst: &'a ConstrainMap<'a>, +pub(super) struct ApplySubst<'s, 'a> { + subst: &'s ConstrainMap<'a>, } -impl<'a> ApplySubst<'a> { - pub(super) fn new(subst: &'a ConstrainMap<'a>) -> Self { +impl<'s, 'a> ApplySubst<'s, 'a> { + pub(super) fn new(subst: &'s ConstrainMap<'a>) -> Self { ApplySubst { subst } } } -impl<'a> VisitMut<'a> for ApplySubst<'a> { - fn visit_nat(&mut self, nat: &mut Nat<'a>) { +impl<'s, 'a> VisitMut<'a> for ApplySubst<'s, 'a> { + fn visit_nat(&mut self, arena: &'a Bump, nat: &mut Nat<'a>) { match nat { Nat::Ident(ident) if self.subst.nat_unifier.contains_key(&ident.name) => { *nat = self.subst.nat_unifier.get(&ident.name).unwrap().clone(); } - _ => visit_mut::walk_nat(self, nat), + _ => visit_mut::walk_nat(self, arena, nat), } } - fn visit_mem(&mut self, mem: & mut Memory<'a>) { + fn visit_mem(&mut self, arena: &'a Bump, mem: &mut Memory<'a>) { match mem { Memory::Ident(ident) if self.subst.mem_unifier.contains_key(&ident.name) => { *mem = self.subst.mem_unifier.get(&ident.name).unwrap().clone(); } - _ => visit_mut::walk_mem(self, mem), + _ => visit_mut::walk_mem(self, arena, mem), } } - fn visit_prv(&mut self, prv: &mut Provenance<'a>) { + fn visit_prv(&mut self, arena: &'a Bump, prv: &mut Provenance<'a>) { match prv { Provenance::Ident(ident) if self.subst.prv_unifier.contains_key(&ident.name) => { *prv = self.subst.prv_unifier.get(&ident.name).unwrap().clone() } - _ => visit_mut::walk_prv(self, prv), + _ => visit_mut::walk_prv(self, arena, prv), } } - fn visit_dty(&mut self, dty: &mut DataTy<'a>) { + fn visit_dty(&mut self, arena: &'a Bump, dty: &mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) if self.subst.dty_unifier.contains_key(&ident.name) => { *dty = self.subst.dty_unifier.get(&ident.name).unwrap().clone() } - _ => visit_mut::walk_dty(self, dty), + _ => visit_mut::walk_dty(self, arena, dty), } } } @@ -830,43 +879,43 @@ impl<'a, S: Constrainable<'a>> SubstIdent<'a, S> { } impl<'a> VisitMut<'a> for SubstIdent<'a, Nat<'a>> { - fn visit_nat(&mut self, nat: &mut Nat<'a>) { + fn visit_nat(&mut self, arena: &'a Bump, nat: &mut Nat<'a>) { match nat { Nat::Ident(ident) if ident.name == self.ident.name => *nat = self.term.clone(), - _ => visit_mut::walk_nat(self, nat), + _ => visit_mut::walk_nat(self, arena, nat), } } } impl<'a> VisitMut<'a> for SubstIdent<'a, Memory<'a>> { - fn visit_mem(&mut self, mem: &mut Memory<'a>) { + fn visit_mem(&mut self, arena: &'a Bump, mem: &mut Memory<'a>) { match mem { Memory::Ident(ident) if ident.name == self.ident.name => *mem = self.term.clone(), - _ => visit_mut::walk_mem(self, mem), + _ => visit_mut::walk_mem(self, arena, mem), } } } impl<'a> VisitMut<'a> for SubstIdent<'a, Provenance<'a>> { - fn visit_prv(&mut self, prv: &mut Provenance<'a>) { + fn visit_prv(&mut self, arena: &'a Bump, prv: &mut Provenance<'a>) { match prv { Provenance::Ident(ident) if ident.name == self.ident.name => *prv = self.term.clone(), - _ => visit_mut::walk_prv(self, prv), + _ => visit_mut::walk_prv(self, arena, prv), } } } impl<'a> VisitMut<'a> for SubstIdent<'a, DataTy<'a>> { - fn visit_dty(&mut self, dty: &mut DataTy<'a>) { + fn visit_dty(&mut self, arena: &'a Bump, dty: &mut DataTy<'a>) { match &mut dty.dty { DataTyKind::Ident(ident) if ident.name == self.ident.name => *dty = self.term.clone(), - _ => visit_mut::walk_dty(self, dty), + _ => visit_mut::walk_dty(self, arena, dty), } } } impl<'a> VisitMut<'a> for SubstIdent<'a, ExecExpr<'a>> { - fn visit_exec_expr(&mut self, exec: &mut ExecExpr<'a>) { + fn visit_exec_expr(&mut self, arena: &'a Bump, exec: &mut ExecExpr<'a>) { if let BaseExec::Ident(i) = &exec.exec.base { if i.name == self.ident.name { let mut subst_exec = self.term.clone(); From 575e724964588c6be6dbfdee9d1b1d4611e753bc Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Thu, 14 Aug 2025 19:35:41 +0200 Subject: [PATCH 51/57] current state of unify implementation --- src/arena_ast/mod.rs | 24 +++++++++++++++++++++++- src/arena_ast/utils.rs | 13 +++++++++++-- src/ty_check/unify.rs | 8 ++++---- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index aebdc93d..d5c72b9c 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -1,7 +1,7 @@ use std::fmt; use crate::arena_ast::internal::PathElem; -use bumpalo::{boxed::Box as BumpBox, collections::Vec as BumpVec, Bump}; +use bumpalo::{collections::Vec as BumpVec, Bump}; use descend_derive::span_derive; use crate::ast::Span; @@ -1243,6 +1243,28 @@ impl<'a> FnTy<'a> { } } +impl<'a> Clone for FnTy<'a> { + fn clone(&self) -> Self { + let mut generics = BumpVec::new_in(self.generics.bump()); + generics.extend(self.generics.iter().cloned()); + + let mut param_sigs = BumpVec::new_in(self.param_sigs.bump()); + param_sigs.extend(self.param_sigs.iter().cloned()); + + let mut nat_constrs = BumpVec::new_in(self.nat_constrs.bump()); + nat_constrs.extend(self.nat_constrs.iter().cloned()); + + FnTy { + generics, + generic_exec: self.generic_exec.clone(), + param_sigs, + exec: self.exec.clone(), + ret_ty: self.ret_ty, + nat_constrs, + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum NatConstr<'a> { True, diff --git a/src/arena_ast/utils.rs b/src/arena_ast/utils.rs index c95fdf28..e458f738 100644 --- a/src/arena_ast/utils.rs +++ b/src/arena_ast/utils.rs @@ -12,12 +12,22 @@ use std::sync::atomic::{AtomicI32, Ordering}; static mut COUNTER: AtomicI32 = AtomicI32::new(0); +/** pub(crate) fn fresh_ident<'a, F, R>(arena: &'a bumpalo::Bump, name: &str, ident_constr: F) -> R where F: Fn(Ident) -> R, { ident_constr(Ident::new_impli(&arena, &fresh_name(name))) } +*/ + +pub(crate) fn fresh_ident<'a, F, R>(arena: &'a bumpalo::Bump, name: &'a str, ident_constr: F) -> R +where + F: FnOnce(Ident<'a>) -> R, +{ + let id = Ident::new(arena, name); + ident_constr(id) +} pub(crate) fn fresh_name(name: &str) -> String { let prefix = format!("${}", name); @@ -47,7 +57,6 @@ pub fn implicit_idents<'a>(f: &FunDef<'a>) -> Option>> { } } -// utils.rs (or wherever you define this trait) pub trait VisitableMut<'a> { fn visit_mut>(&mut self, visitor: &mut V, arena: &'a bumpalo::Bump); } @@ -313,7 +322,7 @@ fn insert_for_ident<'a>( path: merged, }); - // Keep or drop the cached type (choose one) + // Keep or drop the cached type // let new_ty = in_exec.ty; // keep it (may be stale) let new_ty = None; // safer: force re-tycheck later diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index b2a58f4b..01c68014 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -101,7 +101,7 @@ impl<'a> ConstrainMap<'a> { impl<'a> DataTy<'a> { fn bind_to( - &self, + &'a self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>, arena: &'a Bump, @@ -587,7 +587,7 @@ impl<'a> Substitutable<'a> for Dim<'a> { impl<'a> Nat<'a> { fn bind_to( - &self, + &'a self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>, _: &'a mut BumpVec<'a, PrvConstr<'a>>, @@ -671,7 +671,7 @@ impl<'a> Substitutable<'a> for Nat<'a> { impl<'a> Memory<'a> { fn bind_to( - &self, + &'a self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>, arena: &'a Bump, @@ -736,7 +736,7 @@ impl<'a> Substitutable<'a> for Memory<'a> { impl<'a> Provenance<'a> { fn bind_to( - &self, + &'a self, ident: &'a Ident<'a>, constr_map: &'a mut ConstrainMap<'a>, arena: &'a Bump, From fa537b742108217366e239678c17236d7bb9670a Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Fri, 15 Aug 2025 16:17:01 +0200 Subject: [PATCH 52/57] unify and pl_expr arena allocation, added utility methods to arena ast --- src/arena_ast/mod.rs | 200 +++++++++++++++++++++++++++++++++++++ src/ty_check/pl_expr.rs | 137 +++++++++++++++---------- src/ty_check/unify.rs | 214 ++++++++++++++++++++++++++++------------ 3 files changed, 439 insertions(+), 112 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index d5c72b9c..8302b89a 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -156,6 +156,14 @@ impl<'a> IdentExec<'a> { ty: bump.alloc(exec_ty), } } + + pub fn clone_in(&self, arena: &'a Bump) -> Self { + let cloned = self.ty.clone_in(arena); // ExecTy<'a> + IdentExec { + ident: self.ident.clone(), // shallow clone of Ident<'a> is fine + ty: arena.alloc(cloned), // store &'a ExecTy<'a> + } + } } #[derive(Debug, PartialEq, Eq, Clone)] @@ -1201,6 +1209,16 @@ impl<'a> ParamSig<'a> { pub fn new(exec_expr: ExecExpr<'a>, ty: &'a Ty<'a>) -> Self { ParamSig { exec_expr, ty } } + + pub fn clone_in(&self, arena: &'a Bump) -> Self { + ParamSig { + exec_expr: self.exec_expr.clone_in(arena), + ty: { + let t = self.ty.clone_in(arena); + arena.alloc(t) + }, + } + } } #[derive(PartialEq, Eq, Hash, Debug)] @@ -1241,6 +1259,45 @@ impl<'a> FnTy<'a> { nat_constrs: nat_vec, } } + + pub fn clone_in(&self, arena: &'a Bump) -> FnTy<'a> { + // generics + let mut generics = BumpVec::new_in(arena); + generics.extend(self.generics.iter().cloned()); + + // optional generic exec + let generic_exec = self.generic_exec.as_ref().map(|ge| ge.clone_in(arena)); + + // param sigs + let mut param_sigs = BumpVec::new_in(arena); + for ps in self.param_sigs.iter() { + param_sigs.push(ps.clone_in(arena)); + } + + // exec expression + let exec = self.exec.clone_in(arena); + + // return type (allocate cloned Ty in the arena and store the &'a Ty) + let ret_ty_ref: &'a Ty<'a> = { + let ret = self.ret_ty.clone_in(arena); + arena.alloc(ret) + }; + + // nat constraints + let mut nat_constrs = BumpVec::new_in(arena); + for c in self.nat_constrs.iter() { + nat_constrs.push(c.clone_in(arena)); + } + + FnTy { + generics, + generic_exec, + param_sigs, + exec, + ret_ty: ret_ty_ref, + nat_constrs, + } + } } impl<'a> Clone for FnTy<'a> { @@ -1273,6 +1330,39 @@ pub enum NatConstr<'a> { And(&'a NatConstr<'a>, &'a NatConstr<'a>), Or(&'a NatConstr<'a>, &'a NatConstr<'a>), } + +impl<'a> NatConstr<'a> { + pub fn clone_in(&self, arena: &'a Bump) -> NatConstr<'a> { + match self { + NatConstr::True => NatConstr::True, + + NatConstr::Eq(l, r) => { + let l2 = arena.alloc((*l).clone_in(arena)); + let r2 = arena.alloc((*r).clone_in(arena)); + NatConstr::Eq(l2, r2) + } + + NatConstr::Lt(l, r) => { + let l2 = arena.alloc((*l).clone_in(arena)); + let r2 = arena.alloc((*r).clone_in(arena)); + NatConstr::Lt(l2, r2) + } + + NatConstr::And(a, b) => { + let a2 = arena.alloc((*a).clone_in(arena)); + let b2 = arena.alloc((*b).clone_in(arena)); + NatConstr::And(a2, b2) + } + + NatConstr::Or(a, b) => { + let a2 = arena.alloc((*a).clone_in(arena)); + let b2 = arena.alloc((*b).clone_in(arena)); + NatConstr::Or(a2, b2) + } + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum TyKind<'a> { Data(&'a DataTy<'a>), @@ -1331,6 +1421,13 @@ impl<'a> Ty<'a> { } } } + + pub fn clone_in(&self, _arena: &'a bumpalo::Bump) -> Ty<'a> { + Ty { + ty: self.ty.clone(), + span: self.span, + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1384,6 +1481,18 @@ impl<'a> Dim<'a> { _ => Ok(false), } } + + pub fn clone_in(&self, arena: &'a Bump) -> Self { + match *self { + Dim::XYZ(d) => Dim::new_3d(arena, d.0.clone(), d.1.clone(), d.2.clone()), + Dim::XY(d) => Dim::new_2d(arena, Dim::XY, d.0.clone(), d.1.clone()), + Dim::XZ(d) => Dim::new_2d(arena, Dim::XZ, d.0.clone(), d.1.clone()), + Dim::YZ(d) => Dim::new_2d(arena, Dim::YZ, d.0.clone(), d.1.clone()), + Dim::X(d) => Dim::new_1d(arena, Dim::X, d.0.clone()), + Dim::Y(d) => Dim::new_1d(arena, Dim::Y, d.0.clone()), + Dim::Z(d) => Dim::new_1d(arena, Dim::Z, d.0.clone()), + } + } } #[derive(PartialEq, Eq, PartialOrd, Hash, Debug, Copy, Clone)] @@ -1568,6 +1677,70 @@ impl<'a> DataTy<'a> { _ => Ok(false), } } + + pub fn clone_in(&self, arena: &'a bumpalo::Bump) -> DataTy<'a> { + use DataTyKind::*; + + let dty: DataTyKind<'a> = match &self.dty { + // leaf cases (Copy/Clone-by-value) + Scalar(s) => Scalar(*s), + Atomic(a) => Atomic(*a), + Ident(id) => Ident(id.clone()), + + // pointer-carrying cases: clone payloads, allocate where needed + RawPtr(elem) => { + let cloned = elem.clone_in(arena); + RawPtr(arena.alloc(cloned)) + } + + Array(elem, n) => { + let cloned_e = elem.clone_in(arena); + let cloned_n = n.clone_in(arena); + Array(arena.alloc(cloned_e), cloned_n) + } + + ArrayShape(elem, n) => { + let cloned_e = elem.clone_in(arena); + let cloned_n = n.clone_in(arena); + ArrayShape(arena.alloc(cloned_e), cloned_n) + } + + At(elem, mem) => { + let cloned_e = elem.clone_in(arena); + let mem_val = (*mem).clone(); + At(arena.alloc(cloned_e), mem_val) + } + + Ref(r) => { + let inner = r.dty.clone_in(arena); + let reff = RefDty::new(arena, r.rgn.clone(), r.own, r.mem.clone(), inner); + Ref(arena.alloc(reff)) + } + + Tuple(elems) => { + let mut out = bumpalo::collections::Vec::new_in(arena); + out.extend(elems.iter().map(|e| e.clone_in(arena))); + Tuple(out) + } + + Struct(sd) => Struct(*sd), + + Dead(inner) => { + let cloned = inner.clone_in(arena); + Dead(arena.alloc(cloned)) + } + }; + + // clone constraints into this arena + let mut constraints = bumpalo::collections::Vec::new_in(arena); + constraints.extend(self.constraints.iter().cloned()); + + DataTy { + dty, + constraints, + span: self.span, + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1851,6 +2024,33 @@ impl<'a> Nat<'a> { let r_ref = arena.alloc(rhs); Nat::BinOp(op, l_ref, r_ref) } + + pub fn clone_in(&self, arena: &'a Bump) -> Nat<'a> { + match self { + Nat::Ident(id) => Nat::Ident(id.clone()), + Nat::Lit(n) => Nat::Lit(*n), + + Nat::ThreadIdx(c) => Nat::ThreadIdx(*c), + Nat::BlockIdx(c) => Nat::BlockIdx(*c), + Nat::BlockDim(c) => Nat::BlockDim(*c), + Nat::WarpGrpIdx => Nat::WarpGrpIdx, + Nat::WarpIdx => Nat::WarpIdx, + Nat::LaneIdx => Nat::LaneIdx, + Nat::GridIdx => Nat::GridIdx, + + Nat::BinOp(op, l, r) => { + let lc: &'a Nat<'a> = arena.alloc(l.clone_in(arena)); + let rc: &'a Nat<'a> = arena.alloc(r.clone_in(arena)); + Nat::BinOp(*op, lc, rc) + } + + Nat::App(id, args) => { + let mut new_args: BumpVec<'a, Nat<'a>> = BumpVec::new_in(arena); + new_args.extend(args.iter().map(|a| a.clone_in(arena))); + Nat::App(id.clone(), new_args) + } + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)] diff --git a/src/ty_check/pl_expr.rs b/src/ty_check/pl_expr.rs index eda66c57..16e7ffd1 100644 --- a/src/ty_check/pl_expr.rs +++ b/src/ty_check/pl_expr.rs @@ -10,7 +10,7 @@ use crate::ty_check::ctxs::{AccessCtx, GlobalCtx, KindCtx, TyCtx}; use crate::ty_check::unify; use crate::ty_check::unify::ConstrainMap; use crate::ty_check::{exec, ExprTyCtx}; - +use bumpalo::Bump; pub(super) struct PlExprTyCtx<'a> { gl_ctx: &'a GlobalCtx<'a>, nat_ctx: &'a NatCtx<'a>, @@ -54,61 +54,68 @@ impl<'a> From<&'a BorrowCheckCtx<'a>> for PlExprTyCtx<'a> { // Δ; Γ ⊢ω p:τ // p in an ω context has type τ under Δ and Γ -pub(super) fn ty_check<'a>(ctx: &PlExprTyCtx, pl_expr: &'a mut PlaceExpr<'a>) -> TyResult<'a, ()> { - let _mem = ty_check_and_passed_mems(ctx, pl_expr)?; +pub(super) fn ty_check<'a>( + ctx: &'a PlExprTyCtx<'a>, + pl_expr: &'a mut PlaceExpr<'a>, + arena: &'a Bump, +) -> TyResult<'a, ()> { + let _mem = ty_check_and_passed_mems(ctx, pl_expr, arena)?; Ok(()) } pub(super) fn ty_check_and_passed_mems<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, pl_expr: &'a mut PlaceExpr<'a>, + arena: &'a Bump, ) -> TyResult<'a, Vec>> { - let (mem, _) = ty_check_and_passed_mems_prvs(ctx, pl_expr)?; + let (mem, _) = ty_check_and_passed_mems_prvs(ctx, pl_expr, arena)?; Ok(mem) } // Δ; Γ ⊢ω p:τ,{ρ} // p in an ω context has type τ under Δ and Γ, passing through provenances in Vec<ρ> fn ty_check_and_passed_mems_prvs<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, pl_expr: &'a mut PlaceExpr<'a>, + arena: &'a Bump, ) -> TyResult<'a, (Vec>, Vec>)> { let (ty, mem, prvs) = match &mut pl_expr.pl_expr { // TC-Var PlaceExprKind::Ident(ident) => ty_check_ident(ctx, ident)?, // TC-Proj - PlaceExprKind::Proj(tuple_expr, n) => ty_check_proj(ctx, tuple_expr, *n)?, + PlaceExprKind::Proj(tuple_expr, n) => ty_check_proj(ctx, tuple_expr, *n, arena)?, // TC-Field PlaceExprKind::FieldProj(struct_expr, ident) => { - ty_check_field_proj(ctx, struct_expr, ident)? + ty_check_field_proj(ctx, struct_expr, ident, arena)? } // TC-Deref - PlaceExprKind::Deref(borr_expr) => ty_check_deref(ctx, borr_expr)?, + PlaceExprKind::Deref(borr_expr) => ty_check_deref(ctx, borr_expr, arena)?, // TC-Select - PlaceExprKind::Select(p, select_exec) => ty_check_select(ctx, p, select_exec)?, - PlaceExprKind::View(pl_expr, view) => ty_check_view_pl_expr(ctx, pl_expr, view)?, - PlaceExprKind::Idx(pl_expr, idx) => ty_check_index(ctx, pl_expr, idx)?, + PlaceExprKind::Select(p, select_exec) => ty_check_select(ctx, p, select_exec, arena)?, + PlaceExprKind::View(pl_expr, view) => ty_check_view_pl_expr(ctx, pl_expr, view, arena)?, + PlaceExprKind::Idx(pl_expr, idx) => ty_check_index(ctx, pl_expr, idx, arena)?, }; - pl_expr.ty = Some(Box::new(ty)); + pl_expr.ty = Some(arena.alloc(ty)); Ok((mem, prvs)) } fn ty_check_view_pl_expr<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, pl_expr: &'a mut PlaceExpr<'a>, view: &'a mut View<'a>, + arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { - let (mems, prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr)?; - let view_fn_ty = ty_check_view(ctx, view)?; + let (mems, prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr, arena)?; + let view_fn_ty = ty_check_view(ctx, view, arena)?; let in_dty = pl_expr.ty.as_ref().unwrap().dty().clone(); let (res_dty, constr_map) = ty_check_app_view_fn_ty(ctx, &in_dty, view_fn_ty)?; // substitute implicit identifiers in view, that were inferred from the input data type - unify::substitute(&constr_map, view); - Ok((Ty::new(TyKind::Data(Box::new(res_dty))), mems, prvs)) + unify::substitute(&constr_map, view, arena); + Ok((Ty::new(TyKind::Data(arena.alloc(res_dty))), mems, prvs)) } fn ty_check_app_view_fn_ty<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, in_dty: &'a DataTy<'a>, mut view_fn_ty: FnTy<'a>, ) -> TyResult<'a, (DataTy<'a>, ConstrainMap<'a>)> { @@ -125,16 +132,24 @@ fn ty_check_app_view_fn_ty<'a>( ))))), vec![], ); - let (constr_map, _) = unify::constrain(&mut arg_dty_fn_ty, &mut view_fn_ty)?; + let (constr_map, _) = unify::constrain(&mut arg_dty_fn_ty, &mut view_fn_ty, arena)?; let res_dty = arg_dty_fn_ty.ret_ty.dty().clone(); Ok((res_dty, constr_map)) } -fn ty_check_view<'a>(ctx: &PlExprTyCtx, view: &'a mut View<'a>) -> TyResult<'a, FnTy<'a>> { +fn ty_check_view<'a>( + ctx: &'a PlExprTyCtx<'a>, + view: &'a mut View<'a>, + arena: &'a Bump, +) -> TyResult<'a, FnTy<'a>> { let arg_tys = view .args .iter_mut() - .map(|v| Ok(Ty::new(TyKind::FnTy(Box::new(ty_check_view(ctx, v)?))))) + .map(|v| { + Ok(Ty::new(TyKind::FnTy( + arena.alloc(ty_check_view(ctx, v, arena)?), + ))) + }) .collect::>>()?; let view_fn_ty = ctx.gl_ctx.fn_ty_by_ident(&view.name)?; let partially_applied_view_fn_ty = super::apply_gen_args_to_fn_ty_checked( @@ -143,11 +158,12 @@ fn ty_check_view<'a>(ctx: &PlExprTyCtx, view: &'a mut View<'a>) -> TyResult<'a, view_fn_ty, &view.gen_args, )?; - let mut actual_view_fn_ty = create_view_ty_with_input_view_and_free_ret(&ctx.exec, arg_tys); - let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_view_fn_ty); - let (constr_map, _) = unify::constrain(&mut actual_view_fn_ty, &mut mono_fn_ty)?; + let mut actual_view_fn_ty = + create_view_ty_with_input_view_and_free_ret(&ctx.exec, arg_tys, arena); + let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_view_fn_ty, arena); + let (constr_map, _) = unify::constrain(&mut actual_view_fn_ty, &mut mono_fn_ty, arena)?; // substitute implicit identifiers in view, that were inferred without the input data type - unify::substitute(&constr_map, view); + unify::substitute(&constr_map, view, arena); let mut inferred_k_args = super::infer_kinded_args::infer_kinded_args(&partially_applied_view_fn_ty, &mono_fn_ty)?; view.gen_args.append(&mut inferred_k_args); @@ -156,7 +172,7 @@ fn ty_check_view<'a>(ctx: &PlExprTyCtx, view: &'a mut View<'a>) -> TyResult<'a, actual_view_fn_ty.generic_exec.clone(), vec![actual_view_fn_ty.param_sigs.pop().unwrap()], actual_view_fn_ty.exec.clone(), - actual_view_fn_ty.ret_ty.as_ref().clone(), + actual_view_fn_ty.ret_ty.clone(), vec![], ); Ok(res_view_ty) @@ -165,11 +181,14 @@ fn ty_check_view<'a>(ctx: &PlExprTyCtx, view: &'a mut View<'a>) -> TyResult<'a, fn create_view_ty_with_input_view_and_free_ret<'a>( exec: &ExecExpr, mut arg_tys: Vec>, + arena: &'a Bump, ) -> FnTy<'a> { arg_tys.push(Ty::new(TyKind::Data(Box::new(DataTy::new( - utils::fresh_ident("in_view_dty", DataTyKind::Ident), + arena, + utils::fresh_ident(arena, "in_view_dty", DataTyKind::Ident), ))))); FnTy::new( + arena, vec![], None, arg_tys @@ -178,6 +197,7 @@ fn create_view_ty_with_input_view_and_free_ret<'a>( .collect(), exec.clone(), Ty::new(TyKind::Data(Box::new(DataTy::new(utils::fresh_ident( + arena, "view_out_dty", DataTyKind::Ident, ))))), @@ -186,7 +206,7 @@ fn create_view_ty_with_input_view_and_free_ret<'a>( } fn ty_check_ident<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, ident: &'a Ident<'a>, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { // if let Ok(tty) = ctx.ty_ctx.ty_of_ident(ident) { @@ -232,11 +252,12 @@ fn default_mem_by_exec<'a>(exec_ty: &'a ExecTyKind<'a>) -> Option> { // TODO refactor by fusing with ty_check_field_proj fn ty_check_proj<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, tuple_expr: &'a mut PlaceExpr<'a>, n: usize, + arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { - let (mem, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, tuple_expr)?; + let (mem, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, tuple_expr, arena)?; let tuple_dty = match &tuple_expr.ty.as_ref().unwrap().ty { TyKind::Data(dty) => dty, ty_kind => { @@ -250,7 +271,7 @@ fn ty_check_proj<'a>( DataTyKind::Tuple(elem_dtys) => { if let Some(dty) = elem_dtys.get(n) { Ok(( - Ty::new(TyKind::Data(Box::new(dty.clone()))), + Ty::new(TyKind::Data(arena.alloc(dty.clone()))), mem, passed_prvs, )) @@ -261,18 +282,19 @@ fn ty_check_proj<'a>( } } dty_kind => Err(TyError::ExpectedTupleType( - TyKind::Data(Box::new(DataTy::new(dty_kind.clone()))), + TyKind::Data(arena.alloc(DataTy::new(arena, dty_kind.clone()))), tuple_expr.clone(), )), } } fn ty_check_field_proj<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, struct_expr: &'a mut PlaceExpr<'a>, ident: &'a Ident<'a>, + arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { - let (mem, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, struct_expr)?; + let (mem, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, struct_expr, arena)?; let struct_dty = match &struct_expr.ty.as_ref().unwrap().ty { TyKind::Data(dty) => dty, ty_kind => { @@ -287,7 +309,7 @@ fn ty_check_field_proj<'a>( DataTyKind::Struct(struct_decl) => { if let Some(field) = struct_decl.fields.iter().find(|f| &f.0 == ident) { Ok(( - Ty::new(TyKind::Data(Box::new(field.1.clone()))), + Ty::new(TyKind::Data(arena.alloc(field.1.clone()))), mem, passed_prvs, )) @@ -298,17 +320,18 @@ fn ty_check_field_proj<'a>( } } dty_kind => Err(TyError::ExpectedTupleType( - TyKind::Data(Box::new(DataTy::new(dty_kind.clone()))), + TyKind::Data(arena.alloc(DataTy::new(arena, dty_kind.clone()))), struct_expr.clone(), )), } } fn ty_check_deref<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, borr_expr: &'a mut PlaceExpr<'a>, + arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { - let (mut inner_mem, mut passed_prvs) = ty_check_and_passed_mems_prvs(ctx, borr_expr)?; + let (mut inner_mem, mut passed_prvs) = ty_check_and_passed_mems_prvs(ctx, borr_expr, arena)?; let borr_dty = if let TyKind::Data(dty) = &borr_expr.ty.as_ref().unwrap().ty { dty } else { @@ -326,7 +349,7 @@ fn ty_check_deref<'a>( passed_prvs.push(reff.rgn.clone()); inner_mem.push(reff.mem.clone()); Ok(( - Ty::new(TyKind::Data(Box::new(reff.dty.as_ref().clone()))), + Ty::new(TyKind::Data(arena.alloc(reff.dty.clone()))), inner_mem, passed_prvs, )) @@ -334,7 +357,7 @@ fn ty_check_deref<'a>( DataTyKind::RawPtr(dty) => { // TODO is anything of this correct? Ok(( - Ty::new(TyKind::Data(Box::new(dty.as_ref().clone()))), + Ty::new(TyKind::Data(arena.alloc(dty.clone()))), inner_mem, passed_prvs, )) @@ -346,11 +369,12 @@ fn ty_check_deref<'a>( } fn ty_check_select<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, p: &'a mut PlaceExpr<'a>, select_exec: &'a mut ExecExpr<'a>, + arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { - exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, select_exec)?; + exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, select_exec, arena)?; // FIXME this check is required for uniq accesses, but not for shared accesses because there // the duplication of accesses is fine. Move this check into ownership/borrow checking? // if &ctx.exec != select_exec { @@ -358,8 +382,14 @@ fn ty_check_select<'a>( // "Trying select memory for illegal combination of excution resources.".to_string(), // )); // } - let mut outer_exec = select_exec.remove_last_distrib(); - exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, &mut outer_exec)?; + let mut outer_exec = select_exec.remove_last_distrib(arena); + exec::ty_check( + ctx.nat_ctx, + ctx.ty_ctx, + ctx.ident_exec, + &mut outer_exec, + arena, + )?; let outer_ctx = PlExprTyCtx { gl_ctx: ctx.gl_ctx, nat_ctx: ctx.nat_ctx, @@ -370,7 +400,7 @@ fn ty_check_select<'a>( exec_borrow_ctx: ctx.exec_borrow_ctx, own: ctx.own, }; - let (mems, prvs) = ty_check_and_passed_mems_prvs(&outer_ctx, p)?; + let (mems, prvs) = ty_check_and_passed_mems_prvs(&outer_ctx, p, arena)?; let mut p_dty = p.ty.as_ref().unwrap().dty().clone(); match p_dty.dty { DataTyKind::Array(elem_dty, n) | DataTyKind::ArrayShape(elem_dty, n) => { @@ -385,15 +415,16 @@ fn ty_check_select<'a>( return Err(TyError::String("Expected an array or view.".to_string())); } } - Ok((Ty::new(TyKind::Data(Box::new(p_dty))), mems, prvs)) + Ok((Ty::new(TyKind::Data(arena.alloc(p_dty))), mems, prvs)) } fn ty_check_index<'a>( - ctx: &PlExprTyCtx, + ctx: &'a PlExprTyCtx<'a>, pl_expr: &'a mut PlaceExpr<'a>, idx: &'a mut Nat<'a>, + arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { - let (mems, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr)?; + let (mems, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr, arena)?; let pl_expr_dty = if let TyKind::Data(dty) = &pl_expr.ty.as_ref().unwrap().ty { dty } else { @@ -405,7 +436,7 @@ fn ty_check_index<'a>( DataTyKind::Array(elem_dty, n) | DataTyKind::ArrayShape(elem_dty, n) => (*elem_dty, n), DataTyKind::At(arr_dty, _) => { if let DataTyKind::Array(elem_ty, n) = &arr_dty.dty { - (elem_ty.as_ref().clone(), n.clone()) + (*elem_ty.clone(), n.clone()) } else { return Err(TyError::String( "Trying to index into non array type.".to_string(), @@ -425,5 +456,9 @@ fn ty_check_index<'a>( )); } - Ok((Ty::new(TyKind::Data(Box::new(elem_dty))), mems, passed_prvs)) + Ok(( + Ty::new(TyKind::Data(arena.alloc(elem_dty))), + mems, + passed_prvs, + )) } diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index 01c68014..7f02b827 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -8,6 +8,11 @@ use crate::ty_check::subty; use bumpalo::{collections::Vec as BumpVec, Bump}; use std::collections::HashMap; +#[inline] +fn arena_slice<'a, T>(v: &bumpalo::collections::Vec<'a, T>) -> &'a [T] { + unsafe { std::slice::from_raw_parts(v.as_ptr(), v.len()) } +} + type UnifyResult<'a, T> = Result>; pub(super) fn unify<'a, C: Constrainable<'a>>( @@ -47,6 +52,7 @@ pub(super) fn constrain<'a, S: Constrainable<'a>>( Ok((constr_map, prv_rels)) } +/** pub(super) fn inst_fn_ty_scheme<'a>(fn_ty: &'a FnTy<'a>, arena: &'a Bump) -> FnTy<'a> { assert!( fn_ty.generic_exec.is_none(), @@ -69,11 +75,57 @@ pub(super) fn inst_fn_ty_scheme<'a>(fn_ty: &'a FnTy<'a>, arena: &'a Bump) -> FnT } }) .collect(); + let mut inst_fn_ty = fn_ty.clone(); let generics = inst_fn_ty.generics.drain(..).collect::>(); utils::subst_idents_kinded(arena, generics.iter(), mono_idents.iter(), &mut inst_fn_ty); inst_fn_ty } +*/ + +pub(super) fn inst_fn_ty_scheme<'a>(fn_ty: &'a FnTy<'a>, arena: &'a bumpalo::Bump) -> FnTy<'a> { + assert!( + fn_ty.generic_exec.is_none(), + "exec must be substituted before instantiation to make sure that it has the correct type" + ); + + // 1) Build arena-resident args (so the *elements* live for 'a) + let mut mono_args = bumpalo::collections::Vec::new_in(arena); + for g in fn_ty.generics.iter() { + let arg = match g.kind { + Kind::DataTy => { + let dk = utils::fresh_ident(arena, &g.ident.name, |id| DataTyKind::Ident(id)); + ArgKinded::DataTy(DataTy::new(arena, dk)) + } + Kind::Nat => ArgKinded::Nat(utils::fresh_ident(arena, &g.ident.name, |id| { + Nat::Ident(id) + })), + Kind::Memory => ArgKinded::Memory(utils::fresh_ident(arena, &g.ident.name, |id| { + Memory::Ident(id) + })), + Kind::Provenance => { + ArgKinded::Provenance(utils::fresh_ident(arena, &g.ident.name, |id| { + Provenance::Ident(id) + })) + } + }; + mono_args.push(arg); + } + + // 2) Convert to a slice with lifetime 'a (elements are arena-owned) + let args_a: &'a [ArgKinded<'a>] = arena_slice(&mono_args); + + // 3) Make a working copy (whatever “clone” mechanism you have) + let mut inst = fn_ty.clone(); // or your `clone_in(arena)`/rebuild + + // 4) Substitute: domain = original generics (already 'a), codomain = args_a + utils::subst_idents_kinded(arena, fn_ty.generics.iter(), args_a.iter(), &mut inst); + + // 5) Monomorphic result has no generics/exec param + inst.generics.clear(); + inst.generic_exec = None; + inst +} #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub(super) struct PrvConstr<'a>(pub &'a Provenance<'a>, pub &'a Provenance<'a>); @@ -136,7 +188,7 @@ impl<'a> DataTy<'a> { } pub(super) trait Substitutable<'a> { - fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump); + fn substitute<'s>(&mut self, subst: &'s ConstrainMap<'a>, arena: &'a Bump); } pub(super) trait Constrainable<'a>: Visitable<'a> + Substitutable<'a> { @@ -168,8 +220,8 @@ impl<'a> Constrainable<'a> for FnTy<'a> { self.exec .constrain(&mut other.exec, constr_map, prv_rels, arena)?; - substitute(constr_map, self, arena); - substitute(constr_map, other, arena); + substitute(&*constr_map, self, arena); + substitute(&*constr_map, other, arena); if self.param_sigs.len() != other.param_sigs.len() { return Err(UnifyError::CannotUnify); @@ -183,23 +235,32 @@ impl<'a> Constrainable<'a> for FnTy<'a> { (remain_lhs.split_first_mut(), remain_rhs.split_first_mut()) { next_lhs.constrain(next_rhs, constr_map, prv_rels, arena)?; - substitute(constr_map, self, arena); - substitute(constr_map, other, arena); + substitute(&*constr_map, self, arena); + substitute(&*constr_map, other, arena); i += 1; remain_lhs = &mut self.param_sigs[i..]; remain_rhs = &mut other.param_sigs[i..]; } - self.ret_ty - .constrain(&mut other.ret_ty, constr_map, prv_rels, arena)?; - substitute(constr_map, self, arena); - substitute(constr_map, other, arena); + + // self.ret_ty.constrain(&mut other.ret_ty, constr_map, prv_rels, arena)?; + + let mut lhs_ret = self.ret_ty.clone_in(arena); + let mut rhs_ret = other.ret_ty.clone_in(arena); + + lhs_ret.constrain(&mut rhs_ret, constr_map, prv_rels, arena)?; + + self.ret_ty = arena.alloc(lhs_ret); + other.ret_ty = arena.alloc(rhs_ret); + + substitute(&*constr_map, self, arena); + substitute(&*constr_map, other, arena); Ok(()) } } impl<'a> Substitutable<'a> for FnTy<'a> { - fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { + fn substitute<'s>(&mut self, subst: &'s ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_fn_ty(arena, self); } @@ -217,8 +278,17 @@ impl<'a> Constrainable<'a> for ParamSig<'a> { .constrain(&mut other.exec_expr, constr_map, prv_rels, arena)?; substitute(constr_map, self, arena); substitute(constr_map, other, arena); - self.ty - .constrain(&mut other.ty, constr_map, prv_rels, arena)?; + + { + let mut lhs = self.ty.clone_in(arena); + let mut rhs = other.ty.clone_in(arena); + + lhs.constrain(&mut rhs, constr_map, prv_rels, arena)?; + + self.ty = arena.alloc(lhs); + other.ty = arena.alloc(rhs); + } + substitute(constr_map, self, arena); substitute(constr_map, other, arena); Ok(()) @@ -226,7 +296,7 @@ impl<'a> Constrainable<'a> for ParamSig<'a> { } impl<'a> Substitutable<'a> for ParamSig<'a> { - fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { + fn substitute<'s>(&mut self, subst: &'s ConstrainMap<'a>, arena: &'a Bump) { let mut apply_subst = ApplySubst::new(subst); apply_subst.visit_param_sig(arena, self); } @@ -242,69 +312,77 @@ impl<'a> Constrainable<'a> for ExecExpr<'a> { prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, arena: &'a Bump, ) -> UnifyResult<'a, ()> { - match (&mut self.exec.base, &mut other.exec.base) { - (BaseExec::Ident(i1), BaseExec::Ident(i2)) => { - assert!( - !i1.is_implicit, - "Implicit identifier for exec expression should not exist" - ); + use BaseExec as BE; + use ExecPathElem as EPE; + + match (&self.exec.base, &other.exec.base) { + (BE::Ident(i1), BE::Ident(i2)) => { assert!( - !i2.is_implicit, + !i1.is_implicit && !i2.is_implicit, "Implicit identifier for exec expression should not exist" ); - if i1 == i2 { - return Ok(()); - } else { + if i1 != i2 { return Err(UnifyError::CannotUnify); } } - (BaseExec::CpuThread, BaseExec::CpuThread) => {} - (BaseExec::GpuGrid(gdim1, bdim1), BaseExec::GpuGrid(gdim2, bdim2)) => { - gdim1.constrain(gdim2, constr_map, prv_rels, arena)?; - bdim1.constrain(bdim2, constr_map, prv_rels, arena)?; + (BE::CpuThread, BE::CpuThread) => { /* ok */ } + + (BE::GpuGrid(gd1, bd1), BE::GpuGrid(gd2, bd2)) => { + let mut lg = gd1.clone_in(arena); + let mut rg = gd2.clone_in(arena); + lg.constrain(&mut rg, constr_map, prv_rels, arena)?; + + let mut lb = bd1.clone_in(arena); + let mut rb = bd2.clone_in(arena); + lb.constrain(&mut rb, constr_map, prv_rels, arena)?; } + _ => return Err(UnifyError::CannotUnify), } - let mut i = 0; - let mut remain_lhs = &mut self.exec.path[i..]; - let mut remain_rhs = &mut other.exec.path[i..]; - while let (Some((next_lhs, tail_lhs)), Some((next_rhs, tail_rhs))) = - (remain_lhs.split_first_mut(), remain_rhs.split_first_mut()) - { - tail_lhs.iter_mut().for_each(|ep| { - let mut apply_subst = ApplySubst::new(constr_map); - apply_subst.visit_exec_path_elem(arena, ep); - }); - tail_rhs.iter_mut().for_each(|ep| { - let mut apply_subst = ApplySubst::new(constr_map); - apply_subst.visit_exec_path_elem(arena, ep); - }); - - match (next_lhs, next_rhs) { - (ExecPathElem::ForAll(dl), ExecPathElem::ForAll(dr)) - | (ExecPathElem::ToThreads(dl), ExecPathElem::ToThreads(dr)) => { + let l_len = self.exec.path.len(); + let r_len = other.exec.path.len(); + if l_len != r_len { + return Err(UnifyError::CannotUnify); + } + + for i in 0..l_len { + let mut le = self.exec.path[i].clone(); + let mut re = other.exec.path[i].clone(); + + { + let mut ap = ApplySubst::new(constr_map); + ap.visit_exec_path_elem(arena, &mut le); + ap.visit_exec_path_elem(arena, &mut re); + } + + match (&mut le, &mut re) { + (EPE::ForAll(dl), EPE::ForAll(dr)) | (EPE::ToThreads(dl), EPE::ToThreads(dr)) => { if dl != dr { return Err(UnifyError::CannotUnify); } } - (ExecPathElem::TakeRange(rl), ExecPathElem::TakeRange(rr)) => { - if rl.split_dim != rr.split_dim { - return Err(UnifyError::CannotUnify); - } - if rl.left_or_right != rr.left_or_right { + + (EPE::TakeRange(rl), EPE::TakeRange(rr)) => { + if rl.split_dim != rr.split_dim || rl.left_or_right != rr.left_or_right { return Err(UnifyError::CannotUnify); } - rl.pos.constrain(&mut rr.pos, constr_map, prv_rels, arena)? + let mut lp = rl.pos.clone_in(arena); + let mut rp = rr.pos.clone_in(arena); + lp.constrain(&mut rp, constr_map, prv_rels, arena)?; } - (ExecPathElem::ToWarps, ExecPathElem::ToWarps) => {} + + (EPE::ToWarps, EPE::ToWarps) => { /* ok */ } + _ => return Err(UnifyError::CannotUnify), } - - i += 1; - remain_lhs = &mut self.exec.path[i..]; - remain_rhs = &mut other.exec.path[i..]; } + + // Optional: normalize by applying the final substitution to the whole exprs. + // (This rebuilds nodes in the arena and updates the &-fields atomically.) + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); + Ok(()) } } @@ -326,10 +404,24 @@ impl<'a> Constrainable<'a> for Ty<'a> { ) -> UnifyResult<'a, ()> { match (&mut self.ty, &mut other.ty) { (TyKind::FnTy(fn_ty1), TyKind::FnTy(fn_ty2)) => { - fn_ty1.constrain(fn_ty2, constr_map, prv_rels, arena) + { + let mut f1 = (*fn_ty1).clone_in(arena); + let mut f2 = (*fn_ty2).clone_in(arena); + f1.constrain(&mut f2, constr_map, prv_rels, arena)?; + } + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); + Ok(()) } (TyKind::Data(dty1), TyKind::Data(dty2)) => { - dty1.constrain(dty2, constr_map, prv_rels, arena) + { + let mut d1 = (*dty1).clone_in(arena); + let mut d2 = (*dty2).clone_in(arena); + d1.constrain(&mut d2, constr_map, prv_rels, arena)?; + } + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); + Ok(()) } _ => Err(UnifyError::CannotUnify), } @@ -634,7 +726,7 @@ impl<'a> Constrainable<'a> for Nat<'a> { prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, arena: &'a Bump, ) -> UnifyResult<'a, ()> { - match (&mut *self, &mut *other) { + match (&*self, &*other) { (Nat::Ident(n1i), Nat::Ident(n2i)) if n1i.is_implicit || n2i.is_implicit => { match (n1i.is_implicit, n2i.is_implicit) { (true, _) => other.bind_to(n1i, constr_map, prv_rels, arena), @@ -811,8 +903,8 @@ impl<'a> Substitutable<'a> for View<'a> { } } -pub(super) fn substitute<'a, S: Substitutable<'a>>( - subst: &'a ConstrainMap<'a>, +pub(super) fn substitute<'a, 's, S: Substitutable<'a>>( + subst: &'s ConstrainMap<'a>, s: &mut S, arena: &'a Bump, ) { From d7411d594bacd3a40d0d88073fe7c154f95257f8 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Mon, 18 Aug 2025 16:40:12 +0200 Subject: [PATCH 53/57] some work on unify.rs --- src/arena_ast/mod.rs | 87 +++++++++-- src/arena_ast/visit_mut.rs | 8 +- src/ast/mod.rs | 7 +- src/parser/mod.rs | 5 +- src/ty_check/unify.rs | 309 ++++++++++++++++++++++++++++--------- 5 files changed, 328 insertions(+), 88 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index 8302b89a..80d4a43d 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -1068,6 +1068,14 @@ impl<'a> TakeRange<'a> { left_or_right: proj, } } + + pub fn clone_in(&self, arena: &'a Bump) -> &'a TakeRange<'a> { + arena.alloc(TakeRange::new( + self.split_dim, + self.pos.clone_in(arena), + self.left_or_right, + )) + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1084,14 +1092,14 @@ impl<'a> ExecExprKind<'a> { } } - pub fn clone_in(&self, arena: &'a bumpalo::Bump) -> Self { + pub fn clone_in(&self, arena: &'a Bump) -> Self { + let mut new_path = BumpVec::new_in(arena); + for e in self.path.iter() { + new_path.push(e.clone_in(arena)); + } ExecExprKind { - base: self.base.clone(), - path: { - let mut new_path = BumpVec::new_in(arena); - new_path.extend(self.path.iter().cloned()); - new_path - }, + base: self.base.clone_in(arena), + path: new_path, } } @@ -1138,7 +1146,21 @@ impl<'a> ExecExprKind<'a> { pub enum BaseExec<'a> { Ident(Ident<'a>), CpuThread, - GpuGrid(Dim<'a>, Dim<'a>), + GpuGrid(&'a Dim<'a>, &'a Dim<'a>), +} + +impl<'a> BaseExec<'a> { + pub fn clone_in(&self, arena: &'a Bump) -> Self { + match self { + BaseExec::Ident(ie) => BaseExec::Ident(ie.clone()), + BaseExec::CpuThread => BaseExec::CpuThread, + BaseExec::GpuGrid(gdim, bdim) => { + let ng = arena.alloc(gdim.clone_in(arena)); + let nb = arena.alloc(bdim.clone_in(arena)); + BaseExec::GpuGrid(ng, nb) + } // add other variants here if you have them + } + } } #[derive(PartialEq, Eq, Hash, Debug, Clone)] @@ -1149,6 +1171,17 @@ pub enum ExecPathElem<'a> { ToThreads(DimCompo), } +impl<'a> ExecPathElem<'a> { + pub fn clone_in(&self, arena: &'a Bump) -> Self { + match self { + ExecPathElem::TakeRange(tr) => ExecPathElem::TakeRange(tr.clone_in(arena)), + ExecPathElem::ForAll(d) => ExecPathElem::ForAll(*d), + ExecPathElem::ToWarps => ExecPathElem::ToWarps, + ExecPathElem::ToThreads(d) => ExecPathElem::ToThreads(*d), + } + } +} + // ExecTy // fn size(DimCompo) -> usize // fn take_range(DimCompo, Nat) -> ExecTy @@ -1753,7 +1786,7 @@ pub struct RefDty<'a> { impl<'a> RefDty<'a> { pub fn new( - bump: &'a Bump, + arena: &'a Bump, rgn: Provenance<'a>, own: Ownership, mem: Memory<'a>, @@ -1763,7 +1796,18 @@ impl<'a> RefDty<'a> { rgn, own, mem, - dty: bump.alloc(dty), + dty: arena.alloc(dty), + } + } + + pub fn clone_in(&self, arena: &'a bumpalo::Bump) -> Self { + let cloned_dty: &'a DataTy<'a> = arena.alloc(self.dty.clone_in(arena)); + + RefDty { + rgn: self.rgn.clone_in(arena), + own: self.own, // Copy + mem: self.mem.clone_in(arena), + dty: cloned_dty, } } } @@ -1812,6 +1856,15 @@ pub enum Provenance<'a> { Ident(Ident<'a>), } +impl<'a> Provenance<'a> { + pub fn clone_in(&self, arena: &'a Bump) -> Self { + match self { + Provenance::Value(s) => Provenance::Value(arena.alloc_str(s)), + Provenance::Ident(id) => Provenance::Ident(id.clone()), + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone)] pub enum Memory<'a> { CpuMem, @@ -1821,6 +1874,18 @@ pub enum Memory<'a> { Ident(Ident<'a>), } +impl<'a> Memory<'a> { + pub fn clone_in(&self, arena: &'a Bump) -> Self { + match self { + Memory::CpuMem => Memory::CpuMem, + Memory::GpuGlobal => Memory::GpuGlobal, + Memory::GpuShared => Memory::GpuShared, + Memory::GpuLocal => Memory::GpuLocal, + Memory::Ident(id) => Memory::Ident(id.clone()), + } + } +} + #[derive(PartialEq, Eq, Debug, Clone)] pub struct PrvRel<'a> { pub longer: Ident<'a>, @@ -2080,7 +2145,7 @@ mod size_asserts { static_assert_size!(DataTy, 128); static_assert_size!(DataTyKind, 80); static_assert_size!(ExecExpr, 32); - static_assert_size!(ExecExprKind, 72); + static_assert_size!(ExecExprKind, 64); static_assert_size!(ExecPathElem, 16); static_assert_size!(ExecTy, 80); static_assert_size!(ExecTyKind, 64); diff --git a/src/arena_ast/visit_mut.rs b/src/arena_ast/visit_mut.rs index 4c1e6d2f..2e4a1390 100644 --- a/src/arena_ast/visit_mut.rs +++ b/src/arena_ast/visit_mut.rs @@ -922,8 +922,12 @@ pub fn walk_exec<'a, V: VisitMut<'a>>( BaseExec::CpuThread => (), BaseExec::Ident(ident) => visitor.visit_ident(arena, ident), BaseExec::GpuGrid(gdim, bdim) => { - visitor.visit_dim(arena, gdim); - visitor.visit_dim(arena, bdim); + let mut gdim_owned = (**gdim).clone(); + let mut bdim_owned = (**bdim).clone(); + visitor.visit_dim(arena, &mut gdim_owned); + visitor.visit_dim(arena, &mut bdim_owned); + *gdim = arena.alloc(gdim_owned); + *bdim = arena.alloc(bdim_owned); } }; for e in path { diff --git a/src/ast/mod.rs b/src/ast/mod.rs index ae75dfdd..2b7b044e 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1560,9 +1560,10 @@ impl BaseExec { match self { Ident(ident) => arena_ast::BaseExec::Ident(ident.into_arena(arena)), CpuThread => arena_ast::BaseExec::CpuThread, - GpuGrid(d1, d2) => { - arena_ast::BaseExec::GpuGrid(d1.into_arena(arena), d2.into_arena(arena)) - } + GpuGrid(d1, d2) => arena_ast::BaseExec::GpuGrid( + arena.alloc(d1.into_arena(arena)), + arena.alloc(d2.into_arena(arena)), + ), } } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index bd892ccf..aa87fb2c 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -330,7 +330,10 @@ fn replace_exec_idents_with_specific_execs<'a>(arena: &'a Bump, fun_def: &mut Ar arena, ArenaExecExprKind::new( arena, - ArenaBaseExec::GpuGrid(gdim.clone(), bdim.clone()), + ArenaBaseExec::GpuGrid( + arena.alloc(gdim.clone()), + arena.alloc(bdim.clone()), + ), ), ), )); diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index 7f02b827..8b88ae3d 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -153,9 +153,9 @@ impl<'a> ConstrainMap<'a> { impl<'a> DataTy<'a> { fn bind_to( - &'a self, + &self, ident: &'a Ident<'a>, - constr_map: &'a mut ConstrainMap<'a>, + constr_map: &mut ConstrainMap<'a>, arena: &'a Bump, ) -> UnifyResult<'a, ()> { if let DataTyKind::Ident(ty_id) = &self.dty { @@ -179,10 +179,12 @@ impl<'a> DataTy<'a> { ); } } + + let term_ref: &'a DataTy<'a> = arena.alloc(self.clone_in(arena)); constr_map .dty_unifier .values_mut() - .for_each(|dty| SubstIdent::new(ident, self).visit_dty(arena, dty)); + .for_each(|dty| SubstIdent::new(ident, term_ref).visit_dty(arena, dty)); Ok(()) } } @@ -446,9 +448,11 @@ impl<'a> Constrainable<'a> for DataTy<'a> { match (&mut self.dty, &mut other.dty) { (DataTyKind::Ident(i1), DataTyKind::Ident(i2)) => { if i1.is_implicit { - other.bind_to(i1, constr_map, arena)? + let i1_ref: &'a Ident<'a> = arena.alloc(i1.clone()); + other.bind_to(i1_ref, constr_map, arena)? } else if i2.is_implicit { - self.bind_to(i2, constr_map, arena)? + let i2_ref: &'a Ident<'a> = arena.alloc(i2.clone()); + self.bind_to(i2_ref, constr_map, arena)? } else if i1 == i2 { return Ok(()); } else { @@ -458,11 +462,13 @@ impl<'a> Constrainable<'a> for DataTy<'a> { substitute(constr_map, other, arena); } (DataTyKind::Ident(i), _) if i.is_implicit => { - other.bind_to(i, constr_map, arena)?; + let i_ref: &'a Ident<'a> = arena.alloc(i.clone()); + other.bind_to(i_ref, constr_map, arena)?; substitute(constr_map, other, arena); } (_, DataTyKind::Ident(i)) if i.is_implicit => { - self.bind_to(i, constr_map, arena)?; + let i_ref: &'a Ident<'a> = arena.alloc(i.clone()); + self.bind_to(i_ref, constr_map, arena)?; substitute(constr_map, self, arena); } (DataTyKind::Scalar(sty1), DataTyKind::Scalar(sty2)) => { @@ -478,26 +484,40 @@ impl<'a> Constrainable<'a> for DataTy<'a> { own: own1, mem: mem1, dty: dty1, - } = ref1.as_mut(); + } = (**ref1).clone_in(arena); + let RefDty { rgn: rgn2, own: own2, mem: mem2, dty: dty2, - } = ref2.as_mut(); + } = (**ref2).clone_in(arena); if own1 != own2 { return Err(UnifyError::CannotUnify); } - rgn1.constrain(rgn2, constr_map, prv_rels, arena)?; - substitute(constr_map, &mut **dty1, arena); - substitute(constr_map, &mut **dty2, arena); - mem1.constrain(mem2, constr_map, prv_rels, arena)?; - substitute(constr_map, mem1, arena); - substitute(constr_map, mem2, arena); - substitute(constr_map, &mut **dty1, arena); - substitute(constr_map, &mut **dty2, arena); - dty1.constrain(dty2, constr_map, prv_rels, arena)?; + + let mut rgn1 = rgn1; + let mut rgn2 = rgn2; + rgn1.constrain(&mut rgn2, constr_map, prv_rels, arena)?; + + let mut dty1_mut = (*dty1).clone(); + let mut dty2_mut = (*dty2).clone(); + + substitute(constr_map, &mut dty1_mut, arena); + substitute(constr_map, &mut dty2_mut, arena); + + let mut mem1 = mem1; + let mut mem2 = mem2; + mem1.constrain(&mut mem2, constr_map, prv_rels, arena)?; + + substitute(constr_map, &mut mem1, arena); + substitute(constr_map, &mut mem2, arena); + substitute(constr_map, &mut dty1_mut, arena); + substitute(constr_map, &mut dty1_mut, arena); + + dty1_mut.constrain(&mut dty2_mut, constr_map, prv_rels, arena)?; + substitute(constr_map, self, arena); substitute(constr_map, other, arena); } @@ -522,6 +542,27 @@ impl<'a> Constrainable<'a> for DataTy<'a> { } } (DataTyKind::Struct(struct_decl1), DataTyKind::Struct(struct_decl2)) => { + if struct_decl1.fields.len() != struct_decl2.fields.len() { + return Err(UnifyError::CannotUnify); + } + + for ((lname, lty_ref), (rname, rty_ref)) in + struct_decl1.fields.iter().zip(struct_decl2.fields.iter()) + { + if lname != rname { + return Err(UnifyError::CannotUnify); + } + + let mut lty = lty_ref.clone_in(arena); + let mut rty = rty_ref.clone_in(arena); + + lty.constrain(&mut rty, constr_map, prv_rels, arena)?; + } + + substitute(constr_map, self, arena); + substitute(constr_map, other, arena); + + /* let mut i = 0; let mut remain_lhs = &mut struct_decl1.fields[i..]; let mut remain_rhs = &mut struct_decl2.fields[i..]; @@ -547,20 +588,30 @@ impl<'a> Constrainable<'a> for DataTy<'a> { remain_lhs = &mut struct_decl1.fields[i..]; remain_rhs = &mut struct_decl2.fields[i..]; } + */ } (DataTyKind::Array(dty1, n1), DataTyKind::Array(dty2, n2)) | (DataTyKind::ArrayShape(dty1, n1), DataTyKind::ArrayShape(dty2, n2)) => { - dty1.constrain(dty2, constr_map, prv_rels, arena)?; - substitute(constr_map, &mut **dty1, arena); - substitute(constr_map, &mut **dty2, arena); + let mut dty1_owned = (**dty1).clone(); + let mut dty2_owned = (**dty2).clone(); + dty1_owned.constrain(&mut dty2_owned, constr_map, prv_rels, arena)?; + substitute(constr_map, &mut dty1_owned, arena); + substitute(constr_map, &mut dty2_owned, arena); + *dty1 = arena.alloc(dty1_owned); + *dty2 = arena.alloc(dty2_owned); + n1.constrain(n2, constr_map, prv_rels, arena)?; substitute(constr_map, self, arena); substitute(constr_map, other, arena); } (DataTyKind::At(dty1, mem1), DataTyKind::At(dty2, mem2)) => { - dty1.constrain(dty2, constr_map, prv_rels, arena)?; - substitute(constr_map, &mut **dty1, arena); - substitute(constr_map, &mut **dty2, arena); + let mut dty1_owned = (**dty1).clone(); + let mut dty2_owned = (**dty2).clone(); + dty1_owned.constrain(&mut dty2_owned, constr_map, prv_rels, arena)?; + substitute(constr_map, &mut dty1_owned, arena); + substitute(constr_map, &mut dty2_owned, arena); + *dty1 = arena.alloc(dty1_owned); + *dty2 = arena.alloc(dty2_owned); mem1.constrain(mem2, constr_map, prv_rels, arena)?; substitute(constr_map, self, arena); substitute(constr_map, other, arena); @@ -579,7 +630,9 @@ impl<'a> Constrainable<'a> for DataTy<'a> { panic!() } (dty1, DataTyKind::Dead(dty2)) if !matches!(dty1, DataTyKind::Dead(_)) => { - self.constrain(dty2, constr_map, prv_rels, arena)?; + let mut dty2_owned = (**dty2).clone(); + self.constrain(&mut dty2_owned, constr_map, prv_rels, arena)?; + *dty2 = arena.alloc(dty2_owned); substitute(constr_map, self, arena); substitute(constr_map, other, arena); } @@ -609,27 +662,40 @@ impl<'a> Constrainable<'a> for ExecTy<'a> { | (ExecTyKind::GpuThread, ExecTyKind::GpuThread) | (ExecTyKind::GpuWarp, ExecTyKind::GpuWarp) | (_, ExecTyKind::Any) => Ok(()), - (ExecTyKind::GpuWarpGrp(nl), ExecTyKind::GpuWarpGrp(nr)) => { - nl.constrain(nr, constr_map, prv_rels, arena) + + (ExecTyKind::GpuWarpGrp(ln), ExecTyKind::GpuWarpGrp(rn)) => { + let mut l = (*ln).clone_in(arena); + let mut r = (*rn).clone_in(arena); + l.constrain(&mut r, constr_map, prv_rels, arena) } - (ExecTyKind::GpuGrid(lgdim, lbdim), ExecTyKind::GpuGrid(rgdim, rbdim)) - | (ExecTyKind::GpuBlockGrp(lgdim, lbdim), ExecTyKind::GpuBlockGrp(rgdim, rbdim)) => { - lgdim.constrain(rgdim, constr_map, prv_rels, arena)?; - lbdim.constrain(rbdim, constr_map, prv_rels, arena) + + (ExecTyKind::GpuGrid(lg, lb), ExecTyKind::GpuGrid(rg, rb)) + | (ExecTyKind::GpuBlockGrp(lg, lb), ExecTyKind::GpuBlockGrp(rg, rb)) => { + let mut lgc = (*lg).clone_in(arena); + let mut rgc = (*rg).clone_in(arena); + lgc.constrain(&mut rgc, constr_map, prv_rels, arena)?; + + let mut lbc = (*lb).clone_in(arena); + let mut rbc = (*rb).clone_in(arena); + lbc.constrain(&mut rbc, constr_map, prv_rels, arena) } - ( - ExecTyKind::GpuToThreads(ldim_compo, l_inner), - ExecTyKind::GpuToThreads(rdim_compo, r_inner), - ) => { - if ldim_compo != rdim_compo { + + (ExecTyKind::GpuToThreads(ldc, l_inner), ExecTyKind::GpuToThreads(rdc, r_inner)) => { + if ldc != rdc { return Err(UnifyError::CannotUnify); } - l_inner.constrain(r_inner, constr_map, prv_rels, arena) + let mut li = (*l_inner).clone_in(arena); + let mut ri = (*r_inner).clone_in(arena); + li.constrain(&mut ri, constr_map, prv_rels, arena) } - (ExecTyKind::GpuBlock(ldim), ExecTyKind::GpuBlock(rdim)) - | (ExecTyKind::GpuThreadGrp(ldim), ExecTyKind::GpuThreadGrp(rdim)) => { - ldim.constrain(rdim, constr_map, prv_rels, arena) + + (ExecTyKind::GpuBlock(ld), ExecTyKind::GpuBlock(rd)) + | (ExecTyKind::GpuThreadGrp(ld), ExecTyKind::GpuThreadGrp(rd)) => { + let mut lc = (*ld).clone_in(arena); + let mut rc = (*rd).clone_in(arena); + lc.constrain(&mut rc, constr_map, prv_rels, arena) } + _ => Err(UnifyError::CannotUnify), } } @@ -642,6 +708,7 @@ impl<'a> Substitutable<'a> for ExecTy<'a> { } } +/** impl<'a> Constrainable<'a> for Dim<'a> { fn constrain<'m>( &'m mut self, @@ -669,6 +736,57 @@ impl<'a> Constrainable<'a> for Dim<'a> { } } } +*/ + +impl<'a> Constrainable<'a> for Dim<'a> { + fn constrain<'m>( + &'m mut self, + other: &'m mut Self, + constr_map: &'m mut ConstrainMap<'a>, + prv_rels: &'m mut BumpVec<'a, PrvConstr<'a>>, + arena: &'a Bump, + ) -> UnifyResult<'a, ()> { + use Dim::*; + + match (self, other) { + (XYZ(ld), XYZ(rd)) => { + let mut lx = ld.0.clone_in(arena); + let mut rx = rd.0.clone_in(arena); + lx.constrain(&mut rx, constr_map, prv_rels, arena)?; + + let mut ly = ld.1.clone_in(arena); + let mut ry = rd.1.clone_in(arena); + ly.constrain(&mut ry, constr_map, prv_rels, arena)?; + + let mut lz = ld.2.clone_in(arena); + let mut rz = rd.2.clone_in(arena); + lz.constrain(&mut rz, constr_map, prv_rels, arena)?; + + Ok(()) + } + + (XY(ld), XY(rd)) | (XZ(ld), XZ(rd)) | (YZ(ld), YZ(rd)) => { + let mut l0 = ld.0.clone_in(arena); + let mut r0 = rd.0.clone_in(arena); + l0.constrain(&mut r0, constr_map, prv_rels, arena)?; + + let mut l1 = ld.1.clone_in(arena); + let mut r1 = rd.1.clone_in(arena); + l1.constrain(&mut r1, constr_map, prv_rels, arena)?; + + Ok(()) + } + + (X(ld), X(rd)) | (Y(ld), Y(rd)) | (Z(ld), Z(rd)) => { + let mut ln = ld.0.clone_in(arena); + let mut rn = rd.0.clone_in(arena); + ln.constrain(&mut rn, constr_map, prv_rels, arena) + } + + _ => Err(UnifyError::CannotUnify), + } + } +} impl<'a> Substitutable<'a> for Dim<'a> { fn substitute(&mut self, subst: &ConstrainMap<'a>, arena: &'a Bump) { @@ -679,10 +797,9 @@ impl<'a> Substitutable<'a> for Dim<'a> { impl<'a> Nat<'a> { fn bind_to( - &'a self, + &self, ident: &'a Ident<'a>, - constr_map: &'a mut ConstrainMap<'a>, - _: &'a mut BumpVec<'a, PrvConstr<'a>>, + constr_map: &mut ConstrainMap<'a>, arena: &'a Bump, ) -> UnifyResult<'a, ()> { // No occurs check. @@ -698,18 +815,15 @@ impl<'a> Nat<'a> { ) } } + let term_ref: &'a Nat<'a> = arena.alloc(self.clone_in(arena)); constr_map .nat_unifier .values_mut() - .for_each(|n| SubstIdent::new(ident, self).visit_nat(arena, n)); + .for_each(|n| SubstIdent::new(ident, term_ref).visit_nat(arena, n)); Ok(()) } - fn unify( - n1: &'a Nat<'a>, - n2: &'a Nat<'a>, - _constr_map: &'a mut ConstrainMap<'a>, - ) -> UnifyResult<'a, ()> { + fn unify<'m>(n1: &'m Nat<'a>, n2: &'m Nat<'a>) -> UnifyResult<'a, ()> { if n1 == n2 { Ok(()) } else { @@ -729,27 +843,39 @@ impl<'a> Constrainable<'a> for Nat<'a> { match (&*self, &*other) { (Nat::Ident(n1i), Nat::Ident(n2i)) if n1i.is_implicit || n2i.is_implicit => { match (n1i.is_implicit, n2i.is_implicit) { - (true, _) => other.bind_to(n1i, constr_map, prv_rels, arena), - (false, _) => self.bind_to(n2i, constr_map, prv_rels, arena), + (true, _) => other.bind_to(arena.alloc(n1i.clone()), constr_map, arena), + (false, _) => self.bind_to(arena.alloc(n2i.clone()), constr_map, arena), } } (Nat::Ident(n1i), _) if n1i.is_implicit => { - other.bind_to(n1i, constr_map, prv_rels, arena) + other.bind_to(arena.alloc(n1i.clone()), constr_map, arena) } (_, Nat::Ident(n2i)) if n2i.is_implicit => { - self.bind_to(n2i, constr_map, prv_rels, arena) + self.bind_to(arena.alloc(n2i.clone()), constr_map, arena) } (Nat::BinOp(op1, n1l, n1r), Nat::BinOp(op2, n2l, n2r)) if op1 == op2 => { - n1l.constrain(n2l, constr_map, prv_rels, arena)?; - n1r.constrain(n2r, constr_map, prv_rels, arena) + let mut l_left = (*n1l).clone_in(arena); + let mut r_left = (*n2l).clone_in(arena); + l_left.constrain(&mut r_left, constr_map, prv_rels, arena)?; + + let mut l_right = (*n1r).clone_in(arena); + let mut r_right = (*n2r).clone_in(arena); + l_right.constrain(&mut r_right, constr_map, prv_rels, arena)?; + + Ok(()) } (Nat::App(f1, ns1), Nat::App(f2, ns2)) if f1 == f2 => { - for (n1, n2) in ns1.iter_mut().zip(ns2.iter_mut()) { - n1.constrain(n2, constr_map, prv_rels, arena)?; + if ns1.len() != ns2.len() { + return Err(UnifyError::CannotUnify); + } + for (n1, n2) in ns1.iter().zip(ns2.iter()) { + let mut l = n1.clone_in(arena); + let mut r = n2.clone_in(arena); + l.constrain(&mut r, constr_map, prv_rels, arena)?; } Ok(()) } - _ => Self::unify(self, other, constr_map), + _ => Self::unify(self, other), } } } @@ -763,9 +889,9 @@ impl<'a> Substitutable<'a> for Nat<'a> { impl<'a> Memory<'a> { fn bind_to( - &'a self, + &self, ident: &'a Ident<'a>, - constr_map: &'a mut ConstrainMap<'a>, + constr_map: &mut ConstrainMap<'a>, arena: &'a Bump, ) -> UnifyResult<'a, ()> { if Self::occurs_check(&IdentKinded::new(ident, Kind::Memory), self) { @@ -789,10 +915,11 @@ impl<'a> Memory<'a> { ) } } + let term_ref: &'a Memory<'a> = arena.alloc(self.clone_in(arena)); constr_map .mem_unifier .values_mut() - .for_each(|m| SubstIdent::new(ident, self).visit_mem(arena, m)); + .for_each(|m| SubstIdent::new(ident, term_ref).visit_mem(arena, m)); Ok(()) } } @@ -808,11 +935,11 @@ impl<'a> Constrainable<'a> for Memory<'a> { match (&*self, &*other) { (Memory::Ident(i1), Memory::Ident(i2)) if i1 == i2 => Ok(()), (Memory::Ident(i1), Memory::Ident(i2)) => match (i1.is_implicit, i2.is_implicit) { - (true, _) => other.bind_to(i1, constr_map, arena), - (false, _) => self.bind_to(i2, constr_map, arena), + (true, _) => other.bind_to(arena.alloc(i1.clone()), constr_map, arena), + (false, _) => self.bind_to(arena.alloc(i2.clone()), constr_map, arena), }, - (Memory::Ident(i), o) => o.bind_to(i, constr_map, arena), - (s, Memory::Ident(i)) => s.bind_to(i, constr_map, arena), + (Memory::Ident(i), o) => o.bind_to(arena.alloc(i.clone()), constr_map, arena), + (s, Memory::Ident(i)) => s.bind_to(arena.alloc(i.clone()), constr_map, arena), (mem1, mem2) if mem1 == mem2 => Ok(()), _ => Err(UnifyError::CannotUnify), } @@ -828,9 +955,9 @@ impl<'a> Substitutable<'a> for Memory<'a> { impl<'a> Provenance<'a> { fn bind_to( - &'a self, + &self, ident: &'a Ident<'a>, - constr_map: &'a mut ConstrainMap<'a>, + constr_map: &mut ConstrainMap<'a>, arena: &'a Bump, ) -> UnifyResult<'a, ()> { // TODO not necessary, since no recursion possible @@ -855,10 +982,11 @@ impl<'a> Provenance<'a> { ) } } + let term_ref: &'a Provenance<'a> = arena.alloc(self.clone_in(arena)); constr_map .prv_unifier .values_mut() - .for_each(|m| SubstIdent::new(ident, self).visit_prv(arena, m)); + .for_each(|m| SubstIdent::new(ident, term_ref).visit_prv(arena, m)); Ok(()) } } @@ -875,14 +1003,19 @@ impl<'a> Constrainable<'a> for Provenance<'a> { match (&*self, &*other) { (Provenance::Ident(i1), Provenance::Ident(i2)) if i1 == i2 => Ok(()), (Provenance::Ident(i), r) | (r, Provenance::Ident(i)) if i.is_implicit => { - r.bind_to(i, constr_map, arena) + let i_ref: &'a Ident<'a> = arena.alloc(i.clone()); + r.bind_to(i_ref, constr_map, arena) } (Provenance::Ident(_), _) | (_, Provenance::Ident(_)) => { - prv_rels.push(PrvConstr(self.clone(), other.clone())); + let l_ref: &'a Provenance<'a> = arena.alloc(self.clone_in(arena)); + let r_ref: &'a Provenance<'a> = arena.alloc(other.clone_in(arena)); + prv_rels.push(PrvConstr(l_ref, r_ref)); Ok(()) } (Provenance::Value(_), Provenance::Value(_)) => { - prv_rels.push(PrvConstr(self.clone(), other.clone())); + let l_ref: &'a Provenance<'a> = arena.alloc(self.clone_in(arena)); + let r_ref: &'a Provenance<'a> = arena.alloc(other.clone_in(arena)); + prv_rels.push(PrvConstr(l_ref, r_ref)); Ok(()) } } @@ -1006,6 +1139,7 @@ impl<'a> VisitMut<'a> for SubstIdent<'a, DataTy<'a>> { } } +/** impl<'a> VisitMut<'a> for SubstIdent<'a, ExecExpr<'a>> { fn visit_exec_expr(&mut self, arena: &'a Bump, exec: &mut ExecExpr<'a>) { if let BaseExec::Ident(i) = &exec.exec.base { @@ -1017,6 +1151,39 @@ impl<'a> VisitMut<'a> for SubstIdent<'a, ExecExpr<'a>> { } } } +*/ + +impl<'a> VisitMut<'a> for SubstIdent<'a, ExecExpr<'a>> { + fn visit_exec_expr(&mut self, arena: &'a Bump, exec: &mut ExecExpr<'a>) { + use crate::arena_ast::{BaseExec, ExecExpr, ExecExprKind}; + + if let BaseExec::Ident(i) = &exec.exec.base { + if i.name == self.ident.name { + let mut merged = bumpalo::collections::Vec::new_in(arena); + + for e in self.term.exec.path.iter() { + merged.push(e.clone_in(arena)); + } + for e in exec.exec.path.iter() { + merged.push(e.clone_in(arena)); + } + + let new_kind = arena.alloc(ExecExprKind { + base: self.term.exec.base.clone_in(arena), + path: merged, + }); + + *exec = ExecExpr { + exec: new_kind, + ty: exec.ty, + span: exec.span, + }; + + return; + } + } + } +} #[cfg(test)] mod tests { From 475205759ec3442b63d82193587235ad2e288ff3 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 19 Aug 2025 08:32:51 +0200 Subject: [PATCH 54/57] updated unify tests --- src/ty_check/unify.rs | 131 ++++++++++++++++++++++++++++-------------- 1 file changed, 87 insertions(+), 44 deletions(-) diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index 8b88ae3d..e5c81cc9 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -1188,79 +1188,122 @@ impl<'a> VisitMut<'a> for SubstIdent<'a, ExecExpr<'a>> { #[cfg(test)] mod tests { use super::*; + use bumpalo::Bump; + + fn shrd_ref_ty<'a>(arena: &'a Bump) -> DataTy<'a> { + //Dim::X(Box::new(Dim1d(Nat::Lit(32)))); + let elem = DataTy::new(arena, DataTyKind::Scalar(ScalarTy::I32)); + let arr = DataTy::new( + arena, + DataTyKind::Array(arena.alloc(elem), Nat::Ident(Ident::new(arena, "n"))), + ); - fn shrd_ref_ty<'a>() -> DataTy<'a> { - Dim::X(Box::new(Dim1d(Nat::Lit(32)))); - DataTy::new(DataTyKind::Ref(Box::new(RefDty::new( - Provenance::Value("r".to_string()), + let ref_dty = RefDty::new( + arena, + Provenance::Value("r"), Ownership::Shrd, Memory::GpuGlobal, - DataTy::new(DataTyKind::Array( - Box::new(DataTy::new(DataTyKind::Scalar(ScalarTy::I32))), - Nat::Ident(Ident::new("n")), - )), - )))) + arr, + ); + + DataTy::new(arena, DataTyKind::Ref(arena.alloc(ref_dty))) } #[test] fn scalar<'a>() -> UnifyResult<'a, ()> { - let mut i32 = DataTy::new(DataTyKind::Scalar(ScalarTy::I32)); - let mut t = DataTy::new(DataTyKind::Ident(Ident::new_impli("t"))); - let (subst, _) = constrain(&mut i32, &mut t)?; - substitute(&subst, &mut i32); - substitute(&subst, &mut t); - assert_eq!(i32, t); + let arena = Bump::new(); + + let mut i32_ty = DataTy::new(&arena, DataTyKind::Scalar(ScalarTy::I32)); + let mut t = DataTy::new(&arena, DataTyKind::Ident(Ident::new_impli(&arena, "t"))); + + let lhs = arena.alloc(i32_ty.clone_in(&arena)); + let rhs = arena.alloc(t.clone_in(&arena)); + let (subst, _prv) = constrain(lhs, rhs, &arena).unwrap(); + + substitute(&subst, &mut i32_ty, &arena); + substitute(&subst, &mut t, &arena); + + assert_eq!(i32_ty, t); Ok(()) } - #[test] fn shrd_reft<'a>() -> UnifyResult<'a, ()> { - let mut t = DataTy::new(DataTyKind::Ident(Ident::new_impli("t"))); - let mut shrd_ref = shrd_ref_ty(); - let (subst, _) = constrain(&mut shrd_ref, &mut t)?; - substitute(&subst, &mut shrd_ref); - substitute(&subst, &mut t); + let arena = Bump::new(); + + let mut t = DataTy::new(&arena, DataTyKind::Ident(Ident::new_impli(&arena, "t"))); + let mut shrd_ref = shrd_ref_ty(&arena); + + let lhs = arena.alloc(shrd_ref.clone_in(&arena)); + let rhs = arena.alloc(t.clone_in(&arena)); + let (subst, _prv) = constrain(lhs, rhs, &arena).unwrap(); + + substitute(&subst, &mut shrd_ref, &arena); + substitute(&subst, &mut t, &arena); + assert_eq!(shrd_ref, t); Ok(()) } #[test] fn shrd_ref_inner_var<'a>() -> UnifyResult<'a, ()> { - let mut shrd_ref_t = DataTy::new(DataTyKind::Ref(Box::new(RefDty::new( - Provenance::Value("r".to_string()), + use bumpalo::Bump; + + let arena = Bump::new(); + + let inner_t = DataTy::new(&arena, DataTyKind::Ident(Ident::new_impli(&arena, "t"))); + let ref_t = RefDty::new( + &arena, + Provenance::Value("r"), Ownership::Shrd, Memory::GpuGlobal, - DataTy::new(DataTyKind::Ident(Ident::new_impli("t"))), - )))); - let mut shrd_ref = shrd_ref_ty(); - let (subst, _) = constrain(&mut shrd_ref, &mut shrd_ref_t)?; + inner_t, + ); + let mut shrd_ref_t = DataTy::new(&arena, DataTyKind::Ref(arena.alloc(ref_t))); + + let mut shrd_ref = shrd_ref_ty(&arena); + + let lhs = arena.alloc(shrd_ref.clone_in(&arena)); + let rhs = arena.alloc(shrd_ref_t.clone_in(&arena)); + let (subst, _prv) = constrain(lhs, rhs, &arena).unwrap(); println!("{:?}", subst); - substitute(&subst, &mut shrd_ref); - substitute(&subst, &mut shrd_ref_t); + + substitute(&subst, &mut shrd_ref, &arena); + substitute(&subst, &mut shrd_ref_t, &arena); + assert_eq!(shrd_ref, shrd_ref_t); Ok(()) } #[test] fn prv_val_ident<'a>() -> UnifyResult<'a, ()> { - let mut shrd_ref_t = DataTy::new(DataTyKind::Ref(Box::new(RefDty::new( - Provenance::Ident(Ident::new("a")), + use bumpalo::Bump; + + let arena = Bump::new(); + + let inner_t = DataTy::new(&arena, DataTyKind::Ident(Ident::new_impli(&arena, "t"))); + let ref_t = RefDty::new( + &arena, + Provenance::Ident(Ident::new(&arena, "a")), Ownership::Shrd, Memory::GpuGlobal, - DataTy::new(DataTyKind::Ident(Ident::new_impli("t"))), - )))); - let mut shrd_ref = shrd_ref_ty(); - let (subst, prv_rels) = constrain(&mut shrd_ref, &mut shrd_ref_t)?; - println!("{:?}", subst); - substitute(&subst, &mut shrd_ref); - substitute(&subst, &mut shrd_ref_t); - assert_eq!( - prv_rels[0], - PrvConstr( - Provenance::Value("r".to_string()), - Provenance::Ident(Ident::new("a")) - ) + inner_t, + ); + let mut shrd_ref_t = DataTy::new(&arena, DataTyKind::Ref(arena.alloc(ref_t))); + + let mut shrd_ref = shrd_ref_ty(&arena); + + let lhs = arena.alloc(shrd_ref.clone_in(&arena)); + let rhs = arena.alloc(shrd_ref_t.clone_in(&arena)); + let (subst, prv_rels) = constrain(lhs, rhs, &arena).unwrap(); + + substitute(&subst, &mut shrd_ref, &arena); + substitute(&subst, &mut shrd_ref_t, &arena); + + let expected = PrvConstr( + arena.alloc(Provenance::Value("r")), + arena.alloc(Provenance::Ident(Ident::new(&arena, "a"))), ); + assert_eq!(prv_rels[0], expected); Ok(()) } } From 2dde4715450264c725899cb887464bc62f3e29a5 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 19 Aug 2025 08:34:09 +0200 Subject: [PATCH 55/57] fixed error in exec --- src/ty_check/exec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ty_check/exec.rs b/src/ty_check/exec.rs index 5298d4c4..a352bfe6 100644 --- a/src/ty_check/exec.rs +++ b/src/ty_check/exec.rs @@ -27,7 +27,7 @@ pub(super) fn ty_check<'a>( } } BaseExec::CpuThread => ExecTyKind::CpuThread, - BaseExec::GpuGrid(gdim, bdim) => ExecTyKind::GpuGrid(gdim.clone(), bdim.clone()), + BaseExec::GpuGrid(gdim, bdim) => ExecTyKind::GpuGrid((**gdim).clone(), (**bdim).clone()), }; // 2) Bump‐allocate that base kind so we have &'a ExecTyKind From 48bcfbfd621798b419e60f218daa87c8d3b4ae24 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Tue, 19 Aug 2025 16:47:48 +0200 Subject: [PATCH 56/57] worked on pl_expr.rs in type checking, added some arena methods, fixed some bugs --- src/arena_ast/mod.rs | 48 ++++++- src/arena_ast/visit_mut.rs | 2 +- src/ast/mod.rs | 15 +- src/ty_check/ctxs.rs | 12 ++ src/ty_check/infer_kinded_args.rs | 14 +- src/ty_check/pl_expr.rs | 232 ++++++++++++++++++------------ src/ty_check/subty.rs | 72 +++++----- src/ty_check/unify.rs | 6 +- 8 files changed, 258 insertions(+), 143 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index 80d4a43d..1a9ff40a 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -13,6 +13,8 @@ pub mod utils; pub mod visit; pub mod visit_mut; +use std::cell::OnceCell; + #[derive(Debug)] pub struct CompilUnit<'a> { pub items: BumpVec<'a, Item<'a>>, @@ -661,6 +663,16 @@ impl<'a> ArgKinded<'a> { _ => Ok(false), } } + + pub fn clone_in(&self, arena: &'a bumpalo::Bump) -> Self { + match self { + ArgKinded::Ident(i) => ArgKinded::Ident(i.clone()), + ArgKinded::Nat(n) => ArgKinded::Nat(n.clone_in(arena)), + ArgKinded::Memory(m) => ArgKinded::Memory(m.clone_in(arena)), + ArgKinded::DataTy(d) => ArgKinded::DataTy(d.clone_in(arena)), + ArgKinded::Provenance(p) => ArgKinded::Provenance(p.clone_in(arena)), + } + } } #[span_derive(PartialEq, Eq, Hash)] @@ -669,7 +681,7 @@ pub struct PlaceExpr<'a> { pub pl_expr: PlaceExprKind<'a>, // FIXME misusing span_derive_ignore to ignore type on equality checks #[span_derive_ignore] - pub ty: Option<&'a Ty<'a>>, + pub ty: OnceCell<&'a Ty<'a>>, #[span_derive_ignore] pub span: Option, } @@ -713,6 +725,22 @@ impl<'a> View<'a> { Ok(true) } + + pub fn clone_in(&self, arena: &'a bumpalo::Bump) -> Self { + // Clone generic arguments into the arena + let mut gen_args = bumpalo::collections::Vec::new_in(arena); + gen_args.extend(self.gen_args.iter().map(|ga| ga.clone_in(arena))); + + // Clone nested views into the arena + let mut args = bumpalo::collections::Vec::new_in(arena); + args.extend(self.args.iter().map(|v| v.clone_in(arena))); + + View { + name: self.name.clone(), + gen_args, + args, + } + } } // TODO create generic View struct to enable easier extensibility by introducing only @@ -760,7 +788,7 @@ impl<'a> PlaceExpr<'a> { pub fn new(pl_expr: PlaceExprKind<'a>) -> Self { PlaceExpr { pl_expr, - ty: None, + ty: OnceCell::new(), span: None, } } @@ -768,11 +796,23 @@ impl<'a> PlaceExpr<'a> { pub fn with_span(pl_expr: PlaceExprKind<'a>, span: Span) -> Self { PlaceExpr { pl_expr, - ty: None, + ty: OnceCell::new(), span: Some(span), } } + pub fn set_ty(&self, arena: &'a bumpalo::Bump, ty: Ty<'a>) { + let ty_ref = arena.alloc(ty); + // Ignore the error if already set, or assert if you prefer: + let _ = self.ty.set(ty_ref); + // or: self.ty.get_or_init(|| arena.alloc(ty)); + } + + /// Read-only access to the inferred type (if already set). + pub fn get_ty(&self) -> Option<&'a Ty<'a>> { + self.ty.get().copied() + } + pub fn is_place(&self) -> bool { match &self.pl_expr { PlaceExprKind::Ident(_) => true, @@ -1875,7 +1915,7 @@ pub enum Memory<'a> { } impl<'a> Memory<'a> { - pub fn clone_in(&self, arena: &'a Bump) -> Self { + pub fn clone_in(&self, _arena: &'a Bump) -> Self { match self { Memory::CpuMem => Memory::CpuMem, Memory::GpuGlobal => Memory::GpuGlobal, diff --git a/src/arena_ast/visit_mut.rs b/src/arena_ast/visit_mut.rs index 2e4a1390..d04ee72b 100644 --- a/src/arena_ast/visit_mut.rs +++ b/src/arena_ast/visit_mut.rs @@ -36,7 +36,7 @@ pub trait VisitMut<'a>: Sized { fn visit_own(&mut self, _own: &mut Ownership) {} fn visit_mutability(&mut self, _mutbl: &mut Mutability) {} fn visit_lit(&mut self, _lit: &mut Lit) {} - fn visit_ident(&mut self, arena: &'a Bump, _ident: &mut Ident<'a>) {} + fn visit_ident(&mut self, _arena: &'a Bump, _ident: &mut Ident<'a>) {} fn visit_pattern(&mut self, arena: &'a Bump, pattern: &mut Pattern<'a>) { walk_pattern(self, arena, pattern) } fn visit_split(&mut self, arena: &'a Bump, split: &mut Split<'a>) { walk_split(self, arena, split) } fn visit_sched(&mut self, arena: &'a Bump, sched: &mut Sched<'a>) { walk_sched(self, arena, sched) } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 2b7b044e..280a2b0a 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -15,6 +15,7 @@ mod span; pub mod utils; pub mod visit; pub mod visit_mut; +use std::cell::OnceCell; #[derive(Clone, Debug)] pub struct CompilUnit<'a> { @@ -1064,12 +1065,20 @@ pub struct PlaceExpr { } impl PlaceExpr { - pub fn into_arena<'a>(self, arena: &'a Bump) -> arena_ast::PlaceExpr<'a> { - arena_ast::PlaceExpr { + pub fn into_arena<'a>(self, arena: &'a bumpalo::Bump) -> arena_ast::PlaceExpr<'a> { + let out = arena_ast::PlaceExpr { pl_expr: self.pl_expr.into_arena(arena), - ty: self.ty.map(|t| &*arena.alloc(t.into_arena(arena))), + ty: OnceCell::new(), span: self.span, + }; + + if let Some(t) = self.ty { + let t_arena = t.into_arena(arena); + let t_ref: &'a arena_ast::Ty<'a> = arena.alloc(t_arena); + let _ = out.ty.set(t_ref); } + + out } } diff --git a/src/ty_check/ctxs.rs b/src/ty_check/ctxs.rs index 30b8a157..a294a042 100644 --- a/src/ty_check/ctxs.rs +++ b/src/ty_check/ctxs.rs @@ -164,6 +164,18 @@ impl<'a> TyCtx<'a> { } } + /// Return an arena-owned snapshot of the loans for `prv_val_name`. + pub fn loans_in_prv_snapshot( + &self, + prv_val_name: &str, + arena: &'a bumpalo::Bump, + ) -> CtxResult<'a, bumpalo::collections::Vec<'a, Loan<'a>>> { + let set = self.loans_in_prv(prv_val_name)?; + let mut out = bumpalo::collections::Vec::new_in(arena); + out.extend(set.iter().cloned()); + Ok(out) + } + pub fn loans_for_prv_mut( &mut self, prv_val_name: &str, diff --git a/src/ty_check/infer_kinded_args.rs b/src/ty_check/infer_kinded_args.rs index 03ee2bd1..56008e1b 100644 --- a/src/ty_check/infer_kinded_args.rs +++ b/src/ty_check/infer_kinded_args.rs @@ -3,6 +3,7 @@ use crate::arena_ast::{ ArgKinded, BaseExec, DataTy, DataTyKind, Dim, ExecExpr, ExecTy, ExecTyKind, FnTy, Ident, Memory, Nat, ParamSig, Provenance, Ty, TyKind, }; +use bumpalo::collections::Vec as BumpVec; use std::collections::HashMap; // mono_ty is function type, @@ -13,27 +14,24 @@ use std::collections::HashMap; pub fn infer_kinded_args<'a>( poly_fn_ty: &'a FnTy<'a>, mono_fn_ty: &'a FnTy<'a>, -) -> TyResult<'a, Vec>> { + arena: &'a bumpalo::Bump, +) -> TyResult<'a, BumpVec<'a, ArgKinded<'a>>> { if poly_fn_ty.param_sigs.len() != mono_fn_ty.param_sigs.len() { panic!("Unexpected difference in amount of parameters."); } - // Map each generic Ident -> inferred ArgKinded let mut res_map: HashMap<&'a Ident<'a>, ArgKinded<'a>> = HashMap::new(); - // 1) from param sigs for (subst_ps, mono_ps) in poly_fn_ty.param_sigs.iter().zip(&mono_fn_ty.param_sigs) { infer_kargs_param_sig(&mut res_map, subst_ps, mono_ps); } - // 2) from exec expr infer_kargs_exec_expr(&mut res_map, &poly_fn_ty.exec, &mono_fn_ty.exec); - - // 3) from return type infer_kargs_tys(&mut res_map, poly_fn_ty.ret_ty, mono_fn_ty.ret_ty); - // 4) build result vector in the order of generics - let mut res_vec = Vec::with_capacity(poly_fn_ty.generics.len()); + let mut res_vec = BumpVec::new_in(arena); + res_vec.reserve(poly_fn_ty.generics.len()); + for g in &poly_fn_ty.generics { match res_map.remove(&g.ident) { Some(arg) => { diff --git a/src/ty_check/pl_expr.rs b/src/ty_check/pl_expr.rs index 16e7ffd1..6b311abc 100644 --- a/src/ty_check/pl_expr.rs +++ b/src/ty_check/pl_expr.rs @@ -10,7 +10,9 @@ use crate::ty_check::ctxs::{AccessCtx, GlobalCtx, KindCtx, TyCtx}; use crate::ty_check::unify; use crate::ty_check::unify::ConstrainMap; use crate::ty_check::{exec, ExprTyCtx}; +use bumpalo::collections::Vec as BumpVec; use bumpalo::Bump; + pub(super) struct PlExprTyCtx<'a> { gl_ctx: &'a GlobalCtx<'a>, nat_ctx: &'a NatCtx<'a>, @@ -76,132 +78,174 @@ pub(super) fn ty_check_and_passed_mems<'a>( // p in an ω context has type τ under Δ and Γ, passing through provenances in Vec<ρ> fn ty_check_and_passed_mems_prvs<'a>( ctx: &'a PlExprTyCtx<'a>, - pl_expr: &'a mut PlaceExpr<'a>, + pl_expr: &'a PlaceExpr<'a>, arena: &'a Bump, ) -> TyResult<'a, (Vec>, Vec>)> { - let (ty, mem, prvs) = match &mut pl_expr.pl_expr { + let (ty, mem, prvs) = match &pl_expr.pl_expr { // TC-Var PlaceExprKind::Ident(ident) => ty_check_ident(ctx, ident)?, // TC-Proj - PlaceExprKind::Proj(tuple_expr, n) => ty_check_proj(ctx, tuple_expr, *n, arena)?, + PlaceExprKind::Proj(tuple_expr, n) => ty_check_proj(ctx, *tuple_expr, *n, arena)?, // TC-Field PlaceExprKind::FieldProj(struct_expr, ident) => { - ty_check_field_proj(ctx, struct_expr, ident, arena)? + ty_check_field_proj(ctx, *struct_expr, ident, arena)? } // TC-Deref - PlaceExprKind::Deref(borr_expr) => ty_check_deref(ctx, borr_expr, arena)?, + PlaceExprKind::Deref(borr_expr) => ty_check_deref(ctx, *borr_expr, arena)?, // TC-Select - PlaceExprKind::Select(p, select_exec) => ty_check_select(ctx, p, select_exec, arena)?, - PlaceExprKind::View(pl_expr, view) => ty_check_view_pl_expr(ctx, pl_expr, view, arena)?, - PlaceExprKind::Idx(pl_expr, idx) => ty_check_index(ctx, pl_expr, idx, arena)?, + PlaceExprKind::Select(pl_expr, select_exec) => { + ty_check_select(ctx, *pl_expr, *select_exec, arena)? + } + PlaceExprKind::View(pl_expr, view) => ty_check_view_pl_expr(ctx, *pl_expr, *view, arena)?, + PlaceExprKind::Idx(pl_expr, idx) => ty_check_index(ctx, *pl_expr, *idx, arena)?, }; - pl_expr.ty = Some(arena.alloc(ty)); + + let _ = pl_expr.ty.set(arena.alloc(ty)); Ok((mem, prvs)) } fn ty_check_view_pl_expr<'a>( ctx: &'a PlExprTyCtx<'a>, - pl_expr: &'a mut PlaceExpr<'a>, - view: &'a mut View<'a>, + pl_expr: &'a PlaceExpr<'a>, + view: &'a View<'a>, arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mems, prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr, arena)?; - let view_fn_ty = ty_check_view(ctx, view, arena)?; - let in_dty = pl_expr.ty.as_ref().unwrap().dty().clone(); - let (res_dty, constr_map) = ty_check_app_view_fn_ty(ctx, &in_dty, view_fn_ty)?; - // substitute implicit identifiers in view, that were inferred from the input data type - unify::substitute(&constr_map, view, arena); + let mut v_tmp = (*view).clone_in(arena); + let view_fn_ty = ty_check_view(ctx, &mut v_tmp, arena)?; + let in_dty_ref: &'a DataTy<'a> = { + let tmp = pl_expr.ty.get().unwrap().dty().clone_in(arena); + arena.alloc(tmp) + }; + let (res_dty, constr_map) = ty_check_app_view_fn_ty(ctx, in_dty_ref, view_fn_ty, arena)?; + unify::substitute(&constr_map, &mut v_tmp, arena); Ok((Ty::new(TyKind::Data(arena.alloc(res_dty))), mems, prvs)) } fn ty_check_app_view_fn_ty<'a>( ctx: &'a PlExprTyCtx<'a>, in_dty: &'a DataTy<'a>, - mut view_fn_ty: FnTy<'a>, + view_fn_ty: FnTy<'a>, + arena: &'a Bump, ) -> TyResult<'a, (DataTy<'a>, ConstrainMap<'a>)> { - let mut arg_dty_fn_ty = FnTy::new( - vec![], + let arg_dty_fn_ty = FnTy::new( + arena, + std::iter::empty(), None, - vec![ParamSig::new( + [ParamSig::new( ctx.exec.clone(), - Ty::new(TyKind::Data(Box::new(in_dty.clone()))), + arena.alloc(Ty::new(TyKind::Data(arena.alloc(in_dty.clone_in(arena))))), )], ctx.exec.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(DataTyKind::Ident( - Ident::new_impli("ret_dty"), + arena.alloc(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + arena, + DataTyKind::Ident(Ident::new_impli(arena, "ret_dty")), ))))), - vec![], + std::iter::empty(), ); - let (constr_map, _) = unify::constrain(&mut arg_dty_fn_ty, &mut view_fn_ty, arena)?; - let res_dty = arg_dty_fn_ty.ret_ty.dty().clone(); + + let arg_ptr = arena.alloc(arg_dty_fn_ty); + let view_ptr = arena.alloc(view_fn_ty); + + let (constr_map, _prv) = unify::constrain(arg_ptr, view_ptr, arena)?; + + let mut res_dty = DataTy::new(arena, DataTyKind::Ident(Ident::new_impli(arena, "ret_dty"))); + unify::substitute(&constr_map, &mut res_dty, arena); + Ok((res_dty, constr_map)) } -fn ty_check_view<'a>( +fn ty_check_view<'a, 'm>( ctx: &'a PlExprTyCtx<'a>, - view: &'a mut View<'a>, + view: &'m mut View<'a>, arena: &'a Bump, ) -> TyResult<'a, FnTy<'a>> { - let arg_tys = view - .args - .iter_mut() - .map(|v| { - Ok(Ty::new(TyKind::FnTy( - arena.alloc(ty_check_view(ctx, v, arena)?), - ))) - }) - .collect::>>()?; - let view_fn_ty = ctx.gl_ctx.fn_ty_by_ident(&view.name)?; - let partially_applied_view_fn_ty = super::apply_gen_args_to_fn_ty_checked( + let mut arg_tys = BumpVec::new_in(arena); + for v in view.args.iter_mut() { + let inner = ty_check_view(ctx, v, arena)?; + arg_tys.push(Ty::new(TyKind::FnTy(arena.alloc(inner)))); + } + + let name_ref: &'a Ident<'a> = arena.alloc(view.name.clone()); + let view_fn_ty = ctx.gl_ctx.fn_ty_by_ident(name_ref)?; + + let gen_args_ref = { + let mut tmp = BumpVec::new_in(arena); + for ga in view.gen_args.iter() { + tmp.push(ga.clone_in(arena)); + } + arena.alloc(tmp) + }; + + let partially_applied_view_fn_ty = arena.alloc(super::apply_gen_args_to_fn_ty_checked( ctx.kind_ctx, &ctx.exec, view_fn_ty, - &view.gen_args, - )?; - let mut actual_view_fn_ty = - create_view_ty_with_input_view_and_free_ret(&ctx.exec, arg_tys, arena); - let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_view_fn_ty, arena); - let (constr_map, _) = unify::constrain(&mut actual_view_fn_ty, &mut mono_fn_ty, arena)?; - // substitute implicit identifiers in view, that were inferred without the input data type + gen_args_ref, + )?); + + let actual_view_fn_ty = arena.alloc(create_view_ty_with_input_view_and_free_ret( + &ctx.exec, arg_tys, arena, + )); + + let mono_fn_ty = arena.alloc(unify::inst_fn_ty_scheme( + partially_applied_view_fn_ty, + arena, + )); + + let (constr_map, _) = unify::constrain(actual_view_fn_ty, mono_fn_ty, arena)?; + unify::substitute(&constr_map, view, arena); - let mut inferred_k_args = - super::infer_kinded_args::infer_kinded_args(&partially_applied_view_fn_ty, &mono_fn_ty)?; - view.gen_args.append(&mut inferred_k_args); + + let inferred_k_args = super::infer_kinded_args::infer_kinded_args( + partially_applied_view_fn_ty, + mono_fn_ty, + arena, + )?; + view.gen_args.extend(inferred_k_args.into_iter()); + let res_view_ty = FnTy::new( - vec![], + arena, + std::iter::empty(), actual_view_fn_ty.generic_exec.clone(), - vec![actual_view_fn_ty.param_sigs.pop().unwrap()], + std::iter::once(actual_view_fn_ty.param_sigs.pop().expect("param exists")), actual_view_fn_ty.exec.clone(), - actual_view_fn_ty.ret_ty.clone(), - vec![], + actual_view_fn_ty.ret_ty, // &'a Ty<'a> + std::iter::empty(), ); + Ok(res_view_ty) } fn create_view_ty_with_input_view_and_free_ret<'a>( - exec: &ExecExpr, - mut arg_tys: Vec>, + exec: &ExecExpr<'a>, + mut arg_tys: BumpVec<'a, Ty<'a>>, arena: &'a Bump, ) -> FnTy<'a> { - arg_tys.push(Ty::new(TyKind::Data(Box::new(DataTy::new( + arg_tys.push(Ty::new(TyKind::Data(arena.alloc(DataTy::new( arena, utils::fresh_ident(arena, "in_view_dty", DataTyKind::Ident), ))))); + + let mut param_sigs = BumpVec::new_in(arena); + for ty in arg_tys.into_iter() { + let ty_ref: &'a Ty<'a> = arena.alloc(ty); + param_sigs.push(ParamSig::new(exec.clone(), ty_ref)); + } + + let ret_ty_ref: &'a Ty<'a> = arena.alloc(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + arena, + utils::fresh_ident(arena, "view_out_dty", DataTyKind::Ident), + ))))); + FnTy::new( arena, - vec![], + std::iter::empty(), None, - arg_tys - .into_iter() - .map(|ty| ParamSig::new(exec.clone(), ty)) - .collect(), + param_sigs, exec.clone(), - Ty::new(TyKind::Data(Box::new(DataTy::new(utils::fresh_ident( - arena, - "view_out_dty", - DataTyKind::Ident, - ))))), - vec![], + ret_ty_ref, + std::iter::empty(), ) } @@ -253,12 +297,12 @@ fn default_mem_by_exec<'a>(exec_ty: &'a ExecTyKind<'a>) -> Option> { // TODO refactor by fusing with ty_check_field_proj fn ty_check_proj<'a>( ctx: &'a PlExprTyCtx<'a>, - tuple_expr: &'a mut PlaceExpr<'a>, + tuple_expr: &'a PlaceExpr<'a>, n: usize, arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mem, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, tuple_expr, arena)?; - let tuple_dty = match &tuple_expr.ty.as_ref().unwrap().ty { + let tuple_dty = match &tuple_expr.ty.get().unwrap().ty { TyKind::Data(dty) => dty, ty_kind => { return Err(TyError::ExpectedTupleType( @@ -290,12 +334,12 @@ fn ty_check_proj<'a>( fn ty_check_field_proj<'a>( ctx: &'a PlExprTyCtx<'a>, - struct_expr: &'a mut PlaceExpr<'a>, + struct_expr: &'a PlaceExpr<'a>, ident: &'a Ident<'a>, arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mem, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, struct_expr, arena)?; - let struct_dty = match &struct_expr.ty.as_ref().unwrap().ty { + let struct_dty = match &struct_expr.ty.get().unwrap().ty { TyKind::Data(dty) => dty, ty_kind => { return Err(TyError::ExpectedTupleType( @@ -328,11 +372,11 @@ fn ty_check_field_proj<'a>( fn ty_check_deref<'a>( ctx: &'a PlExprTyCtx<'a>, - borr_expr: &'a mut PlaceExpr<'a>, + borr_expr: &'a PlaceExpr<'a>, arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mut inner_mem, mut passed_prvs) = ty_check_and_passed_mems_prvs(ctx, borr_expr, arena)?; - let borr_dty = if let TyKind::Data(dty) = &borr_expr.ty.as_ref().unwrap().ty { + let borr_dty = if let TyKind::Data(dty) = &borr_expr.ty.get().unwrap().ty { dty } else { return Err(TyError::String( @@ -370,11 +414,18 @@ fn ty_check_deref<'a>( fn ty_check_select<'a>( ctx: &'a PlExprTyCtx<'a>, - p: &'a mut PlaceExpr<'a>, - select_exec: &'a mut ExecExpr<'a>, + p: &'a PlaceExpr<'a>, + select_exec: &'a ExecExpr<'a>, arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { - exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, select_exec, arena)?; + let mut select_exec_cloned = select_exec.clone_in(arena); + exec::ty_check( + ctx.nat_ctx, + ctx.ty_ctx, + ctx.ident_exec, + &mut select_exec_cloned, + arena, + )?; // FIXME this check is required for uniq accesses, but not for shared accesses because there // the duplication of accesses is fine. Move this check into ownership/borrow checking? // if &ctx.exec != select_exec { @@ -390,7 +441,7 @@ fn ty_check_select<'a>( &mut outer_exec, arena, )?; - let outer_ctx = PlExprTyCtx { + let outer_ctx = arena.alloc(PlExprTyCtx { gl_ctx: ctx.gl_ctx, nat_ctx: ctx.nat_ctx, kind_ctx: ctx.kind_ctx, @@ -399,17 +450,17 @@ fn ty_check_select<'a>( ty_ctx: ctx.ty_ctx, exec_borrow_ctx: ctx.exec_borrow_ctx, own: ctx.own, - }; - let (mems, prvs) = ty_check_and_passed_mems_prvs(&outer_ctx, p, arena)?; - let mut p_dty = p.ty.as_ref().unwrap().dty().clone(); + }); + let (mems, prvs) = ty_check_and_passed_mems_prvs(outer_ctx, p, arena)?; + let mut p_dty = p.ty.get().unwrap().dty().clone_in(arena); match p_dty.dty { - DataTyKind::Array(elem_dty, n) | DataTyKind::ArrayShape(elem_dty, n) => { + DataTyKind::Array(elem_dty, _n) | DataTyKind::ArrayShape(elem_dty, _n) => { // TODO check sizes // if n != distrib_exec.active_distrib_size() { // return Err(TyError::String("There must be as many elements in the view // as there exist execution resources that select from it.".to_string())); // } - p_dty = *elem_dty; + p_dty = (*elem_dty).clone_in(arena); } _ => { return Err(TyError::String("Expected an array or view.".to_string())); @@ -420,23 +471,24 @@ fn ty_check_select<'a>( fn ty_check_index<'a>( ctx: &'a PlExprTyCtx<'a>, - pl_expr: &'a mut PlaceExpr<'a>, - idx: &'a mut Nat<'a>, + pl_expr: &'a PlaceExpr<'a>, + idx: &'a Nat<'a>, arena: &'a Bump, ) -> TyResult<'a, (Ty<'a>, Vec>, Vec>)> { let (mems, passed_prvs) = ty_check_and_passed_mems_prvs(ctx, pl_expr, arena)?; - let pl_expr_dty = if let TyKind::Data(dty) = &pl_expr.ty.as_ref().unwrap().ty { + + let pl_expr_dty = if let TyKind::Data(dty) = &pl_expr.ty.get().unwrap().ty { dty } else { return Err(TyError::String( "Trying to index into non array type.".to_string(), )); }; - let (elem_dty, n) = match pl_expr_dty.dty.clone() { + let (elem_dty_ref, n_ref): (&'a DataTy<'a>, &'a Nat<'a>) = match &pl_expr_dty.dty { DataTyKind::Array(elem_dty, n) | DataTyKind::ArrayShape(elem_dty, n) => (*elem_dty, n), DataTyKind::At(arr_dty, _) => { if let DataTyKind::Array(elem_ty, n) = &arr_dty.dty { - (*elem_ty.clone(), n.clone()) + (*elem_ty, n) } else { return Err(TyError::String( "Trying to index into non array type.".to_string(), @@ -450,14 +502,16 @@ fn ty_check_index<'a>( } }; - if n.eval(ctx.nat_ctx)? <= idx.eval(ctx.nat_ctx)? { + if n_ref.eval(ctx.nat_ctx)? <= idx.eval(ctx.nat_ctx)? { return Err(TyError::String( "Trying to access array out-of-bounds.".to_string(), )); } + let elem_dty_owned = elem_dty_ref.clone_in(arena); + Ok(( - Ty::new(TyKind::Data(arena.alloc(elem_dty))), + Ty::new(TyKind::Data(arena.alloc(elem_dty_owned))), mems, passed_prvs, )) diff --git a/src/ty_check/subty.rs b/src/ty_check/subty.rs index 51c2b7c8..e6a90f7a 100644 --- a/src/ty_check/subty.rs +++ b/src/ty_check/subty.rs @@ -8,16 +8,15 @@ use crate::arena_ast::internal::Loan; use super::error::{CtxError, SubTyError}; use crate::arena_ast::*; use bumpalo::Bump; -use std::collections::HashSet; type SubTyResult<'a, T> = Result>; // FIXME respect memory always, somehow provenances can be different is this correct? // τ1 is subtype of τ2 under Δ and Γ, producing Γ′ // Δ; Γ ⊢ τ1 ≲ τ2 ⇒ Γ′ -pub(super) fn check<'m, 'a>( +pub(super) fn check<'a>( kind_ctx: &'a KindCtx<'a>, - ty_ctx: &'m mut TyCtx<'a>, + ty_ctx: &mut TyCtx<'a>, sub_dty: &'a DataTy<'a>, super_dty: &'a DataTy<'a>, arena: &'a Bump, @@ -72,9 +71,9 @@ pub(super) fn check<'m, 'a>( // ρ1 outlives ρ2 under Δ and Γ, producing Γ′ // Δ; Γ ⊢ ρ1 :> ρ2 ⇒ Γ′ -pub(super) fn outlives<'m, 'a>( +pub(super) fn outlives<'a>( kind_ctx: &'a KindCtx<'a>, - ty_ctx: &'m mut TyCtx<'a>, + ty_ctx: &mut TyCtx<'a>, longer_prv: &'a Provenance<'a>, shorter_prv: &'a Provenance<'a>, arena: &'a Bump, @@ -112,8 +111,8 @@ pub(super) fn outlives<'m, 'a>( // OL-LocalProvenances // Δ; Γ ⊢ r1 :> r2 ⇒ Γ[r2 ↦→ { Γ(r1) ∪ Γ(r2) }] -fn outl_check_val_prvs<'m, 'a>( - ty_ctx: &'m mut TyCtx<'a>, +fn outl_check_val_prvs<'tcx, 'a>( + ty_ctx: &'tcx mut TyCtx<'a>, longer: &str, shorter: &str, arena: &'a Bump, @@ -142,8 +141,8 @@ fn outl_check_val_prvs<'m, 'a>( Ok(()) } -fn longer_occurs_before_shorter<'m, 'a>( - ty_ctx: &'m TyCtx<'a>, +fn longer_occurs_before_shorter<'tcx, 'a>( + ty_ctx: &'tcx TyCtx<'a>, longer: &str, shorter: &str, ) -> bool { @@ -160,7 +159,7 @@ fn longer_occurs_before_shorter<'m, 'a>( panic!("Neither provenance found in typing context") } -fn exists_deref_loan_with_prv<'m, 'a>(ty_ctx: &'m TyCtx<'a>, prv: &str, arena: &'a Bump) -> bool { +fn exists_deref_loan_with_prv<'a>(ty_ctx: &TyCtx<'a>, prv: &str, arena: &'a bumpalo::Bump) -> bool { ty_ctx .all_places(arena) .into_iter() @@ -171,48 +170,51 @@ fn exists_deref_loan_with_prv<'m, 'a>(ty_ctx: &'m TyCtx<'a>, prv: &str, arena: & }, _ => false, }) - .any(|(place, _)| { - ty_ctx.prv_mappings().into_iter().any(|prv_mapping| { - for loan in prv_mapping.loans.iter() { - if let PlaceExprKind::Deref(pl_expr) = &loan.place_expr.pl_expr { - return pl_expr.equiv(arena, &place); - } - } - false + .any(|(place_owned, _)| { + let place_ref = arena.alloc(place_owned); + ty_ctx.prv_mappings().into_iter().any(|pm| { + pm.loans.iter().any(|loan| match &loan.place_expr.pl_expr { + PlaceExprKind::Deref(pl_expr) => pl_expr.equiv(arena, place_ref), + _ => false, + }) }) }) } -fn outl_check_val_ident_prv<'m, 'a>( - ty_ctx: &'m TyCtx<'a>, +fn outl_check_val_ident_prv<'a>( + ty_ctx: &TyCtx<'a>, longer_val: &str, arena: &'a Bump, ) -> SubTyResult<'a, ()> { // TODO how could the set ever be empty? - let loan_set = ty_ctx.loans_in_prv(longer_val)?; - if loan_set.is_empty() { + let loan_snapshot = arena.alloc(ty_ctx.loans_in_prv_snapshot(longer_val, arena)?); + if loan_snapshot.is_empty() { return Err(SubTyError::PrvNotUsedInBorrow(longer_val.to_string())); } - borrowed_pl_expr_no_ref_to_existing_pl(ty_ctx, loan_set, arena); + borrowed_pl_expr_no_ref_to_existing_pl(ty_ctx, loan_snapshot.as_slice(), arena); panic!("Not yet implemented.") } // FIXME Makes no sense! -fn borrowed_pl_expr_no_ref_to_existing_pl<'m, 'a>( - ty_ctx: &'m TyCtx<'a>, - loan_set: &HashSet>, - arena: &'a Bump, +fn borrowed_pl_expr_no_ref_to_existing_pl<'a>( + ty_ctx: &TyCtx<'a>, + loans: &'a [Loan<'a>], + arena: &'a bumpalo::Bump, ) -> bool { - ty_ctx - .all_places(arena) - .iter() - .any(|(pl, _)| loan_set.iter().any(|loan| loan.place_expr.equiv(arena, pl))) + let places = ty_ctx.all_places(arena); + + places.into_iter().any(|(pl_owned, _)| { + let pl_ref: &'a internal::Place<'a> = arena.alloc(pl_owned); + loans + .iter() + .any(|loan| loan.place_expr.equiv(arena, pl_ref)) + }) } -fn outl_check_ident_val_prv<'m, 'a>( +fn outl_check_ident_val_prv<'tcx, 'a>( kind_ctx: &'a KindCtx<'a>, - ty_ctx: &'m TyCtx<'a>, + ty_ctx: &'tcx TyCtx<'a>, longer_ident: &'a Ident<'a>, shorter_val: &str, ) -> SubTyResult<'a, ()> { @@ -230,9 +232,9 @@ fn outl_check_ident_val_prv<'m, 'a>( } // Δ; Γ ⊢ List[ρ1 :> ρ2] ⇒ Γ′ -pub(super) fn multiple_outlives<'m, 'a, I>( +pub(super) fn multiple_outlives<'a, I>( kind_ctx: &'a KindCtx<'a>, - ty_ctx: &'m mut TyCtx<'a>, + ty_ctx: &'a mut TyCtx<'a>, prv_rels: I, arena: &'a Bump, ) -> SubTyResult<'a, ()> diff --git a/src/ty_check/unify.rs b/src/ty_check/unify.rs index e5c81cc9..ed574f91 100644 --- a/src/ty_check/unify.rs +++ b/src/ty_check/unify.rs @@ -41,9 +41,9 @@ pub(super) fn sub_unify<'a, C: Constrainable<'a>>( Ok(()) } -pub(super) fn constrain<'a, S: Constrainable<'a>>( - t1: &'a mut S, - t2: &'a mut S, +pub(super) fn constrain<'a, 'm, S: Constrainable<'a>>( + t1: &'m mut S, + t2: &'m mut S, arena: &'a Bump, ) -> UnifyResult<'a, (ConstrainMap<'a>, BumpVec<'a, PrvConstr<'a>>)> { let mut constr_map = ConstrainMap::new(); From f0361dff4c0c4d3e4333d58bd7af73a76f308670 Mon Sep 17 00:00:00 2001 From: StoeckOverflow Date: Fri, 23 Jan 2026 21:26:35 +0100 Subject: [PATCH 57/57] some updates --- src/arena_ast/mod.rs | 22 ++ src/ty_check/ctxs.rs | 8 +- src/ty_check/mod.rs | 605 ++++++++++++++++++++++++---------------- src/ty_check/pl_expr.rs | 1 + 4 files changed, 397 insertions(+), 239 deletions(-) diff --git a/src/arena_ast/mod.rs b/src/arena_ast/mod.rs index 1a9ff40a..8bdfba3a 100644 --- a/src/arena_ast/mod.rs +++ b/src/arena_ast/mod.rs @@ -143,6 +143,28 @@ impl<'a> FunDef<'a> { [], ) } + + pub fn clone_in(&self, arena: &'a Bump) -> FunDef<'a> { + let mut generic_params = BumpVec::new_in(arena); + generic_params.extend(self.generic_params.iter().cloned()); + + let mut param_decls = BumpVec::new_in(arena); + param_decls.extend(self.param_decls.iter().cloned()); + + let mut prv_rels = BumpVec::new_in(arena); + prv_rels.extend(self.prv_rels.iter().cloned()); + + FunDef { + ident: self.ident.clone(), + generic_params, + generic_exec: self.generic_exec.clone(), + param_decls, + ret_dty: arena.alloc(self.ret_dty.clone_in(arena)), + exec: self.exec.clone_in(arena), + prv_rels, + body: arena.alloc(self.body.clone_in(arena)), + } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/ty_check/ctxs.rs b/src/ty_check/ctxs.rs index a294a042..4f31e23a 100644 --- a/src/ty_check/ctxs.rs +++ b/src/ty_check/ctxs.rs @@ -677,7 +677,7 @@ pub(super) enum GlobalDecl<'a> { #[derive(Debug)] pub(super) struct GlobalCtx<'a> { - compil_unit: &'a mut CompilUnit<'a>, + pub compil_unit: &'a mut CompilUnit<'a>, checked_funs: BumpVec<'a, (&'a str, &'a [usize])>, decls: BumpVec<'a, GlobalDecl<'a>>, } @@ -732,7 +732,7 @@ impl<'a> GlobalCtx<'a> { pub fn push_fun_checked_under_nats( &mut self, arena: &'a bumpalo::Bump, - fun_def_owned: FunDef<'a>, // take by value + fun_def_owned: FunDef<'a>, nat_vals: &'a [usize], ) { let fun_name = fun_def_owned.ident.name.clone(); @@ -741,7 +741,7 @@ impl<'a> GlobalCtx<'a> { self.checked_funs.push((fun_name, nat_vals)); } - pub fn pop_fun_def(&mut self, name: &'a str) -> Option<&'a FunDef<'a>> { + pub fn pop_fun_def(&mut self, name: &'a str) -> Option> { let index = self.compil_unit.items.iter().position(|item| { if let Item::FunDef(fun_def) = item { fun_def.ident.name == name @@ -751,7 +751,7 @@ impl<'a> GlobalCtx<'a> { }); if let Some(i) = index { if let Item::FunDef(fun_def) = self.compil_unit.items.remove(i) { - Some(fun_def) + Some((*fun_def).clone()) } else { None } diff --git a/src/ty_check/mod.rs b/src/ty_check/mod.rs index e0b15a9d..b3b68b63 100644 --- a/src/ty_check/mod.rs +++ b/src/ty_check/mod.rs @@ -10,9 +10,11 @@ mod unify; use self::pl_expr::PlExprTyCtx; use crate::arena_ast::internal::{Frame, IdentTyped, Loan, Place, PrvMapping}; -use crate::arena_ast::utils; +use crate::arena_ast::{utils}; use crate::arena_ast::*; use crate::error::ErrorReported; +use bumpalo::collections::CollectIn; +use bumpalo::collections::Vec as BumpVec; use bumpalo::Bump; use ctxs::{AccessCtx, GlobalCtx, KindCtx, TyCtx}; use error::*; @@ -37,22 +39,25 @@ pub(crate) use matches_dty; // ∀ε ∈ Σ. Σ ⊢ ε // -------------- // ⊢ Σ -pub fn ty_check<'a>(compil_unit: &mut CompilUnit, arena: &'a Bump) -> Result<(), ErrorReported> { +/** +pub fn ty_check<'a>(compil_unit: &'a mut CompilUnit<'a>, arena: &'a Bump) -> Result<(), ErrorReported> { let mut gl_ctx = GlobalCtx::new( compil_unit, - pre_decl::fun_decls() + pre_decl::fun_decls(arena) .into_iter() - .map(|(fname, fty)| GlobalDecl::FnDecl(Box::from(fname), arena.alloc(fty))) + .map(|(fname, fty)| GlobalDecl::FnDecl(fname, arena.alloc(fty))) .collect_in(arena), + arena ); - let mut nat_ctx = NatCtx::new(); - if let Some(mut main_fun) = gl_ctx.pop_fun_def("main") { - if let Err(err) = ty_check_global_fun_def(&mut gl_ctx, &mut nat_ctx, &mut main_fun, &arena) + let mut nat_ctx = NatCtx::new(arena); + if let Some(main_fun) = &mut gl_ctx.pop_fun_def("main") { + if let Err(err) = ty_check_global_fun_def(&mut gl_ctx, &mut nat_ctx, main_fun, arena) { + drop(gl_ctx); err.emit(compil_unit.source); Err(ErrorReported) } else { - gl_ctx.push_fun_checked_under_nats(main_fun, arena.alloc(vec![])); + gl_ctx.push_fun_checked_under_nats(arena, (*main_fun).clone(), &[]); Ok(()) } } else { @@ -60,6 +65,47 @@ pub fn ty_check<'a>(compil_unit: &mut CompilUnit, arena: &'a Bump) -> Result<(), Err(ErrorReported) } } +*/ + + +pub fn ty_check<'a>( + compil_unit: &'a mut CompilUnit<'a>, + arena: &'a Bump, +) -> Result<(), ErrorReported> { + // Run the pass while holding &mut CompilUnit via gl_ctx. + // Return a TyError if something goes wrong, but DON'T emit yet. + let result: Result<(), TyError<'a>> = { + let predecls = pre_decl::fun_decls(arena) + .into_iter() + .map(|(fname, fty)| GlobalDecl::FnDecl(fname, arena.alloc(fty))) + .collect_in(arena); + + let mut gl_ctx = GlobalCtx::new(compil_unit, predecls, arena); + let mut nat_ctx = NatCtx::new(arena); + + if let Some(mut main_fun) = gl_ctx.pop_fun_def("main") { + match ty_check_global_fun_def(&mut gl_ctx, &mut nat_ctx, &mut main_fun, arena) { + Ok(()) => { + gl_ctx.push_fun_checked_under_nats(arena, main_fun, &[]); + Ok(()) + } + Err(err) => Err(err), + } + } else { + Err(TyError::MissingMain) + } + }; // <- gl_ctx (& its &mut CompilUnit borrow) is dropped here + + // Now it's safe to immutably borrow compil_unit.source to emit. + match result { + Ok(()) => Ok(()), + Err(err) => { + err.emit(compil_unit.source); + Err(ErrorReported) + } + } +} + struct ExprTyCtx<'a> { gl_ctx: &'a mut GlobalCtx<'a>, @@ -80,17 +126,32 @@ fn ty_check_global_fun_def<'a>( arena: &'a Bump, ) -> TyResult<'a, ()> { // TODO check that every prv_rel only uses provenance variables bound in generic_params - let mut kind_ctx = KindCtx::gl_fun_kind_ctx(gf.generic_params.clone(), gf.prv_rels.clone())?; - let mut ty_ctx = TyCtx::new(); + let mut kind_ctx = + KindCtx::gl_fun_kind_ctx(gf.generic_params.clone(), gf.prv_rels.clone(), arena)?; + let mut ty_ctx = TyCtx::new(arena); // Build frame typing for this function // TODO give Frame its own type and move this into frame and/or ParamDecl if let Some(ident_exec) = &gf.generic_exec { - let mut exec_ident = - ExecExpr::new(ExecExprKind::new(BaseExec::Ident(ident_exec.ident.clone()))); - exec::ty_check(nat_ctx, &ty_ctx, gf.generic_exec.as_ref(), &mut exec_ident)?; + let mut exec_ident = ExecExpr::new( + arena, + ExecExprKind::new(arena, BaseExec::Ident(ident_exec.ident.clone())), + ); + exec::ty_check( + nat_ctx, + &ty_ctx, + gf.generic_exec.as_ref(), + &mut exec_ident, + arena, + )?; ty_ctx.append_exec_mapping(ident_exec.ident.clone(), exec_ident); } - exec::ty_check(nat_ctx, &ty_ctx, gf.generic_exec.as_ref(), &mut gf.exec)?; + exec::ty_check( + nat_ctx, + &ty_ctx, + gf.generic_exec.as_ref(), + &mut gf.exec, + arena, + )?; let param_idents_ty = gf .param_decls @@ -103,7 +164,7 @@ fn ty_check_global_fun_def<'a>( exec_expr, }| { let mut exec = exec_expr.as_ref().unwrap_or(&gf.exec).clone(); - exec::ty_check(nat_ctx, &ty_ctx, gf.generic_exec.as_ref(), &mut exec)?; + exec::ty_check(nat_ctx, &ty_ctx, gf.generic_exec.as_ref(), &mut exec, arena)?; Ok(IdentTyped { ident: ident.clone(), ty: ty.as_ref().unwrap().clone(), @@ -120,7 +181,7 @@ fn ty_check_global_fun_def<'a>( ty_ctx.append_prv_mapping(PrvMapping::new(prv)); } - let mut access_ctx = AccessCtx::new(); + let mut access_ctx = AccessCtx::new(arena); let mut ctx = ExprTyCtx { gl_ctx: &mut *gl_ctx, nat_ctx: &mut *nat_ctx, @@ -132,7 +193,7 @@ fn ty_check_global_fun_def<'a>( unsafe_flag: false, }; - ty_check_expr(&mut ctx, &mut gf.body.body)?; + ty_check_expr(&mut ctx, &mut gf.body.body, arena)?; // t <= t_f // unify::constrain( // gf.body_expr.ty.as_ref().unwrap(), @@ -140,12 +201,13 @@ fn ty_check_global_fun_def<'a>( // )?; //coalesce::coalesce_ty(&mut self.term_constr.constr_map, &mut body_ctx, ) - let mut empty_ty_ctx = TyCtx::new(); + let mut empty_ty_ctx = TyCtx::new(arena); subty::check( &kind_ctx, &mut empty_ty_ctx, gf.body.body.ty.as_ref().unwrap().dty(), &gf.ret_dty, + arena, )?; #[cfg(debug_assertions)] @@ -173,59 +235,59 @@ fn ty_check_expr<'a>( let ty = match &mut expr.expr { ExprKind::PlaceExpr(pl_expr) => { if pl_expr.is_place() { - ty_check_place(ctx, pl_expr)? + ty_check_place(ctx, pl_expr, arena)? } else { - ty_check_non_place(ctx, pl_expr)? + ty_check_non_place(ctx, pl_expr, arena)? } } - ExprKind::Block(block) => ty_check_block(ctx, block)?, - ExprKind::Let(pattern, ty, e) => ty_check_let(ctx, pattern, ty, e)?, + ExprKind::Block(block) => ty_check_block(ctx, block, arena)?, + ExprKind::Let(pattern, ty, e) => ty_check_let(ctx, pattern, ty, e, arena)?, ExprKind::LetUninit(annot_exec, ident, ty) => { - ty_check_let_uninit(ctx, annot_exec, ident, ty)? + ty_check_let_uninit(ctx, annot_exec, ident, ty, arena)? } - ExprKind::Seq(es) => ty_check_seq(ctx, es)?, - ExprKind::Lit(l) => ty_check_literal(l), - ExprKind::Array(elems) => ty_check_array(ctx, elems)?, - ExprKind::Tuple(elems) => ty_check_tuple(ctx, elems)?, + ExprKind::Seq(es) => ty_check_seq(ctx, es, arena)?, + ExprKind::Lit(l) => ty_check_literal(l, arena), + ExprKind::Array(elems) => ty_check_array(ctx, elems, arena)?, + ExprKind::Tuple(elems) => ty_check_tuple(ctx, elems, arena)?, // ExprKind::Proj(e, i) => ty_check_proj(ctx, e, *i)?, - ExprKind::App(fn_ident, gen_args, args) => ty_check_app(ctx, fn_ident, gen_args, args)?, + ExprKind::App(fn_ident, gen_args, args) => ty_check_app(ctx, fn_ident, gen_args, args, arena)?, ExprKind::DepApp(fn_ident, gen_args) => Ty::new(TyKind::FnTy( - arena.alloc(ty_check_dep_app(ctx, fn_ident, gen_args)?), + arena.alloc(ty_check_dep_app(ctx, fn_ident, gen_args, arena)?), )), - ExprKind::AppKernel(app_kernel) => ty_check_app_kernel(ctx, app_kernel)?, - ExprKind::Ref(prv, own, pl_expr) => ty_check_borrow(ctx, prv, *own, pl_expr)?, + ExprKind::AppKernel(app_kernel) => ty_check_app_kernel(ctx, app_kernel, arena)?, + ExprKind::Ref(prv, own, pl_expr) => ty_check_borrow(ctx, prv, *own, pl_expr, arena)?, ExprKind::Assign(pl_expr, e) => { if pl_expr.is_place() { - ty_check_assign_place(ctx, pl_expr, e)? + ty_check_assign_place(ctx, pl_expr, e, arena)? } else { - ty_check_assign_non_place(ctx, pl_expr, e)? + ty_check_assign_non_place(ctx, pl_expr, e, arena)? } } - ExprKind::IdxAssign(pl_expr, idx, e) => ty_check_idx_assign(ctx, pl_expr, idx, e)?, - ExprKind::Split(split) => ty_check_split(ctx, split)?, - ExprKind::Sched(sched) => ty_check_sched(ctx, sched)?, - ExprKind::ForNat(var, range, body) => ty_check_for_nat(ctx, var, range, body)?, - ExprKind::For(ident, collec, body) => ty_check_for(ctx, ident, collec, body)?, + ExprKind::IdxAssign(pl_expr, idx, e) => ty_check_idx_assign(ctx, pl_expr, idx, e, arena)?, + ExprKind::Split(split) => ty_check_split(ctx, split, arena)?, + ExprKind::Sched(sched) => ty_check_sched(ctx, sched, arena)?, + ExprKind::ForNat(var, range, body) => ty_check_for_nat(ctx, var, range, body, arena)?, + ExprKind::For(ident, collec, body) => ty_check_for(ctx, ident, collec, body, arena)?, ExprKind::IfElse(cond, case_true, case_false) => { - ty_check_if_else(ctx, cond, case_true, case_false)? + ty_check_if_else(ctx, cond, case_true, case_false, arena)? } - ExprKind::If(cond, case_true) => ty_check_if(ctx, cond, case_true)?, - ExprKind::While(cond, body) => ty_check_while(ctx, cond, body)?, + ExprKind::If(cond, case_true) => ty_check_if(ctx, cond, case_true, arena)?, + ExprKind::While(cond, body) => ty_check_while(ctx, cond, body, arena)?, // ExprKind::Lambda(params, lambda_exec_ident, ret_ty, body) => { // ty_check_lambda(ctx, params, lambda_exec_ident, ret_ty, body)? // } - ExprKind::BinOp(bin_op, lhs, rhs) => ty_check_binary_op(ctx, bin_op, lhs, rhs)?, - ExprKind::UnOp(un_op, e) => ty_check_unary_op(ctx, un_op, e)?, - ExprKind::Sync(exec) => ty_check_sync(ctx, exec)?, + ExprKind::BinOp(bin_op, lhs, rhs) => ty_check_binary_op(ctx, bin_op, lhs, rhs, arena)?, + ExprKind::UnOp(un_op, e) => ty_check_unary_op(ctx, un_op, e, arena)?, + ExprKind::Sync(exec) => ty_check_sync(ctx, exec, arena)?, ExprKind::Unsafe(e) => { ctx.unsafe_flag = true; - ty_check_expr(ctx, e)?; + ty_check_expr(ctx, e, arena)?; ctx.unsafe_flag = false; e.ty.as_ref().unwrap().as_ref().clone() } - ExprKind::Cast(expr, dty) => ty_check_cast(ctx, expr, dty)?, + ExprKind::Cast(expr, dty) => ty_check_cast(ctx, expr, dty, arena)?, ExprKind::Range(_, _) => unimplemented!(), //ty_check_range(ctx, l, u)?, - ExprKind::Hole => ty_check_hole(ctx)?, + ExprKind::Hole => ty_check_hole(ctx, arena)?, }; // TODO reintroduce!!!! @@ -239,7 +301,8 @@ fn ty_check_expr<'a>( fn ty_check_hole<'a>(ctx: &ExprTyCtx, arena: &'a Bump) -> TyResult<'a, Ty<'a>> { if ctx.unsafe_flag { Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( - DataTyKind::Ident(Ident::new_impli(&utils::fresh_name("hole"))), + arena, + DataTyKind::Ident(Ident::new_impli(arena, &utils::fresh_name("hole"))), ))))) } else { Err(TyError::UnsafeRequired) @@ -249,19 +312,21 @@ fn ty_check_hole<'a>(ctx: &ExprTyCtx, arena: &'a Bump) -> TyResult<'a, Ty<'a>> { fn ty_check_sync<'a>( ctx: &mut ExprTyCtx, exec: &'a mut Option>, + arena: &'a Bump, ) -> TyResult<'a, Ty<'a>> { let synced = match exec { Some(exec) => { - exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, exec)?; + exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, exec, arena)?; exec } None => &ctx.exec, }; syncable_under_exec(synced, &ctx.exec)?; - ctx.access_ctx.clear_sync_for(ctx.ty_ctx, synced); - Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), - ))) + ctx.access_ctx.clear_sync_for(ctx.ty_ctx, synced, arena); + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + arena, + DataTyKind::Scalar(ScalarTy::Unit), + ))))) } // assumes fully typed ExecExpr as input @@ -317,16 +382,17 @@ fn ty_check_for_nat<'a>( range: &NatRange<'a>, // TODO make this a block body: &mut Expr<'a>, + arena: &'a Bump, ) -> TyResult<'a, Ty<'a>> { let compare_ty_ctx = ctx.ty_ctx.clone(); - let lifted_range = range.lift(ctx.nat_ctx)?; + let lifted_range = range.lift(arena, ctx.nat_ctx)?; for i in lifted_range { - ctx.ty_ctx.push_empty_frame(); - ctx.nat_ctx.push_empty_frame(); - ctx.nat_ctx.append(&ident.name, i); + ctx.ty_ctx.push_empty_frame(arena); + ctx.nat_ctx.push_empty_frame(arena); + ctx.nat_ctx.append(&ident.name, i, arena); - ty_check_expr(ctx, body)?; + ty_check_expr(ctx, body, arena)?; ctx.nat_ctx.pop_frame(); ctx.ty_ctx.pop_frame(); @@ -340,9 +406,10 @@ fn ty_check_for_nat<'a>( return Err(TyError::UnexpectedType); } } - Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), - ))) + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + arena, + DataTyKind::Scalar(ScalarTy::Unit), + ))))) } fn ty_check_for<'a>( @@ -350,8 +417,9 @@ fn ty_check_for<'a>( ident: &Ident<'a>, collec: &mut Expr<'a>, body: &mut Expr<'a>, + arena: &'a Bump, ) -> TyResult<'a, Ty<'a>> { - ty_check_expr(ctx, collec)?; + ty_check_expr(ctx, collec, arena)?; let collec_dty = if let TyKind::Data(collec_dty) = &collec.ty.as_ref().unwrap().ty { collec_dty.as_ref() } else { @@ -366,12 +434,14 @@ fn ty_check_for<'a>( DataTyKind::Array(elem_dty, n) => unimplemented!(), DataTyKind::Ref(reff) => match &reff.dty.as_ref().dty { DataTyKind::Array(elem_dty, _) => DataTyKind::Ref(arena.alloc(RefDty::new( + arena, reff.rgn.clone(), reff.own, reff.mem.clone(), elem_dty.as_ref().clone(), ))), DataTyKind::ArrayShape(elem_dty, _) => DataTyKind::Ref(arena.alloc(RefDty::new( + arena, reff.rgn.clone(), reff.own, reff.mem.clone(), @@ -393,45 +463,47 @@ fn ty_check_for<'a>( } }; let compare_ty_ctx = ctx.ty_ctx.clone(); - let mut frame = Frame::new(); - frame.append_idents_typed(vec![IdentTyped::new( + let mut frame = Frame::new_in(arena); + frame.append_idents_typed(vec![IdentTyped::new_in(arena ident.clone(), - Ty::new(TyKind::Data(arena.alloc(DataTy::new(ident_dty)))), + Ty::new(TyKind::Data(arena.alloc(DataTy::new(arena, ident_dty)))), Mutability::Const, ctx.exec.clone(), )]); ctx.ty_ctx.push_frame(frame); - ty_check_expr(ctx, body)?; + ty_check_expr(ctx, body, arena)?; ctx.ty_ctx.pop_frame(); if ctx.ty_ctx != &compare_ty_ctx { return Err(TyError::String( "Using a data type in loop that can only be used once.".to_string(), )); } - Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), - ))) + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + arena, + DataTyKind::Scalar(ScalarTy::Unit), + ))))) } fn ty_check_while<'a>( ctx: &mut ExprTyCtx, cond: &'a mut Expr<'a>, body: &'a mut Expr<'a>, + arena: &'a Bump, ) -> TyResult<'a, Ty<'a>> { - ty_check_expr(&mut *ctx, cond)?; - ctx.ty_ctx.push_empty_frame(); - ty_check_expr(ctx, body)?; + ty_check_expr(&mut *ctx, cond, arena)?; + ctx.ty_ctx.push_empty_frame(arena); + ty_check_expr(ctx, body, arena)?; ctx.ty_ctx.pop_frame(); let compare_ty_ctx = ctx.ty_ctx.clone(); // Is it better/more correct to push and pop scope around this as well? - ty_check_expr(ctx, cond)?; + ty_check_expr(ctx, cond, arena)?; if ctx.ty_ctx != &compare_ty_ctx { return Err(TyError::String( "Context should have stayed the same".to_string(), )); } - ctx.ty_ctx.push_empty_frame(); - ty_check_expr(ctx, body)?; + ctx.ty_ctx.push_empty_frame(arena); + ty_check_expr(ctx, body, arena)?; ctx.ty_ctx.pop_frame(); if ctx.ty_ctx != &compare_ty_ctx { return Err(TyError::String( @@ -466,9 +538,10 @@ fn ty_check_while<'a>( body_ty ))); } - Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), - ))) + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + arena, + DataTyKind::Scalar(ScalarTy::Unit), + ))))) } fn ty_check_if_else<'a>( @@ -476,9 +549,10 @@ fn ty_check_if_else<'a>( cond: &'a mut Expr<'a>, case_true: &'a mut Expr<'a>, case_false: &'a mut Expr<'a>, + arena: &'a Bump, ) -> TyResult<'a, Ty<'a>> { // TODO deal with provenances in cases - ty_check_expr(ctx, cond)?; + ty_check_expr(ctx, cond, arena)?; // TODO acccess_ctx clone let mut ty_ctx_clone = ctx.ty_ctx.clone(); let mut ctx_clone = ExprTyCtx { @@ -491,9 +565,9 @@ fn ty_check_if_else<'a>( access_ctx: &mut *ctx.access_ctx, unsafe_flag: ctx.unsafe_flag, }; - let _case_true_ty_ctx = ty_check_expr(&mut ctx_clone, case_true)?; - ctx.ty_ctx.push_empty_frame(); - ty_check_expr(ctx, case_false)?; + let _case_true_ty_ctx = ty_check_expr(&mut ctx_clone, case_true, arena)?; + ctx.ty_ctx.push_empty_frame(arena); + ty_check_expr(ctx, case_false, arena)?; ctx.ty_ctx.pop_frame(); let cond_ty = cond.ty.as_ref().unwrap(); @@ -537,20 +611,22 @@ fn ty_check_if_else<'a>( ))); } - Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), - ))) + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + arena, + DataTyKind::Scalar(ScalarTy::Unit), + ))))) } fn ty_check_if<'a>( ctx: &mut ExprTyCtx, cond: &'a mut Expr<'a>, case_true: &'a mut Expr<'a>, + arena: &'a Bump, ) -> TyResult<'a, Ty<'a>> { // TODO deal with provenances in cases - ty_check_expr(ctx, cond)?; - ctx.ty_ctx.push_empty_frame(); - ty_check_expr(ctx, case_true)?; + ty_check_expr(ctx, cond, arena)?; + ctx.ty_ctx.push_empty_frame(arena); + ty_check_expr(ctx, case_true, arena)?; ctx.ty_ctx.pop_frame(); let cond_ty = cond.ty.as_ref().unwrap(); @@ -581,12 +657,17 @@ fn ty_check_if<'a>( ))); } - Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), - ))) + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + arena, + DataTyKind::Scalar(ScalarTy::Unit), + ))))) } -fn ty_check_split<'a>(ctx: &mut ExprTyCtx, indep: &mut Split<'a>) -> TyResult<'a, Ty<'a>> { +fn ty_check_split<'a>( + ctx: &'a mut ExprTyCtx<'a>, + indep: &'a mut Split<'a>, + arena: &'a Bump, +) -> TyResult<'a, Ty<'a>> { // exec::ty_check( // ctx.kind_ctx, // ctx.ty_ctx, @@ -598,9 +679,10 @@ fn ty_check_split<'a>(ctx: &mut ExprTyCtx, indep: &mut Split<'a>) -> TyResult<'a ctx.ty_ctx, ctx.ident_exec, &mut indep.split_exec, + arena, )?; - legal_exec_under_current(ctx, &indep.split_exec)?; - let expanded_exec_expr = expand_exec_expr(ctx, &indep.split_exec)?; + legal_exec_under_current(ctx, &indep.split_exec, arena)?; + let expanded_exec_expr = expand_exec_expr(ctx, &indep.split_exec, arena)?; if indep.branch_idents.len() != indep.branch_bodies.len() { panic!( "Amount of branch identifiers and amount of branches do not match:\ @@ -617,18 +699,28 @@ fn ty_check_split<'a>(ctx: &mut ExprTyCtx, indep: &mut Split<'a>) -> TyResult<'a } for i in 0..indep.branch_bodies.len() { - let mut branch_exec = ExecExpr::new(expanded_exec_expr.exec.clone().split_proj( - indep.dim_compo, - indep.pos.clone(), - if i == 0 { - LeftOrRight::Left - } else if i == 1 { - LeftOrRight::Right - } else { - panic!("Unexepected projection.") - }, - )); - exec::ty_check(&ctx.nat_ctx, &ctx.ty_ctx, ctx.ident_exec, &mut branch_exec)?; + let mut branch_exec = ExecExpr::new( + arena, + expanded_exec_expr.exec.clone().split_proj( + arena, + indep.dim_compo, + indep.pos.clone(), + if i == 0 { + LeftOrRight::Left + } else if i == 1 { + LeftOrRight::Right + } else { + panic!("Unexepected projection.") + }, + ), + ); + exec::ty_check( + &ctx.nat_ctx, + &ctx.ty_ctx, + ctx.ident_exec, + &mut branch_exec, + arena, + )?; let mut branch_expr_ty_ctx = ExprTyCtx { gl_ctx: ctx.gl_ctx, nat_ctx: &mut *ctx.nat_ctx, @@ -641,11 +733,11 @@ fn ty_check_split<'a>(ctx: &mut ExprTyCtx, indep: &mut Split<'a>) -> TyResult<'a }; branch_expr_ty_ctx .ty_ctx - .push_empty_frame() + .push_empty_frame(arena) .append_exec_mapping(indep.branch_idents[i].clone(), branch_exec.clone()); - ty_check_expr(&mut branch_expr_ty_ctx, &mut indep.branch_bodies[i])?; + ty_check_expr(&mut branch_expr_ty_ctx, &mut indep.branch_bodies[i], arena)?; if indep.branch_bodies[i].ty.as_ref().unwrap().ty - != TyKind::Data(arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit)))) + != TyKind::Data(arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit)))) { return Err(TyError::String( "A par_branch branch must not return a value.".to_string(), @@ -654,21 +746,21 @@ fn ty_check_split<'a>(ctx: &mut ExprTyCtx, indep: &mut Split<'a>) -> TyResult<'a branch_expr_ty_ctx.ty_ctx.pop_frame(); } Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit))), ))) } -fn ty_check_sched<'a>(ctx: &mut ExprTyCtx, sched: &'a mut Sched<'a>) -> TyResult<'a, Ty<'a>> { +fn ty_check_sched<'a>(ctx: &'a mut ExprTyCtx<'a>, sched: &'a mut Sched<'a>, arena: &'a Bump) -> TyResult<'a, Ty<'a>> { exec::ty_check( ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, - &mut sched.sched_exec, + &mut sched.sched_exec, arena )?; - legal_exec_under_current(ctx, &sched.sched_exec)?; - let expanded_exec_expr = expand_exec_expr(ctx, &sched.sched_exec)?; - let mut body_exec = ExecExpr::new(expanded_exec_expr.exec.forall(sched.dim)); - exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, &mut body_exec)?; + legal_exec_under_current(ctx, &sched.sched_exec, arena)?; + let expanded_exec_expr = expand_exec_expr(ctx, &sched.sched_exec, arena)?; + let mut body_exec = ExecExpr::new(arena expanded_exec_expr.exec.forall(sched.dim)); + exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, &mut body_exec, arena)?; let mut schedule_body_ctx = ExprTyCtx { gl_ctx: ctx.gl_ctx, nat_ctx: &mut *ctx.nat_ctx, @@ -679,7 +771,7 @@ fn ty_check_sched<'a>(ctx: &mut ExprTyCtx, sched: &'a mut Sched<'a>) -> TyResult access_ctx: &mut *ctx.access_ctx, unsafe_flag: ctx.unsafe_flag, }; - schedule_body_ctx.ty_ctx.push_empty_frame(); + schedule_body_ctx.ty_ctx.push_empty_frame(arena); if let Some(ident) = &sched.inner_exec_ident { schedule_body_ctx .ty_ctx @@ -690,48 +782,49 @@ fn ty_check_sched<'a>(ctx: &mut ExprTyCtx, sched: &'a mut Sched<'a>) -> TyResult .ty_ctx .append_prv_mapping(PrvMapping::new(prv)); } - ty_check_expr(&mut schedule_body_ctx, &mut sched.body.body)?; + ty_check_expr(&mut schedule_body_ctx, &mut sched.body.body, arena)?; schedule_body_ctx.ty_ctx.pop_frame(); Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit))), ))) } -fn ty_check_block<'a>(ctx: &mut ExprTyCtx, block: &'a mut Block<'a>) -> TyResult<'a, Ty<'a>> { - ctx.ty_ctx.push_empty_frame(); +fn ty_check_block<'a>(ctx: &'a mut ExprTyCtx<'a>, block: &'a mut Block<'a>, arena: &'a Bump) -> TyResult<'a, Ty<'a>> { + ctx.ty_ctx.push_empty_frame(arena); for prv in &block.prvs { ctx.ty_ctx.append_prv_mapping(PrvMapping::new(prv)); } - ty_check_expr(ctx, &mut block.body)?; + ty_check_expr(ctx, &mut block.body, arena)?; ctx.ty_ctx.pop_frame(); - ctx.access_ctx.garbage_collect(ctx.ty_ctx); + ctx.access_ctx.garbage_collect(ctx.ty_ctx, arena); Ok(block.body.ty.as_ref().unwrap().as_ref().clone()) } -fn collect_valid_loans<'a>(ty_ctx: &TyCtx, mut loans: HashSet>) -> HashSet> { +fn collect_valid_loans<'a>(ty_ctx: &TyCtx, mut loans: HashSet>, arena: &'a Bump) -> HashSet> { // FIXME this implementations assumes unique names which is not the case loans.retain(|l| { - let root_ident = &l.place_expr.to_pl_ctx_and_most_specif_pl().1.ident; + let root_ident = &l.place_expr.to_pl_ctx_and_most_specif_pl(arena).1.ident; ty_ctx.contains(root_ident) }); loans } -fn check_mutable<'a>(ty_ctx: &TyCtx, pl: &'a Place<'a>) -> TyResult<'a, ()> { +fn check_mutable<'a>(ty_ctx: &'a TyCtx<'a>, pl: &'a Place<'a>, arena: &'a Bump) -> TyResult<'a, ()> { let ident_ty = ty_ctx.ident_ty(&pl.ident)?; if ident_ty.mutbl != Mutability::Mut { - return Err(TyError::AssignToConst(pl.to_place_expr())); + return Err(TyError::AssignToConst(pl.to_place_expr(arena))); } Ok(()) } fn ty_check_assign_place<'a>( - ctx: &mut ExprTyCtx, + ctx: &'a mut ExprTyCtx<'a>, pl_expr: &'a mut PlaceExpr<'a>, e: &'a mut Expr<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { - ty_check_expr(ctx, e)?; - let pl = pl_expr.to_place().unwrap(); + ty_check_expr(ctx, e, arena)?; + let pl = pl_expr.to_place(arena).unwrap(); let mut place_ty = ctx.ty_ctx.place_dty(&pl)?; // FIXME this should be checked for ArrayViews as well // fn contains_view_dty(ty: &TyKind) -> bool { @@ -743,11 +836,11 @@ fn ty_check_assign_place<'a>( // e // ))); // } - check_mutable(ctx.ty_ctx, &pl)?; + check_mutable(ctx.ty_ctx, &pl, arena)?; // If the place is not dead, check that it is safe to use, otherwise it is safe to use anyway. if !matches!(&place_ty.dty, DataTyKind::Dead(_),) { - borrow_check::borrow_check(&BorrowCheckCtx::new(ctx, vec![], Ownership::Uniq), pl_expr) + borrow_check::borrow_check(&BorrowCheckCtx::new(ctx, vec![], Ownership::Uniq), pl_expr, arena) .map_err(|err| { TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Uniq, err) })?; @@ -758,7 +851,7 @@ fn ty_check_assign_place<'a>( } else { return Err(TyError::UnexpectedType); }; - let err = unify::sub_unify(ctx.kind_ctx, ctx.ty_ctx, e_dty, &mut place_ty); + let err = unify::sub_unify(ctx.kind_ctx, ctx.ty_ctx, e_dty, &mut place_ty, arena); if let Err(err) = err { return Err(match err { UnifyError::CannotUnify => { @@ -768,27 +861,29 @@ fn ty_check_assign_place<'a>( }); } ctx.ty_ctx - .set_place_dty(&pl, e_dty.clone()) + .set_place_dty(&pl, e_dty.clone(), arena) .without_reborrow_loans(pl_expr); // TODO remove: not required for correctness // removing this leads to problems in Codegen, because the pl_expr is not annotated with a // type which is required by gen_pl_expr - pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr)?; + pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr, arena)?; Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit))), ))) } fn ty_check_assign_non_place<'a>( - ctx: &mut ExprTyCtx, + ctx: &'a mut ExprTyCtx<'a>, deref_expr: &'a mut PlaceExpr<'a>, e: &'a mut Expr<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { - ty_check_expr(ctx, e)?; - pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), deref_expr)?; + ty_check_expr(ctx, e, arena)?; + pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), deref_expr, arena)?; let potential_accesses = borrow_check::access_safety_check( &BorrowCheckCtx::new(ctx, vec![], Ownership::Uniq), deref_expr, + arena ) .map_err(|err| { TyError::ConflictingBorrow(arena.alloc(deref_expr.clone()), Ownership::Uniq, err) @@ -800,6 +895,7 @@ fn ty_check_assign_non_place<'a>( ctx.ty_ctx, e.ty.as_mut().unwrap().as_mut(), deref_ty, + arena )?; if !deref_ty.is_fully_alive() { return Err(TyError::String( @@ -809,7 +905,7 @@ fn ty_check_assign_non_place<'a>( // FIXME needs subtyping check on p, e types if let TyKind::Data(_) = &deref_ty.ty { Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit))), ))) } else { Err(TyError::String( @@ -819,13 +915,14 @@ fn ty_check_assign_non_place<'a>( } fn ty_check_idx_assign<'a>( - ctx: &mut ExprTyCtx, + ctx: &'a mut ExprTyCtx<'a>, pl_expr: &'a mut PlaceExpr<'a>, idx: &'a Nat<'a>, e: &'a mut Expr<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { - ty_check_expr(ctx, e)?; - pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr)?; + ty_check_expr(ctx, e, arena)?; + pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr, arena)?; let pl_expr_dty = if let TyKind::Data(dty) = &pl_expr.ty.as_ref().unwrap().ty { dty } else { @@ -886,29 +983,31 @@ fn ty_check_idx_assign<'a>( let potential_accesses = borrow_check::access_safety_check( &BorrowCheckCtx::new(ctx, vec![], Ownership::Uniq), pl_expr, + arena ) .map_err(|err| { TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Shrd, err) })?; ctx.access_ctx.insert(potential_accesses); - subty::check(ctx.kind_ctx, ctx.ty_ctx, e.ty.as_ref().unwrap().dty(), dty)?; + subty::check(ctx.kind_ctx, ctx.ty_ctx, e.ty.as_ref().unwrap().dty(), dty, arena)?; Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit))), ))) } // FIXME currently assumes that binary operators exist only for f32 and i32 and that both // arguments have to be of the same type fn ty_check_binary_op<'a>( - ctx: &mut ExprTyCtx, + ctx: &mut ExprTyCtx<'a>, bin_op: &BinOp, lhs: &mut Expr<'a>, rhs: &mut Expr<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { // FIXME certain operations should only be allowed for certain data types // true > false is currently valid - ty_check_expr(ctx, lhs)?; - ty_check_expr(ctx, rhs)?; + ty_check_expr(ctx, lhs, arena)?; + ty_check_expr(ctx, rhs, arena)?; let lhs_ty = lhs.ty.as_ref().unwrap(); let rhs_ty = rhs.ty.as_ref().unwrap(); let ret_dty = match bin_op { @@ -929,7 +1028,7 @@ fn ty_check_binary_op<'a>( | BinOp::And | BinOp::Or | BinOp::Neq => Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Bool))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Bool))), )), }; match bin_op { @@ -1005,8 +1104,9 @@ fn ty_check_unary_op<'a>( ctx: &mut ExprTyCtx, un_op: &UnOp, e: &'a mut Expr<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { - ty_check_expr(ctx, e)?; + ty_check_expr(ctx, e, arena)?; let e_ty = e.ty.as_ref().unwrap(); let e_dty = if let TyKind::Data(dty) = &e_ty.ty { dty.as_ref() @@ -1028,11 +1128,12 @@ fn ty_check_unary_op<'a>( } fn ty_check_cast<'a>( - ctx: &mut ExprTyCtx, + ctx: &'a mut ExprTyCtx<'a>, e: &mut Expr<'a>, dty: &'a DataTy<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { - ty_check_expr(ctx, e)?; + ty_check_expr(ctx, e, arena)?; let e_ty = e.ty.as_ref().unwrap(); match &e_ty.dty().dty { DataTyKind::Scalar(ScalarTy::F32) @@ -1072,26 +1173,27 @@ fn ty_check_cast<'a>( } fn ty_check_app<'a>( - ctx: &mut ExprTyCtx, + ctx: &'a mut ExprTyCtx<'a>, fn_ident: &'a mut Ident<'a>, gen_args: &'a mut Vec>, args: &'a mut [Expr<'a>], + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { // TODO check well-kinded: FrameTyping, Prv, Ty - let partially_applied_dep_fn_ty = ty_check_dep_app(ctx, fn_ident, gen_args)?; + let partially_applied_dep_fn_ty = ty_check_dep_app(ctx, fn_ident, gen_args, arena)?; for arg in args.iter_mut() { - ty_check_expr(ctx, arg)?; + ty_check_expr(ctx, arg,arena)?; } let param_sigs_for_args = args .iter() .map(|arg| ParamSig::new(ctx.exec.clone(), arg.ty.as_ref().unwrap().as_ref().clone())) .collect(); let ret_dty_placeholder = Ty::new(TyKind::Data( - arena.alloc(DataTy::new(utils::fresh_ident("ret_ty", DataTyKind::Ident))), + arena.alloc(DataTy::new(arena, utils::fresh_ident(arena, "ret_ty", DataTyKind::Ident))), )); - let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_dep_fn_ty); + let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_dep_fn_ty, arena); unify::unify( - &mut FnTy::new( + &mut FnTy::new(arena, vec![], None, param_sigs_for_args, @@ -1100,9 +1202,10 @@ fn ty_check_app<'a>( vec![], ), &mut mono_fn_ty, + arena )?; let mut inferred_gen_args = - infer_kinded_args::infer_kinded_args(&partially_applied_dep_fn_ty, &mono_fn_ty)?; + infer_kinded_args::infer_kinded_args(&partially_applied_dep_fn_ty, &mono_fn_ty, arena)?; gen_args.append(&mut inferred_gen_args); if let Some(mut fn_def) = ctx.gl_ctx.pop_fun_def(&fn_ident.name) { @@ -1117,10 +1220,10 @@ fn ty_check_app<'a>( } if !ctx.gl_ctx.has_been_checked(&fn_ident.name, &nat_vals) { let mut called_nat_ctx = - NatCtx::with_frame(nat_names.into_iter().zip(nat_vals.clone()).collect()); - ty_check_global_fun_def(ctx.gl_ctx, &mut called_nat_ctx, &mut fn_def)?; + NatCtx::with_frame(arena, nat_names.into_iter().zip(nat_vals.clone()).collect(), ); + ty_check_global_fun_def(ctx.gl_ctx, &mut called_nat_ctx, &mut fn_def, arena)?; ctx.gl_ctx - .push_fun_checked_under_nats(fn_def, Box::from(nat_vals)) + .push_fun_checked_under_nats(arena,fn_def, arena.alloc(nat_vals)) } } @@ -1153,10 +1256,11 @@ fn ty_check_dep_app<'a>( ctx: &mut ExprTyCtx, fn_ident: &'a Ident<'a>, gen_args: &'a [ArgKinded<'a>], + arena: &'a Bump ) -> TyResult<'a, FnTy<'a>> { //ty_check_expr(ctx, ef)?; let fn_ty = ctx.gl_ctx.fn_ty_by_ident(fn_ident)?; - apply_gen_args_to_fn_ty_checked(ctx.kind_ctx, &ctx.exec, &fn_ty, gen_args) + apply_gen_args_to_fn_ty_checked(ctx.kind_ctx, &ctx.exec, &fn_ty, gen_args, arena) // } else { // Err(TyError::String(format!( // "The provided function expression\n {:?}\n does not have a function type.", @@ -1170,17 +1274,19 @@ fn apply_gen_args_to_fn_ty_checked<'a>( exec: &'a ExecExpr<'a>, fn_ty: &'a FnTy<'a>, gen_args: &'a [ArgKinded<'a>], + arena: &'a Bump ) -> TyResult<'a, FnTy<'a>> { let mut subst_fn_ty = fn_ty.clone(); - apply_gen_args_checked(kind_ctx, &mut subst_fn_ty, gen_args)?; - apply_exec_checked(&mut subst_fn_ty, exec)?; + apply_gen_args_checked(kind_ctx, &mut subst_fn_ty, gen_args, arena)?; + apply_exec_checked(&mut subst_fn_ty, exec, arena)?; Ok(subst_fn_ty) } fn apply_gen_args_checked<'a>( kind_ctx: &'a KindCtx<'a>, - fn_ty: &mut FnTy<'a>, + fn_ty: &'a mut FnTy<'a>, gen_args: &'a [ArgKinded<'a>], + arena: &'a Bump ) -> TyResult<'a, ()> { if fn_ty.generics.len() < gen_args.len() { return Err(TyError::String(format!( @@ -1193,7 +1299,7 @@ fn apply_gen_args_checked<'a>( check_arg_has_correct_kind(kind_ctx, &gen_param.kind, gen_arg)?; } let substituted_gen_idents = fn_ty.generics.drain(..gen_args.len()).collect::>(); - utils::subst_idents_kinded(&substituted_gen_idents, gen_args, fn_ty); + utils::subst_idents_kinded(arena, &substituted_gen_idents, gen_args, fn_ty); Ok(()) } @@ -1214,7 +1320,7 @@ fn check_arg_has_correct_kind<'a>( // FIXME the correct way to do this is to unify execs and to unify an identifier with an exec_expr // only if the types match (i.e., the exec expr type check must happen within unify) -fn apply_exec_checked<'a>(fn_ty: &'a mut FnTy<'a>, exec: &'a ExecExpr<'a>) -> TyResult<'a, ()> { +fn apply_exec_checked<'a>(fn_ty: &'a mut FnTy<'a>, exec: &'a ExecExpr<'a>, arena: &'a Bump) -> TyResult<'a, ()> { // TODO reintroduce // exec::ty_check( // ctx.kind_ctx, @@ -1227,19 +1333,21 @@ fn apply_exec_checked<'a>(fn_ty: &'a mut FnTy<'a>, exec: &'a ExecExpr<'a>) -> Ty unify::unify( &mut exec.ty.as_ref().unwrap().as_ref().clone(), &mut ge.ty.clone(), + arena )?; let gen_exec_ident = ge.ident.clone(); fn_ty.generic_exec = None; - utils::subst_ident_exec(&gen_exec_ident, exec, fn_ty); + utils::subst_ident_exec(arena, &gen_exec_ident, exec, fn_ty); } // if no generic exec was substituted, execs must still be unifable - unify::unify(&mut fn_ty.exec, &mut exec.clone())?; + unify::unify(&mut fn_ty.exec, &mut exec.clone(), arena)?; Ok(()) } fn ty_check_app_kernel<'a>( ctx: &mut ExprTyCtx, app_kernel: &'a mut AppKernel<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { // current exec = cpu.thread if !matches!(ctx.exec.ty.as_ref().unwrap().ty, ExecTyKind::CpuThread) { @@ -1249,13 +1357,13 @@ fn ty_check_app_kernel<'a>( } // type check argument list for arg in app_kernel.args.iter_mut() { - ty_check_expr(ctx, arg)?; + ty_check_expr(ctx, arg, arena)?; } - let mut kernel_exec = ExecExpr::new(ExecExprKind::new(BaseExec::GpuGrid( + let mut kernel_exec = ExecExpr::new(arena, ExecExprKind::new(arena,BaseExec::GpuGrid( app_kernel.grid_dim.clone(), app_kernel.block_dim.clone(), ))); - exec::ty_check(ctx.nat_ctx, &TyCtx::new(), None, &mut kernel_exec)?; + exec::ty_check(ctx.nat_ctx, &TyCtx::new(arena), None, &mut kernel_exec, arena)?; let mut kernel_ctx = ExprTyCtx { gl_ctx: &mut *ctx.gl_ctx, @@ -1264,7 +1372,7 @@ fn ty_check_app_kernel<'a>( kind_ctx: ctx.kind_ctx, exec: kernel_exec, ty_ctx: &mut *ctx.ty_ctx, - access_ctx: &mut AccessCtx::new(), + access_ctx: &mut AccessCtx::new(arena), unsafe_flag: ctx.unsafe_flag, }; exec::ty_check( @@ -1272,6 +1380,7 @@ fn ty_check_app_kernel<'a>( kernel_ctx.ty_ctx, None, &mut kernel_ctx.exec, + arena )?; // add explicit provenances to typing context (see ty_check_block) for prv in &app_kernel.shared_mem_prvs { @@ -1282,9 +1391,10 @@ fn ty_check_app_kernel<'a>( .shared_mem_dtys .iter() .map(|dty| { - IdentTyped::new( - Ident::new_impli(&utils::fresh_name("shared_mem")), - Ty::new(TyKind::Data(arena.alloc(DataTy::new(DataTyKind::At( + IdentTyped::new_in( + arena, + Ident::new_impli(arena, &utils::fresh_name("shared_mem")), + Ty::new(TyKind::Data(arena.alloc(DataTy::new(arena, DataTyKind::At( arena.alloc(dty.clone()), Memory::GpuShared, ))))), @@ -1315,7 +1425,7 @@ fn ty_check_app_kernel<'a>( }) .collect::>(); for shrd_mem_arg in refs_to_shrd.iter_mut() { - ty_check_expr(&mut kernel_ctx, shrd_mem_arg)?; + ty_check_expr(&mut kernel_ctx, shrd_mem_arg, arena)?; } // create extended argument list with references to shared memory let extended_arg_sigs = app_kernel @@ -1328,7 +1438,7 @@ fn ty_check_app_kernel<'a>( ) }) .chain(refs_to_shrd.into_iter().map(|a| { - let block_exec = exec_distrib_over_blocks(&kernel_ctx.exec); + let block_exec = exec_distrib_over_blocks(&kernel_ctx.exec, arena); ParamSig::new(block_exec, *a.ty.unwrap()) })) .collect::>(); @@ -1337,25 +1447,29 @@ fn ty_check_app_kernel<'a>( &mut kernel_ctx, &mut app_kernel.fun_ident, &mut app_kernel.gen_args, + arena )?; // build expected type to unify with let unit_ty = Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit))), )); - let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_dep_fn_ty); + let mut mono_fn_ty = unify::inst_fn_ty_scheme(&partially_applied_dep_fn_ty, arena); unify::unify( &mut FnTy::new( + arena, vec![], None, extended_arg_sigs, kernel_ctx.exec, unit_ty.clone(), vec![], + ), &mut mono_fn_ty, + arena )?; let mut inferred_k_args = - infer_kinded_args::infer_kinded_args(&partially_applied_dep_fn_ty, &mono_fn_ty)?; + infer_kinded_args::infer_kinded_args(&partially_applied_dep_fn_ty, &mono_fn_ty, arena)?; app_kernel.gen_args.append(&mut inferred_k_args); if let Some(mut fn_def) = ctx.gl_ctx.pop_fun_def(&app_kernel.fun_ident.name) { @@ -1373,17 +1487,17 @@ fn ty_check_app_kernel<'a>( .has_been_checked(&app_kernel.fun_ident.name, &nat_vals) { let mut called_nat_ctx = - NatCtx::with_frame(nat_names.into_iter().zip(nat_vals.clone()).collect()); - ty_check_global_fun_def(ctx.gl_ctx, &mut called_nat_ctx, &mut fn_def)?; + NatCtx::with_frame(arena, nat_names.into_iter().zip(nat_vals.clone()).collect()); + ty_check_global_fun_def(ctx.gl_ctx, &mut called_nat_ctx, &mut fn_def, arena)?; ctx.gl_ctx - .push_fun_checked_under_nats(fn_def, Box::from(nat_vals)) + .push_fun_checked_under_nats(arena, fn_def, Box::from(nat_vals)) } } Ok(unit_ty) } -fn exec_distrib_over_blocks<'a>(exec_expr: &'a ExecExpr<'a>) -> ExecExpr<'a> { - let base_clone = ExecExprKind::new(exec_expr.exec.base.clone()); +fn exec_distrib_over_blocks<'a>(exec_expr: &'a ExecExpr<'a>, arena: &'a Bump) -> ExecExpr<'a> { + let base_clone = ExecExprKind::new(arena, exec_expr.exec.base.clone()); let distrib_over_blocks = if let BaseExec::GpuGrid(gdim, _) = &exec_expr.exec.base { match gdim { Dim::XYZ(_) => base_clone @@ -1400,12 +1514,12 @@ fn exec_distrib_over_blocks<'a>(exec_expr: &'a ExecExpr<'a>) -> ExecExpr<'a> { } else { panic!("Expected GPU grid.") }; - ExecExpr::new(distrib_over_blocks) + ExecExpr::new(arena, distrib_over_blocks) } -fn ty_check_tuple<'a>(ctx: &mut ExprTyCtx, elems: &'a mut [Expr<'a>]) -> TyResult<'a, Ty<'a>> { +fn ty_check_tuple<'a>(ctx: &mut ExprTyCtx, elems: &'a mut [Expr<'a>], arena: &'a Bump) -> TyResult<'a, Ty<'a>> { for elem in elems.iter_mut() { - ty_check_expr(ctx, elem)?; + ty_check_expr(ctx, elem, arena)?; } let elem_tys: TyResult> = elems .iter() @@ -1417,15 +1531,15 @@ fn ty_check_tuple<'a>(ctx: &mut ExprTyCtx, elems: &'a mut [Expr<'a>]) -> TyResul }) .collect(); Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Tuple(elem_tys?))), + arena.alloc(DataTy::new(arena, DataTyKind::Tuple(elem_tys?))), ))) } -fn ty_check_proj<'a>(ctx: &mut ExprTyCtx, e: &'a mut Expr<'a>, i: usize) -> TyResult<'a, Ty<'a>> { +fn ty_check_proj<'a>(ctx: &mut ExprTyCtx, e: &'a mut Expr<'a>, i: usize, arena: &'a Bump) -> TyResult<'a, Ty<'a>> { if let ExprKind::PlaceExpr(_) = e.expr { panic!("Place expression should have been typechecked by a different rule.") } - ty_check_expr(ctx, e)?; + ty_check_expr(ctx, e, arena)?; let e_dty = if let TyKind::Data(dty) = &e.ty.as_ref().unwrap().ty { dty.as_ref() } else { @@ -1435,10 +1549,10 @@ fn ty_check_proj<'a>(ctx: &mut ExprTyCtx, e: &'a mut Expr<'a>, i: usize) -> TyRe Ok(Ty::new(TyKind::Data(arena.alloc(elem_ty?)))) } -fn ty_check_array<'a>(ctx: &mut ExprTyCtx, elems: &'a mut Vec>) -> TyResult<'a, Ty<'a>> { +fn ty_check_array<'a>(ctx: &'a mut ExprTyCtx<'a>, elems: &'a mut Vec>, arena: &'a Bump) -> TyResult<'a, Ty<'a>> { assert!(!elems.is_empty()); for elem in elems.iter_mut() { - ty_check_expr(ctx, elem)?; + ty_check_expr(ctx, elem, arena)?; } let ty = elems.first().unwrap().ty.as_ref(); if !matches!(&ty.unwrap().ty, TyKind::Data(_)) { @@ -1451,7 +1565,7 @@ fn ty_check_array<'a>(ctx: &mut ExprTyCtx, elems: &'a mut Vec>) -> TyRe "Not all provided elements have the same type.".to_string(), )) } else { - Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new( + Ok(Ty::new(TyKind::Data(arena.alloc(DataTy::new(arena, DataTyKind::Array( arena.alloc(ty.as_ref().unwrap().dty().clone()), Nat::Lit(elems.len()), @@ -1460,7 +1574,7 @@ fn ty_check_array<'a>(ctx: &mut ExprTyCtx, elems: &'a mut Vec>) -> TyRe } } -fn ty_check_literal<'a>(l: &mut Lit) -> Ty<'a> { +fn ty_check_literal<'a>(l: &mut Lit, arena: &'a Bump) -> Ty<'a> { let scalar_data = match l { Lit::Unit => ScalarTy::Unit, Lit::Bool(_) => ScalarTy::Bool, @@ -1472,7 +1586,7 @@ fn ty_check_literal<'a>(l: &mut Lit) -> Ty<'a> { Lit::F64(_) => ScalarTy::F64, }; Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(scalar_data))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(scalar_data))), )) } @@ -1480,6 +1594,7 @@ fn infer_pattern_ident_tys<'a>( ctx: &mut ExprTyCtx, pattern: &'a Pattern<'a>, pattern_ty: &'a Ty<'a>, + arena: &'a Bump ) -> TyResult<'a, ()> { let pattern_dty = if let TyKind::Data(dty) = &pattern_ty.ty { dty.as_ref() @@ -1488,7 +1603,8 @@ fn infer_pattern_ident_tys<'a>( }; match (pattern, &pattern_dty.dty) { (Pattern::Ident(mutbl, ident), _) => { - let ident_with_annotated_ty = IdentTyped::new( + let ident_with_annotated_ty = IdentTyped::new_in( + arena, ident.clone(), Ty::new(TyKind::Data(arena.alloc(pattern_dty.clone()))), *mutbl, @@ -1500,7 +1616,7 @@ fn infer_pattern_ident_tys<'a>( (Pattern::Wildcard, _) => Ok(()), (Pattern::Tuple(patterns), DataTyKind::Tuple(elem_tys)) => { for (p, tty) in patterns.iter().zip(elem_tys) { - infer_pattern_ident_tys(ctx, p, &Ty::new(TyKind::Data(arena.alloc(tty.clone()))))?; + infer_pattern_ident_tys(ctx, p, &Ty::new(TyKind::Data(arena.alloc(tty.clone()))), arena)?; } Ok(()) } @@ -1509,40 +1625,43 @@ fn infer_pattern_ident_tys<'a>( } fn infer_tys_and_append_idents<'a>( - ctx: &mut ExprTyCtx, + ctx: &'a mut ExprTyCtx<'a>, pattern: &'a Pattern<'a>, pattern_ty: &'a mut Option>>, assign_ty: &'a mut Ty<'a>, + arena: &'a Bump ) -> TyResult<'a, ()> { let pattern_ty = if let Some(pty) = pattern_ty { - unify::sub_unify(ctx.kind_ctx, ctx.ty_ctx, assign_ty, pty)?; + unify::sub_unify(ctx.kind_ctx, ctx.ty_ctx, assign_ty, pty, arena)?; pty.as_ref().clone() } else { assign_ty.clone() }; - infer_pattern_ident_tys(ctx, pattern, &pattern_ty) + infer_pattern_ident_tys(ctx, pattern, &pattern_ty, arena) } fn ty_check_let<'a>( - ctx: &mut ExprTyCtx, + ctx: &'a mut ExprTyCtx<'a>, pattern: &'a Pattern<'a>, pattern_ty: &'a mut Option>>, expr: &'a mut Expr<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { - ty_check_expr(ctx, expr)?; + ty_check_expr(ctx, expr, arena)?; let e_ty = expr.ty.as_mut().unwrap(); - infer_tys_and_append_idents(ctx, pattern, pattern_ty, e_ty)?; + infer_tys_and_append_idents(ctx, pattern, pattern_ty, e_ty, arena)?; Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit))), ))) } // TODO respect exec? fn ty_check_let_uninit<'a>( - ctx: &mut ExprTyCtx, + ctx: &'a mut ExprTyCtx<'a>, annot_exec: &'a Option>>, ident: &'a Ident<'a>, ty: &'a Ty<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { // TODO is the type well-formed? if let TyKind::Data(dty) = &ty.ty { @@ -1551,27 +1670,28 @@ fn ty_check_let_uninit<'a>( } else { ctx.exec.clone() }; - exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, &mut exec_expr)?; - let ident_with_ty = IdentTyped::new( + exec::ty_check(ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, &mut exec_expr, arena)?; + let ident_with_ty = IdentTyped::new_in( + arena, ident.clone(), Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Dead(dty.clone()))), + arena.alloc(DataTy::new(arena, DataTyKind::Dead(dty.clone()))), )), Mutability::Mut, exec_expr, ); ctx.ty_ctx.append_ident_typed(ident_with_ty); Ok(Ty::new(TyKind::Data( - arena.alloc(DataTy::new(DataTyKind::Scalar(ScalarTy::Unit))), + arena.alloc(DataTy::new(arena, DataTyKind::Scalar(ScalarTy::Unit))), ))) } else { Err(TyError::MutabilityNotAllowed(ty.clone())) } } -fn ty_check_seq<'a>(ctx: &mut ExprTyCtx, es: &'a mut [Expr<'a>]) -> TyResult<'a, Ty<'a>> { +fn ty_check_seq<'a>(ctx: &mut ExprTyCtx, es: &'a mut [Expr<'a>], arena: &'a Bump) -> TyResult<'a, Ty<'a>> { for e in &mut *es { - ty_check_expr(ctx, e)?; + ty_check_expr(ctx, e, arena)?; ctx.ty_ctx.garbage_collect_loans(); } Ok(es.last().unwrap().ty.as_ref().unwrap().as_ref().clone()) @@ -1580,8 +1700,9 @@ fn ty_check_seq<'a>(ctx: &mut ExprTyCtx, es: &'a mut [Expr<'a>]) -> TyResult<'a, fn ty_check_non_place<'a>( ctx: &mut ExprTyCtx, pl_expr: &'a mut PlaceExpr<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { - pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Shrd), pl_expr)?; + pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Shrd), pl_expr, arena)?; if !pl_expr.ty.as_ref().unwrap().is_fully_alive() { return Err(TyError::String(format!( "Part of Place {:?} was moved before.", @@ -1591,13 +1712,15 @@ fn ty_check_non_place<'a>( unify::unify( pl_expr.ty.as_mut().unwrap().as_mut(), &mut Ty::new(TyKind::Data(arena.alloc(DataTy::with_constr( - utils::fresh_ident("pl_deref", DataTyKind::Ident), + arena, utils::fresh_ident(arena, "pl_deref", DataTyKind::Ident), vec![Constraint::Copyable], )))), + arena )?; let potential_accesses = borrow_check::access_safety_check( &BorrowCheckCtx::new(ctx, vec![], Ownership::Shrd), pl_expr, + arena ) .map_err(|err| { TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Shrd, err) @@ -1610,9 +1733,9 @@ fn ty_check_non_place<'a>( } } -fn ty_check_place<'a>(ctx: &mut ExprTyCtx, pl_expr: &'a mut PlaceExpr<'a>) -> TyResult<'a, Ty<'a>> { - pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr)?; - let place = pl_expr.clone().to_place().unwrap(); +fn ty_check_place<'a>(ctx: &mut ExprTyCtx, pl_expr: &'a mut PlaceExpr<'a>, arena: &'a Bump) -> TyResult<'a, Ty<'a>> { + pl_expr::ty_check(&PlExprTyCtx::new(ctx, Ownership::Uniq), pl_expr, assert_mem_uninitialized_valid();)?; + let place = pl_expr.clone().to_place(arena).unwrap(); let pl_ty = ctx.ty_ctx.place_dty(&place)?; if !pl_ty.is_fully_alive() { return Err(TyError::String(format!( @@ -1625,6 +1748,7 @@ fn ty_check_place<'a>(ctx: &mut ExprTyCtx, pl_expr: &'a mut PlaceExpr<'a>) -> Ty borrow_check::access_safety_check( &BorrowCheckCtx::new(ctx, vec![], Ownership::Shrd), pl_expr, + arena ) .map_err(|err| { TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Shrd, err) @@ -1633,11 +1757,12 @@ fn ty_check_place<'a>(ctx: &mut ExprTyCtx, pl_expr: &'a mut PlaceExpr<'a>) -> Ty borrow_check::access_safety_check( &BorrowCheckCtx::new(ctx, vec![], Ownership::Uniq), pl_expr, + arena ) .map_err(|err| { TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), Ownership::Uniq, err) })?; - ctx.ty_ctx.kill_place(&place); + ctx.ty_ctx.kill_place(&place, arena); }; Ok(Ty::new(TyKind::Data(arena.alloc(pl_ty)))) } @@ -1647,9 +1772,10 @@ fn ty_check_borrow<'a>( prv_val_name: &Option, own: Ownership, pl_expr: &'a mut PlaceExpr<'a>, + arena: &'a Bump ) -> TyResult<'a, Ty<'a>> { // If borrowing a place uniquely, is it mutable? - if let Some(place) = pl_expr.to_place() { + if let Some(place) = pl_expr.to_place(arena) { if own == Ownership::Uniq && ctx.ty_ctx.ident_ty(&place.ident)?.mutbl == Mutability::Const { return Err(TyError::ConstBorrow(pl_expr.clone())); } @@ -1658,8 +1784,8 @@ fn ty_check_borrow<'a>( if !ctx.ty_ctx.loans_in_prv(&prv_val_name)?.is_empty() { return Err(TyError::PrvValueAlreadyInUse(prv_val_name)); } - let mems = pl_expr::ty_check_and_passed_mems(&PlExprTyCtx::new(ctx, own), pl_expr)?; - let loans = borrow_check::access_safety_check(&BorrowCheckCtx::new(ctx, vec![], own), pl_expr) + let mems = pl_expr::ty_check_and_passed_mems(&PlExprTyCtx::new(ctx, own), pl_expr, arena)?; + let loans = borrow_check::access_safety_check(&BorrowCheckCtx::new(ctx, vec![], own), pl_expr, arena) .map_err(|err| TyError::ConflictingBorrow(arena.alloc(pl_expr.clone()), own, err))?; mems.iter() .try_for_each(|mem| accessible_memory(ctx.exec.ty.as_ref().unwrap().as_ref(), mem))?; @@ -1694,7 +1820,8 @@ fn ty_check_borrow<'a>( "Trying to take reference of unaddressable gpu.local memory.".to_string(), )); } - let res_dty = DataTy::new(DataTyKind::Ref(arena.alloc(RefDty::new( + let res_dty = DataTy::new(arena, DataTyKind::Ref(arena.alloc(RefDty::new( + arena, Provenance::Value(prv_val_name.clone()), own, rmem, @@ -1738,6 +1865,7 @@ fn ty_well_formed<'a>( ty_ctx: &'a TyCtx<'a>, exec_ty: &'a ExecTy<'a>, ty: &'a Ty<'a>, + arena: &'a Bump ) -> TyResult<'a, ()> { match &ty.ty { TyKind::Data(dty) => match &dty.dty { @@ -1800,14 +1928,14 @@ fn ty_well_formed<'a>( } } } - ty_well_formed(kind_ctx, ty_ctx, exec_ty, &elem_ty)?; + ty_well_formed(kind_ctx, ty_ctx, exec_ty, &elem_ty, arena)?; } Provenance::Ident(ident) => { let elem_ty = Ty::new(TyKind::Data(reff.dty.clone())); if !kind_ctx.ident_of_kind_exists(ident, Kind::Provenance) { Err(CtxError::KindedIdentNotFound(ident.clone()))? } - ty_well_formed(kind_ctx, ty_ctx, exec_ty, &elem_ty)?; + ty_well_formed(kind_ctx, ty_ctx, exec_ty, &elem_ty, arena)?; } }; } @@ -1818,12 +1946,13 @@ fn ty_well_formed<'a>( ty_ctx, exec_ty, &Ty::new(TyKind::Data(arena.alloc(elem_dty.clone()))), + arena )?; } } DataTyKind::Struct(struct_decl) => { for (_, dty) in &struct_decl.fields { - ty_well_formed(kind_ctx, ty_ctx, exec_ty, &Ty::new(TyKind::Data(arena.alloc(dty.clone()))))?; + ty_well_formed(kind_ctx, ty_ctx, exec_ty, &Ty::new(TyKind::Data(arena.alloc(dty.clone()))), arena)?; } } DataTyKind::Array(elem_dty, n) => { @@ -1832,6 +1961,7 @@ fn ty_well_formed<'a>( ty_ctx, exec_ty, &Ty::new(TyKind::Data(elem_dty.clone())), + arena )?; // TODO well-formed nat } @@ -1841,6 +1971,7 @@ fn ty_well_formed<'a>( ty_ctx, exec_ty, &Ty::new(TyKind::Data(elem_dty.clone())), + arena )? // TODO well-formed nat } @@ -1855,6 +1986,7 @@ fn ty_well_formed<'a>( ty_ctx, exec_ty, &Ty::new(TyKind::Data(elem_dty.clone())), + arena )?; } DataTyKind::At(elem_dty, _) => { @@ -1863,6 +1995,7 @@ fn ty_well_formed<'a>( ty_ctx, exec_ty, &Ty::new(TyKind::Data(elem_dty.clone())), + arena )?; } }, @@ -1870,29 +2003,30 @@ fn ty_well_formed<'a>( TyKind::FnTy(fn_ty) => { let mut extended_kind_ctx = kind_ctx.clone(); extended_kind_ctx.append_idents(fn_ty.generics.clone()); - ty_well_formed(&extended_kind_ctx, ty_ctx, exec_ty, &fn_ty.ret_ty)?; + ty_well_formed(&extended_kind_ctx, ty_ctx, exec_ty, &fn_ty.ret_ty, arena)?; for param_sig in &fn_ty.param_sigs { // TODO which checks are necessary for the execution resource in // param_sig.exec_expr? - ty_well_formed(&extended_kind_ctx, ty_ctx, exec_ty, ¶m_sig.ty)?; + ty_well_formed(&extended_kind_ctx, ty_ctx, exec_ty, ¶m_sig.ty, arena)?; } } } Ok(()) } -pub fn callable_in<'a>(callee_exec_ty: &'a ExecTy<'a>, caller_exec_ty: &'a ExecTy<'a>) -> bool { +pub fn callable_in<'a>(callee_exec_ty: &'a ExecTy<'a>, caller_exec_ty: &'a ExecTy<'a>, arena: &'a Bump) -> bool { if &callee_exec_ty.ty == &ExecTyKind::Any { true } else { - let res = unify::unify(&mut callee_exec_ty.clone(), &mut caller_exec_ty.clone()); + let res = unify::unify(&mut callee_exec_ty.clone(), &mut caller_exec_ty.clone(), arena); res.is_ok() } } fn expand_exec_expr<'a>( - ctx: &ExprTyCtx, + ctx: &'a ExprTyCtx<'a>, exec_expr: &'a ExecExpr<'a>, + arena: &'a Bump ) -> TyResult<'a, ExecExpr<'a>> { match &exec_expr.exec.base { BaseExec::CpuThread | BaseExec::GpuGrid(_, _) => Ok(exec_expr.clone()), @@ -1902,20 +2036,21 @@ fn expand_exec_expr<'a>( let mut new_exec_path = inner_exec_expr.exec.path.clone(); new_exec_path.append(&mut exec_expr.exec.path.clone()); let mut expanded_exec_expr: ExecExpr = - ExecExpr::new(ExecExprKind::with_path(new_base, new_exec_path)); + ExecExpr::new(arena, ExecExprKind::with_path(new_base, new_exec_path)); exec::ty_check( ctx.nat_ctx, ctx.ty_ctx, ctx.ident_exec, &mut expanded_exec_expr, + arena )?; Ok(expanded_exec_expr) } } } -fn legal_exec_under_current<'a>(ctx: &ExprTyCtx, exec: &'a ExecExpr<'a>) -> TyResult<'a, ()> { - let expanded_exec_expr = expand_exec_expr(ctx, exec)?; +fn legal_exec_under_current<'a>(ctx: &'a ExprTyCtx<'a>, exec: &'a ExecExpr<'a>, arena: &'a Bump) -> TyResult<'a, ()> { + let expanded_exec_expr = expand_exec_expr(ctx, exec, arena)?; if ctx.exec != expanded_exec_expr { let current_exec_ty = &ctx.exec.ty.as_ref().unwrap().ty; let expanded_exec_ty = expanded_exec_expr.ty.unwrap().ty; diff --git a/src/ty_check/pl_expr.rs b/src/ty_check/pl_expr.rs index 6b311abc..6e508acb 100644 --- a/src/ty_check/pl_expr.rs +++ b/src/ty_check/pl_expr.rs @@ -182,6 +182,7 @@ fn ty_check_view<'a, 'm>( &ctx.exec, view_fn_ty, gen_args_ref, + arena, )?); let actual_view_fn_ty = arena.alloc(create_view_ty_with_input_view_and_free_ret(