Bend icon indicating copy to clipboard operation
Bend copied to clipboard

Execution is stuck until termination when running on CUDA in WSL2

Open wtfil opened this issue 1 year ago • 19 comments

Reproducing the behavior

The issue

Hi, I am having issues running code with bend run-cu on CUDA inside the WSL2. There are not errors, but code is not executing either. Execution is frozen, similary to while (true) {}. Code executes without any issues when using bend run or bend run-c Compiling with bend gen-cu and nvcc has the same result. I've tried both 12.4 and 12.5 and result is the same.

What I attempted

I tried different code examples from the repo, but result is always the same. Since bend allowed to compile code to cuda with gen-cu, I tried to find what is broken inside generated file (assuming bend run-cu will use the same code). This issue happened inside gnet_normalize function, where code could never exit the for loop. This break is never callen (rlen always has the same value)

CUDA verification

Just to rule CUDA out, I have successfully installed CUDA and can confirm it is recognised by compiling and running this code.

cuda-test.cu:

#include <cuda.h>
#include <stdio.h>

int main(int argc, char** argv) {
  int driver_version = 0, runtime_version = 0;

  cudaDriverGetVersion(&driver_version);
  cudaRuntimeGetVersion(&runtime_version);

  printf(
    "Driver Version: %d\nRuntime Version: %d\n",
    driver_version,
    runtime_version
  );

  return 0;
}

output

~> nvcc cuda-test.cu -o cuda-test && ./cuda-test
Driver Version: 10010
Runtime Version: 12040

nvidia-smi

Calling from wsl

>  nvidia-smi.exe
Sun Jun  2 16:32:08 2024
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 552.44                 Driver Version: 552.44         CUDA Version: 12.4     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                     TCC/WDDM  | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 3070      WDDM  |   00000000:08:00.0  On |                  N/A |
| 49%   56C    P3             41W /  220W |    6496MiB /   8192MiB |     36%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A      3832    C+G   ...oogle\Chrome\Application\chrome.exe      N/A      |
|    0   N/A  N/A      8292    C+G   C:\Windows\explorer.exe                     N/A      |
|    0   N/A  N/A     21004    C+G   ...\cef\cef.win7x64\steamwebhelper.exe      N/A      |
|    0   N/A  N/A     21416    C+G   ...wekyb3d8bbwe\XboxGameBarWidgets.exe      N/A      |
|    0   N/A  N/A     27344    C+G   ...ience\NVIDIA GeForce Experience.exe      N/A      |
....
+-----------------------------------------------------------------------------------------+

System Settings

Example:

  • HVM: 2.0.18
  • Bend: 0.2.27
  • OS: Ubuntu 20.04.6 LTS
  • WSL: 2.1.5.0
  • CPU: AMD Ryzen 9 5900X
  • GPU: RTX 3070
  • Cuda Version: 12.5, V12.5.40

Additional context

No response

wtfil avatar Jun 02 '24 15:06 wtfil

Is this for any program you try to run? Also, what compiler version is nvcc using? By default it should be g++ and you can check its version with g++ --version

developedby avatar Jun 04 '24 12:06 developedby

Yes, all exmples from examples folder have the same beheviour. For example compiled fib and it fail to break the same loop, because rlen is aways has the same value (which is different from run to run, but never zero)

nvcc and g++

~ > nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2024 NVIDIA Corporation
Built on Wed_Apr_17_19:19:55_PDT_2024
Cuda compilation tools, release 12.5, V12.5.40
Build cuda_12.5.r12.5/compiler.34177558_0
~ > g++ --version
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

wtfil avatar Jun 04 '24 21:06 wtfil

I would like to also add that I have this same issue on my laptop running ubuntu linux. I have tried the sorter.bend script from the README on three machines now and I have gotten it to run on my other two (one has a laptop 3080 gpu and the other running dual RTX A4000s) however it won't run on my laptop with a Quadro P600 (cuda version 12.2). It does the same thing @wtfil is describing where it simply hangs.

Looking at the processor usage, it seems as though it might be having an issue allocating GPU memory (?). I can see it running 100% on a single cpu core but never load either the RAM or VRAM and there is no processing being run on the GPU either. Here are some specs from the machine in question if this might be a bug to be fixed in the future. (Already love this programming language BTW, really hoping I can start switching over to it at work when more support is added in).

Info: HVM: 2.0.19 Bend: 0.2.27 OS: Ubuntu 22.04.4 LTS Kernel: 6.5.0-35 CPU: Intel i5-9300H GPU: Nvidia Quadro P600 Mobile g++: 11.4.0 nvcc: 12.2 nvidia driver: 535.171.04

keaneflynn avatar Jun 05 '24 19:06 keaneflynn

I'm getting the same issue with: HVM: 2.0.19 Bend: 0.2.33 Ubuntu 22.04.4 LTS x86_64 Kernel: 6.5.0-35 CPU: AMD Ryzen 7 5800H GPU: NVIDIA GeForce RTX 3070 Mobile g++: 11.4.0 nvcc: 12.5 nvidia driver: 550.67

NemoInfo avatar Jun 06 '24 13:06 NemoInfo

Same issue here on Ubuntu (not WSL). I tried debugging this issue in the official discord server here.

As @keaneflynn observed, it doesn't allocate vram correctly, and hangs for a long time until it crashes with the following message:

Failed to launch kernels. Error code: an illegal memory access was encountered.
Errors:
Failed to parse result from HVM.

I waited 45 minutes while another discord server member only waited 30 minutes with his example in a virtual machine. I don't think the time is as important since the program crashed shortly after I launched another application (steam in my case).

A quick summary of the debugging we did in discord: Downgrading from cuda 12.5 to 12.4 doesn't help. Examples unrelated to bend compiled by nvcc work just fine, so it's not a (simple) issue with cuda. Using run and run-c work for the examples provided by bend while using run-cu directly or gen-cu then compiling with nvcc hangs. A different member of the server mentioned it could be an issue with the smaller L1 cache size of my GXT 1660, but that doesn't seem to be the case due to multiple 3070's listed here also not working.

My Specs

HVM: 2.0.18
Bend: 0.2.27
Ubuntu 22.04.4 LTS x86_64
Kernel: 6.5.0-35
CPU: AMD Ryzen 7 5800X 8-Core Processor
GPU: NVIDIA GeForce GTX 1660 (ti I think?)
g++: 11.4.0
nvcc: V12.4.131
nvidia driver: 555.42.02

nmay231 avatar Jun 06 '24 19:06 nmay231

I'm getting the same issue with: HVM: 2.0.19 Bend: 0.2.33 Ubuntu 22.04.4 LTS x86_64 Kernel: 6.5.0-35 CPU: AMD Ryzen 7 5800H GPU: NVIDIA GeForce RTX 3070 Mobile g++: 11.4.0 nvcc: 12.5 nvidia driver: 550.67

This is fascinating as I have a laptop with nearly identical specs that does manage to use the run-cu properly. I have the 5800H on ubuntu 22.04 except it has a 3080 mobile. I am pretty sure the cache on these two chips are identical per @nmay231 inquiry. Hoping to see some bug fixes here soon!

keaneflynn avatar Jun 06 '24 20:06 keaneflynn

Same issue here

GTX 1050 Ti (Nvidia Studio driver 551.23)
Intel i5-6400
Windows 10 22H2 (OS Build 19045.4474) --> WSL 2.0.14.0 (Kernel version 5.15.133.1-1) --> Ubuntu 24.04 LTS
g++ 13.2.0
nvcc cuda_12.5.r12.5/compiler.34177558_0
hvm 2.0.18
bend 0.2.27

hopperelec avatar Jun 07 '24 11:06 hopperelec

Hey, I am also facing the same issue. All the dedicated GPU memory gets full. And the process is stuck.

bend 0.2.33
hvm 2.0.19
nvcc V12.5.40
wsl-ubuntu 22.04.3 LTS
gpu NVIDIA GeForce RTX 2060

Imran-S-heikh avatar Jun 07 '24 14:06 Imran-S-heikh

@Imran-S-heikh I'm not certain if we have the same issue. My Video RAM for the bend/hvm process never went above 100 MiB.

Perhaps we should all make sure we are experiencing the same thing. Here's a very simple program, that shouldn't need much memory. It hangs with bend run-cu. I checked my GPU memory usage with nvtop (98 MiB VRAM, 0% GPU, 102 MiB RAM, 100% on a CPU core).

def main:
  return (1 + 1)

Also, I forgot to mention I did try running run-cu --verbose and this is the output of the program above.

bend run-cu --verbose simple.bend

% bend run-cu -v simple.bend
(Map/empty) = Map/Leaf

(Map/get map key) = match map = map { Map/Leaf: (*, map); Map/Node: switch _ = (== 0 key) { 0: switch _ = (% key 2) { 0: let (got, rest) = (Map/get map.left (/ key 2)); (got, (Map/Node map.value rest map.right)); _ _-1: let (got, rest) = (Map/get map.right (/ key 2)); (got, (Map/Node map.value map.left rest)); }; _ _-1: (map.value, map); }; }

(Map/set map key value) = match map = map { Map/Node: switch _ = (== 0 key) { 0: switch _ = (% key 2) { 0: (Map/Node map.value (Map/set map.left (/ key 2) value) map.right); _ _-1: (Map/Node map.value map.left (Map/set map.right (/ key 2) value)); }; _ _-1: (Map/Node value map.left map.right); }; Map/Leaf: switch _ = (== 0 key) { 0: switch _ = (% key 2) { 0: (Map/Node * (Map/set Map/Leaf (/ key 2) value) Map/Leaf); _ _-1: (Map/Node * Map/Leaf (Map/set Map/Leaf (/ key 2) value)); }; _ _-1: (Map/Node value Map/Leaf Map/Leaf); }; }

(IO/MAGIC) = (13683217, 16719857)

(IO/wrap x) = (IO/Done IO/MAGIC x)

(IO/bind a b) = match a = a { IO/Done: (b a.expr); IO/Call: (IO/Call IO/MAGIC a.func a.argm λx (IO/bind (a.cont x) b)); }

(call func argm) = (IO/Call IO/MAGIC func argm λx (IO/Done IO/MAGIC x))

(print text) = (IO/Call IO/MAGIC "PUT_TEXT" text λx (IO/Done IO/MAGIC x))

(get_time) = (IO/Call IO/MAGIC "GET_TIME" * λx (IO/Done IO/MAGIC x))

(sleep hi_lo) = (IO/Call IO/MAGIC "PUT_TIME" hi_lo λx (IO/Done IO/MAGIC x))

(main) = (+ 1 1)

nmay231 avatar Jun 07 '24 17:06 nmay231

@nmay231 I get the exact same output. I also have the same results- it uses all my CPU but no GPU

hopperelec avatar Jun 07 '24 19:06 hopperelec

Can someone with the issue try running cuda version 11.x? (sudo apt install nvidia-cuda-toolkit will get version 11) With my 980Ti, on cuda 11, I would instantly get the Failed to launch kernels error, whereas on cuda 12.5, the program just hangs. This issue is most likely same as #364, where GPU memory architecture is the cause because bend was only tested on an rtx 4090.

TimotejFasiang avatar Jun 08 '24 10:06 TimotejFasiang

@TimotejFasiang For me, sudo apt install nvidia-cuda-toolkit installed version 12.0.140~12.0.1-4build4, and I couldn't find any full 11.x version numbers to specify (e.g: E: Unable to locate package [email protected]). I don't use Linux very often so I might be doing something silly, though

hopperelec avatar Jun 08 '24 16:06 hopperelec

I have a little update on the issue, hope this will help to understand it better. Initially I faced this issue when used [email protected] from WSL. Today I tried my second image - [email protected] on the same machine and it worked! This image was almost fresh so I run installations steps from the README and bend run-cu worked right away

Here are the version of relevant tools for both images

name [email protected] [email protected]
os Ubuntu 20.04.6 LTS Ubuntu 22.04.3 LTS
gcc gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0 gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
nvcc release 12.5, V12.5.40 release 12.5, V12.5.40
hvm 2.0.19 2.0.19
bend 0.2.33 0.2.33
cargo 1.80.0-nightly 1.78.0

The only major different is gcc between two

I also noticed that nvidia-smi (not the nvidia-smi.exe) is failing on [email protected] with following error:

NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

nvidia-smi on [email protected] works fine

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 555.85                 Driver Version: 555.85         CUDA Version: 12.5     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                  Driver-Model | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 3070      WDDM  |   00000000:08:00.0  On |                  N/A |
|  0%   46C    P8             22W /  220W |    2652MiB /   8192MiB |     36%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

[email protected]

~/www/bend-examples > time bend run bitonic_sort.bend
Result: 16646144

real    0m35.908s
user    0m33.658s
sys     0m2.250s
~/www/bend-examples > time bend run-c bitonic_sort.bend
Result: 16646144

real    0m10.611s
user    1m3.683s
sys     1m44.188s
~/www/bend-examples > time bend run-cu bitonic_sort.bend
Result: 16646144

real    0m2.410s
user    0m1.996s
sys     0m0.080s

wtfil avatar Jun 08 '24 17:06 wtfil

I am noticing similar. When running on WSL2, I noticed that the default parallel_hello_world would not finish (before I got bored of waiting and figured something was wrong). I have a standard RTX 3070, btw. I rewrote things to play around, and found that it ran plenty fast when running gen(13), just not gen(16). My guess is some issue with using too much GPU memory and getting stuck, as some have mentioned here.

Moreover, when running gen(16), my GPU continued to be fully running after CTRL+C the command line and attempting to terminate the process. Is this related to having no IO?

Info: HVM: 2.0.19 Bend: 0.2.27 OS: wsl-ubuntu 22.04.3 LTS Kernel: 6.5.0-35 CPU: RYZEN 3600X GPU: RTX 3070 g++: 11.4.0

evbxll avatar Jun 14 '24 23:06 evbxll

@evbxll Sounds like a different issue. The issue I and others are describing happens even for a very simple program like the one below

def main:
  return (1 + 1)

Also, the issue we're describing results in all our CPU being used, but none of our GPU, and CTRL+C does stop it from using all the CPU for me

hopperelec avatar Jun 15 '24 00:06 hopperelec

@evbxll Sounds like a different issue. The issue I and others are describing happens even for a very simple program like the one below

def main:
  return (1 + 1)

Also, the issue we're describing results in all our CPU being used, but none of our GPU, and CTRL+C does stop it from using all the CPU for me

Eh, I feel like the original issue these comments are under is similar to me. Execution stuck when running CUDA WSL2

evbxll avatar Jun 15 '24 01:06 evbxll

Yeah, one also get this issue, so one followed a few steps:

  1. #364 solution (since one had an 1080 Ti) but modify on the current latest version hvm v2.0.19 (instead of the v2.0.13 @hubble14567 originally mentioned).
  2. Follow @wtfil suggestion to install ubuntu 22.04 (and 24.04 LTS just in case, but both are installed on separate disk because you can't install both on the same folder same disk, otherwise, it'll share a single virtual disk and that's a huge issue); in the end, both works.
  3. Update driver from 536.xx (forgot the exact version) to 555.99 (the current latest version). If one tries to run nvidia-smi now should get segmentation fault. Restart your computer, then the error should be gone. Now, run bend run-cu simple.bend -s and it'll have no problem.

The fix is quite stupid, because it seems to take so long to move data from cpu to gpu that running the simple.bend suggested above took 5-6 seconds.

wabinab@...: $ bend run-cu simple.bend -s
Result: 2
- ITRS: 2
- LEAK: 0
- TIME: 5.83s
- MIPS: 0.00

Edit: Anyway, one tries to run a second time and it seems to decrease in time, although the simple isn't worth it.

wabinab@...: $ bend run-cu simple.bend -s
Result: 2
- ITRS: 2
- LEAK: 0
- TIME: 0.29s
- MIPS: 0.00

Similarly, if we try run the parallel_sum.bend as a hello world, the results aren't enticing with 1080 Ti:

bend run-c parallel_sum.bend -s
Result: 5908768
- ITRS: 45999971
- TIME: 0.69s
- MIPS: 66.89

bend run-cu parallel_sum.bend -s
Result: 5908768
- ITRS: 45983587
- LEAK: 37606783
- TIME: 0.83s
- MIPS: 55.62

There's a lot of LEAK, and calculations are slower compared to 4-core CPU (i5-7400).

Wabinab avatar Jun 17 '24 11:06 Wabinab

is there a fix for this? running into same issue

tczee36 avatar Jun 23 '24 01:06 tczee36

I am also experiencing an issue where the process for run-cu doesn't terminate, but run-rs works fine. I've tried different examples from the source code, including the simple hello_world.bend and the result is always the same. I'm on native Linux Ubuntu Desktop.

Ubuntu 24.04.2 LTS RTX 5070 Ti NVIDIA Driver Version: 12.9 CUDA Runtime / NVCC Version: 12.8.93 Bend Version: 0.2.38 HVM Version: 2.0.22 GCC Version: 13.3.0

Is there a way to log what's happening on the HVM side when running bend code?

The ouput when running a simple 1+1 example shows that it suddenly stops doing anything after some HVM Math calls:

bend run-cu 1p1.bend --verbose List/flatten: ((List (List T)) -> (List T)) (List/flatten (List/Cons x xs)) = (List/concat x (List/flatten xs)) (List/flatten (List/Nil)) = List/Nil

List/concat: ((List T) -> (List T) -> (List T)) (List/concat (List/Cons x xs) ys) = (List/Cons x (List/concat xs ys)) (List/concat (List/Nil) ys) = ys

List/filter: ((List T) -> (T -> u24) -> (List T)) (List/filter (List/Nil) _) = List/Nil (List/filter (List/Cons x xs) pred) = switch %cond = (pred x) { 0: (List/filter xs pred); _ %cond-1: (List/Cons x (List/filter xs pred)); }

String/equals: (String -> String -> u24) (String/equals (String/Nil) (String/Nil)) = 1 (String/equals (String/Cons x xs) (String/Cons y ys)) = switch %cond = (== x y) { 0: 0; _ %cond-1: (String/equals xs ys); } (String/equals * *) = 0

String/split: (String -> u24 -> (List String)) (String/split s delim) = (String/split.go s delim [""])

String/split.go: (String -> u24 -> (List String) -> (List String)) (String/split.go (String/Nil) _ acc) = (List/reverse acc) (String/split.go (String/Cons c cs) delim acc) = switch %cond = (== c delim) { 0: match acc = acc { List/Cons: (String/split.go cs delim (List/Cons (String/Cons c acc.head) acc.tail)); List/Nil: []; }; _ %cond-1: (String/split.go cs delim (List/Cons String/Nil acc)); }

IO/FS/STDIN: u24 (IO/FS/STDIN) = 0

IO/FS/STDOUT: u24 (IO/FS/STDOUT) = 1

IO/FS/STDERR: u24 (IO/FS/STDERR) = 2

IO/FS/SEEK_SET: i24 (IO/FS/SEEK_SET) = +0

IO/FS/SEEK_CUR: i24 (IO/FS/SEEK_CUR) = +1

IO/FS/SEEK_END: i24 (IO/FS/SEEK_END) = +2

Utf8/REPLACEMENT_CHARACTER: u24 (Utf8/REPLACEMENT_CHARACTER) = 65533

String/decode_utf8: ((List u24) -> String) (String/decode_utf8 []) = String/Nil (String/decode_utf8 bytes) = let (got, rest) = (Utf8/decode_character bytes); match rest = rest { List/Nil: (String/Cons got String/Nil); List/Cons: (String/Cons got (String/decode_utf8 rest)); }

Utf8/decode_character: ((List u24) -> (u24, (List u24))) (Utf8/decode_character []) = (0, []) (Utf8/decode_character [a]) = switch %cond = (<= a 127) { 0: (Utf8/REPLACEMENT_CHARACTER, []); _ %cond-1: (a, []); } (Utf8/decode_character [a, b]) = use Utf8/maskx = 63; use Utf8/mask2 = 31; switch %cond = (<= a 127) { 0: switch %cond = (== (& a 224) 192) { 0: (Utf8/REPLACEMENT_CHARACTER, []); _ %cond-1: let r = (| (<< (& a Utf8/mask2) 6) (& b Utf8/maskx)); (r, []); }; _ %cond-1: (a, [b]); } (Utf8/decode_character [a, b, c]) = use Utf8/maskx = 63; use Utf8/mask2 = 31; use Utf8/mask3 = 15; switch %cond = (<= a 127) { 0: switch %cond = (== (& a 224) 192) { 0: switch %cond = (== (& a 240) 224) { 0: (Utf8/REPLACEMENT_CHARACTER, []); _ %cond-1: let r = (| (<< (& a Utf8/mask3) 12) (| (<< (& b Utf8/maskx) 6) (& c Utf8/maskx))); (r, []); }; _ %cond-1: let r = (| (<< (& a Utf8/mask2) 6) (& b Utf8/maskx)); (r, [c]); }; _ %cond-1: (a, [b, c]); } (Utf8/decode_character (List/Cons a (List/Cons b (List/Cons c (List/Cons d rest))))) = use Utf8/maskx = 63; use Utf8/mask2 = 31; use Utf8/mask3 = 15; use Utf8/mask4 = 7; switch %cond = (<= a 127) { 0: switch %cond = (== (& a 224) 192) { 0: switch %cond = (== (& a 240) 224) { 0: switch %cond = (== (& a 248) 240) { 0: (Utf8/REPLACEMENT_CHARACTER, rest); _ %cond-1: let r = (| (<< (& a Utf8/mask4) 18) (| (<< (& b Utf8/maskx) 12) (| (<< (& c Utf8/maskx) 6) (& d Utf8/maskx)))); (r, rest); }; _ %cond-1: let r = (| (<< (& a Utf8/mask3) 12) (| (<< (& b Utf8/maskx) 6) (& c Utf8/maskx))); (r, (List/Cons d rest)); }; _ %cond-1: let r = (| (<< (& a Utf8/mask2) 6) (& b Utf8/maskx)); (r, (List/Cons c (List/Cons d rest))); }; _ %cond-1: (a, (List/Cons b (List/Cons c (List/Cons d rest)))); }

String/encode_utf8: (String -> (List u24)) (String/encode_utf8 (String/Nil)) = List/Nil (String/encode_utf8 (String/Cons x xs)) = use Utf8/rune1max = 127; use Utf8/rune2max = 2047; use Utf8/rune3max = 65535; use Utf8/tx = 128; use Utf8/t2 = 192; use Utf8/t3 = 224; use Utf8/t4 = 240; use Utf8/maskx = 63; switch %cond = (<= x Utf8/rune1max) { 0: switch %cond = (<= x Utf8/rune2max) { 0: switch %cond = (<= x Utf8/rune3max) { 0: let b1 = (| Utf8/t4 (>> x 18)); let b2 = (| Utf8/tx (& (>> x 12) Utf8/maskx)); let b3 = (| Utf8/tx (& (>> x 6) Utf8/maskx)); let b4 = (| Utf8/tx (& x Utf8/maskx)); (List/Cons b1 (List/Cons b2 (List/Cons b3 (List/Cons b4 (String/encode_utf8 xs))))); _ %cond-1: let b1 = (| Utf8/t3 (>> x 12)); let b2 = (| Utf8/tx (& (>> x 6) Utf8/maskx)); let b3 = (| Utf8/tx (& x Utf8/maskx)); (List/Cons b1 (List/Cons b2 (List/Cons b3 (String/encode_utf8 xs)))); }; _ %cond-1: let b1 = (| Utf8/t2 (>> x 6)); let b2 = (| Utf8/tx (& x Utf8/maskx)); (List/Cons b1 (List/Cons b2 (String/encode_utf8 xs))); }; _ %cond-1: (List/Cons x (String/encode_utf8 xs)); }

String/decode_ascii: ((List u24) -> String) (String/decode_ascii (List/Cons x xs)) = (String/Cons x (String/decode_ascii xs)) (String/decode_ascii (List/Nil)) = String/Nil

String/encode_ascii: (String -> (List u24)) (String/encode_ascii (String/Cons x xs)) = (List/Cons x (String/encode_ascii xs)) (String/encode_ascii (String/Nil)) = List/Nil

Math/cot: (f24 -> f24) (Math/cot a) = (/ 1.000 (Math/tan a))

Math/sec: (f24 -> f24) (Math/sec a) = (/ 1.000 (Math/cos a))

Math/csc: (f24 -> f24) (Math/csc a) = (/ 1.000 (Math/sin a))

Math/atan: (f24 -> f24) (Math/atan a) = (Math/atan2 a 1.000)

Math/asin: (f24 -> f24) (Math/asin a) = (Math/atan2 a (Math/sqrt (- 1.000 (* a a))))

Math/acos: (f24 -> f24) (Math/acos a) = (Math/atan2 (Math/sqrt (- 1.000 (* a a))) a)

Math/radians: (f24 -> f24) (Math/radians a) = (* a (/ Math/PI 180.000))

Math/sqrt: (f24 -> f24) (Math/sqrt n) = (** n 0.500)

List/length: ((List T) -> (u24, (List T))) (List/length xs) = fold xs = xs with len = 0, acc = DiffList/new, { List/Nil: (len, (DiffList/to_list acc)); List/Cons: (xs.tail (+ len 1) (DiffList/append acc xs.head)); }

List/reverse: ((List T) -> (List T)) (List/reverse xs) = fold xs = xs with acc = [], { List/Nil: acc; List/Cons: (xs.tail (List/Cons xs.head acc)); }

List/split_once: ((List T) -> (T -> u24) -> (Result ((List T), (List T)) (List T))) (List/split_once xs cond) = (List/split_once.go xs cond DiffList/new)

List/split_once.go: ((List T) -> (T -> u24) -> ((List T) -> (List T)) -> (Result ((List T), (List T)) (List T))) (List/split_once.go xs cond acc) = match xs = xs { List/Nil: (Result/Err (DiffList/to_list acc)); List/Cons: switch %pred = (cond xs.head) { 0: (List/split_once.go xs.tail cond (DiffList/append acc xs.head)); _ %pred-1: (Result/Ok ((DiffList/to_list acc), xs.tail)); }; }

DiffList/new: ((List T) -> (List T)) (DiffList/new) = λx x

DiffList/wrap: (T -> (List T) -> (List T)) (DiffList/wrap head) = λtail (List/Cons head tail)

DiffList/append: (((List T) -> (List T)) -> T -> (List T) -> (List T)) (DiffList/append diff val) = λx (diff (List/Cons val x))

DiffList/concat: (((List T) -> (List T)) -> ((List T) -> (List T)) -> (List T) -> (List T)) (DiffList/concat left right) = λx (left (right x))

DiffList/cons: (((List T) -> (List T)) -> T -> (List T) -> (List T)) (DiffList/cons diff val) = λx (List/Cons val (diff x))

DiffList/to_list: (((List T) -> (List T)) -> (List T)) (DiffList/to_list diff) = (diff List/Nil)

Result/unwrap: ((Result T E) -> Any) (Result/unwrap res) = match res = res { Result/Ok: res.val; Result/Err: res.val; }

Result/and: ((Result A E) -> (Result B E) -> (Result B E)) (Result/and fst snd) = match fst = fst { Result/Ok: snd; Result/Err: fst; }

Result/map_err: ((Result T E) -> (E -> F) -> (Result T F)) (Result/map_err res f) = match res = res { Result/Ok: (Result/Ok res.val); Result/Err: (Result/Err (f res.val)); }

Tree/to_list: ((Tree T) -> (List T)) (Tree/to_list tree) = let list = fold tree = tree { Tree/Leaf: (DiffList/wrap tree.value); Tree/Node: (DiffList/concat tree.left tree.right); }; (DiffList/to_list list)

Tree/reverse: ((Tree T) -> (Tree T)) (Tree/reverse tree) = fold tree = tree { Tree/Leaf: (Tree/Leaf tree.value); Tree/Node: (Tree/Node tree.right tree.left); }

Maybe/unwrap: ((Maybe T) -> T) (Maybe/unwrap m) = match m = m { Maybe/Some: m.value; Maybe/None: unreachable; }

Map/empty: (Map T) (Map/empty) = Map/Leaf

Map/get: ((Map T) -> u24 -> (T, (Map T))) (Map/get map key) = match map = map { Map/Leaf: (unreachable, map); Map/Node: switch %pred = (== 0 key) { 0: switch %pred = (== (% key 2) 0) { 0: let (got, rest) = (Map/get map.right (/ key 2)); (got, (Map/Node map.value map.left rest)); _ %pred-1: let (got, rest) = (Map/get map.left (/ key 2)); (got, (Map/Node map.value rest map.right)); }; _ %pred-1: ((Maybe/unwrap map.value), map); }; }

Map/get_check: ((Map T) -> u24 -> ((Maybe T), (Map T))) (Map/get_check map key) = match map = map { Map/Leaf: (Maybe/None, map); Map/Node: switch %pred = (== 0 key) { 0: switch %pred = (== (% key 2) 0) { 0: let (new_value, new_map) = (Map/get_check map.right (/ key 2)); (new_value, (Map/Node map.value map.left new_map)); _ %pred-1: let (new_value, new_map) = (Map/get_check map.left (/ key 2)); (new_value, (Map/Node map.value new_map map.right)); }; _ %pred-1: (map.value, map); }; }

Map/set: ((Map T) -> u24 -> T -> (Map T)) (Map/set map key value) = match map = map { Map/Node: switch %pred = (== 0 key) { 0: switch %pred = (== (% key 2) 0) { 0: (Map/Node map.value map.left (Map/set map.right (/ key 2) value)); _ %pred-1: (Map/Node map.value (Map/set map.left (/ key 2) value) map.right); }; _ %pred-1: (Map/Node (Maybe/Some value) map.left map.right); }; Map/Leaf: switch %pred = (== 0 key) { 0: switch %pred = (== (% key 2) 0) { 0: (Map/Node Maybe/None Map/Leaf (Map/set Map/Leaf (/ key 2) value)); _ %pred-1: (Map/Node Maybe/None (Map/set Map/Leaf (/ key 2) value) Map/Leaf); }; _ %pred-1: (Map/Node (Maybe/Some value) Map/Leaf Map/Leaf); }; }

Map/contains: ((Map T) -> u24 -> (u24, (Map T))) (Map/contains map key) = match map = map { Map/Leaf: (0, map); Map/Node: switch %pred = (== 0 key) { 0: switch %pred = (== (% key 2) 0) { 0: let (new_value, new_map) = (Map/contains map.right (/ key 2)); (new_value, (Map/Node map.value map.left new_map)); _ %pred-1: let (new_value, new_map) = (Map/contains map.left (/ key 2)); (new_value, (Map/Node map.value new_map map.right)); }; _ %pred-1: match map.value = map.value { Maybe/Some: (1, map); Maybe/None: (0, map); }; }; }

Map/map: ((Map T) -> u24 -> (T -> T) -> (Map T)) (Map/map map key f) = match map = map { Map/Leaf: Map/Leaf; Map/Node: switch %pred = (== 0 key) { 0: switch %pred = (== (% key 2) 0) { 0: (Map/Node map.value map.left (Map/map map.right (/ key 2) f)); _ %pred-1: (Map/Node map.value (Map/map map.left (/ key 2) f) map.right); }; _ %pred-1: (Map/Node (Maybe/Some (f (Maybe/unwrap map.value))) map.left map.right); }; }

IOError/unwrap_inner: ((IOError T) -> T) (IOError/unwrap_inner err) = match err = err { IOError/Type: unreachable; IOError/Name: unreachable; IOError/Inner: err.value; }

IO/MAGIC: (u24, u24) (IO/MAGIC) = (13683217, 16719857)

IO/wrap: (T -> (IO T)) (IO/wrap x) = (IO/Done IO/MAGIC x)

IO/bind: ((IO A) -> ((Id -> Id) -> A -> (IO B)) -> (IO B)) (IO/bind a b) = match a = a { IO/Done: (undefer b a.expr); IO/Call: (IO/Call a.magic a.func a.argm λx (IO/bind (a.cont x) b)); }

IO/call: (String -> Any -> (IO (Result Any (IOError Any)))) (IO/call func argm) = (IO/Call IO/MAGIC func argm λx (IO/Done IO/MAGIC x))

IO/map: ((IO A) -> (A -> B) -> (IO B)) (IO/map io f) = with IO { ask a = io; (wrap (f a)) }

IO/unwrap_inner: ((IO (Result A (IOError B))) -> (IO (Result A B))) (IO/unwrap_inner io) = with IO { ask res = io; match res = res { Result/Ok: (wrap (Result/Ok res.val)); Result/Err: (wrap (Result/Err (IOError/unwrap_inner res.val))); } }

IO/get_time: (IO (u24, u24)) (IO/get_time) = with IO { ask res = (IO/call "GET_TIME" *); (wrap (Result/unwrap res)) }

IO/nanosleep: ((u24, u24) -> (IO None)) (IO/nanosleep hi_lo) = with IO { ask res = (IO/call "SLEEP" hi_lo); (wrap (Result/unwrap res)) }

IO/sleep: (f24 -> (IO None)) (IO/sleep seconds) = let nanos = (* seconds 1000000000.000); let lo = (f24/to_u24 (% nanos 16777216.000)); let hi = (f24/to_u24 (/ nanos 16777216.000)); (IO/nanosleep (hi, lo))

IO/FS/open: (String -> String -> (IO (Result u24 u24))) (IO/FS/open path mode) = (IO/unwrap_inner (IO/call "OPEN" (path, mode)))

IO/FS/close: (u24 -> (IO (Result None u24))) (IO/FS/close file) = (IO/unwrap_inner (IO/call "CLOSE" file))

IO/FS/read: (u24 -> u24 -> (IO (Result (List u24) u24))) (IO/FS/read file num_bytes) = (IO/unwrap_inner (IO/call "READ" (file, num_bytes)))

IO/FS/write: (u24 -> (List u24) -> (IO (Result None u24))) (IO/FS/write file bytes) = (IO/unwrap_inner (IO/call "WRITE" (file, bytes)))

IO/FS/seek: (u24 -> i24 -> i24 -> (IO (Result None u24))) (IO/FS/seek file offset mode) = (IO/unwrap_inner (IO/call "SEEK" (file, (offset, mode))))

IO/FS/flush: (u24 -> (IO (Result None u24))) (IO/FS/flush file) = (IO/unwrap_inner (IO/call "FLUSH" file))

IO/FS/read_file: (String -> (IO (Result (List u24) u24))) (IO/FS/read_file path) = with IO { ask res_fd = (IO/FS/open path "r"); match res_fd = res_fd { Result/Ok: let fd = res_fd.val; ask res1 = (IO/FS/read_to_end fd); ask res2 = (IO/FS/close fd); (wrap (Result/and res2 res1)); Result/Err: (wrap (Result/Err res_fd.val)); } }

IO/FS/read_to_end: (u24 -> (IO (Result (List u24) u24))) (IO/FS/read_to_end fd) = (IO/FS/read_to_end.read_chunks fd [])

IO/FS/read_to_end.read_chunks: (u24 -> (List (List u24)) -> (IO (Result (List u24) u24))) (IO/FS/read_to_end.read_chunks fd chunks) = with IO { ask res_chunk = (IO/FS/read fd 1048576); match res_chunk = res_chunk { Result/Ok: let chunk = res_chunk.val; match chunk = chunk { List/Nil: (wrap (Result/Ok (List/flatten chunks))); List/Cons: (IO/FS/read_to_end.read_chunks fd (List/Cons chunk chunks)); }; Result/Err: (wrap (Result/Err res_chunk.val)); } }

IO/FS/read_line: (u24 -> (IO (Result (List u24) u24))) (IO/FS/read_line fd) = (IO/FS/read_line.read_chunks fd [])

IO/FS/read_line.read_chunks: (u24 -> (List (List u24)) -> (IO (Result (List u24) u24))) (IO/FS/read_line.read_chunks fd chunks) = with IO { ask res_chunk = (IO/FS/read fd 1024); match res_chunk = res_chunk { Result/Ok: let chunk = res_chunk.val; match res = (List/split_once chunk λx (== x 10)) { Result/Ok: let (line, rest) = res.val; let (length, ) = (List/length rest); ask res_seek = (IO/FS/seek fd ( (u24/to_i24 length) -1) IO/FS/SEEK_CUR); match res_seek = res_seek { Result/Ok: let chunks = (List/Cons line chunks); let bytes = (List/flatten chunks); (wrap (Result/Ok bytes)); Result/Err: (wrap (Result/Err res_seek.val)); }; Result/Err: let line = res.val; let (length, line) = (List/length line); switch %pred = (== length 0) { 0: let chunks = (List/Cons line chunks); (IO/FS/read_line.read_chunks fd chunks); _ %pred-1: let bytes = (List/flatten chunks); (wrap (Result/Ok bytes)); }; }; Result/Err: (wrap (Result/Err res_chunk.val)); } }

IO/FS/write_file: (String -> (List u24) -> (IO (Result None u24))) (IO/FS/write_file path bytes) = with IO { ask res_f = (IO/FS/open path "w"); match res_f = res_f { Result/Ok: let f = res_f.val; ask res1 = (IO/FS/write f bytes); ask res2 = (IO/FS/close f); (wrap (Result/and res2 res1)); Result/Err: (wrap (Result/Err res_f.val)); } }

IO/print: (String -> (IO None)) (IO/print text) = with IO { ask res = (IO/FS/write IO/FS/STDOUT (String/encode_utf8 text)); (wrap (Result/unwrap res)) }

IO/input: (IO (Result String u24)) (IO/input) = (IO/input.go DiffList/new)

IO/input.go: (((List u24) -> (List u24)) -> (IO (Result String u24))) (IO/input.go acc) = with IO { ask res_byte = (IO/FS/read IO/FS/STDIN 1); match res_byte = res_byte { Result/Ok: let byte = res_byte.val; match byte = byte { List/Nil: (IO/input.go acc); List/Cons: switch %pred = (== byte.head 10) { 0: let acc = (DiffList/append acc byte.head); (IO/input.go acc); _ %pred-1: let bytes = (DiffList/to_list acc); let text = (String/decode_utf8 bytes); (wrap (Result/Ok text)); }; }; Result/Err: (wrap (Result/Err res_byte.val)); } }

IO/DyLib/open: (String -> u24 -> (IO (Result u24 String))) (IO/DyLib/open path lazy) = (IO/unwrap_inner (IO/call "DL_OPEN" (path, lazy)))

IO/DyLib/call: (u24 -> String -> Any -> (IO (Result Any String))) (IO/DyLib/call dl fn args) = (IO/unwrap_inner (IO/call "DL_CALL" (dl, (fn, args))))

IO/DyLib/close: (u24 -> (IO (Result None String))) (IO/DyLib/close dl) = (IO/unwrap_inner (IO/call "DL_CLOSE" dl))

defer: (T -> (T -> T) -> T) (defer val) = λx (x val)

defer_arg: (((Id -> Id) -> A -> B) -> A -> (Id -> Id) -> B) (defer_arg defered arg) = λx (defered x arg)

undefer: (((Id -> Id) -> T) -> T) (undefer defered) = (defered λx x)

unreachable: Any (unreachable) = *

u24/to_string: (u24 -> String) (u24/to_string n) = def (go n) = let r = (% n 10); let d = (/ n 10); let c = (+ 48 r); switch %pred = (== d 0) { 0: λt (go d (String/Cons c t)); _ %pred-1: λt (String/Cons c t); }(go n String/Nil)

Math/PI: f24 (Math/PI) = 3.142

Math/E: f24 (Math/E) = 2.718

Math/ceil: (f24 -> f24) (Math/ceil n) = let i_n = (i24/to_f24 (f24/to_i24 n)); switch %pred = (<= n i_n) { 0: (+ i_n 1.000); _ %pred-1: i_n; }

Math/floor: (f24 -> f24) (Math/floor n) = let i_n = (i24/to_f24 (f24/to_i24 n)); switch %pred = (< n i_n) { 0: i_n; _ %pred-1: (- i_n 1.000); }

Math/round: (f24 -> f24) (Math/round n) = let i_n = (i24/to_f24 (f24/to_i24 n)); switch %pred = (< (- n i_n) 0.500) { 0: (Math/ceil n); _ %pred-1: (Math/floor n); }

unchecked main: Any (main) = (+ 1 1)hvm f24/to_u24: ($([u24] ret) ret)

hvm i24/to_u24: ($([u24] ret) ret)

hvm u24/to_i24: ($([i24] ret) ret)

hvm f24/to_i24: ($([i24] ret) ret)

hvm u24/to_f24: ($([f24] ret) ret)

hvm i24/to_f24: ($([f24] ret) ret)

hvm Math/log: (x ($([|] $(x ret)) ret))

hvm Math/atan2: ($([&] $(y ret)) (y ret))

hvm Math/sin: ($([<<0x0000000] a) a)

hvm Math/cos: (a b) & @Math/PI ~ $([:/0x0400000] $([-] $(a $([<<0x0000000] b))))

hvm Math/tan: ($([>>0x0000000] a) a)

wirkelzirkel avatar Jul 19 '25 16:07 wirkelzirkel