├── public ├── js │ ├── janet.wasm │ ├── playground.js │ ├── fmt.janet │ └── janet.js ├── index.html ├── play.html ├── cookbook.html ├── style.css └── ace │ └── mode-janet.js ├── janet ├── noderepl.js ├── play.c └── janet.h ├── project.janet ├── .gitignore ├── LICENSE ├── playground ├── README.md └── playground.janet /public/js/janet.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MikeBeller/janet-playground/HEAD/public/js/janet.wasm -------------------------------------------------------------------------------- /janet/noderepl.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | // emcc -s MODULARIZE=1 -o janet.js janet.c play.c -s "EXPORTED_FUNCTIONS=['_run_janet']" -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap']" 4 | // node noderepl.js 5 | // 6 | 7 | var factory = require('./janet.js'); 8 | 9 | factory().then(mod => 10 | { 11 | var run_janet = mod.cwrap("run_janet", 'number', ['string']); 12 | run_janet('(print "hello")'); 13 | //mod.asm.run_janet('3'); 14 | } 15 | ); 16 | 17 | -------------------------------------------------------------------------------- /project.janet: -------------------------------------------------------------------------------- 1 | (declare-project 2 | :name "janet-playground" 3 | :author "Mike Beller" 4 | :license "MIT" 5 | :version "0.0.1" 6 | :url "https://github.com/mikebeller/janet-playground" 7 | :repo "git+https://github.com/mikebeller/janet-playground.git" 8 | :dependencies [ 9 | "https://github.com/swlkr/osprey" 10 | "https://github.com/andrewchambers/janet-sh" 11 | "https://github.com/janet-lang/spork"]) 12 | 13 | (declare-binscript 14 | :main "playground" 15 | :hardcode-syspath true) 16 | 17 | (declare-source 18 | :source ["playground.janet"]) 19 | 20 | -------------------------------------------------------------------------------- /janet/play.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "janet.h" 3 | 4 | EMSCRIPTEN_KEEPALIVE 5 | int run_janet(char *source) { 6 | // Initialize the virtual machine. 7 | janet_init(); 8 | 9 | // Get the core janet environment. 10 | JanetTable *env = janet_core_env(NULL); 11 | 12 | // Run the code in the source argument, and pretty-print the result 13 | Janet result; 14 | int ret = janet_dostring(env, source, "playground", &result); 15 | janet_printf("RESULT> %q\n", result); 16 | 17 | // Free all resources associated with Janet 18 | janet_deinit(); 19 | 20 | return ret; 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Vim savefiles 2 | .*.swp 3 | 4 | # Build directory 5 | build/* 6 | jpm_tree/ 7 | 8 | # Prerequisites 9 | *.d 10 | 11 | # Object files 12 | *.o 13 | *.ko 14 | *.obj 15 | *.elf 16 | 17 | # Linker output 18 | *.ilk 19 | *.map 20 | *.exp 21 | 22 | # Precompiled Headers 23 | *.gch 24 | *.pch 25 | 26 | # Libraries 27 | *.lib 28 | *.a 29 | *.la 30 | *.lo 31 | 32 | # Shared objects (inc. Windows DLLs) 33 | *.dll 34 | *.so 35 | *.so.* 36 | *.dylib 37 | 38 | # Executables 39 | *.exe 40 | *.out 41 | *.app 42 | *.i*86 43 | *.x86_64 44 | *.hex 45 | 46 | # Debug files 47 | *.dSYM/ 48 | *.su 49 | *.idb 50 | *.pdb 51 | 52 | # Kernel Module Compile Results 53 | *.mod* 54 | *.cmd 55 | .tmp_versions/ 56 | modules.order 57 | Module.symvers 58 | Mkfile.old 59 | dkms.conf 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 MikeBeller 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /playground: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env janet 2 | 3 | (import "./playground" :as play) 4 | 5 | (def args (dyn :args)) 6 | 7 | (def usage 8 | "Script usage." 9 | ``` [action] 10 | 11 | Actions: 12 | help - Print this usage information 13 | update-janet - Downloads janet.c/janet.h for version to janet/ subdirectory 14 | build - Build the janet and playground wasm and js artifacts (using local emcc) 15 | build-docker - Build the janet and playground wasm and js artifacts (using docker emcc) 16 | install - Move the janet and playground wasm and js artifacts to the public directory 17 | clean - Delete the generated wasm and js artifacts 18 | serve []- Serves current site on (default localhost:8000) 19 | version - Print the playground version 20 | ```) 21 | 22 | (when (< (length args) 2) 23 | (eprint "missing command") 24 | (eprint usage) 25 | (os/exit -1)) 26 | 27 | (def action (in args 1)) 28 | 29 | # Do actions 30 | (case action 31 | "help" (print (args 0) usage) 32 | "version" (print play/version) 33 | "clean" (play/clean) 34 | "serve" (play/serve (get args 2)) 35 | "update-janet" (play/update-janet (get args 2)) 36 | "install" (play/install) 37 | "build" (play/build false) 38 | "build-docker" (play/build true) 39 | (do 40 | (eprint "Invalid command") 41 | (eprint usage) 42 | (os/exit 1))) 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # janet-playground 2 | 3 | A WebAssembly based playground for Janet (https://janet-lang.org) 4 | like that of https://play.golang.org 5 | 6 | Intended to enable sharing of "runnable" example code in the Janet community. 7 | 8 | Currently the janet.wasm artifact produced here is used by the "playground" 9 | functionality in [JanetDocs](https://janetdocs.com/playground) 10 | 11 | ## Installation 12 | 13 | ### Prerequisites 14 | 15 | You must have janet and JPM installed. 16 | 17 | You can build the WASM artifact using a locally installed emcc or 18 | using emcc via docker. 19 | 20 | To use local emcc, you must first install emscripten (emsdk) > 2.0 21 | and ensure that it is in your path and executable. (Generally you have 22 | to do something like source ./emsdk_env.sh in the emsdk install directory.) 23 | 24 | To use docker, make sure docker is running and that you have docker 25 | privileges. 26 | 27 | # Clone janet-playground 28 | 29 | ```sh 30 | git clone https://github.com/MikeBeller/janet-playground.git 31 | ``` 32 | 33 | # Create the WASM binary 34 | 35 | Note -- we do not actually install the playground.janet module. 36 | We use the one in the current directory. (So no `jpm install` ) 37 | 38 | ``` 39 | cd janet-playground 40 | jpm --local deps 41 | jpm --local janet playground update-janet latest # or 'v1.40.1' for that specific version 42 | jpm --local janet playground build # or build-docker 43 | ``` 44 | 45 | # Run it on port 8000 46 | 47 | ``` 48 | jpm --local janet playground install 49 | jpm --local janet playground serve 50 | ``` 51 | 52 | Then point your browser to http://localhost:8000/ to try it out. 53 | 54 | ## To Update Janet Version In JanetDocs 55 | 56 | After building as per above copy janet.wasm and janet.js from the 57 | `public/js` directory of this repository to the `public/playground` 58 | directory of the janetdocs repository. 59 | 60 | ## FAQ 61 | 62 | **Q: How does this relate to the web repl on https://janet-lang.org?** 63 | 64 | A: The web repl on janet-lang.org, as currently constituted, can only be 65 | used for use case "A" above. And even there, because it doesn't allow 66 | multi-line editing, it's difficult to use for any larger examples. That 67 | said, the janet-lang.org web repl *does* permit sequential execution of 68 | Janet forms, with subsequent forms operating on the same running fiber 69 | as the previous forms. By contrast, janet-playground creates 70 | an interpreter, runs the example, and then de-inits janet. 71 | 72 | ## Note of thanks to Go Playground 73 | 74 | The playground UI is styled based on the go playground, and uses it's style 75 | sheet static/style.css . As such, portions of this code may be 76 | Copyright (C) 2014 The Go Authors. See: https://github.com/golang/playground 77 | 78 | -------------------------------------------------------------------------------- /public/js/playground.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | function htmlEscape(text) { 3 | //text = ansi_up.ansi_to_html(text); 4 | return text 5 | .replace(/&/g, "&") 6 | .replace(//g, ">") 8 | .replace(/"/g, """) 9 | .replace(/'/g, "'") 10 | .replace(/ /g, " ") 11 | .replace('\n', '
', 'g'); 12 | } 13 | 14 | function cleanContentEditableInput(text) { 15 | text = text.replace(/\u00A0/g, " "); 16 | return text; 17 | } 18 | 19 | function print(text, isErr=false) { 20 | //if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' '); 21 | var element = window.Module.outputElement; 22 | if (typeof(element) == "string") { 23 | window.Module.outputElement += text; 24 | } else if (!element) { 25 | console.log("No output element. Tried to print: " + text); 26 | } else { 27 | if (isErr) { 28 | element.innerHTML += '' + htmlEscape(text + '\n') + ''; 29 | } else { 30 | element.innerHTML += htmlEscape(text); 31 | } 32 | element.scrollTop = element.scrollHeight; // focus on bottom 33 | } 34 | } 35 | 36 | function run_janet_for_output(code) { 37 | window.Module.outputElement = ""; 38 | let cleanCode = cleanContentEditableInput(code); 39 | let result = window.run_janet(cleanCode); 40 | if (result != 0) { 41 | return "ERROR: " + result + "\n" + window.Module.outputElement; 42 | } else { 43 | return window.Module.outputElement; 44 | } 45 | } 46 | 47 | function run_janet_code(code, outputElement) { 48 | outputElement.innerHTML = ""; 49 | window.Module.outputElement = outputElement; 50 | let cleanCode = cleanContentEditableInput(code); 51 | let result = window.run_janet(cleanCode); 52 | if (result != 0) 53 | window.Module.printErr("ERROREXIT: " + result + "\n"); 54 | } 55 | 56 | var Module = { 57 | outputElement: null, 58 | preRun: [], 59 | print: function(x) { 60 | print(x + '\n', isErr=false); 61 | }, 62 | printErr: function(text) { 63 | if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' '); 64 | print(text + "\n", isErr=true); 65 | }, 66 | postRun: [function() { 67 | window.run_janet_code = run_janet_code; 68 | window.run_janet_for_output = run_janet_for_output; 69 | window.run_janet = Module.cwrap("run_janet", 'number', ['string']); 70 | }], 71 | }; 72 | 73 | window.Module = Module; 74 | })(); 75 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The Janet Playground 5 | 6 | 7 |

The Janet Playground

8 | This page has a few examples of the potential use of the "janet-playground" 9 | -- https://github.com/mikebeller/janet-playground. 10 | 11 |

Use Case A -- online Janet execution with no install

12 |

Intent is to allow for people to try Janet with no install. Different 13 | from the online REPL on janet-lang.org because the multiline code window 14 | and "run" button (also ctrl-enter) allows for a more comfortable 15 | environment for trying out longer code examples.

16 | 17 | Try out use case A here 18 | 19 |

This use case requires no back end code and so it can sit on a static server.

20 | 21 |

Use Case B -- live tutorial docs

22 |

In this use case, we integrate a "run" button into examples of code 23 | in a web page. For example, below is a page of the "janet-cookbook" 24 | modified to have runnable sample code.

25 | 26 | Try out use case B here 27 | 28 |

This use case requires no back end code and so it can sit on a static server.

29 | 30 |

Use Case C -- sharing live code snippets

31 |

In this use case, we integrate a "save" button into the playground, 32 | which saves the code in the window and returns a unique URL which can 33 | be used to send to someone else so they can bring up and run that playground 34 | with that specific code example. This is available in play.golang.org and is 35 | a huge boon to their community. The downside is this requires a back end service 36 | to save the example. The community has some active webservers (e.g. 37 | janet-lang.org and janetdocs.com). Maybe this could be integrated with them?

38 | 39 |

This is a work in progress so nothing to try out yet. I am debating possible 40 | approaches to saving the data and interested in input. Possible approaches: 41 | 42 |

    43 |
  • Save code examples in a local database. (e.g. sqlite would be sufficient). 44 | The downside is that someone needs to maintain the database. If we were 45 | to lose it then live examples posted in various forums would become 404s. 46 | This is the approach used by play.golang.org
  • 47 |
  • Save the code examples to a gist. This would require some github API 48 | integration. The RUST playground autogenerates gists on their own 49 | account when people press "save as gist" on that playground. I wonder 50 | why they don't get in trouble with github for creating so many gists? 51 | Anyway this is certainly an alternative.
  • 52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /public/play.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The Janet Playground 5 | 6 | 7 | 8 | 9 | 45 | 46 | 47 | 54 |
55 |
56 | (defn sumsq [n] 57 | (sum 58 | (seq [x :range [1 n]] 59 | (* x x)))) 60 | 61 | (print "Hello, World!") 62 | (sumsq 99) 63 |
64 |
65 |
66 | 67 | 68 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /public/cookbook.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Janet Live Cookbook 5 | 6 | 7 | 8 | 23 | 24 | 25 |

Janet Live Cookbook

26 |

A simple proof-of-concept demonstration of a "live cookbook" for Janet. 27 | Examples can be run right in the page. Obviously the style needs lots 28 | of work. Wish I knew CSS better. :-)

29 |

Note that you can even edit the code examples right on the page!

30 |

Working with Arrays And Tuples

31 |

Janet's indexed combinators (e.g. map, filter, reduce) return new 32 | arrays, regardless of whether the collection argument passed to them was 33 | a tuple or an array.

34 | 35 | 38 |
39 |

If you need the result in a tuple you can force it with tuple 40 | or tuple/slice as follows:

41 | 42 | 46 |
47 | 48 |

Increment a value in an array

49 |

The augmented arithmetic assignment operators, ++,--,+=, = (where X is +,-,*,/,%) 50 | are actually macros so you can use them on an indexed data structure like an array.

51 | 52 | 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | /* Portions of this file may be Copyright (c) 2014 The Go Authors. All rights reserved. */ 2 | html { 3 | height: 100%; 4 | } 5 | body { 6 | color: black; 7 | padding: 0; 8 | margin: 0; 9 | width: 100%; 10 | height: 100%; 11 | } 12 | a { 13 | color: #009; 14 | } 15 | #wrap, 16 | #about { 17 | padding: 5px; 18 | margin: 0; 19 | 20 | position: absolute; 21 | top: 50px; 22 | bottom: 25%; 23 | left: 0; 24 | right: 0; 25 | 26 | background: #FFD; 27 | } 28 | #about { 29 | display: none; 30 | z-index: 1; 31 | padding: 10px 40px; 32 | font-size: 16px; 33 | font-family: sans-serif; 34 | overflow: auto; 35 | } 36 | #about p { 37 | max-width: 520px; 38 | } 39 | #about ul { 40 | max-width: 480px; 41 | } 42 | #about li { 43 | margin-bottom: 1em; 44 | } 45 | #code, #output, pre, .lines { 46 | /* The default monospace font on OS X is ugly, so specify Menlo 47 | * instead. On other systems the default monospace font will be used. */ 48 | font-family: Menlo, monospace; 49 | font-size: 11pt; 50 | } 51 | 52 | #code { 53 | color: black; 54 | background: inherit; 55 | 56 | width: 100%; 57 | height: 100%; 58 | padding: 0; margin: 0; 59 | border: none; 60 | outline: none; 61 | resize: none; 62 | wrap: off; 63 | float: right; 64 | } 65 | #output { 66 | position: absolute; 67 | top: 75%; 68 | bottom: 0; 69 | left: 0; 70 | right: 0; 71 | padding: 8px; 72 | } 73 | #output .system, #output .loading { 74 | color: #999; 75 | } 76 | #output .stderr, #output .error { 77 | color: #900; 78 | } 79 | #output pre { 80 | margin: 0; 81 | } 82 | #banner { 83 | display: flex; 84 | flex-wrap: wrap; 85 | align-items: center; 86 | position: absolute; 87 | left: 0; 88 | right: 0; 89 | top: 0; 90 | height: 50px; 91 | background-color: #E0EBF5; 92 | } 93 | #banner > * { 94 | margin-top: 10px; 95 | margin-bottom: 10px; 96 | margin-right: 5px; 97 | border-radius: 5px; 98 | box-sizing: border-box; 99 | height: 30px; 100 | } 101 | #head { 102 | padding-left: 10px; 103 | padding-right: 20px; 104 | padding-top: 5px; 105 | font-size: 20px; 106 | font-family: sans-serif; 107 | } 108 | #aboutButton { 109 | margin-left: auto; 110 | margin-right: 15px; 111 | } 112 | input[type=button], 113 | #importsBox { 114 | height: 30px; 115 | border: 1px solid #375EAB; 116 | font-size: 16px; 117 | font-family: sans-serif; 118 | background: #375EAB; 119 | color: white; 120 | position: static; 121 | top: 1px; 122 | border-radius: 5px; 123 | -webkit-appearance: none; 124 | } 125 | #importsBox { 126 | padding: 0.25em 7px; 127 | } 128 | #importsBox input { 129 | position: relative; 130 | top: -2px; 131 | left: 1px; 132 | height: 10px; 133 | width: 10px; 134 | margin-left: 0; 135 | } 136 | #shareURL { 137 | width: 280px; 138 | font-size: 16px; 139 | border: 1px solid #ccc; 140 | background: #eee; 141 | color: black; 142 | } 143 | #embedLabel { 144 | font-family: sans-serif; 145 | padding-top: 5px; 146 | } 147 | #banner > select { 148 | font-size: 0.875rem; 149 | border: 0.0625rem solid #375EAB; 150 | } 151 | .lines { 152 | float: left; 153 | overflow: hidden; 154 | text-align: right; 155 | } 156 | .lines div { 157 | padding-right: 5px; 158 | color: lightgray; 159 | } 160 | .lineerror { 161 | color: red; 162 | background: #FDD; 163 | } 164 | .exit { 165 | color: lightgray; 166 | } 167 | 168 | .embedded #banner { 169 | display: none; 170 | } 171 | .embedded #wrap { 172 | top: 0; 173 | } 174 | #embedRun { 175 | display: none; 176 | } 177 | .embedded #embedRun { 178 | display: block; 179 | position: absolute; 180 | z-index: 1; 181 | top: 10px; 182 | right: 10px; 183 | } 184 | -------------------------------------------------------------------------------- /playground.janet: -------------------------------------------------------------------------------- 1 | (import spork/path) 2 | (import sh) 3 | (use osprey) 4 | 5 | (def version "0.0.3") 6 | 7 | (defn clean 8 | ```Clean up build artifacts``` 9 | [] 10 | (try 11 | (do 12 | (each pth ["fmt.jimage" "janet.js" "janet.wasm"] 13 | (def fuller-path (path/join "build" pth)) 14 | (when (os/stat fuller-path) 15 | (os/rm fuller-path))) 16 | (os/rmdir "build")) 17 | ([err] 18 | (eprintf "%s" err)))) 19 | 20 | (defn build-fmt-image [] 21 | (def env (require "spork/fmt")) 22 | (spit "fmt.jimage" (make-image env))) 23 | 24 | (defn build 25 | ```Build wasm module. Emsdk must be installed and runnable in the current 26 | shell (on linux, for example, `source emsdk_env.sh` in the emsdk directory,) 27 | else docker must be installed and running, and the user must have docker privileges.``` 28 | [use-docker] 29 | (def stat (os/stat "build")) 30 | (when (nil? stat) 31 | (os/mkdir "build")) 32 | (def emcc 33 | (if use-docker 34 | @["docker" "run" "--rm" 35 | "-v" (string/join @[(os/cwd) ":/src"]) 36 | "-u" (string/trimr (sh/$< "sh" "-c" "echo $(id -u):$(id -g)")) 37 | "emscripten/emsdk" "emcc"] 38 | @["emcc"] 39 | )) 40 | (os/cd "build") 41 | (build-fmt-image) 42 | (os/cd "..") 43 | (def result 44 | (try 45 | (do 46 | (os/execute 47 | (array/join emcc @["-O2" "-o" (path/join "build" "janet.js") 48 | (path/join "janet" "janet.c") 49 | (path/join "janet" "play.c") 50 | (string "-I" "janet") 51 | "--embed-file" (path/join "build" "fmt.jimage") 52 | "-s" "EXPORTED_FUNCTIONS=['_run_janet']" 53 | "-s" "ALLOW_MEMORY_GROWTH=1" 54 | "-s" "AGGRESSIVE_VARIABLE_ELIMINATION=1" 55 | "-s" "EXPORTED_RUNTIME_METHODS=['ccall','cwrap']" 56 | ] 57 | ) 58 | :p)) 59 | ([err] (eprint "Can't run emcc. Ensure emcc is installed and in your path, and emsdk_env.sh has been sourced into your current environment")))) 60 | (when (not= result 0) 61 | (eprint "Error running emcc. Build failed."))) 62 | 63 | (defn install 64 | ```Move build artifacts into site tree``` 65 | [] 66 | (try 67 | (do 68 | (os/rm (path/join "public" "js" "janet.js")) 69 | (os/rm (path/join "public" "js" "janet.wasm"))) 70 | ([err])) 71 | (os/rename (path/join "build" "janet.js") (path/join "public" "js" "janet.js")) 72 | (os/rename (path/join "build" "janet.wasm") (path/join "public" "js" "janet.wasm"))) 73 | 74 | (defn get-release-file [ver name] 75 | (def url 76 | (if (= ver "latest") 77 | (path/join "https://github.com/janet-lang/janet/releases/latest/download" name) 78 | (path/join "https://github.com/janet-lang/janet/releases/download" ver name) 79 | )) 80 | (print "GETTING: " url) 81 | (os/execute ["curl" "-sfL" "-o" (path/join "janet" name) url] :xp)) 82 | 83 | (defn update-janet 84 | ```Download janet.j/janet.h for the requested version``` 85 | [ver] 86 | (def result 87 | (try 88 | (do 89 | (get-release-file ver "janet.c") 90 | (get-release-file ver "janet.h")) 91 | ([err] (eprint err)))) 92 | (when (not= result 0) 93 | (eprint "Error downloading requested Janet version"))) 94 | 95 | #(GET "/" (redirect "play.html")) 96 | 97 | (defn serve 98 | ```Serve playground. Optional host:port.``` 99 | [&opt host] 100 | (default host "localhost:8000") 101 | (def [addr port] (string/split ":" host)) 102 | (when (or (nil? addr) (nil? port) (nil? (scan-number port))) 103 | (eprint "Invalid host:port string") 104 | (os/exit 1)) 105 | (enable :static-files) 106 | (prin "Starting server at ") 107 | (print host) 108 | (server (scan-number port) addr)) 109 | 110 | -------------------------------------------------------------------------------- /public/js/fmt.janet: -------------------------------------------------------------------------------- 1 | ### 2 | ### fmt.janet 3 | ### 4 | ### Janet code formatter. 5 | ### 6 | 7 | (defn- pnode 8 | "Make a capture function for a node." 9 | [tag] 10 | (fn [x] [tag x])) 11 | 12 | (def- parse-peg 13 | "Peg to parse Janet with extra information, namely comments." 14 | (peg/compile 15 | ~{:ws (+ (set " \t\r\f\0\v") '"\n") 16 | :readermac (/ '(set "';~,|") ,(pnode :readermac)) 17 | :symchars (+ (range "09" "AZ" "az" "\x80\xFF") (set "!$%&*+-./:@^_")) 18 | :token (some :symchars) 19 | :hex (range "09" "af" "AF") 20 | :escape (* "\\" (+ (set "ntrzfev0\"\\") 21 | (* "x" :hex :hex) 22 | (* "u" :hex :hex :hex :hex) 23 | (* "U" :hex :hex :hex :hex :hex :hex) 24 | (error (constant "bad hex escape")))) 25 | :comment (/ (* "#" '(any (if-not (+ "\n" -1) 1)) (+ "\n" -1)) ,(pnode :comment)) 26 | :spacing (any (* (any :ws) (? :comment))) 27 | :span (/ ':token ,(pnode :span)) 28 | :bytes '(* "\"" (any (+ :escape (if-not "\"" 1))) "\"") 29 | :string (/ :bytes ,(pnode :string)) 30 | :buffer (/ (* "@" :bytes) ,(pnode :buffer)) 31 | :long-bytes '{:delim (some "`") 32 | :open (capture :delim :n) 33 | :close (cmt (* (not (> -1 "`")) (-> :n) ':delim) ,=) 34 | :main (drop (* :open (any (if-not :close 1)) :close))} 35 | :long-string (/ :long-bytes ,(pnode :string)) 36 | :long-buffer (/ (* "@" :long-bytes) ,(pnode :buffer)) 37 | :raw-value (+ :string :buffer :long-string :long-buffer 38 | :parray :barray :ptuple :btuple :struct :dict :span) 39 | :value (* :spacing (any (+ :ws :readermac)) :raw-value :spacing) 40 | :root (any :value) 41 | :root2 (any (* :value :value)) 42 | :ptuple (/ (group (* "(" :root (+ ")" (error)))) ,(pnode :ptuple)) 43 | :btuple (/ (group (* "[" :root (+ "]" (error)))) ,(pnode :btuple)) 44 | :struct (/ (group (* "{" :root2 (+ "}" (error)))) ,(pnode :struct)) 45 | :parray (/ (group (* "@(" :root (+ ")" (error)))) ,(pnode :array)) 46 | :barray (/ (group (* "@[" :root (+ "]" (error)))) ,(pnode :array)) 47 | :dict (/ (group (* "@{" :root2 (+ "}" (error)))) ,(pnode :table)) 48 | :main (* :root (+ -1 (error)))})) 49 | 50 | (defn- make-tree 51 | "Turn a string of source code into a tree that will be printed" 52 | [source] 53 | [:top (peg/match parse-peg source)]) 54 | 55 | (defn- remove-extra-newlines 56 | "Remove leading and trailing newlines. Also remove 57 | some some extra consecutive newlines." 58 | [node] 59 | (match node 60 | [tag (xs (array? xs))] 61 | (do 62 | (while (= "\n" (array/peek xs)) (array/pop xs)) # remove trailing newlines 63 | (when-let [index (find-index |(not= "\n" $) xs)] 64 | (array/remove xs 0 index)) # remove leading newlines 65 | # remove too many consecutive newlines 66 | (def max-consec (if (= tag :top) 3 2)) 67 | (var i 0) 68 | (var consec-count 0) 69 | (while (< i (length xs)) 70 | (if (= (in xs i) "\n") 71 | (if (= consec-count max-consec) (array/remove xs i) (do (++ i) (++ consec-count))) 72 | (do (set consec-count 0) (++ i)))) 73 | node) 74 | node)) 75 | 76 | (def- indent-2-forms 77 | "A list of forms that are control forms and should be indented two spaces." 78 | (invert ["fn" "match" "with" "with-dyns" "def" "def-" "var" "var-" "defn" "defn-" 79 | "varfn" "defmacro" "defmacro-" "defer" "edefer" "loop" "seq" "generate" "coro" 80 | "for" "each" "eachp" "eachk" "case" "cond" "do" "defglobal" "varglobal" 81 | "if" "when" "when-let" "when-with" "while" "with-syms" "with-vars" 82 | "if-let" "if-not" "if-with" "let" "short-fn" "try" "unless" "default" "forever" 83 | "repeat" "eachy" "forv"])) 84 | 85 | (def- indent-2-peg 86 | "Peg to use to fuzzy match certain forms." 87 | (peg/compile ~(+ "with-" "def" "if-" "when-"))) 88 | 89 | (defn- check-indent-2 90 | "Check if a tuple needs a 2 space indent or not" 91 | [items] 92 | (if-let [[tag body] (get items 0)] 93 | (cond 94 | (= "\n" (get items 1)) true 95 | (not= tag :span) nil 96 | (in indent-2-forms body) true 97 | (peg/match indent-2-peg body) true))) 98 | 99 | (defn- fmt 100 | "Emit formatted." 101 | [tree] 102 | 103 | (var col 0) 104 | (def ident-stack @[]) 105 | (var ident "") 106 | (def white @"") 107 | 108 | (defn emit [& xs] (each x xs (+= col (length x)) (prin x))) 109 | (defn indent [&opt delta] 110 | (array/push ident-stack ident) 111 | (set ident (string/repeat " " (+ col (or delta 0))))) 112 | (defn dedent [] (set ident (array/pop ident-stack))) 113 | (defn flushwhite [] (emit white) (buffer/clear white)) 114 | (defn dropwhite [] (buffer/clear white)) 115 | (defn addwhite [] (buffer/push-string white " ")) 116 | (defn newline [] (dropwhite) (print) (buffer/push-string white ident) (set col 0)) 117 | 118 | # Mutual recursion 119 | (var fmt-1-recur nil) 120 | 121 | (defn emit-body 122 | [open xs close &opt delta] 123 | (emit open) 124 | (indent delta) 125 | (each x xs (fmt-1-recur x)) 126 | (dropwhite) 127 | (dedent) 128 | (emit close) 129 | (addwhite)) 130 | 131 | (defn emit-funcall 132 | [xs] 133 | (emit "(") 134 | (def len (length xs)) 135 | (when (pos? len) 136 | (fmt-1-recur (xs 0)) 137 | (indent 1) 138 | (for i 1 len (fmt-1-recur (xs i))) 139 | (dropwhite) 140 | (dedent)) 141 | (emit ")") 142 | (addwhite)) 143 | 144 | (defn emit-string 145 | [x] 146 | (def parts (interpose "\n" (string/split "\n" x))) 147 | (each p parts (if (= p "\n") (do (newline) (dropwhite)) (emit p)))) 148 | 149 | (defn fmt-1 150 | [node] 151 | (remove-extra-newlines node) 152 | (unless (= node "\n") (flushwhite)) 153 | (match node 154 | "\n" (newline) 155 | [:comment x] (do (emit "#" x) (newline)) 156 | [:readermac x] (emit x) 157 | [:span x] (do (emit x) (addwhite)) 158 | [:string x] (do (emit-string x) (addwhite)) 159 | [:buffer x] (do (emit "@") (emit-string x) (addwhite)) 160 | [:array xs] (emit-body "@[" xs "]") 161 | [:btuple xs] (emit-body "[" xs "]") 162 | [:ptuple xs] (if (check-indent-2 xs) 163 | (emit-body "(" xs ")" 1) 164 | (emit-funcall xs)) 165 | [:struct xs] (emit-body "{" xs "}") 166 | [:table xs] (emit-body "@{" xs "}") 167 | [:top xs] (emit-body "" xs ""))) 168 | 169 | (set fmt-1-recur fmt-1) 170 | (fmt-1 tree) 171 | (newline) 172 | (flush)) 173 | 174 | # 175 | # Public API 176 | # 177 | 178 | (defn format-print 179 | "Format a string of source code and print the result." 180 | [source] 181 | (-> source make-tree fmt)) 182 | 183 | (defn format 184 | "Format a string of source code to a buffer." 185 | [source] 186 | (def out @"") 187 | (with-dyns [:out out] 188 | (format-print source)) 189 | out) 190 | 191 | (defn format-file 192 | "Format a file" 193 | [file] 194 | (def source (slurp file)) 195 | (def out (format source)) 196 | (spit file out)) 197 | -------------------------------------------------------------------------------- /public/ace/mode-janet.js: -------------------------------------------------------------------------------- 1 | define("ace/mode/janet_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],(function(e,t,r){"use strict";var n=e("../lib/oop"),a=e("./text_highlight_rules").TextHighlightRules,i=function(){var e=this.createKeywordMapper({keyword:"try var def defn do fn if let loop quote set","constant.language":"true false nil","support.function":"% %= * *= *args* *current-file* *debug* *defdyn-prefix* *doc-color* *doc-width* *err* *err-color* *executable* *exit* *exit-value* *ffi-context* *lint-error* *lint-levels* *lint-warn* *macro-form* *macro-lints* *module-cache* *module-loaders* *module-loading* *module-make-env* *module-paths* *out* *peg-grammar* *pretty-format* *profilepath* *redef* *repl-prompt* *syspath* *task-id* + ++ += - -- -= -> ->> -?> -?>> / /= < <= = > >= abstract? accumulate accumulate2 all all-bindings all-dynamics and any? apply array array/clear array/concat array/ensure array/fill array/insert array/join array/new array/new-filled array/peek array/pop array/push array/remove array/slice array/trim array/weak array? as-> as-macro as?-> asm assert assertf bad-compile bad-parse band blshift bnot boolean? bor brshift brushift buffer buffer/bit buffer/bit-clear buffer/bit-set buffer/bit-toggle buffer/blit buffer/clear buffer/fill buffer/format buffer/format-at buffer/from-bytes buffer/new buffer/new-filled buffer/popn buffer/push buffer/push-at buffer/push-byte buffer/push-float32 buffer/push-float64 buffer/push-string buffer/push-uint16 buffer/push-uint32 buffer/push-uint64 buffer/push-word buffer/slice buffer/trim buffer? bundle/add bundle/add-bin bundle/add-directory bundle/add-file bundle/install bundle/installed? bundle/list bundle/manifest bundle/prune bundle/reinstall bundle/replace bundle/topolist bundle/uninstall bundle/update-all bundle/whois bxor bytes? cancel case catseq cfunction? chr cli-main cmp comment comp compare compare< compare<= compare= compare> compare>= compif compile complement comptime compwhen cond coro count curenv debug debug/arg-stack debug/break debug/fbreak debug/lineage debug/stack debug/stacktrace debug/step debug/unbreak debug/unfbreak debugger debugger-env debugger-on-status dec deep-not= deep= def- default default-peg-grammar defdyn defer defglobal defmacro defmacro- defn- delay describe dictionary? disasm distinct div doc doc* doc-format doc-of dofile drop drop-until drop-while dyn each eachk eachp edefer eflush empty? env-lookup eprin eprinf eprint eprintf error errorf ev/acquire-lock ev/acquire-rlock ev/acquire-wlock ev/all-tasks ev/call ev/cancel ev/capacity ev/chan ev/chan-close ev/chunk ev/close ev/count ev/deadline ev/do-thread ev/full ev/gather ev/give ev/give-supervisor ev/go ev/lock ev/read ev/release-lock ev/release-rlock ev/release-wlock ev/rselect ev/rwlock ev/select ev/sleep ev/spawn ev/spawn-thread ev/take ev/thread ev/thread-chan ev/to-file ev/with-deadline ev/with-lock ev/with-rlock ev/with-wlock ev/write eval eval-string even? every? extreme false? ffi/align ffi/call ffi/calling-conventions ffi/close ffi/context ffi/defbind ffi/defbind-alias ffi/free ffi/jitfn ffi/lookup ffi/malloc ffi/native ffi/pointer-buffer ffi/pointer-cfunction ffi/read ffi/signature ffi/size ffi/struct ffi/trampoline ffi/write fiber-fn fiber/can-resume? fiber/current fiber/getenv fiber/last-value fiber/maxstack fiber/new fiber/root fiber/setenv fiber/setmaxstack fiber/status fiber? file/close file/flush file/lines file/open file/read file/seek file/tell file/temp file/write filewatch/add filewatch/listen filewatch/new filewatch/remove filewatch/unlisten filter find find-index first flatten flatten-into flush flycheck for forever forv freeze frequencies from-pairs function? gccollect gcinterval gcsetinterval generate gensym geomean get get-in getline getproto group-by has-key? has-value? hash idempotent? identity if-let if-not if-with import import* in inc index-of indexed? int/s64 int/to-bytes int/to-number int/u64 int? interleave interpose invert janet/build janet/config-bits janet/version juxt juxt* keep keep-syntax keep-syntax! keys keyword keyword/slice keyword? kvs label last length lengthable? let load-image load-image-dict loop macex macex1 maclintf make-env make-image make-image-dict map mapcat marshal match math/-inf math/abs math/acos math/acosh math/asin math/asinh math/atan math/atan2 math/atanh math/cbrt math/ceil math/cos math/cosh math/e math/erf math/erfc math/exp math/exp2 math/expm1 math/floor math/frexp math/gamma math/gcd math/hypot math/inf math/int-max math/int-min math/int32-max math/int32-min math/lcm math/ldexp math/log math/log-gamma math/log10 math/log1p math/log2 math/nan math/next math/pi math/pow math/random math/rng math/rng-buffer math/rng-int math/rng-uniform math/round math/seedrandom math/sin math/sinh math/sqrt math/tan math/tanh math/trunc max max-of mean memcmp merge merge-into merge-module min min-of mod module/add-paths module/cache module/expand-path module/find module/loaders module/loading module/paths module/value nan? nat? native neg? net/accept net/accept-loop net/address net/address-unpack net/chunk net/close net/connect net/flush net/listen net/localname net/peername net/read net/recv-from net/send-to net/server net/setsockopt net/shutdown net/write next nil? not not= number? odd? one? or os/arch os/cd os/chmod os/clock os/compiler os/cpu-count os/cryptorand os/cwd os/date os/dir os/environ os/execute os/exit os/getenv os/isatty os/link os/lstat os/mkdir os/mktime os/open os/perm-int os/perm-string os/pipe os/posix-exec os/posix-fork os/proc-close os/proc-kill os/proc-wait os/readlink os/realpath os/rename os/rm os/rmdir os/setenv os/setlocale os/shell os/sigaction os/sleep os/spawn os/stat os/strftime os/symlink os/time os/touch os/umask os/which pairs parse parse-all parser/byte parser/clone parser/consume parser/eof parser/error parser/flush parser/has-more parser/insert parser/new parser/produce parser/state parser/status parser/where partial partition partition-by peg/compile peg/find peg/find-all peg/match peg/replace peg/replace-all pos? postwalk pp prewalk prin prinf print printf product prompt propagate protect put put-in quit range reduce reduce2 repeat repl require resume return reverse reverse! root-env run-context sandbox scan-number seq setdyn short-fn signal slice slurp some sort sort-by sorted sorted-by spit stderr stdin stdout string string/ascii-lower string/ascii-upper string/bytes string/check-set string/find string/find-all string/format string/from-bytes string/has-prefix? string/has-suffix? string/join string/repeat string/replace string/replace-all string/reverse string/slice string/split string/trim string/triml string/trimr string? struct struct/getproto struct/proto-flatten struct/rawget struct/to-table struct/with-proto struct? sum symbol symbol/slice symbol? table table/clear table/clone table/getproto table/new table/proto-flatten table/rawget table/setproto table/to-struct table/weak table/weak-keys table/weak-values table? tabseq take take-until take-while thaw toggle trace tracev true? truthy? try tuple tuple/brackets tuple/join tuple/setmap tuple/slice tuple/sourcemap tuple/type tuple? type unless unmarshal untrace update update-in use values var- varfn varglobal walk warn-compile when when-let when-with with with-dyns with-env with-syms with-vars xprin xprinf xprint xprintf yield zero? zipcoll"},"identifier",!1," ");this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"keyword",regex:"[\\(|\\)]"},{token:"keyword",regex:"[\\'\\(]"},{token:"keyword",regex:"[\\[|\\]]"},{token:"keyword",regex:"[\\&]"},{token:"keyword",regex:"[\\#\\^\\{]"},{token:"keyword",regex:"[\\%]"},{token:"keyword",regex:"[@]"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language",regex:"[!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+||=|!=|<=|>=|<>|<|>|!|&&]"},{token:e,regex:"[a-zA-Z_$][a-zA-Z0-9_$\\-/]*\\b"},{token:"string",regex:'"',next:"string"},{token:"string.start",regex:/(`{1,})/,onMatch:function(e,t,r){const n=e.length;return r||(r=[]),r.unshift("bt-"+n),this.next="bt-"+n,this.token}},{token:"constant",regex:/:[^()\[\]{}'"\^%`,;\s]+/},{token:"string.regexp",regex:'/#"(?:\\.|(?:\\")|[^""\n])*"/g'}],string:[{token:"constant.language.escape",regex:"\\\\.|\\\\$"},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}]};for(let e=1;e<=10;e++){const t="bt-"+e;this.$rules[t]=[{token:"string.end",regex:"`".repeat(e),onMatch:function(e,t,r){return r.shift(),this.next="start","string.end"}},{token:"constant.language.escape",regex:/\\./},{token:"string",regex:"[^\\\\`]+"},{token:"string",regex:"[`]+"}]}};n.inherits(i,a),t.JanetHighlightRules=i})),define("ace/mode/matching_parens_outdent",["require","exports","module","ace/range"],(function(e,t,r){"use strict";var n=e("../range").Range,a=function(){};(function(){this.checkOutdent=function(e,t){return!!/^\s+$/.test(e)&&/^\s*\)/.test(t)},this.autoOutdent=function(e,t){var r=e.getLine(t).match(/^(\s*\))/);if(!r)return 0;var a=r[1].length,i=e.findMatchingBracket({row:t,column:a});if(!i||i.row==t)return 0;var o=this.$getIndent(e.getLine(i.row));e.replace(new n(t,0,t,a-1),o)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(a.prototype),t.MatchingParensOutdent=a})),define("ace/mode/janet",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/janet_highlight_rules","ace/mode/matching_parens_outdent"],(function(e,t,r){"use strict";var n=e("../lib/oop"),a=e("./text").Mode,i=e("./janet_highlight_rules").JanetHighlightRules,o=e("./matching_parens_outdent").MatchingParensOutdent,s=function(){this.HighlightRules=i,this.$outdent=new o,this.$behaviour=this.$defaultBehaviour};n.inherits(s,a),function(){this.lineCommentStart=";",this.minorIndentFunctions=["defn","defn-","defmacro","def","deftest","testing"],this.$toIndent=function(e){return e.split("").map((function(e){return/\s/.exec(e)?e:" "})).join("")},this.$calculateIndent=function(e,t){for(var r,n,a=this.$getIndent(e),i=0,o=e.length-1;o>=0&&("("===(n=e[o])?(i--,r=!0):"("===n||"["===n||"{"===n?(i--,r=!1):(")"===n||"]"===n||"}"===n)&&i++,!(i<0));o--);if(!(i<0&&r))return i<0&&!r?this.$toIndent(e.substring(0,o+1)):i>0?a=a.substring(0,a.length-t.length):a;for(var s=o+=1,l="";;){if(" "===(n=e[o])||"\t"===n)return-1!==this.minorIndentFunctions.indexOf(l)?this.$toIndent(e.substring(0,s-1)+t):this.$toIndent(e.substring(0,o+1));if(void 0===n)return this.$toIndent(e.substring(0,s-1)+t);l+=e[o],o++}},this.getNextLineIndent=function(e,t,r){return this.$calculateIndent(t,r)},this.checkOutdent=function(e,t,r){return this.$outdent.checkOutdent(t,r)},this.autoOutdent=function(e,t,r){this.$outdent.autoOutdent(t,r)},this.$id="ace/mode/janet",this.snippetFileId="ace/snippets/janet"}.call(s.prototype),t.Mode=s})),window.require(["ace/mode/janet"],(function(e){"object"==typeof module&&"object"==typeof exports&&module&&(module.exports=e)})); 2 | -------------------------------------------------------------------------------- /public/js/janet.js: -------------------------------------------------------------------------------- 1 | var Module=typeof Module!="undefined"?Module:{};var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var _scriptName=globalThis.document?.currentScript?.src;if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);HEAPU32=new Uint32Array(b);HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.initialized)FS.init();TTY.init();wasmExports["__wasm_call_ctors"]();FS.ignorePermissions=false}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("janet.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={env:wasmImports,wasi_snapshot_preview1:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var runDependencies=0;var dependenciesFulfilled=null;var removeRunDependency=id=>{runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}};var addRunDependency=id=>{runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)};var noExitRuntime=true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.slice(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.slice(0,-1)}return root+dir},basename:path=>path&&path.match(/([^\/]+|\/)\/*$/)[1],join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(ENVIRONMENT_IS_NODE){var nodeCrypto=require("crypto");return view=>nodeCrypto.randomFillSync(view)}return view=>crypto.getRandomValues(view)};var randomFill=view=>{(randomFill=initRandomFill())(view)};var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).slice(1);to=PATH_FS.resolve(to).slice(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var intArrayFromString=(stringy,dontAddNull,length)=>{var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array};var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(globalThis.window?.prompt){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output?.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var mmapAlloc=size=>{abort()};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16895,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.atime=node.mtime=node.ctime=Date.now();if(parent){parent.contents[name]=node;parent.atime=parent.mtime=parent.ctime=node.atime}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.atime);attr.mtime=new Date(node.mtime);attr.ctime=new Date(node.ctime);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){for(const key of["mode","atime","mtime","ctime"]){if(attr[key]!=null){node[key]=attr[key]}}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){if(!MEMFS.doesNotExistError){MEMFS.doesNotExistError=new FS.ErrnoError(44);MEMFS.doesNotExistError.stack=""}throw MEMFS.doesNotExistError},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){if(FS.isDir(old_node.mode)){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}FS.hashRemoveNode(new_node)}delete old_node.parent.contents[old_node.name];new_dir.contents[new_name]=old_node;old_node.name=new_name;new_dir.ctime=new_dir.mtime=old_node.parent.ctime=old_node.parent.mtime=Date.now()},unlink(parent,name){delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},readdir(node){return[".","..",...Object.keys(node.contents)]},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var asyncLoad=async url=>{var arrayBuffer=await readAsync(url);return new Uint8Array(arrayBuffer)};var FS_createDataFile=(...args)=>FS.createDataFile(...args);var getUniqueRunDependency=id=>id;var preloadPlugins=[];var FS_handledByPreloadPlugin=async(byteArray,fullname)=>{if(typeof Browser!="undefined")Browser.init();for(var plugin of preloadPlugins){if(plugin["canHandle"](fullname)){return plugin["handle"](byteArray,fullname)}}return byteArray};var FS_preloadFile=async(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);addRunDependency(dep);try{var byteArray=url;if(typeof url=="string"){byteArray=await asyncLoad(url)}byteArray=await FS_handledByPreloadPlugin(byteArray,fullname);preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}}finally{removeRunDependency(dep)}};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{FS_preloadFile(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish).then(onload).catch(onerror)};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,filesystems:null,syncFSRequests:0,readFiles:{},ErrnoError:class{name="ErrnoError";constructor(errno){this.errno=errno}},FSStream:class{shared={};get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{node_ops={};stream_ops={};readMode=292|73;writeMode=146;mounted=null;constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.rdev=rdev;this.atime=this.mtime=this.ctime=Date.now()}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){if(!path){throw new FS.ErrnoError(44)}opts.follow_mount??=true;if(!PATH.isAbs(path)){path=FS.cwd()+"/"+path}linkloop:for(var nlinks=0;nlinks<40;nlinks++){var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){if(!FS.isDir(dir.mode)){return 54}try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&(512|64)){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},checkOpExists(op,err){if(!op){throw new FS.ErrnoError(err)}return op},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},doSetAttr(stream,node,attr){var setattr=stream?.stream_ops.setattr;var arg=setattr?stream:node;setattr??=node.node_ops.setattr;FS.checkOpExists(setattr,63);setattr(arg,attr)},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}for(var mount of mounts){if(mount.type.syncfs){mount.type.syncfs(mount,populate,done)}else{done(null)}}},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);for(var[hash,current]of Object.entries(FS.nameTable)){while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}}node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name){throw new FS.ErrnoError(28)}if(name==="."||name===".."){throw new FS.ErrnoError(20)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},statfs(path){return FS.statfsNode(FS.lookupPath(path,{follow:true}).node)},statfsStream(stream){return FS.statfsNode(stream.node)},statfsNode(node){var rtn={bsize:4096,frsize:4096,blocks:1e6,bfree:5e5,bavail:5e5,files:FS.nextInode,ffree:FS.nextInode-1,fsid:42,flags:2,namelen:255};if(node.node_ops.statfs){Object.assign(rtn,node.node_ops.statfs(node.mount.opts.root))}return rtn},create(path,mode=438){mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode=511){mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var dir of dirs){if(!dir)continue;if(d||PATH.isAbs(path))d+="/";d+=dir;try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name);old_node.parent=new_dir}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var readdir=FS.checkOpExists(node.node_ops.readdir,54);return readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return link.node_ops.readlink(link)},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;var getattr=FS.checkOpExists(node.node_ops.getattr,63);return getattr(node)},fstat(fd){var stream=FS.getStreamChecked(fd);var node=stream.node;var getattr=stream.stream_ops.getattr;var arg=getattr?stream:node;getattr??=node.node_ops.getattr;FS.checkOpExists(getattr,63);return getattr(arg)},lstat(path){return FS.stat(path,true)},doChmod(stream,node,mode,dontFollow){FS.doSetAttr(stream,node,{mode:mode&4095|node.mode&~4095,ctime:Date.now(),dontFollow})},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChmod(null,node,mode,dontFollow)},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.doChmod(stream,stream.node,mode,false)},doChown(stream,node,dontFollow){FS.doSetAttr(stream,node,{timestamp:Date.now(),dontFollow})},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChown(null,node,dontFollow)},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.doChown(stream,stream.node,false)},doTruncate(stream,node,len){if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}FS.doSetAttr(stream,node,{size:len,timestamp:Date.now()})},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}FS.doTruncate(null,node,len)},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if(len<0||(stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.doTruncate(stream,stream.node,len)},utime(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var setattr=FS.checkOpExists(node.node_ops.setattr,63);setattr(node,{atime,mtime})},open(path,flags,mode=438){if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;var isDirPath;if(typeof path=="object"){node=path}else{isDirPath=path.endsWith("/");var lookup=FS.lookupPath(path,{follow:!(flags&131072),noent_okay:true});node=lookup.node;path=lookup.path}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else if(isDirPath){throw new FS.ErrnoError(31)}else{node=FS.mknod(path,mode|511,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node,path:FS.getPath(node),flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(created){FS.chmod(node,mode&511)}if(Module["logReadFiles"]&&!(flags&1)){if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){abort(`Invalid encoding type "${opts.encoding}"`)}var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){buf=UTF8ArrayToString(buf)}FS.close(stream);return buf},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){data=new Uint8Array(intArrayFromString(data,true))}if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{abort("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length,llseek:()=>0});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomFill(randomBuffer);randomLeft=randomBuffer.byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16895,73);node.stream_ops={llseek:MEMFS.stream_ops.llseek};node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path},id:fd+1};ret.parent=ret;return ret},readdir(){return Array.from(FS.streams.entries()).filter(([k,v])=>v).map(([k,v])=>k.toString())}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;for(var stream of FS.streams){if(stream){FS.close(stream)}}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){if(e.errno!=20)throw e}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)abort("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)abort("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")abort("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(globalThis.XMLHttpRequest){if(!ENVIRONMENT_IS_WORKER)abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};for(const[key,fn]of Object.entries(node.stream_ops)){stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}}function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return dir+"/"+path},writeStat(buf,stat){HEAPU32[buf>>2]=stat.dev;HEAPU32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAPU32[buf+12>>2]=stat.uid;HEAPU32[buf+16>>2]=stat.gid;HEAPU32[buf+20>>2]=stat.rdev;HEAP64[buf+24>>3]=BigInt(stat.size);HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();HEAP64[buf+40>>3]=BigInt(Math.floor(atime/1e3));HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;HEAP64[buf+56>>3]=BigInt(Math.floor(mtime/1e3));HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;HEAP64[buf+72>>3]=BigInt(Math.floor(ctime/1e3));HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;HEAP64[buf+88>>3]=BigInt(stat.ino);return 0},writeStatFs(buf,stats){HEAPU32[buf+4>>2]=stats.bsize;HEAPU32[buf+60>>2]=stats.bsize;HEAP64[buf+8>>3]=BigInt(stats.blocks);HEAP64[buf+16>>3]=BigInt(stats.bfree);HEAP64[buf+24>>3]=BigInt(stats.bavail);HEAP64[buf+32>>3]=BigInt(stats.files);HEAP64[buf+40>>3]=BigInt(stats.ffree);HEAPU32[buf+48>>2]=stats.fsid;HEAPU32[buf+64>>2]=stats.flags;HEAPU32[buf+56>>2]=stats.namelen},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_chdir(path){try{path=SYSCALLS.getStr(path);FS.chdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_chmod(path,mode){try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var syscallGetVarargI=()=>{var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret};var syscallGetVarargP=syscallGetVarargI;function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{return SYSCALLS.writeStat(buf,FS.fstat(fd))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>3]=BigInt(id);HEAP64[dirp+pos+8>>3]=BigInt((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21537:case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.lstat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.writeStat(buf,nofollow?FS.lstat(path):FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_renameat(olddirfd,oldpath,newdirfd,newpath){try{oldpath=SYSCALLS.getStr(oldpath);newpath=SYSCALLS.getStr(newpath);oldpath=SYSCALLS.calculateAt(olddirfd,oldpath);newpath=SYSCALLS.calculateAt(newdirfd,newpath);FS.rename(oldpath,newpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_symlinkat(target,dirfd,linkpath){try{target=SYSCALLS.getStr(target);linkpath=SYSCALLS.getStr(linkpath);linkpath=SYSCALLS.calculateAt(dirfd,linkpath);FS.symlink(target,linkpath);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(!flags){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{return-28}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var readI53FromI64=ptr=>HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296;function ___syscall_utimensat(dirfd,path,times,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path,true);var now=Date.now(),atime,mtime;if(!times){atime=now;mtime=now}else{var seconds=readI53FromI64(times);var nanoseconds=HEAP32[times+8>>2];if(nanoseconds==1073741823){atime=now}else if(nanoseconds==1073741822){atime=null}else{atime=seconds*1e3+nanoseconds/(1e3*1e3)}times+=16;seconds=readI53FromI64(times);nanoseconds=HEAP32[times+8>>2];if(nanoseconds==1073741823){mtime=now}else if(nanoseconds==1073741822){mtime=null}else{mtime=seconds*1e3+nanoseconds/(1e3*1e3)}}if((mtime??atime)!==null){FS.utime(path,atime,mtime)}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>abort("");var __emscripten_fs_load_embedded_files=ptr=>{do{var name_addr=HEAPU32[ptr>>2];ptr+=4;var len=HEAPU32[ptr>>2];ptr+=4;var content=HEAPU32[ptr>>2];ptr+=4;var name=UTF8ToString(name_addr);FS.createPath("/",PATH.dirname(name),true,true);FS.createDataFile(name,null,HEAP8.subarray(content,content+len),true,true,true)}while(HEAPU32[ptr>>2])};var __emscripten_throw_longjmp=()=>{throw Infinity};var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>numINT53_MAX?NaN:Number(num);function __gmtime_js(time,tmPtr){time=bigintToI53Checked(time);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};function __localtime_js(time,tmPtr){time=bigintToI53Checked(time);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}var __mktime_js=function(tmPtr){var ret=(()=>{var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();var timeMs=date.getTime();if(isNaN(timeMs)){return-1}return timeMs/1e3})();return BigInt(ret)};var __timegm_js=function(tmPtr){var ret=(()=>{var time=Date.UTC(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var date=new Date(time);HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;return date.getTime()/1e3})();return BigInt(ret)};var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);if(summerOffsetperformance.now();var _emscripten_date_now=()=>Date.now();var nowIsMonotonic=1;var checkWasiClock=clock_id=>clock_id>=0&&clock_id<=3;function _clock_time_get(clk_id,ignored_precision,ptime){ignored_precision=bigintToI53Checked(ignored_precision);if(!checkWasiClock(clk_id)){return 28}var now;if(clk_id===0){now=_emscripten_date_now()}else if(nowIsMonotonic){now=_emscripten_get_now()}else{return 52}var nsec=Math.round(now*1e3*1e3);HEAP64[ptime>>3]=BigInt(nsec);return 0}var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.language||"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;var envp=0;for(var string of getEnvStrings()){var ptr=environ_buf+bufSize;HEAPU32[__environ+envp>>2]=ptr;bufSize+=stringToUTF8(string,ptr,Infinity)+1;envp+=4}return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;for(var string of strings){bufSize+=lengthBytesUTF8(string)+1}HEAPU32[penviron_buf_size>>2]=bufSize;return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf]=type;HEAP16[pbuf+2>>1]=flags;HEAP64[pbuf+8>>3]=BigInt(rightsBase);HEAP64[pbuf+16>>3]=BigInt(rightsInheriting);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset,whence,newOffset){offset=bigintToI53Checked(offset);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);HEAP64[newOffset>>3]=BigInt(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};var FS_createPath=(...args)=>FS.createPath(...args);var FS_unlink=(...args)=>FS.unlink(...args);var FS_createLazyFile=(...args)=>FS.createLazyFile(...args);var FS_createDevice=(...args)=>FS.createDevice(...args);FS.createPreloadedFile=FS_createPreloadedFile;FS.preloadFile=FS_preloadFile;FS.staticInit();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["preloadPlugins"])preloadPlugins=Module["preloadPlugins"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["FS_preloadFile"]=FS_preloadFile;Module["FS_unlink"]=FS_unlink;Module["FS_createPath"]=FS_createPath;Module["FS_createDevice"]=FS_createDevice;Module["FS_createDataFile"]=FS_createDataFile;Module["FS_createLazyFile"]=FS_createLazyFile;var _run_janet,_setThrew,__emscripten_stack_restore,__emscripten_stack_alloc,_emscripten_stack_get_current,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){_run_janet=Module["_run_janet"]=wasmExports["run_janet"];_setThrew=wasmExports["setThrew"];__emscripten_stack_restore=wasmExports["_emscripten_stack_restore"];__emscripten_stack_alloc=wasmExports["_emscripten_stack_alloc"];_emscripten_stack_get_current=wasmExports["emscripten_stack_get_current"];memory=wasmMemory=wasmExports["memory"];__indirect_function_table=wasmTable=wasmExports["__indirect_function_table"]}var wasmImports={__syscall_chdir:___syscall_chdir,__syscall_chmod:___syscall_chmod,__syscall_fcntl64:___syscall_fcntl64,__syscall_fstat64:___syscall_fstat64,__syscall_getcwd:___syscall_getcwd,__syscall_getdents64:___syscall_getdents64,__syscall_ioctl:___syscall_ioctl,__syscall_lstat64:___syscall_lstat64,__syscall_mkdirat:___syscall_mkdirat,__syscall_newfstatat:___syscall_newfstatat,__syscall_openat:___syscall_openat,__syscall_readlinkat:___syscall_readlinkat,__syscall_renameat:___syscall_renameat,__syscall_rmdir:___syscall_rmdir,__syscall_stat64:___syscall_stat64,__syscall_symlinkat:___syscall_symlinkat,__syscall_unlinkat:___syscall_unlinkat,__syscall_utimensat:___syscall_utimensat,_abort_js:__abort_js,_emscripten_fs_load_embedded_files:__emscripten_fs_load_embedded_files,_emscripten_throw_longjmp:__emscripten_throw_longjmp,_gmtime_js:__gmtime_js,_localtime_js:__localtime_js,_mktime_js:__mktime_js,_timegm_js:__timegm_js,_tzset_js:__tzset_js,clock_time_get:_clock_time_get,emscripten_date_now:_emscripten_date_now,emscripten_get_now:_emscripten_get_now,emscripten_resize_heap:_emscripten_resize_heap,environ_get:_environ_get,environ_sizes_get:_environ_sizes_get,exit:_exit,fd_close:_fd_close,fd_fdstat_get:_fd_fdstat_get,fd_read:_fd_read,fd_seek:_fd_seek,fd_write:_fd_write,invoke_ii,invoke_iii,invoke_iiii,invoke_v,invoke_vi,invoke_vii,invoke_viii,proc_exit:_proc_exit};function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;createWasm();run(); 2 | -------------------------------------------------------------------------------- /janet/janet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025 Calvin Rose 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | * IN THE SOFTWARE. 21 | */ 22 | 23 | /* This will be generated by the build system if this file is not used */ 24 | 25 | #ifndef JANETCONF_H 26 | #define JANETCONF_H 27 | 28 | #define JANET_VERSION_MAJOR 1 29 | #define JANET_VERSION_MINOR 40 30 | #define JANET_VERSION_PATCH 1 31 | #define JANET_VERSION_EXTRA "" 32 | #define JANET_VERSION "1.40.1" 33 | 34 | /* #define JANET_BUILD "local" */ 35 | 36 | /* These settings all affect linking, so use cautiously. */ 37 | /* #define JANET_SINGLE_THREADED */ 38 | /* #define JANET_THREAD_LOCAL _Thread_local */ 39 | /* #define JANET_NO_DYNAMIC_MODULES */ 40 | /* #define JANET_NO_NANBOX */ 41 | /* #define JANET_API __attribute__((visibility ("default"))) */ 42 | 43 | /* These settings should be specified before amalgamation is 44 | * built. Any build with these set should be considered non-standard, and 45 | * certain Janet libraries should be expected not to work. */ 46 | /* #define JANET_NO_DOCSTRINGS */ 47 | /* #define JANET_NO_SOURCEMAPS */ 48 | /* #define JANET_REDUCED_OS */ 49 | /* #define JANET_NO_PROCESSES */ 50 | /* #define JANET_NO_ASSEMBLER */ 51 | /* #define JANET_NO_PEG */ 52 | /* #define JANET_NO_NET */ 53 | /* #define JANET_NO_INT_TYPES */ 54 | /* #define JANET_NO_EV */ 55 | /* #define JANET_NO_FILEWATCH */ 56 | /* #define JANET_NO_REALPATH */ 57 | /* #define JANET_NO_SYMLINKS */ 58 | /* #define JANET_NO_UMASK */ 59 | /* #define JANET_NO_THREADS */ 60 | /* #define JANET_NO_FFI */ 61 | /* #define JANET_NO_FFI_JIT */ 62 | 63 | /* Other settings */ 64 | /* #define JANET_DEBUG */ 65 | /* #define JANET_PRF */ 66 | /* #define JANET_NO_UTC_MKTIME */ 67 | /* #define JANET_OUT_OF_MEMORY do { printf("janet out of memory\n"); exit(1); } while (0) */ 68 | /* #define JANET_EXIT(msg) do { printf("C assert failed executing janet: %s\n", msg); exit(1); } while (0) */ 69 | /* #define JANET_TOP_LEVEL_SIGNAL(msg) call_my_function((msg), stderr) */ 70 | /* #define JANET_RECURSION_GUARD 1024 */ 71 | /* #define JANET_MAX_PROTO_DEPTH 200 */ 72 | /* #define JANET_MAX_MACRO_EXPAND 200 */ 73 | /* #define JANET_STACK_MAX 16384 */ 74 | /* #define JANET_OS_NAME my-custom-os */ 75 | /* #define JANET_ARCH_NAME pdp-8 */ 76 | /* #define JANET_EV_NO_EPOLL */ 77 | /* #define JANET_EV_NO_KQUEUE */ 78 | /* #define JANET_NO_INTERPRETER_INTERRUPT */ 79 | /* #define JANET_NO_IPV6 */ 80 | /* #define JANET_NO_CRYPTORAND */ 81 | /* #define JANET_USE_STDATOMIC */ 82 | 83 | /* Custom vm allocator support */ 84 | /* #include */ 85 | /* #define janet_malloc(X) mi_malloc((X)) */ 86 | /* #define janet_realloc(X, Y) mi_realloc((X), (Y)) */ 87 | /* #define janet_calloc(X, Y) mi_calloc((X), (Y)) */ 88 | /* #define janet_free(X) mi_free((X)) */ 89 | 90 | /* Main client settings, does not affect library code */ 91 | /* #define JANET_SIMPLE_GETLINE */ 92 | 93 | #endif /* end of include guard: JANETCONF_H */ 94 | 95 | 96 | #ifndef JANET_H_defined 97 | #define JANET_H_defined 98 | 99 | #ifdef __cplusplus 100 | extern "C" { 101 | #endif 102 | 103 | /* Variable length arrays are ok */ 104 | #ifdef _MSC_VER 105 | #pragma warning( push ) 106 | #pragma warning( disable : 4200 ) 107 | #endif 108 | 109 | /***** START SECTION CONFIG *****/ 110 | 111 | #ifndef JANET_VERSION 112 | #define JANET_VERSION "latest" 113 | #endif 114 | 115 | #ifndef JANET_BUILD 116 | #define JANET_BUILD "local" 117 | #endif 118 | 119 | /* 120 | * Detect OS and endianness. 121 | * From webkit source. There is likely some extreneous 122 | * detection for unsupported platforms 123 | */ 124 | 125 | /* Check for any flavor of BSD (except apple) */ 126 | #if defined(__FreeBSD__) || defined(__DragonFly__) || \ 127 | defined(__NetBSD__) || defined(__OpenBSD__) 128 | #define JANET_BSD 1 129 | #endif 130 | 131 | /* Check for macOS or OS X */ 132 | #if defined(__APPLE__) && defined(__MACH__) 133 | #define JANET_APPLE 1 134 | #endif 135 | 136 | /* Check for Linux */ 137 | #ifdef __linux__ 138 | #define JANET_LINUX 1 139 | #endif 140 | 141 | /* Check for Android */ 142 | #ifdef __ANDROID__ 143 | #define JANET_ANDROID 1 144 | #endif 145 | 146 | /* Check for Cygwin */ 147 | #if defined(__CYGWIN__) 148 | #define JANET_CYGWIN 1 149 | #endif 150 | 151 | /* Check for Illumos */ 152 | #if defined(__illumos__) 153 | #define JANET_ILLUMOS 1 154 | #endif 155 | 156 | /* Check Unix */ 157 | #if defined(_AIX) \ 158 | || defined(__APPLE__) /* Darwin */ \ 159 | || defined(__FreeBSD__) || defined(__DragonFly__) \ 160 | || defined(__FreeBSD_kernel__) \ 161 | || defined(__GNU__) /* GNU/Hurd */ \ 162 | || defined(__HAIKU__) \ 163 | || defined(__linux__) \ 164 | || defined(__NetBSD__) \ 165 | || defined(__OpenBSD__) \ 166 | || defined(__QNXNTO__) \ 167 | || defined(sun) || defined(__sun) /* Solaris */ \ 168 | || defined(unix) || defined(__unix) || defined(__unix__) 169 | #define JANET_POSIX 1 170 | #elif defined(__EMSCRIPTEN__) 171 | #define JANET_WEB 1 172 | #elif defined(WIN32) || defined(_WIN32) 173 | #define JANET_WINDOWS 1 174 | #endif 175 | 176 | /* Check if compiling with MSVC - else assume a GCC-like compiler by default */ 177 | #ifdef _MSC_VER 178 | #define JANET_MSVC 179 | #endif 180 | 181 | /* Check Mingw 32-bit and 64-bit */ 182 | #ifdef __MINGW32__ 183 | #define JANET_MINGW 184 | #endif 185 | 186 | /* Check 64-bit vs 32-bit */ 187 | #if ((defined(__x86_64__) || defined(_M_X64)) \ 188 | && (defined(JANET_POSIX) || defined(JANET_WINDOWS))) \ 189 | || (defined(_WIN64)) /* Windows 64 bit */ \ 190 | || (defined(__ia64__) && defined(__LP64__)) /* Itanium in LP64 mode */ \ 191 | || defined(__alpha__) /* DEC Alpha */ \ 192 | || (defined(__sparc__) && defined(__arch64__) || defined (__sparcv9)) /* BE */ \ 193 | || defined(__s390x__) /* S390 64-bit (BE) */ \ 194 | || (defined(__ppc64__) || defined(__PPC64__)) \ 195 | || defined(__aarch64__) /* ARM 64-bit */ \ 196 | || (defined(__riscv) && (__riscv_xlen == 64)) /* RISC-V 64-bit */ \ 197 | || defined(__loongarch64) /* LoongArch64 64-bit */ 198 | #define JANET_64 1 199 | #else 200 | #define JANET_32 1 201 | #endif 202 | 203 | /* Check big endian */ 204 | #if defined(__LITTLE_ENDIAN__) || \ 205 | (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) 206 | /* If we know the target is LE, always use that - e.g. ppc64 little endian 207 | * defines the __LITTLE_ENDIAN__ macro in the ABI spec, so we can rely 208 | * on that and if that's not defined, fall back to big endian assumption 209 | */ 210 | #define JANET_LITTLE_ENDIAN 1 211 | #elif defined(__MIPSEB__) /* MIPS 32-bit */ \ 212 | || defined(__ppc__) || defined(__PPC__) /* CPU(PPC) - PowerPC 32-bit */ \ 213 | || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) \ 214 | || defined(_M_PPC) || defined(__PPC) \ 215 | || defined(__ppc64__) || defined(__PPC64__) /* PowerPC 64-bit */ \ 216 | || defined(__sparc) /* Sparc 32bit */ \ 217 | || defined(__sparc__) /* Sparc 64-bit */ \ 218 | || defined(__s390x__) /* S390 64-bit */ \ 219 | || defined(__s390__) /* S390 32-bit */ \ 220 | || defined(__ARMEB__) /* ARM big endian */ \ 221 | || defined(__AARCH64EB__) /* ARM64 big endian */ \ 222 | || ((defined(__CC_ARM) || defined(__ARMCC__)) /* ARM RealView compiler */ \ 223 | && defined(__BIG_ENDIAN)) 224 | #define JANET_BIG_ENDIAN 1 225 | #else 226 | #define JANET_LITTLE_ENDIAN 1 227 | #endif 228 | 229 | /* Limits for converting doubles to 64 bit integers */ 230 | #define JANET_INTMAX_DOUBLE 9007199254740992.0 231 | #define JANET_INTMIN_DOUBLE (-9007199254740992.0) 232 | #define JANET_INTMAX_INT64 9007199254740992 233 | #define JANET_INTMIN_INT64 (-9007199254740992) 234 | 235 | /* Check emscripten */ 236 | #ifdef __EMSCRIPTEN__ 237 | #define JANET_NO_DYNAMIC_MODULES 238 | #define JANET_NO_PROCESSES 239 | #endif 240 | 241 | /* Check sun */ 242 | #if defined(__sun) && !defined(JANET_ILLUMOS) 243 | #define JANET_NO_UTC_MKTIME 244 | #endif 245 | 246 | /* Define how global janet state is declared */ 247 | /* Also enable the thread library only if not single-threaded */ 248 | #ifdef JANET_SINGLE_THREADED 249 | #define JANET_THREAD_LOCAL 250 | #elif !(defined(JANET_THREAD_LOCAL)) && defined(__GNUC__) 251 | #define JANET_THREAD_LOCAL __thread 252 | #elif !(defined(JANET_THREAD_LOCAL)) && defined(_MSC_BUILD) 253 | #define JANET_THREAD_LOCAL __declspec(thread) 254 | #elif !(defined(JANET_THREAD_LOCAL)) 255 | #define JANET_THREAD_LOCAL 256 | #endif 257 | 258 | /* Enable or disable dynamic module loading. Enabled by default. */ 259 | #ifndef JANET_NO_DYNAMIC_MODULES 260 | #define JANET_DYNAMIC_MODULES 261 | #endif 262 | 263 | /* Enable or disable the FFI library. Currently, FFI only enabled on 264 | * x86-64 operating systems. */ 265 | #ifndef JANET_NO_FFI 266 | #if !defined(__EMSCRIPTEN__) 267 | #define JANET_FFI 268 | #endif 269 | #endif 270 | 271 | /* If FFI is enabled and FFI-JIT is not disabled... */ 272 | #ifdef JANET_FFI 273 | #ifndef JANET_NO_FFI_JIT 274 | #define JANET_FFI_JIT 275 | #endif 276 | #endif 277 | 278 | /* Enable or disable the assembler. Enabled by default. */ 279 | #ifndef JANET_NO_ASSEMBLER 280 | #define JANET_ASSEMBLER 281 | #endif 282 | 283 | /* Enable or disable the peg module */ 284 | #ifndef JANET_NO_PEG 285 | #define JANET_PEG 286 | #endif 287 | 288 | /* Enable or disable event loop */ 289 | #if !defined(JANET_NO_EV) && !defined(__EMSCRIPTEN__) 290 | #define JANET_EV 291 | #endif 292 | 293 | /* Enable or disable the filewatch/ module */ 294 | #if !defined(JANET_NO_FILEWATCH) 295 | #define JANET_FILEWATCH 296 | #endif 297 | 298 | /* Enable or disable networking */ 299 | #if defined(JANET_EV) && !defined(JANET_NO_NET) && !defined(__EMSCRIPTEN__) 300 | #define JANET_NET 301 | #endif 302 | 303 | /* Enable or disable large int types (for now 64 bit, maybe 128 / 256 bit integer types) */ 304 | #ifndef JANET_NO_INT_TYPES 305 | #define JANET_INT_TYPES 306 | #endif 307 | 308 | /* Enable or disable epoll on Linux */ 309 | #if defined(JANET_LINUX) && !defined(JANET_EV_NO_EPOLL) 310 | #define JANET_EV_EPOLL 311 | #endif 312 | 313 | /* Enable or disable kqueue on BSD */ 314 | #if defined(JANET_BSD) && !defined(JANET_EV_NO_KQUEUE) 315 | #define JANET_EV_KQUEUE 316 | #endif 317 | 318 | /* Enable or disable kqueue on Apple */ 319 | #if defined(JANET_APPLE) && !defined(JANET_EV_NO_KQUEUE) 320 | #define JANET_EV_KQUEUE 321 | #endif 322 | 323 | /* Use poll as last resort */ 324 | #if !defined(JANET_WINDOWS) && !defined(JANET_EV_EPOLL) && !defined(JANET_EV_KQUEUE) 325 | #define JANET_EV_POLL 326 | #endif 327 | 328 | /* How to export symbols */ 329 | #ifndef JANET_EXPORT 330 | #ifdef JANET_WINDOWS 331 | #define JANET_EXPORT __declspec(dllexport) 332 | #else 333 | #define JANET_EXPORT __attribute__((visibility ("default"))) 334 | #endif 335 | #endif 336 | 337 | /* How declare API functions */ 338 | #ifndef JANET_API 339 | #ifdef JANET_WINDOWS 340 | #ifdef JANET_DLL_IMPORT 341 | #define JANET_API __declspec(dllimport) 342 | #else 343 | #define JANET_API __declspec(dllexport) 344 | #endif 345 | #else 346 | #define JANET_API __attribute__((visibility ("default"))) 347 | #endif 348 | #endif 349 | 350 | /* Tell compiler some functions don't return */ 351 | #ifndef JANET_NO_RETURN 352 | #ifdef JANET_WINDOWS 353 | #define JANET_NO_RETURN __declspec(noreturn) 354 | #else 355 | #define JANET_NO_RETURN __attribute__((noreturn)) 356 | #endif 357 | #endif 358 | 359 | /* Prevent some recursive functions from recursing too deeply 360 | * and crashing (the parser). Instead, error out. */ 361 | #define JANET_RECURSION_GUARD 1024 362 | 363 | /* Maximum depth to follow table prototypes before giving up and returning nil. */ 364 | #define JANET_MAX_PROTO_DEPTH 200 365 | 366 | /* Prevent macros to expand too deeply and error out. */ 367 | #define JANET_MAX_MACRO_EXPAND 200 368 | 369 | /* Define default max stack size for stacks before raising a stack overflow error. 370 | * This can also be set on a per fiber basis. */ 371 | #ifndef JANET_STACK_MAX 372 | #define JANET_STACK_MAX 0x7fffffff 373 | #endif 374 | 375 | /* Use nanboxed values - uses 8 bytes per value instead of 12 or 16. 376 | * To turn of nanboxing, for debugging purposes or for certain 377 | * architectures (Nanboxing only tested on x86 and x64), comment out 378 | * the JANET_NANBOX define.*/ 379 | 380 | #if defined(_M_ARM64) || defined(_M_ARM) || defined(__aarch64__) 381 | #define JANET_NO_NANBOX 382 | #endif 383 | 384 | #ifndef JANET_NO_NANBOX 385 | #ifdef JANET_32 386 | #define JANET_NANBOX_32 387 | #elif defined(__x86_64__) || defined(_WIN64) || defined(__riscv) 388 | /* We will only enable nanboxing by default on 64 bit systems 389 | * for x64 and risc-v. This is mainly because the approach is tied to the 390 | * implicit 47 bit address space. Many arches allow/require this, but not all, 391 | * and it requires cooperation from the OS. ARM should also work in many configurations. */ 392 | #define JANET_NANBOX_64 393 | #endif 394 | #endif 395 | 396 | /* Runtime config constants */ 397 | #ifdef JANET_NO_NANBOX 398 | #define JANET_NANBOX_BIT 0 399 | #else 400 | #define JANET_NANBOX_BIT 0x1 401 | #endif 402 | 403 | #ifdef JANET_SINGLE_THREADED 404 | #define JANET_SINGLE_THREADED_BIT 0x2 405 | #else 406 | #define JANET_SINGLE_THREADED_BIT 0 407 | #endif 408 | 409 | #define JANET_CURRENT_CONFIG_BITS \ 410 | (JANET_SINGLE_THREADED_BIT | \ 411 | JANET_NANBOX_BIT) 412 | 413 | /* Represents the settings used to compile Janet, as well as the version */ 414 | typedef struct { 415 | unsigned major; 416 | unsigned minor; 417 | unsigned patch; 418 | unsigned bits; 419 | } JanetBuildConfig; 420 | 421 | /* Get config of current compilation unit. */ 422 | #ifdef __cplusplus 423 | /* C++11 syntax */ 424 | #define janet_config_current() (JanetBuildConfig { \ 425 | JANET_VERSION_MAJOR, \ 426 | JANET_VERSION_MINOR, \ 427 | JANET_VERSION_PATCH, \ 428 | JANET_CURRENT_CONFIG_BITS }) 429 | #else 430 | /* C99 syntax */ 431 | #define janet_config_current() ((JanetBuildConfig){ \ 432 | JANET_VERSION_MAJOR, \ 433 | JANET_VERSION_MINOR, \ 434 | JANET_VERSION_PATCH, \ 435 | JANET_CURRENT_CONFIG_BITS }) 436 | #endif 437 | 438 | /* Some extra includes if EV is enabled */ 439 | #ifdef JANET_EV 440 | typedef struct JanetOSMutex JanetOSMutex; 441 | typedef struct JanetOSRWLock JanetOSRWLock; 442 | typedef struct JanetChannel JanetChannel; 443 | #endif 444 | 445 | /***** END SECTION CONFIG *****/ 446 | 447 | /***** START SECTION TYPES *****/ 448 | 449 | #ifdef JANET_WINDOWS 450 | /* Must be defined before including stdlib.h */ 451 | #define _CRT_RAND_S 452 | #endif 453 | 454 | #include 455 | #include 456 | #include 457 | #include 458 | #include 459 | #include 460 | #include 461 | 462 | /* What to do when out of memory */ 463 | #ifndef JANET_OUT_OF_MEMORY 464 | #define JANET_OUT_OF_MEMORY do { fprintf(stderr, "%s:%d - janet out of memory\n", __FILE__, __LINE__); exit(1); } while (0) 465 | #endif 466 | 467 | #ifdef JANET_BSD 468 | int _setjmp(jmp_buf); 469 | JANET_NO_RETURN void _longjmp(jmp_buf, int); 470 | #endif 471 | 472 | /* Names of all of the types */ 473 | JANET_API extern const char *const janet_type_names[16]; 474 | JANET_API extern const char *const janet_signal_names[14]; 475 | JANET_API extern const char *const janet_status_names[16]; 476 | 477 | /* For various IO routines, we want to use an int on posix and HANDLE on windows */ 478 | #ifdef JANET_WINDOWS 479 | typedef void *JanetHandle; 480 | #define JANET_HANDLE_NONE NULL 481 | #else 482 | typedef int JanetHandle; 483 | #define JANET_HANDLE_NONE (-1) 484 | #endif 485 | 486 | /* Fiber signals */ 487 | typedef enum { 488 | JANET_SIGNAL_OK, 489 | JANET_SIGNAL_ERROR, 490 | JANET_SIGNAL_DEBUG, 491 | JANET_SIGNAL_YIELD, 492 | JANET_SIGNAL_USER0, 493 | JANET_SIGNAL_USER1, 494 | JANET_SIGNAL_USER2, 495 | JANET_SIGNAL_USER3, 496 | JANET_SIGNAL_USER4, 497 | JANET_SIGNAL_USER5, 498 | JANET_SIGNAL_USER6, 499 | JANET_SIGNAL_USER7, 500 | JANET_SIGNAL_USER8, 501 | JANET_SIGNAL_USER9, 502 | JANET_SIGNAL_INTERRUPT = JANET_SIGNAL_USER8, 503 | JANET_SIGNAL_EVENT = JANET_SIGNAL_USER9, 504 | } JanetSignal; 505 | 506 | /* Fiber statuses - mostly corresponds to signals. */ 507 | typedef enum { 508 | JANET_STATUS_DEAD, 509 | JANET_STATUS_ERROR, 510 | JANET_STATUS_DEBUG, 511 | JANET_STATUS_PENDING, 512 | JANET_STATUS_USER0, 513 | JANET_STATUS_USER1, 514 | JANET_STATUS_USER2, 515 | JANET_STATUS_USER3, 516 | JANET_STATUS_USER4, 517 | JANET_STATUS_USER5, 518 | JANET_STATUS_USER6, 519 | JANET_STATUS_USER7, 520 | JANET_STATUS_USER8, 521 | JANET_STATUS_USER9, 522 | JANET_STATUS_NEW, 523 | JANET_STATUS_ALIVE 524 | } JanetFiberStatus; 525 | 526 | /* For encapsulating all thread-local Janet state (except natives) */ 527 | typedef struct JanetVM JanetVM; 528 | 529 | /* Use type punning for GC objects */ 530 | typedef struct JanetGCObject JanetGCObject; 531 | 532 | /* All of the primary Janet GCed types */ 533 | typedef struct JanetFunction JanetFunction; 534 | typedef struct JanetArray JanetArray; 535 | typedef struct JanetBuffer JanetBuffer; 536 | typedef struct JanetTable JanetTable; 537 | typedef struct JanetFiber JanetFiber; 538 | 539 | /* Prefixed Janet types */ 540 | typedef struct JanetTupleHead JanetTupleHead; 541 | typedef struct JanetStructHead JanetStructHead; 542 | typedef struct JanetStringHead JanetStringHead; 543 | typedef struct JanetAbstractHead JanetAbstractHead; 544 | 545 | /* Other structs */ 546 | typedef struct JanetFuncDef JanetFuncDef; 547 | typedef struct JanetFuncEnv JanetFuncEnv; 548 | typedef struct JanetKV JanetKV; 549 | typedef struct JanetStackFrame JanetStackFrame; 550 | typedef struct JanetAbstractType JanetAbstractType; 551 | typedef struct JanetReg JanetReg; 552 | typedef struct JanetRegExt JanetRegExt; 553 | typedef struct JanetMethod JanetMethod; 554 | typedef struct JanetSourceMapping JanetSourceMapping; 555 | typedef struct JanetSymbolMap JanetSymbolMap; 556 | typedef struct JanetView JanetView; 557 | typedef struct JanetByteView JanetByteView; 558 | typedef struct JanetDictView JanetDictView; 559 | typedef struct JanetRange JanetRange; 560 | typedef struct JanetRNG JanetRNG; 561 | 562 | /* Basic types for all Janet Values */ 563 | typedef enum JanetType { 564 | JANET_NUMBER, 565 | JANET_NIL, 566 | JANET_BOOLEAN, 567 | JANET_FIBER, 568 | JANET_STRING, 569 | JANET_SYMBOL, 570 | JANET_KEYWORD, 571 | JANET_ARRAY, 572 | JANET_TUPLE, 573 | JANET_TABLE, 574 | JANET_STRUCT, 575 | JANET_BUFFER, 576 | JANET_FUNCTION, 577 | JANET_CFUNCTION, 578 | JANET_ABSTRACT, 579 | JANET_POINTER 580 | } JanetType; 581 | 582 | /* Recursive type (Janet) */ 583 | #ifdef JANET_NANBOX_64 584 | typedef union Janet Janet; 585 | union Janet { 586 | uint64_t u64; 587 | int64_t i64; 588 | double number; 589 | void *pointer; 590 | }; 591 | #elif defined(JANET_NANBOX_32) 592 | typedef union Janet Janet; 593 | union Janet { 594 | struct { 595 | #ifdef JANET_BIG_ENDIAN 596 | uint32_t type; 597 | union { 598 | int32_t integer; 599 | void *pointer; 600 | } payload; 601 | #else 602 | union { 603 | int32_t integer; 604 | void *pointer; 605 | } payload; 606 | uint32_t type; 607 | #endif 608 | } tagged; 609 | double number; 610 | uint64_t u64; 611 | }; 612 | #else 613 | typedef struct Janet Janet; 614 | struct Janet { 615 | union { 616 | uint64_t u64; 617 | double number; 618 | int32_t integer; 619 | void *pointer; 620 | const void *cpointer; 621 | } as; 622 | JanetType type; 623 | }; 624 | #endif 625 | 626 | /* C functions */ 627 | typedef Janet(*JanetCFunction)(int32_t argc, Janet *argv); 628 | 629 | /* String and other aliased pointer types */ 630 | typedef const uint8_t *JanetString; 631 | typedef const uint8_t *JanetSymbol; 632 | typedef const uint8_t *JanetKeyword; 633 | typedef const Janet *JanetTuple; 634 | typedef const JanetKV *JanetStruct; 635 | typedef void *JanetAbstract; 636 | 637 | #define JANET_COUNT_TYPES (JANET_POINTER + 1) 638 | 639 | /* Type flags */ 640 | #define JANET_TFLAG_NIL (1 << JANET_NIL) 641 | #define JANET_TFLAG_BOOLEAN (1 << JANET_BOOLEAN) 642 | #define JANET_TFLAG_FIBER (1 << JANET_FIBER) 643 | #define JANET_TFLAG_NUMBER (1 << JANET_NUMBER) 644 | #define JANET_TFLAG_STRING (1 << JANET_STRING) 645 | #define JANET_TFLAG_SYMBOL (1 << JANET_SYMBOL) 646 | #define JANET_TFLAG_KEYWORD (1 << JANET_KEYWORD) 647 | #define JANET_TFLAG_ARRAY (1 << JANET_ARRAY) 648 | #define JANET_TFLAG_TUPLE (1 << JANET_TUPLE) 649 | #define JANET_TFLAG_TABLE (1 << JANET_TABLE) 650 | #define JANET_TFLAG_STRUCT (1 << JANET_STRUCT) 651 | #define JANET_TFLAG_BUFFER (1 << JANET_BUFFER) 652 | #define JANET_TFLAG_FUNCTION (1 << JANET_FUNCTION) 653 | #define JANET_TFLAG_CFUNCTION (1 << JANET_CFUNCTION) 654 | #define JANET_TFLAG_ABSTRACT (1 << JANET_ABSTRACT) 655 | #define JANET_TFLAG_POINTER (1 << JANET_POINTER) 656 | 657 | #define JANET_TFLAG_BYTES (JANET_TFLAG_STRING | JANET_TFLAG_SYMBOL | JANET_TFLAG_BUFFER | JANET_TFLAG_KEYWORD) 658 | #define JANET_TFLAG_INDEXED (JANET_TFLAG_ARRAY | JANET_TFLAG_TUPLE) 659 | #define JANET_TFLAG_DICTIONARY (JANET_TFLAG_TABLE | JANET_TFLAG_STRUCT) 660 | #define JANET_TFLAG_LENGTHABLE (JANET_TFLAG_BYTES | JANET_TFLAG_INDEXED | JANET_TFLAG_DICTIONARY) 661 | #define JANET_TFLAG_CALLABLE (JANET_TFLAG_FUNCTION | JANET_TFLAG_CFUNCTION | \ 662 | JANET_TFLAG_LENGTHABLE | JANET_TFLAG_ABSTRACT) 663 | 664 | /* Event Loop Types */ 665 | #ifdef JANET_EV 666 | 667 | #define JANET_STREAM_CLOSED 0x1 668 | #define JANET_STREAM_SOCKET 0x2 669 | #define JANET_STREAM_UNREGISTERED 0x4 670 | #define JANET_STREAM_READABLE 0x200 671 | #define JANET_STREAM_WRITABLE 0x400 672 | #define JANET_STREAM_ACCEPTABLE 0x800 673 | #define JANET_STREAM_UDPSERVER 0x1000 674 | #define JANET_STREAM_NOT_CLOSEABLE 0x2000 675 | #define JANET_STREAM_TOCLOSE 0x10000 676 | 677 | typedef enum { 678 | JANET_ASYNC_EVENT_INIT = 0, 679 | JANET_ASYNC_EVENT_MARK = 1, 680 | JANET_ASYNC_EVENT_DEINIT = 2, 681 | JANET_ASYNC_EVENT_CLOSE = 3, 682 | JANET_ASYNC_EVENT_ERR = 4, 683 | JANET_ASYNC_EVENT_HUP = 5, 684 | JANET_ASYNC_EVENT_READ = 6, 685 | JANET_ASYNC_EVENT_WRITE = 7, 686 | JANET_ASYNC_EVENT_COMPLETE = 8, /* Used on windows for IOCP */ 687 | JANET_ASYNC_EVENT_FAILED = 9 /* Used on windows for IOCP */ 688 | } JanetAsyncEvent; 689 | 690 | typedef enum { 691 | JANET_ASYNC_LISTEN_READ = 1, 692 | JANET_ASYNC_LISTEN_WRITE, 693 | JANET_ASYNC_LISTEN_BOTH 694 | } JanetAsyncMode; 695 | 696 | typedef struct JanetStream JanetStream; 697 | 698 | /* Wrapper around file descriptors and HANDLEs that can be polled. */ 699 | struct JanetStream { 700 | JanetHandle handle; 701 | uint32_t flags; 702 | uint32_t index; 703 | JanetFiber *read_fiber; 704 | JanetFiber *write_fiber; 705 | const void *methods; /* Methods for this stream */ 706 | }; 707 | 708 | typedef void (*JanetEVCallback)(JanetFiber *fiber, JanetAsyncEvent event); 709 | 710 | /* Start listening for events from a stream on the current root fiber. After 711 | * calling this, users should call janet_await() before returning from the 712 | * current C Function. This also will call janet_await. 713 | * mode is which events to listen for, and callback is the function pointer to 714 | * call when ever an event is sent from the event loop. state is an optional (can be NULL) 715 | * pointer to data allocated with janet_malloc. This pointer will be passed to callback as 716 | * fiber->ev_state. It will also be freed for you by the runtime when the event loop determines 717 | * it can no longer be referenced. On windows, the contents of state MUST contained an OVERLAPPED struct at the 0 offset. */ 718 | 719 | JANET_API void janet_async_start_fiber(JanetFiber *fiber, JanetStream *stream, JanetAsyncMode mode, JanetEVCallback callback, void *state); 720 | JANET_API JANET_NO_RETURN void janet_async_start(JanetStream *stream, JanetAsyncMode mode, JanetEVCallback callback, void *state); 721 | 722 | /* Do not send any more events to the given callback. Call this after scheduling fiber to be resume 723 | * or canceled. */ 724 | JANET_API void janet_async_end(JanetFiber *fiber); 725 | 726 | /* Needed for windows to mark a fiber as waiting for an IOCP completion event. Noop on other platforms. */ 727 | JANET_API void janet_async_in_flight(JanetFiber *fiber); 728 | 729 | /* On some platforms, it is important to be able to control if a stream is edge-trigger or level triggered. 730 | * For example, a server that is accepting connections might want to be level triggered or edge-triggered 731 | * depending on expected service. */ 732 | JANET_API void janet_stream_edge_triggered(JanetStream *stream); 733 | JANET_API void janet_stream_level_triggered(JanetStream *stream); 734 | 735 | #endif 736 | 737 | /* Janet uses atomic integers in several places for synchronization between threads and 738 | * signals. Define them here */ 739 | #ifdef JANET_WINDOWS 740 | typedef long JanetAtomicInt; 741 | #else 742 | typedef int32_t JanetAtomicInt; 743 | #endif 744 | JANET_API JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x); 745 | JANET_API JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x); 746 | JANET_API JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x); 747 | JANET_API JanetAtomicInt janet_atomic_load_relaxed(JanetAtomicInt volatile *x); 748 | 749 | /* We provide three possible implementations of Janets. The preferred 750 | * nanboxing approach, for 32 or 64 bits, and the standard C version. Code in the rest of the 751 | * application must interact through exposed interface. */ 752 | 753 | /* Required interface for Janet */ 754 | /* wrap and unwrap for all types */ 755 | /* Get type quickly */ 756 | /* Check against type quickly */ 757 | /* Small footprint */ 758 | /* 32 bit integer support */ 759 | 760 | /* janet_type(x) 761 | * janet_checktype(x, t) 762 | * janet_wrap_##TYPE(x) 763 | * janet_unwrap_##TYPE(x) 764 | * janet_truthy(x) 765 | * janet_memclear(p, n) - clear memory for hash tables to nils 766 | * janet_u64(x) - get 64 bits of payload for hashing 767 | */ 768 | 769 | /***** START SECTION NON-C API *****/ 770 | 771 | /* Some janet types use offset tricks to make operations easier in C. For 772 | * external bindings, we should prefer using the Head structs directly, and 773 | * use the host language to add sugar around the manipulation of the Janet types. */ 774 | 775 | JANET_API JanetStructHead *janet_struct_head(JanetStruct st); 776 | JANET_API JanetAbstractHead *janet_abstract_head(const void *abstract); 777 | JANET_API JanetStringHead *janet_string_head(JanetString s); 778 | JANET_API JanetTupleHead *janet_tuple_head(JanetTuple tuple); 779 | 780 | /* Some language bindings won't have access to the macro versions. */ 781 | 782 | JANET_API JanetType janet_type(Janet x); 783 | JANET_API int janet_checktype(Janet x, JanetType type); 784 | JANET_API int janet_checktypes(Janet x, int typeflags); 785 | JANET_API int janet_truthy(Janet x); 786 | 787 | JANET_API JanetStruct janet_unwrap_struct(Janet x); 788 | JANET_API JanetTuple janet_unwrap_tuple(Janet x); 789 | JANET_API JanetFiber *janet_unwrap_fiber(Janet x); 790 | JANET_API JanetArray *janet_unwrap_array(Janet x); 791 | JANET_API JanetTable *janet_unwrap_table(Janet x); 792 | JANET_API JanetBuffer *janet_unwrap_buffer(Janet x); 793 | JANET_API JanetString janet_unwrap_string(Janet x); 794 | JANET_API JanetSymbol janet_unwrap_symbol(Janet x); 795 | JANET_API JanetKeyword janet_unwrap_keyword(Janet x); 796 | JANET_API JanetAbstract janet_unwrap_abstract(Janet x); 797 | JANET_API void *janet_unwrap_pointer(Janet x); 798 | JANET_API JanetFunction *janet_unwrap_function(Janet x); 799 | JANET_API JanetCFunction janet_unwrap_cfunction(Janet x); 800 | JANET_API int janet_unwrap_boolean(Janet x); 801 | JANET_API double janet_unwrap_number(Janet x); 802 | JANET_API int32_t janet_unwrap_integer(Janet x); 803 | 804 | JANET_API Janet janet_wrap_nil(void); 805 | JANET_API Janet janet_wrap_number(double x); 806 | JANET_API Janet janet_wrap_true(void); 807 | JANET_API Janet janet_wrap_false(void); 808 | JANET_API Janet janet_wrap_boolean(int x); 809 | JANET_API Janet janet_wrap_string(JanetString x); 810 | JANET_API Janet janet_wrap_symbol(JanetSymbol x); 811 | JANET_API Janet janet_wrap_keyword(JanetKeyword x); 812 | JANET_API Janet janet_wrap_array(JanetArray *x); 813 | JANET_API Janet janet_wrap_tuple(JanetTuple x); 814 | JANET_API Janet janet_wrap_struct(JanetStruct x); 815 | JANET_API Janet janet_wrap_fiber(JanetFiber *x); 816 | JANET_API Janet janet_wrap_buffer(JanetBuffer *x); 817 | JANET_API Janet janet_wrap_function(JanetFunction *x); 818 | JANET_API Janet janet_wrap_cfunction(JanetCFunction x); 819 | JANET_API Janet janet_wrap_table(JanetTable *x); 820 | JANET_API Janet janet_wrap_abstract(JanetAbstract x); 821 | JANET_API Janet janet_wrap_pointer(void *x); 822 | JANET_API Janet janet_wrap_integer(int32_t x); 823 | 824 | /***** END SECTION NON-C API *****/ 825 | 826 | #ifdef JANET_NANBOX_64 827 | 828 | #include 829 | 830 | #define janet_u64(x) ((x).u64) 831 | 832 | #define JANET_NANBOX_TAGBITS 0xFFFF800000000000llu 833 | #define JANET_NANBOX_PAYLOADBITS 0x00007FFFFFFFFFFFllu 834 | #define janet_nanbox_lowtag(type) ((uint64_t)(type) | 0x1FFF0) 835 | #define janet_nanbox_tag(type) (janet_nanbox_lowtag(type) << 47) 836 | #define janet_type(x) \ 837 | (isnan((x).number) \ 838 | ? (JanetType) (((x).u64 >> 47) & 0xF) \ 839 | : JANET_NUMBER) 840 | 841 | #define janet_nanbox_checkauxtype(x, type) \ 842 | (((x).u64 & JANET_NANBOX_TAGBITS) == janet_nanbox_tag((type))) 843 | 844 | #define janet_nanbox_isnumber(x) \ 845 | (!isnan((x).number) || ((((x).u64 >> 47) & 0xF) == JANET_NUMBER)) 846 | 847 | #define janet_checktype(x, t) \ 848 | (((t) == JANET_NUMBER) \ 849 | ? janet_nanbox_isnumber(x) \ 850 | : janet_nanbox_checkauxtype((x), (t))) 851 | 852 | /* Use JANET_API so that modules will use a local version of these functions if possible */ 853 | JANET_API void *janet_nanbox_to_pointer(Janet x); 854 | JANET_API Janet janet_nanbox_from_pointer(void *p, uint64_t tagmask); 855 | JANET_API Janet janet_nanbox_from_cpointer(const void *p, uint64_t tagmask); 856 | JANET_API Janet janet_nanbox_from_double(double d); 857 | JANET_API Janet janet_nanbox_from_bits(uint64_t bits); 858 | 859 | #define janet_truthy(x) \ 860 | (!janet_checktype((x), JANET_NIL) && \ 861 | (!janet_checktype((x), JANET_BOOLEAN) || ((x).u64 & 0x1))) 862 | 863 | #define janet_nanbox_from_payload(t, p) \ 864 | janet_nanbox_from_bits(janet_nanbox_tag(t) | (p)) 865 | 866 | #define janet_nanbox_wrap_(p, t) \ 867 | janet_nanbox_from_pointer((p), janet_nanbox_tag(t)) 868 | 869 | #define janet_nanbox_wrap_c(p, t) \ 870 | janet_nanbox_from_cpointer((p), janet_nanbox_tag(t)) 871 | 872 | /* Wrap the simple types */ 873 | #define janet_wrap_nil() janet_nanbox_from_payload(JANET_NIL, 1) 874 | #define janet_wrap_true() janet_nanbox_from_payload(JANET_BOOLEAN, 1) 875 | #define janet_wrap_false() janet_nanbox_from_payload(JANET_BOOLEAN, 0) 876 | #define janet_wrap_boolean(b) janet_nanbox_from_payload(JANET_BOOLEAN, !!(b)) 877 | #define janet_wrap_number(r) janet_nanbox_from_double(r) 878 | 879 | /* Unwrap the simple types */ 880 | #define janet_unwrap_boolean(x) ((x).u64 & 0x1) 881 | #define janet_unwrap_number(x) ((x).number) 882 | 883 | /* Wrap the pointer types */ 884 | #define janet_wrap_struct(s) janet_nanbox_wrap_c((s), JANET_STRUCT) 885 | #define janet_wrap_tuple(s) janet_nanbox_wrap_c((s), JANET_TUPLE) 886 | #define janet_wrap_fiber(s) janet_nanbox_wrap_((s), JANET_FIBER) 887 | #define janet_wrap_array(s) janet_nanbox_wrap_((s), JANET_ARRAY) 888 | #define janet_wrap_table(s) janet_nanbox_wrap_((s), JANET_TABLE) 889 | #define janet_wrap_buffer(s) janet_nanbox_wrap_((s), JANET_BUFFER) 890 | #define janet_wrap_string(s) janet_nanbox_wrap_c((s), JANET_STRING) 891 | #define janet_wrap_symbol(s) janet_nanbox_wrap_c((s), JANET_SYMBOL) 892 | #define janet_wrap_keyword(s) janet_nanbox_wrap_c((s), JANET_KEYWORD) 893 | #define janet_wrap_abstract(s) janet_nanbox_wrap_((s), JANET_ABSTRACT) 894 | #define janet_wrap_function(s) janet_nanbox_wrap_((s), JANET_FUNCTION) 895 | #define janet_wrap_cfunction(s) janet_nanbox_wrap_((s), JANET_CFUNCTION) 896 | #define janet_wrap_pointer(s) janet_nanbox_wrap_((s), JANET_POINTER) 897 | 898 | /* Unwrap the pointer types */ 899 | #define janet_unwrap_struct(x) ((JanetStruct)janet_nanbox_to_pointer(x)) 900 | #define janet_unwrap_tuple(x) ((JanetTuple)janet_nanbox_to_pointer(x)) 901 | #define janet_unwrap_fiber(x) ((JanetFiber *)janet_nanbox_to_pointer(x)) 902 | #define janet_unwrap_array(x) ((JanetArray *)janet_nanbox_to_pointer(x)) 903 | #define janet_unwrap_table(x) ((JanetTable *)janet_nanbox_to_pointer(x)) 904 | #define janet_unwrap_buffer(x) ((JanetBuffer *)janet_nanbox_to_pointer(x)) 905 | #define janet_unwrap_string(x) ((JanetString)janet_nanbox_to_pointer(x)) 906 | #define janet_unwrap_symbol(x) ((JanetSymbol)janet_nanbox_to_pointer(x)) 907 | #define janet_unwrap_keyword(x) ((const uint8_t *)janet_nanbox_to_pointer(x)) 908 | #define janet_unwrap_abstract(x) (janet_nanbox_to_pointer(x)) 909 | #define janet_unwrap_pointer(x) (janet_nanbox_to_pointer(x)) 910 | #define janet_unwrap_function(x) ((JanetFunction *)janet_nanbox_to_pointer(x)) 911 | #define janet_unwrap_cfunction(x) ((JanetCFunction)janet_nanbox_to_pointer(x)) 912 | 913 | #elif defined(JANET_NANBOX_32) 914 | 915 | #define JANET_DOUBLE_OFFSET 0xFFFF 916 | 917 | #define janet_u64(x) ((x).u64) 918 | #define janet_type(x) (((x).tagged.type < JANET_DOUBLE_OFFSET) ? (JanetType)((x).tagged.type) : JANET_NUMBER) 919 | #define janet_checktype(x, t) ((t) == JANET_NUMBER \ 920 | ? (x).tagged.type >= JANET_DOUBLE_OFFSET \ 921 | : (x).tagged.type == (t)) 922 | #define janet_truthy(x) \ 923 | ((x).tagged.type != JANET_NIL && ((x).tagged.type != JANET_BOOLEAN || ((x).tagged.payload.integer & 0x1))) 924 | 925 | JANET_API Janet janet_nanbox32_from_tagi(uint32_t tag, int32_t integer); 926 | JANET_API Janet janet_nanbox32_from_tagp(uint32_t tag, void *pointer); 927 | 928 | #define janet_wrap_nil() janet_nanbox32_from_tagi(JANET_NIL, 0) 929 | #define janet_wrap_true() janet_nanbox32_from_tagi(JANET_BOOLEAN, 1) 930 | #define janet_wrap_false() janet_nanbox32_from_tagi(JANET_BOOLEAN, 0) 931 | #define janet_wrap_boolean(b) janet_nanbox32_from_tagi(JANET_BOOLEAN, !!(b)) 932 | 933 | /* Wrap the pointer types */ 934 | #define janet_wrap_struct(s) janet_nanbox32_from_tagp(JANET_STRUCT, (void *)(s)) 935 | #define janet_wrap_tuple(s) janet_nanbox32_from_tagp(JANET_TUPLE, (void *)(s)) 936 | #define janet_wrap_fiber(s) janet_nanbox32_from_tagp(JANET_FIBER, (void *)(s)) 937 | #define janet_wrap_array(s) janet_nanbox32_from_tagp(JANET_ARRAY, (void *)(s)) 938 | #define janet_wrap_table(s) janet_nanbox32_from_tagp(JANET_TABLE, (void *)(s)) 939 | #define janet_wrap_buffer(s) janet_nanbox32_from_tagp(JANET_BUFFER, (void *)(s)) 940 | #define janet_wrap_string(s) janet_nanbox32_from_tagp(JANET_STRING, (void *)(s)) 941 | #define janet_wrap_symbol(s) janet_nanbox32_from_tagp(JANET_SYMBOL, (void *)(s)) 942 | #define janet_wrap_keyword(s) janet_nanbox32_from_tagp(JANET_KEYWORD, (void *)(s)) 943 | #define janet_wrap_abstract(s) janet_nanbox32_from_tagp(JANET_ABSTRACT, (void *)(s)) 944 | #define janet_wrap_function(s) janet_nanbox32_from_tagp(JANET_FUNCTION, (void *)(s)) 945 | #define janet_wrap_cfunction(s) janet_nanbox32_from_tagp(JANET_CFUNCTION, (void *)(s)) 946 | #define janet_wrap_pointer(s) janet_nanbox32_from_tagp(JANET_POINTER, (void *)(s)) 947 | 948 | #define janet_unwrap_struct(x) ((JanetStruct)(x).tagged.payload.pointer) 949 | #define janet_unwrap_tuple(x) ((JanetTuple)(x).tagged.payload.pointer) 950 | #define janet_unwrap_fiber(x) ((JanetFiber *)(x).tagged.payload.pointer) 951 | #define janet_unwrap_array(x) ((JanetArray *)(x).tagged.payload.pointer) 952 | #define janet_unwrap_table(x) ((JanetTable *)(x).tagged.payload.pointer) 953 | #define janet_unwrap_buffer(x) ((JanetBuffer *)(x).tagged.payload.pointer) 954 | #define janet_unwrap_string(x) ((JanetString)(x).tagged.payload.pointer) 955 | #define janet_unwrap_symbol(x) ((JanetSymbol)(x).tagged.payload.pointer) 956 | #define janet_unwrap_keyword(x) ((JanetKeyword)(x).tagged.payload.pointer) 957 | #define janet_unwrap_abstract(x) ((x).tagged.payload.pointer) 958 | #define janet_unwrap_pointer(x) ((x).tagged.payload.pointer) 959 | #define janet_unwrap_function(x) ((JanetFunction *)(x).tagged.payload.pointer) 960 | #define janet_unwrap_cfunction(x) ((JanetCFunction)(x).tagged.payload.pointer) 961 | #define janet_unwrap_boolean(x) ((x).tagged.payload.integer) 962 | 963 | #else 964 | 965 | #define janet_u64(x) ((x).as.u64) 966 | #define janet_type(x) ((x).type) 967 | #define janet_checktype(x, t) ((x).type == (t)) 968 | #define janet_truthy(x) \ 969 | ((x).type != JANET_NIL && ((x).type != JANET_BOOLEAN || ((x).as.u64 & 0x1))) 970 | 971 | #define janet_unwrap_struct(x) ((JanetStruct)(x).as.pointer) 972 | #define janet_unwrap_tuple(x) ((JanetTuple)(x).as.pointer) 973 | #define janet_unwrap_fiber(x) ((JanetFiber *)(x).as.pointer) 974 | #define janet_unwrap_array(x) ((JanetArray *)(x).as.pointer) 975 | #define janet_unwrap_table(x) ((JanetTable *)(x).as.pointer) 976 | #define janet_unwrap_buffer(x) ((JanetBuffer *)(x).as.pointer) 977 | #define janet_unwrap_string(x) ((JanetString)(x).as.pointer) 978 | #define janet_unwrap_symbol(x) ((JanetSymbol)(x).as.pointer) 979 | #define janet_unwrap_keyword(x) ((JanetKeyword)(x).as.pointer) 980 | #define janet_unwrap_abstract(x) ((x).as.pointer) 981 | #define janet_unwrap_pointer(x) ((x).as.pointer) 982 | #define janet_unwrap_function(x) ((JanetFunction *)(x).as.pointer) 983 | #define janet_unwrap_cfunction(x) ((JanetCFunction)(x).as.pointer) 984 | #define janet_unwrap_boolean(x) ((x).as.u64 & 0x1) 985 | #define janet_unwrap_number(x) ((x).as.number) 986 | 987 | /* End of tagged union implementation */ 988 | #endif 989 | 990 | JANET_API int janet_checkint16(Janet x); 991 | JANET_API int janet_checkuint16(Janet x); 992 | JANET_API int janet_checkint(Janet x); 993 | JANET_API int janet_checkuint(Janet x); 994 | JANET_API int janet_checkint64(Janet x); 995 | JANET_API int janet_checkuint64(Janet x); 996 | JANET_API int janet_checksize(Janet x); 997 | JANET_API JanetAbstract janet_checkabstract(Janet x, const JanetAbstractType *at); 998 | #define janet_checkint16range(x) ((x) >= INT16_MIN && (x) <= INT16_MAX && (x) == (int16_t)(x)) 999 | #define janet_checkuint16range(x) ((x) >= 0 && (x) <= UINT16_MAX && (x) == (uint16_t)(x)) 1000 | #define janet_checkintrange(x) ((x) >= INT32_MIN && (x) <= INT32_MAX && (x) == (int32_t)(x)) 1001 | #define janet_checkuintrange(x) ((x) >= 0 && (x) <= UINT32_MAX && (x) == (uint32_t)(x)) 1002 | #define janet_checkint64range(x) ((x) >= JANET_INTMIN_DOUBLE && (x) <= JANET_INTMAX_DOUBLE && (x) == (int64_t)(x)) 1003 | #define janet_checkuint64range(x) ((x) >= 0 && (x) <= JANET_INTMAX_DOUBLE && (x) == (uint64_t)(x)) 1004 | #define janet_unwrap_integer(x) ((int32_t) janet_unwrap_number(x)) 1005 | #define janet_wrap_integer(x) janet_wrap_number((int32_t)(x)) 1006 | 1007 | #define janet_checktypes(x, tps) ((1 << janet_type(x)) & (tps)) 1008 | 1009 | /* GC Object type pun. The lower 16 bits of flags are reserved for the garbage collector, 1010 | * but the upper 16 can be used per type for custom flags. The current collector is a linked 1011 | * list of blocks, which is naive but works. */ 1012 | struct JanetGCObject { 1013 | int32_t flags; 1014 | union { 1015 | JanetGCObject *next; 1016 | volatile JanetAtomicInt refcount; /* For threaded abstract types */ 1017 | } data; 1018 | }; 1019 | 1020 | /* A lightweight green thread in janet. Does not correspond to 1021 | * operating system threads. */ 1022 | struct JanetFiber { 1023 | JanetGCObject gc; /* GC Object stuff */ 1024 | int32_t flags; /* More flags */ 1025 | int32_t frame; /* Index of the stack frame */ 1026 | int32_t stackstart; /* Beginning of next args */ 1027 | int32_t stacktop; /* Top of stack. Where values are pushed and popped from. */ 1028 | int32_t capacity; /* How big is the stack memory */ 1029 | int32_t maxstack; /* Arbitrary defined limit for stack overflow */ 1030 | JanetTable *env; /* Dynamic bindings table (usually current environment). */ 1031 | Janet *data; /* Dynamically resized stack memory */ 1032 | JanetFiber *child; /* Keep linked list of fibers for restarting pending fibers */ 1033 | Janet last_value; /* Last returned value from a fiber */ 1034 | #ifdef JANET_EV 1035 | /* These fields are only relevant for fibers that are used as "root fibers" - 1036 | * that is, fibers that are scheduled on the event loop and behave much like threads 1037 | * in a multi-tasking system. It would be possible to move these fields to a new 1038 | * type, say "JanetTask", that as separate from fibers to save a bit of space. */ 1039 | uint32_t sched_id; /* Increment everytime fiber is scheduled by event loop */ 1040 | JanetEVCallback ev_callback; /* Call this before starting scheduled fibers */ 1041 | JanetStream *ev_stream; /* which stream we are waiting on */ 1042 | void *ev_state; /* Extra data for ev callback state. On windows, first element must be OVERLAPPED. */ 1043 | void *supervisor_channel; /* Channel to push self to when complete */ 1044 | #endif 1045 | }; 1046 | 1047 | /* Mark if a stack frame is a tail call for debugging */ 1048 | #define JANET_STACKFRAME_TAILCALL 1 1049 | 1050 | /* Mark if a stack frame is an entrance frame */ 1051 | #define JANET_STACKFRAME_ENTRANCE 2 1052 | 1053 | /* A stack frame on the fiber. Is stored along with the stack values. */ 1054 | struct JanetStackFrame { 1055 | JanetFunction *func; 1056 | uint32_t *pc; 1057 | JanetFuncEnv *env; 1058 | int32_t prevframe; 1059 | int32_t flags; 1060 | }; 1061 | 1062 | /* Number of Janets a frame takes up in the stack 1063 | * Should be constant across architectures */ 1064 | #define JANET_FRAME_SIZE 4 1065 | 1066 | /* A dynamic array type. */ 1067 | struct JanetArray { 1068 | JanetGCObject gc; 1069 | int32_t count; 1070 | int32_t capacity; 1071 | Janet *data; 1072 | }; 1073 | 1074 | /* A byte buffer type. Used as a mutable string or string builder. */ 1075 | struct JanetBuffer { 1076 | JanetGCObject gc; 1077 | int32_t count; 1078 | int32_t capacity; 1079 | uint8_t *data; 1080 | }; 1081 | 1082 | /* A mutable associative data type. Backed by a hashtable. */ 1083 | struct JanetTable { 1084 | JanetGCObject gc; 1085 | int32_t count; 1086 | int32_t capacity; 1087 | int32_t deleted; 1088 | JanetKV *data; 1089 | JanetTable *proto; 1090 | }; 1091 | 1092 | /* A key value pair in a struct or table */ 1093 | struct JanetKV { 1094 | Janet key; 1095 | Janet value; 1096 | }; 1097 | 1098 | /* Prefix for a tuple */ 1099 | struct JanetTupleHead { 1100 | JanetGCObject gc; 1101 | int32_t length; 1102 | int32_t hash; 1103 | int32_t sm_line; 1104 | int32_t sm_column; 1105 | const Janet data[]; 1106 | }; 1107 | 1108 | /* Prefix for a struct */ 1109 | struct JanetStructHead { 1110 | JanetGCObject gc; 1111 | int32_t length; 1112 | int32_t hash; 1113 | int32_t capacity; 1114 | const JanetKV *proto; 1115 | const JanetKV data[]; 1116 | }; 1117 | 1118 | /* Prefix for a string */ 1119 | struct JanetStringHead { 1120 | JanetGCObject gc; 1121 | int32_t length; 1122 | int32_t hash; 1123 | const uint8_t data[]; 1124 | }; 1125 | 1126 | /* Prefix for an abstract value */ 1127 | struct JanetAbstractHead { 1128 | JanetGCObject gc; 1129 | const JanetAbstractType *type; 1130 | size_t size; 1131 | long long data[]; /* Use long long to ensure most general alignment */ 1132 | }; 1133 | 1134 | /* Some function definition flags */ 1135 | #define JANET_FUNCDEF_FLAG_VARARG 0x10000 1136 | #define JANET_FUNCDEF_FLAG_NEEDSENV 0x20000 1137 | #define JANET_FUNCDEF_FLAG_HASSYMBOLMAP 0x40000 1138 | #define JANET_FUNCDEF_FLAG_HASNAME 0x80000 1139 | #define JANET_FUNCDEF_FLAG_HASSOURCE 0x100000 1140 | #define JANET_FUNCDEF_FLAG_HASDEFS 0x200000 1141 | #define JANET_FUNCDEF_FLAG_HASENVS 0x400000 1142 | #define JANET_FUNCDEF_FLAG_HASSOURCEMAP 0x800000 1143 | #define JANET_FUNCDEF_FLAG_STRUCTARG 0x1000000 1144 | #define JANET_FUNCDEF_FLAG_HASCLOBITSET 0x2000000 1145 | #define JANET_FUNCDEF_FLAG_TAG 0xFFFF 1146 | 1147 | /* Source mapping structure for a bytecode instruction */ 1148 | struct JanetSourceMapping { 1149 | int32_t line; 1150 | int32_t column; 1151 | }; 1152 | 1153 | /* Symbol to slot mapping & lifetime structure. */ 1154 | struct JanetSymbolMap { 1155 | uint32_t birth_pc; 1156 | uint32_t death_pc; 1157 | uint32_t slot_index; 1158 | const uint8_t *symbol; 1159 | }; 1160 | 1161 | /* A function definition. Contains information needed to instantiate closures. */ 1162 | struct JanetFuncDef { 1163 | JanetGCObject gc; 1164 | int32_t *environments; /* Which environments to capture from parent. */ 1165 | Janet *constants; 1166 | JanetFuncDef **defs; 1167 | uint32_t *bytecode; 1168 | uint32_t *closure_bitset; /* Bit set indicating which slots can be referenced by closures. */ 1169 | 1170 | /* Various debug information */ 1171 | JanetSourceMapping *sourcemap; 1172 | JanetString source; 1173 | JanetString name; 1174 | JanetSymbolMap *symbolmap; 1175 | 1176 | int32_t flags; 1177 | int32_t slotcount; /* The amount of stack space required for the function */ 1178 | int32_t arity; /* Not including varargs */ 1179 | int32_t min_arity; /* Including varargs */ 1180 | int32_t max_arity; /* Including varargs */ 1181 | int32_t constants_length; 1182 | int32_t bytecode_length; 1183 | int32_t environments_length; 1184 | int32_t defs_length; 1185 | int32_t symbolmap_length; 1186 | }; 1187 | 1188 | /* A function environment */ 1189 | struct JanetFuncEnv { 1190 | JanetGCObject gc; 1191 | union { 1192 | JanetFiber *fiber; 1193 | Janet *values; 1194 | } as; 1195 | int32_t length; /* Size of environment */ 1196 | int32_t offset; /* Stack offset when values still on stack. If offset is <= 0, then 1197 | environment is no longer on the stack. */ 1198 | }; 1199 | 1200 | #define JANET_FUNCFLAG_TRACE (1 << 16) 1201 | 1202 | /* A function */ 1203 | struct JanetFunction { 1204 | JanetGCObject gc; 1205 | JanetFuncDef *def; 1206 | JanetFuncEnv *envs[]; 1207 | }; 1208 | 1209 | typedef struct JanetParseState JanetParseState; 1210 | typedef struct JanetParser JanetParser; 1211 | 1212 | enum JanetParserStatus { 1213 | JANET_PARSE_ROOT, 1214 | JANET_PARSE_ERROR, 1215 | JANET_PARSE_PENDING, 1216 | JANET_PARSE_DEAD 1217 | }; 1218 | 1219 | /* A janet parser */ 1220 | struct JanetParser { 1221 | Janet *args; 1222 | const char *error; 1223 | JanetParseState *states; 1224 | uint8_t *buf; 1225 | size_t argcount; 1226 | size_t argcap; 1227 | size_t statecount; 1228 | size_t statecap; 1229 | size_t bufcount; 1230 | size_t bufcap; 1231 | size_t line; 1232 | size_t column; 1233 | size_t pending; 1234 | int lookback; 1235 | int flag; 1236 | }; 1237 | 1238 | /* A context for marshaling and unmarshaling abstract types */ 1239 | typedef struct { 1240 | void *m_state; 1241 | void *u_state; 1242 | int flags; 1243 | const uint8_t *data; 1244 | const JanetAbstractType *at; 1245 | } JanetMarshalContext; 1246 | 1247 | /* Defines an abstract type */ 1248 | struct JanetAbstractType { 1249 | const char *name; 1250 | int (*gc)(void *data, size_t len); 1251 | int (*gcmark)(void *data, size_t len); 1252 | int (*get)(void *data, Janet key, Janet *out); 1253 | void (*put)(void *data, Janet key, Janet value); 1254 | void (*marshal)(void *p, JanetMarshalContext *ctx); 1255 | void *(*unmarshal)(JanetMarshalContext *ctx); 1256 | void (*tostring)(void *p, JanetBuffer *buffer); 1257 | int (*compare)(void *lhs, void *rhs); 1258 | int32_t (*hash)(void *p, size_t len); 1259 | Janet(*next)(void *p, Janet key); 1260 | Janet(*call)(void *p, int32_t argc, Janet *argv); 1261 | size_t (*length)(void *p, size_t len); 1262 | JanetByteView(*bytes)(void *p, size_t len); 1263 | int (*gcperthread)(void *data, size_t len); 1264 | }; 1265 | 1266 | /* Some macros to let us add extra types to JanetAbstract types without 1267 | * needing to changing native modules that declare them as static const 1268 | * structures. If more fields are added, these macros are modified to include 1269 | * default values (usually NULL). This silences missing field warnings. */ 1270 | #define JANET_ATEND_NAME NULL,JANET_ATEND_GC 1271 | #define JANET_ATEND_GC NULL,JANET_ATEND_GCMARK 1272 | #define JANET_ATEND_GCMARK NULL,JANET_ATEND_GET 1273 | #define JANET_ATEND_GET NULL,JANET_ATEND_PUT 1274 | #define JANET_ATEND_PUT NULL,JANET_ATEND_MARSHAL 1275 | #define JANET_ATEND_MARSHAL NULL,JANET_ATEND_UNMARSHAL 1276 | #define JANET_ATEND_UNMARSHAL NULL,JANET_ATEND_TOSTRING 1277 | #define JANET_ATEND_TOSTRING NULL,JANET_ATEND_COMPARE 1278 | #define JANET_ATEND_COMPARE NULL,JANET_ATEND_HASH 1279 | #define JANET_ATEND_HASH NULL,JANET_ATEND_NEXT 1280 | #define JANET_ATEND_NEXT NULL,JANET_ATEND_CALL 1281 | #define JANET_ATEND_CALL NULL,JANET_ATEND_LENGTH 1282 | #define JANET_ATEND_LENGTH NULL,JANET_ATEND_BYTES 1283 | #define JANET_ATEND_BYTES NULL,JANET_ATEND_GCPERTHREAD 1284 | #define JANET_ATEND_GCPERTHREAD 1285 | 1286 | struct JanetReg { 1287 | const char *name; 1288 | JanetCFunction cfun; 1289 | const char *documentation; 1290 | }; 1291 | 1292 | struct JanetRegExt { 1293 | const char *name; 1294 | JanetCFunction cfun; 1295 | const char *documentation; 1296 | const char *source_file; 1297 | int32_t source_line; 1298 | }; 1299 | 1300 | struct JanetMethod { 1301 | const char *name; 1302 | JanetCFunction cfun; 1303 | }; 1304 | 1305 | struct JanetView { 1306 | const Janet *items; 1307 | int32_t len; 1308 | }; 1309 | 1310 | struct JanetByteView { 1311 | const uint8_t *bytes; 1312 | int32_t len; 1313 | }; 1314 | 1315 | struct JanetDictView { 1316 | const JanetKV *kvs; 1317 | int32_t len; 1318 | int32_t cap; 1319 | }; 1320 | 1321 | struct JanetRange { 1322 | int32_t start; 1323 | int32_t end; 1324 | }; 1325 | 1326 | struct JanetRNG { 1327 | uint32_t a, b, c, d; 1328 | uint32_t counter; 1329 | }; 1330 | 1331 | typedef struct JanetFile JanetFile; 1332 | struct JanetFile { 1333 | FILE *file; 1334 | int32_t flags; 1335 | }; 1336 | 1337 | /* For janet_try and janet_restore */ 1338 | typedef struct { 1339 | /* old state */ 1340 | int32_t stackn; 1341 | int gc_handle; 1342 | JanetFiber *vm_fiber; 1343 | jmp_buf *vm_jmp_buf; 1344 | Janet *vm_return_reg; 1345 | /* new state */ 1346 | jmp_buf buf; 1347 | Janet payload; 1348 | int coerce_error; 1349 | } JanetTryState; 1350 | 1351 | /***** END SECTION TYPES *****/ 1352 | 1353 | /***** START SECTION OPCODES *****/ 1354 | 1355 | /* Bytecode op argument types */ 1356 | enum JanetOpArgType { 1357 | JANET_OAT_SLOT, 1358 | JANET_OAT_ENVIRONMENT, 1359 | JANET_OAT_CONSTANT, 1360 | JANET_OAT_INTEGER, 1361 | JANET_OAT_TYPE, 1362 | JANET_OAT_SIMPLETYPE, 1363 | JANET_OAT_LABEL, 1364 | JANET_OAT_FUNCDEF 1365 | }; 1366 | 1367 | /* Various types of instructions */ 1368 | enum JanetInstructionType { 1369 | JINT_0, /* No args */ 1370 | JINT_S, /* Slot(3) */ 1371 | JINT_L, /* Label(3) */ 1372 | JINT_SS, /* Slot(1), Slot(2) */ 1373 | JINT_SL, /* Slot(1), Label(2) */ 1374 | JINT_ST, /* Slot(1), Slot(2) */ 1375 | JINT_SI, /* Slot(1), Immediate(2) */ 1376 | JINT_SD, /* Slot(1), Closure(2) */ 1377 | JINT_SU, /* Slot(1), Unsigned Immediate(2) */ 1378 | JINT_SSS, /* Slot(1), Slot(1), Slot(1) */ 1379 | JINT_SSI, /* Slot(1), Slot(1), Immediate(1) */ 1380 | JINT_SSU, /* Slot(1), Slot(1), Unsigned Immediate(1) */ 1381 | JINT_SES, /* Slot(1), Environment(1), Far Slot(1) */ 1382 | JINT_SC /* Slot(1), Constant(2) */ 1383 | }; 1384 | 1385 | /* All opcodes for the bytecode interpreter. */ 1386 | enum JanetOpCode { 1387 | JOP_NOOP, 1388 | JOP_ERROR, 1389 | JOP_TYPECHECK, 1390 | JOP_RETURN, 1391 | JOP_RETURN_NIL, 1392 | JOP_ADD_IMMEDIATE, 1393 | JOP_ADD, 1394 | JOP_SUBTRACT_IMMEDIATE, 1395 | JOP_SUBTRACT, 1396 | JOP_MULTIPLY_IMMEDIATE, 1397 | JOP_MULTIPLY, 1398 | JOP_DIVIDE_IMMEDIATE, 1399 | JOP_DIVIDE, 1400 | JOP_DIVIDE_FLOOR, 1401 | JOP_MODULO, 1402 | JOP_REMAINDER, 1403 | JOP_BAND, 1404 | JOP_BOR, 1405 | JOP_BXOR, 1406 | JOP_BNOT, 1407 | JOP_SHIFT_LEFT, 1408 | JOP_SHIFT_LEFT_IMMEDIATE, 1409 | JOP_SHIFT_RIGHT, 1410 | JOP_SHIFT_RIGHT_IMMEDIATE, 1411 | JOP_SHIFT_RIGHT_UNSIGNED, 1412 | JOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE, 1413 | JOP_MOVE_FAR, 1414 | JOP_MOVE_NEAR, 1415 | JOP_JUMP, 1416 | JOP_JUMP_IF, 1417 | JOP_JUMP_IF_NOT, 1418 | JOP_JUMP_IF_NIL, 1419 | JOP_JUMP_IF_NOT_NIL, 1420 | JOP_GREATER_THAN, 1421 | JOP_GREATER_THAN_IMMEDIATE, 1422 | JOP_LESS_THAN, 1423 | JOP_LESS_THAN_IMMEDIATE, 1424 | JOP_EQUALS, 1425 | JOP_EQUALS_IMMEDIATE, 1426 | JOP_COMPARE, 1427 | JOP_LOAD_NIL, 1428 | JOP_LOAD_TRUE, 1429 | JOP_LOAD_FALSE, 1430 | JOP_LOAD_INTEGER, 1431 | JOP_LOAD_CONSTANT, 1432 | JOP_LOAD_UPVALUE, 1433 | JOP_LOAD_SELF, 1434 | JOP_SET_UPVALUE, 1435 | JOP_CLOSURE, 1436 | JOP_PUSH, 1437 | JOP_PUSH_2, 1438 | JOP_PUSH_3, 1439 | JOP_PUSH_ARRAY, 1440 | JOP_CALL, 1441 | JOP_TAILCALL, 1442 | JOP_RESUME, 1443 | JOP_SIGNAL, 1444 | JOP_PROPAGATE, 1445 | JOP_IN, 1446 | JOP_GET, 1447 | JOP_PUT, 1448 | JOP_GET_INDEX, 1449 | JOP_PUT_INDEX, 1450 | JOP_LENGTH, 1451 | JOP_MAKE_ARRAY, 1452 | JOP_MAKE_BUFFER, 1453 | JOP_MAKE_STRING, 1454 | JOP_MAKE_STRUCT, 1455 | JOP_MAKE_TABLE, 1456 | JOP_MAKE_TUPLE, 1457 | JOP_MAKE_BRACKET_TUPLE, 1458 | JOP_GREATER_THAN_EQUAL, 1459 | JOP_LESS_THAN_EQUAL, 1460 | JOP_NEXT, 1461 | JOP_NOT_EQUALS, 1462 | JOP_NOT_EQUALS_IMMEDIATE, 1463 | JOP_CANCEL, 1464 | JOP_INSTRUCTION_COUNT 1465 | }; 1466 | 1467 | /* Info about all instructions */ 1468 | extern enum JanetInstructionType janet_instructions[JOP_INSTRUCTION_COUNT]; 1469 | 1470 | /***** END SECTION OPCODES *****/ 1471 | 1472 | /***** START SECTION MAIN *****/ 1473 | 1474 | #ifdef JANET_EV 1475 | 1476 | extern JANET_API const JanetAbstractType janet_stream_type; 1477 | extern JANET_API const JanetAbstractType janet_channel_type; 1478 | 1479 | /* Run the event loop */ 1480 | JANET_API void janet_loop(void); 1481 | 1482 | /* Run the event loop, but allow for user scheduled interrupts triggered 1483 | * by janet_loop1_interrupt being called in library code, a signal handler, or 1484 | * another thread. 1485 | * 1486 | * Example: 1487 | * 1488 | * while (!janet_loop_done()) { 1489 | * // One turn of the event loop 1490 | * JanetFiber *interrupted_fiber = janet_loop1(); 1491 | * // interrupted_fiber may be NULL 1492 | * // do some work here periodically... 1493 | * if (NULL != interrupted_fiber) { 1494 | * if (cancel_interrupted_fiber) { 1495 | * janet_cancel(interrupted_fiber, janet_cstringv("fiber was interrupted for [reason]")); 1496 | * } else { 1497 | * janet_schedule(interrupted_fiber, janet_wrap_nil()); 1498 | * } 1499 | * } 1500 | * } 1501 | * 1502 | */ 1503 | JANET_API int janet_loop_done(void); 1504 | JANET_API JanetFiber *janet_loop1(void); 1505 | JANET_API void janet_loop1_interrupt(JanetVM *vm); 1506 | 1507 | /* Wrapper around streams */ 1508 | JANET_API JanetStream *janet_stream(JanetHandle handle, uint32_t flags, const JanetMethod *methods); 1509 | JANET_API JanetStream *janet_stream_ext(JanetHandle handle, uint32_t flags, const JanetMethod *methods, size_t size); /* Allow for type punning streams */ 1510 | JANET_API void janet_stream_close(JanetStream *stream); 1511 | JANET_API Janet janet_cfun_stream_close(int32_t argc, Janet *argv); 1512 | JANET_API Janet janet_cfun_stream_read(int32_t argc, Janet *argv); 1513 | JANET_API Janet janet_cfun_stream_chunk(int32_t argc, Janet *argv); 1514 | JANET_API Janet janet_cfun_stream_write(int32_t argc, Janet *argv); 1515 | JANET_API void janet_stream_flags(JanetStream *stream, uint32_t flags); 1516 | 1517 | /* Queue a fiber to run on the event loop */ 1518 | JANET_API void janet_schedule(JanetFiber *fiber, Janet value); 1519 | JANET_API void janet_cancel(JanetFiber *fiber, Janet value); 1520 | JANET_API void janet_schedule_signal(JanetFiber *fiber, Janet value, JanetSignal sig); 1521 | JANET_API void janet_schedule_soon(JanetFiber *fiber, Janet value, JanetSignal sig); 1522 | 1523 | /* Shorthand for yielding to event loop in C */ 1524 | JANET_NO_RETURN JANET_API void janet_await(void); 1525 | JANET_NO_RETURN JANET_API void janet_sleep_await(double sec); 1526 | 1527 | /* For use inside listeners - adds a timeout to the current fiber, such that 1528 | * it will be resumed after sec seconds if no other event schedules the current fiber. */ 1529 | JANET_API void janet_addtimeout(double sec); 1530 | JANET_API void janet_addtimeout_nil(double sec); 1531 | JANET_API void janet_ev_inc_refcount(void); 1532 | JANET_API void janet_ev_dec_refcount(void); 1533 | 1534 | /* Thread aware abstract types and helpers */ 1535 | JANET_API void *janet_abstract_begin_threaded(const JanetAbstractType *atype, size_t size); 1536 | JANET_API void *janet_abstract_end_threaded(void *x); 1537 | JANET_API void *janet_abstract_threaded(const JanetAbstractType *atype, size_t size); 1538 | JANET_API int32_t janet_abstract_incref(void *abst); 1539 | JANET_API int32_t janet_abstract_decref(void *abst); 1540 | 1541 | /* Expose channel utilities */ 1542 | JANET_API JanetChannel *janet_channel_make(uint32_t limit); 1543 | JANET_API JanetChannel *janet_channel_make_threaded(uint32_t limit); 1544 | JANET_API JanetChannel *janet_getchannel(const Janet *argv, int32_t n); 1545 | JANET_API JanetChannel *janet_optchannel(const Janet *argv, int32_t argc, int32_t n, JanetChannel *dflt); 1546 | JANET_API int janet_channel_give(JanetChannel *channel, Janet x); 1547 | JANET_API int janet_channel_take(JanetChannel *channel, Janet *out); 1548 | 1549 | /* Expose some OS sync primitives */ 1550 | JANET_API size_t janet_os_mutex_size(void); 1551 | JANET_API size_t janet_os_rwlock_size(void); 1552 | JANET_API void janet_os_mutex_init(JanetOSMutex *mutex); 1553 | JANET_API void janet_os_mutex_deinit(JanetOSMutex *mutex); 1554 | JANET_API void janet_os_mutex_lock(JanetOSMutex *mutex); 1555 | JANET_API void janet_os_mutex_unlock(JanetOSMutex *mutex); 1556 | JANET_API void janet_os_rwlock_init(JanetOSRWLock *rwlock); 1557 | JANET_API void janet_os_rwlock_deinit(JanetOSRWLock *rwlock); 1558 | JANET_API void janet_os_rwlock_rlock(JanetOSRWLock *rwlock); 1559 | JANET_API void janet_os_rwlock_wlock(JanetOSRWLock *rwlock); 1560 | JANET_API void janet_os_rwlock_runlock(JanetOSRWLock *rwlock); 1561 | JANET_API void janet_os_rwlock_wunlock(JanetOSRWLock *rwlock); 1562 | 1563 | /* Get last error from an IO operation */ 1564 | JANET_API Janet janet_ev_lasterr(void); 1565 | 1566 | /* Async service for calling a function or syscall in a background thread. This is not 1567 | * as efficient in the slightest as using Streams but can be used for arbitrary blocking 1568 | * functions and syscalls. */ 1569 | 1570 | /* Used to pass data between the main thread and worker threads for simple tasks. 1571 | * We could just use a pointer but this prevents malloc/free in the common case 1572 | * of only a handful of arguments. */ 1573 | typedef struct { 1574 | int tag; 1575 | int argi; 1576 | void *argp; 1577 | Janet argj; 1578 | JanetFiber *fiber; 1579 | } JanetEVGenericMessage; 1580 | 1581 | /* How to resume or cancel after a threaded call. Not exhaustive of the possible 1582 | * ways one might want to resume after returning from a threaded call, but should 1583 | * cover most of the common cases. For something more complicated, such as resuming 1584 | * with an abstract type or a struct, one should use janet_ev_threaded_call instead 1585 | * of janet_ev_threaded_await with a custom callback. */ 1586 | 1587 | #define JANET_EV_TCTAG_NIL 0 /* resume with nil */ 1588 | #define JANET_EV_TCTAG_INTEGER 1 /* resume with janet_wrap_integer(argi) */ 1589 | #define JANET_EV_TCTAG_STRING 2 /* resume with janet_cstringv((const char *) argp) */ 1590 | #define JANET_EV_TCTAG_STRINGF 3 /* resume with janet_cstringv((const char *) argp), then call free on argp. */ 1591 | #define JANET_EV_TCTAG_KEYWORD 4 /* resume with janet_ckeywordv((const char *) argp) */ 1592 | #define JANET_EV_TCTAG_ERR_STRING 5 /* cancel with janet_cstringv((const char *) argp) */ 1593 | #define JANET_EV_TCTAG_ERR_STRINGF 6 /* cancel with janet_cstringv((const char *) argp), then call free on argp. */ 1594 | #define JANET_EV_TCTAG_ERR_KEYWORD 7 /* cancel with janet_ckeywordv((const char *) argp) */ 1595 | #define JANET_EV_TCTAG_BOOLEAN 8 /* resume with janet_wrap_boolean(argi) */ 1596 | 1597 | /* Function pointer that is run in the thread pool */ 1598 | typedef JanetEVGenericMessage(*JanetThreadedSubroutine)(JanetEVGenericMessage arguments); 1599 | 1600 | /* Handler for events posted to the event loop */ 1601 | typedef void (*JanetCallback)(JanetEVGenericMessage return_value); 1602 | 1603 | /* Handler that is run in the main thread with the result of the JanetAsyncSubroutine (same as JanetCallback) */ 1604 | typedef void (*JanetThreadedCallback)(JanetEVGenericMessage return_value); 1605 | 1606 | /* API calls for quickly offloading some work in C to a new thread or thread pool. */ 1607 | JANET_API void janet_ev_threaded_call(JanetThreadedSubroutine fp, JanetEVGenericMessage arguments, JanetThreadedCallback cb); 1608 | JANET_NO_RETURN JANET_API void janet_ev_threaded_await(JanetThreadedSubroutine fp, int tag, int argi, void *argp); 1609 | 1610 | /* Post callback + userdata to an event loop. Takes the vm parameter to allow posting from other 1611 | * threads or signal handlers. Use NULL to post to the current thread. */ 1612 | JANET_API void janet_ev_post_event(JanetVM *vm, JanetCallback cb, JanetEVGenericMessage msg); 1613 | 1614 | /* Callback used by janet_ev_threaded_await */ 1615 | JANET_API void janet_ev_default_threaded_callback(JanetEVGenericMessage return_value); 1616 | 1617 | /* Read async from a stream */ 1618 | JANET_NO_RETURN JANET_API void janet_ev_read(JanetStream *stream, JanetBuffer *buf, int32_t nbytes); 1619 | JANET_NO_RETURN JANET_API void janet_ev_readchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes); 1620 | #ifdef JANET_NET 1621 | JANET_NO_RETURN JANET_API void janet_ev_recv(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags); 1622 | JANET_NO_RETURN JANET_API void janet_ev_recvchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags); 1623 | JANET_NO_RETURN JANET_API void janet_ev_recvfrom(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags); 1624 | #endif 1625 | 1626 | /* Write async to a stream */ 1627 | JANET_NO_RETURN JANET_API void janet_ev_write_buffer(JanetStream *stream, JanetBuffer *buf); 1628 | JANET_NO_RETURN JANET_API void janet_ev_write_string(JanetStream *stream, JanetString str); 1629 | #ifdef JANET_NET 1630 | JANET_NO_RETURN JANET_API void janet_ev_send_buffer(JanetStream *stream, JanetBuffer *buf, int flags); 1631 | JANET_NO_RETURN JANET_API void janet_ev_send_string(JanetStream *stream, JanetString str, int flags); 1632 | JANET_NO_RETURN JANET_API void janet_ev_sendto_buffer(JanetStream *stream, JanetBuffer *buf, void *dest, int flags); 1633 | JANET_NO_RETURN JANET_API void janet_ev_sendto_string(JanetStream *stream, JanetString str, void *dest, int flags); 1634 | #endif 1635 | 1636 | #endif 1637 | 1638 | /* Parsing */ 1639 | extern JANET_API const JanetAbstractType janet_parser_type; 1640 | JANET_API void janet_parser_init(JanetParser *parser); 1641 | JANET_API void janet_parser_deinit(JanetParser *parser); 1642 | JANET_API void janet_parser_consume(JanetParser *parser, uint8_t c); 1643 | JANET_API enum JanetParserStatus janet_parser_status(JanetParser *parser); 1644 | JANET_API Janet janet_parser_produce(JanetParser *parser); 1645 | JANET_API Janet janet_parser_produce_wrapped(JanetParser *parser); 1646 | JANET_API const char *janet_parser_error(JanetParser *parser); 1647 | JANET_API void janet_parser_flush(JanetParser *parser); 1648 | JANET_API void janet_parser_eof(JanetParser *parser); 1649 | JANET_API int janet_parser_has_more(JanetParser *parser); 1650 | 1651 | /* Assembly */ 1652 | #ifdef JANET_ASSEMBLER 1653 | typedef struct JanetAssembleResult JanetAssembleResult; 1654 | enum JanetAssembleStatus { 1655 | JANET_ASSEMBLE_OK, 1656 | JANET_ASSEMBLE_ERROR 1657 | }; 1658 | struct JanetAssembleResult { 1659 | JanetFuncDef *funcdef; 1660 | JanetString error; 1661 | enum JanetAssembleStatus status; 1662 | }; 1663 | JANET_API JanetAssembleResult janet_asm(Janet source, int flags); 1664 | JANET_API Janet janet_disasm(JanetFuncDef *def); 1665 | JANET_API Janet janet_asm_decode_instruction(uint32_t instr); 1666 | #endif 1667 | 1668 | /* Compilation */ 1669 | typedef struct JanetCompileResult JanetCompileResult; 1670 | enum JanetCompileStatus { 1671 | JANET_COMPILE_OK, 1672 | JANET_COMPILE_ERROR 1673 | }; 1674 | struct JanetCompileResult { 1675 | JanetFuncDef *funcdef; 1676 | JanetString error; 1677 | JanetFiber *macrofiber; 1678 | JanetSourceMapping error_mapping; 1679 | enum JanetCompileStatus status; 1680 | }; 1681 | JANET_API JanetCompileResult janet_compile(Janet source, JanetTable *env, JanetString where); 1682 | JANET_API JanetCompileResult janet_compile_lint( 1683 | Janet source, 1684 | JanetTable *env, 1685 | JanetString where, 1686 | JanetArray *lints); 1687 | 1688 | /* Get the default environment for janet */ 1689 | JANET_API JanetTable *janet_core_env(JanetTable *replacements); 1690 | JANET_API JanetTable *janet_core_lookup_table(JanetTable *replacements); 1691 | 1692 | /* Execute strings */ 1693 | #define JANET_DO_ERROR_RUNTIME 0x01 1694 | #define JANET_DO_ERROR_COMPILE 0x02 1695 | #define JANET_DO_ERROR_PARSE 0x04 1696 | JANET_API int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out); 1697 | JANET_API int janet_dostring(JanetTable *env, const char *str, const char *sourcePath, Janet *out); 1698 | 1699 | /* Run the entrypoint of a wrapped program */ 1700 | JANET_API int janet_loop_fiber(JanetFiber *fiber); 1701 | 1702 | /* Number scanning */ 1703 | JANET_API int janet_scan_number(const uint8_t *str, int32_t len, double *out); 1704 | JANET_API int janet_scan_number_base(const uint8_t *str, int32_t len, int32_t base, double *out); 1705 | JANET_API int janet_scan_int64(const uint8_t *str, int32_t len, int64_t *out); 1706 | JANET_API int janet_scan_uint64(const uint8_t *str, int32_t len, uint64_t *out); 1707 | #ifdef JANET_INT_TYPES 1708 | JANET_API int janet_scan_numeric(const uint8_t *str, int32_t len, Janet *out); 1709 | #endif 1710 | 1711 | /* Debugging */ 1712 | JANET_API void janet_debug_break(JanetFuncDef *def, int32_t pc); 1713 | JANET_API void janet_debug_unbreak(JanetFuncDef *def, int32_t pc); 1714 | JANET_API void janet_debug_find( 1715 | JanetFuncDef **def_out, int32_t *pc_out, 1716 | JanetString source, int32_t line, int32_t column); 1717 | 1718 | /* RNG */ 1719 | extern JANET_API const JanetAbstractType janet_rng_type; 1720 | JANET_API JanetRNG *janet_default_rng(void); 1721 | JANET_API void janet_rng_seed(JanetRNG *rng, uint32_t seed); 1722 | JANET_API void janet_rng_longseed(JanetRNG *rng, const uint8_t *bytes, int32_t len); 1723 | JANET_API uint32_t janet_rng_u32(JanetRNG *rng); 1724 | JANET_API double janet_rng_double(JanetRNG *rng); 1725 | 1726 | /* Array functions */ 1727 | JANET_API JanetArray *janet_array(int32_t capacity); 1728 | JANET_API JanetArray *janet_array_weak(int32_t capacity); 1729 | JANET_API JanetArray *janet_array_n(const Janet *elements, int32_t n); 1730 | JANET_API void janet_array_ensure(JanetArray *array, int32_t capacity, int32_t growth); 1731 | JANET_API void janet_array_setcount(JanetArray *array, int32_t count); 1732 | JANET_API void janet_array_push(JanetArray *array, Janet x); 1733 | JANET_API Janet janet_array_pop(JanetArray *array); 1734 | JANET_API Janet janet_array_peek(JanetArray *array); 1735 | 1736 | /* Buffer functions */ 1737 | #define JANET_BUFFER_FLAG_NO_REALLOC 0x10000 1738 | JANET_API JanetBuffer *janet_buffer(int32_t capacity); 1739 | JANET_API JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity); 1740 | JANET_API JanetBuffer *janet_pointer_buffer_unsafe(void *memory, int32_t capacity, int32_t count); 1741 | JANET_API void janet_buffer_deinit(JanetBuffer *buffer); 1742 | JANET_API void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth); 1743 | JANET_API void janet_buffer_setcount(JanetBuffer *buffer, int32_t count); 1744 | JANET_API void janet_buffer_extra(JanetBuffer *buffer, int32_t n); 1745 | JANET_API void janet_buffer_push_bytes(JanetBuffer *buffer, const uint8_t *string, int32_t len); 1746 | JANET_API void janet_buffer_push_string(JanetBuffer *buffer, JanetString string); 1747 | JANET_API void janet_buffer_push_cstring(JanetBuffer *buffer, const char *cstring); 1748 | JANET_API void janet_buffer_push_u8(JanetBuffer *buffer, uint8_t x); 1749 | JANET_API void janet_buffer_push_u16(JanetBuffer *buffer, uint16_t x); 1750 | JANET_API void janet_buffer_push_u32(JanetBuffer *buffer, uint32_t x); 1751 | JANET_API void janet_buffer_push_u64(JanetBuffer *buffer, uint64_t x); 1752 | 1753 | /* Tuple */ 1754 | 1755 | #define JANET_TUPLE_FLAG_BRACKETCTOR 0x10000 1756 | 1757 | #define janet_tuple_head(t) ((JanetTupleHead *)((char *)t - offsetof(JanetTupleHead, data))) 1758 | #define janet_tuple_from_head(gcobject) ((JanetTuple)((char *)gcobject + offsetof(JanetTupleHead, data))) 1759 | #define janet_tuple_length(t) (janet_tuple_head(t)->length) 1760 | #define janet_tuple_hash(t) (janet_tuple_head(t)->hash) 1761 | #define janet_tuple_sm_line(t) (janet_tuple_head(t)->sm_line) 1762 | #define janet_tuple_sm_column(t) (janet_tuple_head(t)->sm_column) 1763 | #define janet_tuple_flag(t) (janet_tuple_head(t)->gc.flags) 1764 | JANET_API Janet *janet_tuple_begin(int32_t length); 1765 | JANET_API JanetTuple janet_tuple_end(Janet *tuple); 1766 | JANET_API JanetTuple janet_tuple_n(const Janet *values, int32_t n); 1767 | 1768 | /* String/Symbol functions */ 1769 | #define janet_string_head(s) ((JanetStringHead *)((char *)s - offsetof(JanetStringHead, data))) 1770 | #define janet_string_length(s) (janet_string_head(s)->length) 1771 | #define janet_string_hash(s) (janet_string_head(s)->hash) 1772 | JANET_API uint8_t *janet_string_begin(int32_t length); 1773 | JANET_API JanetString janet_string_end(uint8_t *str); 1774 | JANET_API JanetString janet_string(const uint8_t *buf, int32_t len); 1775 | JANET_API JanetString janet_cstring(const char *cstring); 1776 | JANET_API int janet_string_compare(JanetString lhs, JanetString rhs); 1777 | JANET_API int janet_string_equal(JanetString lhs, JanetString rhs); 1778 | JANET_API int janet_string_equalconst(JanetString lhs, const uint8_t *rhs, int32_t rlen, int32_t rhash); 1779 | JANET_API JanetString janet_description(Janet x); 1780 | JANET_API JanetString janet_to_string(Janet x); 1781 | JANET_API void janet_to_string_b(JanetBuffer *buffer, Janet x); 1782 | JANET_API void janet_description_b(JanetBuffer *buffer, Janet x); 1783 | #define janet_cstringv(cstr) janet_wrap_string(janet_cstring(cstr)) 1784 | #define janet_stringv(str, len) janet_wrap_string(janet_string((str), (len))) 1785 | JANET_API JanetString janet_formatc(const char *format, ...); 1786 | JANET_API JanetBuffer *janet_formatb(JanetBuffer *bufp, const char *format, ...); 1787 | JANET_API void janet_formatbv(JanetBuffer *bufp, const char *format, va_list args); 1788 | 1789 | /* Symbol functions */ 1790 | JANET_API JanetSymbol janet_symbol(const uint8_t *str, int32_t len); 1791 | JANET_API JanetSymbol janet_csymbol(const char *str); 1792 | JANET_API JanetSymbol janet_symbol_gen(void); 1793 | #define janet_symbolv(str, len) janet_wrap_symbol(janet_symbol((str), (len))) 1794 | #define janet_csymbolv(cstr) janet_wrap_symbol(janet_csymbol(cstr)) 1795 | 1796 | /* Keyword functions */ 1797 | #define janet_keyword janet_symbol 1798 | #define janet_ckeyword janet_csymbol 1799 | #define janet_keywordv(str, len) janet_wrap_keyword(janet_keyword((str), (len))) 1800 | #define janet_ckeywordv(cstr) janet_wrap_keyword(janet_ckeyword(cstr)) 1801 | 1802 | /* Structs */ 1803 | #define janet_struct_head(t) ((JanetStructHead *)((char *)t - offsetof(JanetStructHead, data))) 1804 | #define janet_struct_from_head(t) ((JanetStruct)((char *)gcobject + offsetof(JanetStructHead, data))) 1805 | #define janet_struct_length(t) (janet_struct_head(t)->length) 1806 | #define janet_struct_capacity(t) (janet_struct_head(t)->capacity) 1807 | #define janet_struct_hash(t) (janet_struct_head(t)->hash) 1808 | #define janet_struct_proto(t) (janet_struct_head(t)->proto) 1809 | JANET_API JanetKV *janet_struct_begin(int32_t count); 1810 | JANET_API void janet_struct_put(JanetKV *st, Janet key, Janet value); 1811 | JANET_API JanetStruct janet_struct_end(JanetKV *st); 1812 | JANET_API Janet janet_struct_get(JanetStruct st, Janet key); 1813 | JANET_API Janet janet_struct_rawget(JanetStruct st, Janet key); 1814 | JANET_API Janet janet_struct_get_ex(JanetStruct st, Janet key, JanetStruct *which); 1815 | JANET_API JanetTable *janet_struct_to_table(JanetStruct st); 1816 | JANET_API const JanetKV *janet_struct_find(JanetStruct st, Janet key); 1817 | 1818 | /* Table functions */ 1819 | JANET_API JanetTable *janet_table(int32_t capacity); 1820 | JANET_API JanetTable *janet_table_init(JanetTable *table, int32_t capacity); 1821 | JANET_API JanetTable *janet_table_init_raw(JanetTable *table, int32_t capacity); 1822 | JANET_API void janet_table_deinit(JanetTable *table); 1823 | JANET_API Janet janet_table_get(JanetTable *t, Janet key); 1824 | JANET_API Janet janet_table_get_ex(JanetTable *t, Janet key, JanetTable **which); 1825 | JANET_API Janet janet_table_rawget(JanetTable *t, Janet key); 1826 | JANET_API Janet janet_table_remove(JanetTable *t, Janet key); 1827 | JANET_API void janet_table_put(JanetTable *t, Janet key, Janet value); 1828 | JANET_API JanetStruct janet_table_to_struct(JanetTable *t); 1829 | JANET_API void janet_table_merge_table(JanetTable *table, JanetTable *other); 1830 | JANET_API void janet_table_merge_struct(JanetTable *table, JanetStruct other); 1831 | JANET_API JanetKV *janet_table_find(JanetTable *t, Janet key); 1832 | JANET_API JanetTable *janet_table_clone(JanetTable *table); 1833 | JANET_API void janet_table_clear(JanetTable *table); 1834 | JANET_API JanetTable *janet_table_weakk(int32_t capacity); 1835 | JANET_API JanetTable *janet_table_weakv(int32_t capacity); 1836 | JANET_API JanetTable *janet_table_weakkv(int32_t capacity); 1837 | 1838 | /* Fiber */ 1839 | JANET_API JanetFiber *janet_fiber(JanetFunction *callee, int32_t capacity, int32_t argc, const Janet *argv); 1840 | JANET_API JanetFiber *janet_fiber_reset(JanetFiber *fiber, JanetFunction *callee, int32_t argc, const Janet *argv); 1841 | JANET_API JanetFiberStatus janet_fiber_status(JanetFiber *fiber); 1842 | JANET_API int janet_fiber_can_resume(JanetFiber *fiber); 1843 | JANET_API JanetFiber *janet_current_fiber(void); 1844 | JANET_API JanetFiber *janet_root_fiber(void); 1845 | 1846 | /* Treat similar types through uniform interfaces for iteration */ 1847 | JANET_API int janet_indexed_view(Janet seq, const Janet **data, int32_t *len); 1848 | JANET_API int janet_bytes_view(Janet str, const uint8_t **data, int32_t *len); 1849 | JANET_API int janet_dictionary_view(Janet tab, const JanetKV **data, int32_t *len, int32_t *cap); 1850 | JANET_API Janet janet_dictionary_get(const JanetKV *data, int32_t cap, Janet key); 1851 | JANET_API const JanetKV *janet_dictionary_next(const JanetKV *kvs, int32_t cap, const JanetKV *kv); 1852 | 1853 | /* Abstract */ 1854 | #define janet_abstract_head(u) ((JanetAbstractHead *)((char *)u - offsetof(JanetAbstractHead, data))) 1855 | #define janet_abstract_from_head(gcobject) ((JanetAbstract)((char *)gcobject + offsetof(JanetAbstractHead, data))) 1856 | #define janet_abstract_type(u) (janet_abstract_head(u)->type) 1857 | #define janet_abstract_size(u) (janet_abstract_head(u)->size) 1858 | JANET_API void *janet_abstract_begin(const JanetAbstractType *type, size_t size); 1859 | JANET_API JanetAbstract janet_abstract_end(void *abstractTemplate); 1860 | JANET_API JanetAbstract janet_abstract(const JanetAbstractType *type, size_t size); /* begin and end in one call */ 1861 | 1862 | /* Native */ 1863 | typedef void (*JanetModule)(JanetTable *); 1864 | typedef JanetBuildConfig(*JanetModconf)(void); 1865 | JANET_API JanetModule janet_native(const char *name, JanetString *error); 1866 | 1867 | /* Marshaling */ 1868 | #define JANET_MARSHAL_UNSAFE 0x20000 1869 | #define JANET_MARSHAL_NO_CYCLES 0x40000 1870 | 1871 | JANET_API void janet_marshal( 1872 | JanetBuffer *buf, 1873 | Janet x, 1874 | JanetTable *rreg, 1875 | int flags); 1876 | JANET_API Janet janet_unmarshal( 1877 | const uint8_t *bytes, 1878 | size_t len, 1879 | int flags, 1880 | JanetTable *reg, 1881 | const uint8_t **next); 1882 | JANET_API JanetTable *janet_env_lookup(JanetTable *env); 1883 | JANET_API void janet_env_lookup_into(JanetTable *renv, JanetTable *env, const char *prefix, int recurse); 1884 | 1885 | /* GC */ 1886 | JANET_API void janet_mark(Janet x); 1887 | JANET_API void janet_sweep(void); 1888 | JANET_API void janet_collect(void); 1889 | JANET_API void janet_clear_memory(void); 1890 | JANET_API void janet_gcroot(Janet root); 1891 | JANET_API int janet_gcunroot(Janet root); 1892 | JANET_API int janet_gcunrootall(Janet root); 1893 | JANET_API int janet_gclock(void); 1894 | JANET_API void janet_gcunlock(int handle); 1895 | JANET_API void janet_gcpressure(size_t s); 1896 | 1897 | /* Functions */ 1898 | JANET_API JanetFuncDef *janet_funcdef_alloc(void); 1899 | JANET_API JanetFunction *janet_thunk(JanetFuncDef *def); 1900 | JANET_API JanetFunction *janet_thunk_delay(Janet x); 1901 | JANET_API int janet_verify(JanetFuncDef *def); 1902 | 1903 | /* Pretty printing */ 1904 | #define JANET_PRETTY_COLOR 1 1905 | #define JANET_PRETTY_ONELINE 2 1906 | #define JANET_PRETTY_NOTRUNC 4 1907 | JANET_API JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, Janet x); 1908 | 1909 | /* Misc */ 1910 | #ifdef JANET_PRF 1911 | #define JANET_HASH_KEY_SIZE 16 1912 | JANET_API void janet_init_hash_key(uint8_t key[JANET_HASH_KEY_SIZE]); 1913 | #endif 1914 | JANET_API void janet_try_init(JanetTryState *state); 1915 | #if defined(JANET_BSD) || defined(JANET_APPLE) 1916 | #define janet_try(state) (janet_try_init(state), (JanetSignal) _setjmp((state)->buf)) 1917 | #else 1918 | #define janet_try(state) (janet_try_init(state), (JanetSignal) setjmp((state)->buf)) 1919 | #endif 1920 | JANET_API void janet_restore(JanetTryState *state); 1921 | JANET_API int janet_equals(Janet x, Janet y); 1922 | JANET_API int32_t janet_hash(Janet x); 1923 | JANET_API int janet_compare(Janet x, Janet y); 1924 | JANET_API int janet_cstrcmp(JanetString str, const char *other); 1925 | JANET_API Janet janet_in(Janet ds, Janet key); 1926 | JANET_API Janet janet_get(Janet ds, Janet key); 1927 | JANET_API Janet janet_next(Janet ds, Janet key); 1928 | JANET_API Janet janet_getindex(Janet ds, int32_t index); 1929 | JANET_API int32_t janet_length(Janet x); 1930 | JANET_API Janet janet_lengthv(Janet x); 1931 | JANET_API void janet_put(Janet ds, Janet key, Janet value); 1932 | JANET_API void janet_putindex(Janet ds, int32_t index, Janet value); 1933 | #define janet_flag_at(F, I) ((F) & ((1ULL) << (I))) 1934 | JANET_API Janet janet_wrap_number_safe(double x); 1935 | JANET_API int janet_keyeq(Janet x, const char *cstring); 1936 | JANET_API int janet_streq(Janet x, const char *cstring); 1937 | JANET_API int janet_symeq(Janet x, const char *cstring); 1938 | JANET_API int32_t janet_sorted_keys(const JanetKV *dict, int32_t cap, int32_t *index_buffer); 1939 | 1940 | /* VM functions */ 1941 | JANET_API int janet_init(void); 1942 | JANET_API void janet_deinit(void); 1943 | JANET_API JanetVM *janet_vm_alloc(void); 1944 | JANET_API JanetVM *janet_local_vm(void); 1945 | JANET_API void janet_vm_free(JanetVM *vm); 1946 | JANET_API void janet_vm_save(JanetVM *into); 1947 | JANET_API void janet_vm_load(JanetVM *from); 1948 | JANET_API void janet_interpreter_interrupt(JanetVM *vm); 1949 | JANET_API void janet_interpreter_interrupt_handled(JanetVM *vm); 1950 | JANET_API JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out); 1951 | JANET_API JanetSignal janet_continue_signal(JanetFiber *fiber, Janet in, Janet *out, JanetSignal sig); 1952 | JANET_API JanetSignal janet_pcall(JanetFunction *fun, int32_t argn, const Janet *argv, Janet *out, JanetFiber **f); 1953 | JANET_API JanetSignal janet_step(JanetFiber *fiber, Janet in, Janet *out); 1954 | JANET_API Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv); 1955 | JANET_API Janet janet_mcall(const char *name, int32_t argc, Janet *argv); 1956 | JANET_API void janet_stacktrace(JanetFiber *fiber, Janet err); 1957 | JANET_API void janet_stacktrace_ext(JanetFiber *fiber, Janet err, const char *prefix); 1958 | 1959 | /* Sandboxing API */ 1960 | #define JANET_SANDBOX_SANDBOX 1 1961 | #define JANET_SANDBOX_SUBPROCESS 2 1962 | #define JANET_SANDBOX_NET_CONNECT 4 1963 | #define JANET_SANDBOX_NET_LISTEN 8 1964 | #define JANET_SANDBOX_FFI_DEFINE 16 1965 | #define JANET_SANDBOX_FS_WRITE 32 1966 | #define JANET_SANDBOX_FS_READ 64 1967 | #define JANET_SANDBOX_HRTIME 128 1968 | #define JANET_SANDBOX_ENV 256 1969 | #define JANET_SANDBOX_DYNAMIC_MODULES 512 1970 | #define JANET_SANDBOX_FS_TEMP 1024 1971 | #define JANET_SANDBOX_FFI_USE 2048 1972 | #define JANET_SANDBOX_FFI_JIT 4096 1973 | #define JANET_SANDBOX_SIGNAL 8192 1974 | #define JANET_SANDBOX_CHROOT 16384 1975 | #define JANET_SANDBOX_FFI (JANET_SANDBOX_FFI_DEFINE | JANET_SANDBOX_FFI_USE | JANET_SANDBOX_FFI_JIT) 1976 | #define JANET_SANDBOX_FS (JANET_SANDBOX_FS_WRITE | JANET_SANDBOX_FS_READ | JANET_SANDBOX_FS_TEMP) 1977 | #define JANET_SANDBOX_NET (JANET_SANDBOX_NET_CONNECT | JANET_SANDBOX_NET_LISTEN) 1978 | #define JANET_SANDBOX_ALL (UINT32_MAX) 1979 | JANET_API void janet_sandbox(uint32_t flags); 1980 | JANET_API void janet_sandbox_assert(uint32_t forbidden_flags); 1981 | 1982 | /* Scratch Memory API */ 1983 | typedef void (*JanetScratchFinalizer)(void *); 1984 | 1985 | JANET_API void *janet_smalloc(size_t size); 1986 | JANET_API void *janet_srealloc(void *mem, size_t size); 1987 | JANET_API void *janet_scalloc(size_t nmemb, size_t size); 1988 | JANET_API void janet_sfinalizer(void *mem, JanetScratchFinalizer finalizer); 1989 | JANET_API void janet_sfree(void *mem); 1990 | 1991 | /* C Library helpers */ 1992 | typedef enum { 1993 | JANET_BINDING_NONE, 1994 | JANET_BINDING_DEF, 1995 | JANET_BINDING_VAR, 1996 | JANET_BINDING_MACRO, 1997 | JANET_BINDING_DYNAMIC_DEF, 1998 | JANET_BINDING_DYNAMIC_MACRO 1999 | } JanetBindingType; 2000 | 2001 | typedef struct { 2002 | JanetBindingType type; 2003 | Janet value; 2004 | enum { 2005 | JANET_BINDING_DEP_NONE, 2006 | JANET_BINDING_DEP_RELAXED, 2007 | JANET_BINDING_DEP_NORMAL, 2008 | JANET_BINDING_DEP_STRICT, 2009 | } deprecation; 2010 | } JanetBinding; 2011 | 2012 | JANET_API void janet_def(JanetTable *env, const char *name, Janet val, const char *documentation); 2013 | JANET_API void janet_var(JanetTable *env, const char *name, Janet val, const char *documentation); 2014 | JANET_API void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns); 2015 | JANET_API void janet_cfuns_prefix(JanetTable *env, const char *regprefix, const JanetReg *cfuns); 2016 | JANET_API JanetBindingType janet_resolve(JanetTable *env, JanetSymbol sym, Janet *out); 2017 | JANET_API JanetBinding janet_resolve_ext(JanetTable *env, JanetSymbol sym); 2018 | 2019 | /* Get values from the core environment. */ 2020 | JANET_API Janet janet_resolve_core(const char *name); 2021 | 2022 | /* New C API */ 2023 | 2024 | /* Shorthand for janet C function declarations */ 2025 | #define JANET_CFUN(name) Janet name (int32_t argc, Janet *argv) 2026 | 2027 | /* Declare a C function with documentation and source mapping */ 2028 | #define JANET_REG_END {NULL, NULL, NULL, NULL, 0} 2029 | 2030 | /* no docstrings or sourcemaps */ 2031 | #define JANET_REG_(JNAME, CNAME) {JNAME, CNAME, NULL, NULL, 0} 2032 | #define JANET_FN_(CNAME, USAGE, DOCSTRING) \ 2033 | Janet CNAME (int32_t argc, Janet *argv) 2034 | #define JANET_DEF_(ENV, JNAME, VAL, DOC) \ 2035 | janet_def(ENV, JNAME, VAL, NULL) 2036 | 2037 | /* sourcemaps only */ 2038 | #define JANET_REG_S(JNAME, CNAME) {JNAME, CNAME, NULL, __FILE__, CNAME##_sourceline_} 2039 | #define JANET_FN_S(CNAME, USAGE, DOCSTRING) \ 2040 | static const int32_t CNAME##_sourceline_ = __LINE__; \ 2041 | Janet CNAME (int32_t argc, Janet *argv) 2042 | #define JANET_DEF_S(ENV, JNAME, VAL, DOC) \ 2043 | janet_def_sm(ENV, JNAME, VAL, NULL, __FILE__, __LINE__) 2044 | 2045 | /* docstring only */ 2046 | #define JANET_REG_D(JNAME, CNAME) {JNAME, CNAME, CNAME##_docstring_, NULL, 0} 2047 | #define JANET_FN_D(CNAME, USAGE, DOCSTRING) \ 2048 | static const char CNAME##_docstring_[] = USAGE "\n\n" DOCSTRING; \ 2049 | Janet CNAME (int32_t argc, Janet *argv) 2050 | #define JANET_DEF_D(ENV, JNAME, VAL, DOC) \ 2051 | janet_def(ENV, JNAME, VAL, DOC) 2052 | 2053 | /* sourcemaps and docstrings */ 2054 | #define JANET_REG_SD(JNAME, CNAME) {JNAME, CNAME, CNAME##_docstring_, __FILE__, CNAME##_sourceline_} 2055 | #define JANET_FN_SD(CNAME, USAGE, DOCSTRING) \ 2056 | static const int32_t CNAME##_sourceline_ = __LINE__; \ 2057 | static const char CNAME##_docstring_[] = USAGE "\n\n" DOCSTRING; \ 2058 | Janet CNAME (int32_t argc, Janet *argv) 2059 | #define JANET_DEF_SD(ENV, JNAME, VAL, DOC) \ 2060 | janet_def_sm(ENV, JNAME, VAL, DOC, __FILE__, __LINE__) 2061 | 2062 | /* Choose defaults for source mapping and docstring based on config defs */ 2063 | #if defined(JANET_NO_SOURCEMAPS) && defined(JANET_NO_DOCSTRINGS) 2064 | #define JANET_REG JANET_REG_ 2065 | #define JANET_FN JANET_FN_ 2066 | #define JANET_DEF JANET_DEF_ 2067 | #elif defined(JANET_NO_SOURCEMAPS) && !defined(JANET_NO_DOCSTRINGS) 2068 | #define JANET_REG JANET_REG_D 2069 | #define JANET_FN JANET_FN_D 2070 | #define JANET_DEF JANET_DEF_D 2071 | #elif !defined(JANET_NO_SOURCEMAPS) && defined(JANET_NO_DOCSTRINGS) 2072 | #define JANET_REG JANET_REG_S 2073 | #define JANET_FN JANET_FN_S 2074 | #define JANET_DEF JANET_DEF_S 2075 | #elif !defined(JANET_NO_SOURCEMAPS) && !defined(JANET_NO_DOCSTRINGS) 2076 | #define JANET_REG JANET_REG_SD 2077 | #define JANET_FN JANET_FN_SD 2078 | #define JANET_DEF JANET_DEF_SD 2079 | #endif 2080 | 2081 | /* Define things with source mapping information */ 2082 | JANET_API void janet_cfuns_ext(JanetTable *env, const char *regprefix, const JanetRegExt *cfuns); 2083 | JANET_API void janet_cfuns_ext_prefix(JanetTable *env, const char *regprefix, const JanetRegExt *cfuns); 2084 | JANET_API void janet_def_sm(JanetTable *env, const char *name, Janet val, const char *documentation, const char *source_file, int32_t source_line); 2085 | JANET_API void janet_var_sm(JanetTable *env, const char *name, Janet val, const char *documentation, const char *source_file, int32_t source_line); 2086 | 2087 | /* Legacy definition of C functions */ 2088 | JANET_API void janet_register(const char *name, JanetCFunction cfun); 2089 | 2090 | /* Allow setting entry name for static libraries */ 2091 | #ifdef __cplusplus 2092 | #define JANET_MODULE_PREFIX extern "C" 2093 | #else 2094 | #define JANET_MODULE_PREFIX 2095 | #endif 2096 | #ifndef JANET_ENTRY_NAME 2097 | #define JANET_MODULE_ENTRY \ 2098 | JANET_MODULE_PREFIX JANET_EXPORT JanetBuildConfig _janet_mod_config(void) { \ 2099 | return janet_config_current(); \ 2100 | } \ 2101 | JANET_MODULE_PREFIX JANET_EXPORT void _janet_init 2102 | #else 2103 | #define JANET_MODULE_ENTRY JANET_MODULE_PREFIX JANET_API void JANET_ENTRY_NAME 2104 | #endif 2105 | 2106 | JANET_NO_RETURN JANET_API void janet_signalv(JanetSignal signal, Janet message); 2107 | JANET_NO_RETURN JANET_API void janet_panicv(Janet message); 2108 | JANET_NO_RETURN JANET_API void janet_panic(const char *message); 2109 | JANET_NO_RETURN JANET_API void janet_panics(JanetString message); 2110 | JANET_NO_RETURN JANET_API void janet_panicf(const char *format, ...); 2111 | JANET_API void janet_dynprintf(const char *name, FILE *dflt_file, const char *format, ...); 2112 | #define janet_printf(...) janet_dynprintf("out", stdout, __VA_ARGS__) 2113 | #define janet_eprintf(...) janet_dynprintf("err", stderr, __VA_ARGS__) 2114 | JANET_NO_RETURN JANET_API void janet_panic_type(Janet x, int32_t n, int expected); 2115 | JANET_NO_RETURN JANET_API void janet_panic_abstract(Janet x, int32_t n, const JanetAbstractType *at); 2116 | JANET_API void janet_arity(int32_t arity, int32_t min, int32_t max); 2117 | JANET_API void janet_fixarity(int32_t arity, int32_t fix); 2118 | 2119 | JANET_API int janet_getmethod(JanetKeyword method, const JanetMethod *methods, Janet *out); 2120 | JANET_API Janet janet_nextmethod(const JanetMethod *methods, Janet key); 2121 | 2122 | JANET_API double janet_getnumber(const Janet *argv, int32_t n); 2123 | JANET_API JanetArray *janet_getarray(const Janet *argv, int32_t n); 2124 | JANET_API JanetTuple janet_gettuple(const Janet *argv, int32_t n); 2125 | JANET_API JanetTable *janet_gettable(const Janet *argv, int32_t n); 2126 | JANET_API JanetStruct janet_getstruct(const Janet *argv, int32_t n); 2127 | JANET_API JanetString janet_getstring(const Janet *argv, int32_t n); 2128 | JANET_API const char *janet_getcstring(const Janet *argv, int32_t n); 2129 | JANET_API const char *janet_getcbytes(const Janet *argv, int32_t n); 2130 | JANET_API JanetSymbol janet_getsymbol(const Janet *argv, int32_t n); 2131 | JANET_API JanetKeyword janet_getkeyword(const Janet *argv, int32_t n); 2132 | JANET_API JanetBuffer *janet_getbuffer(const Janet *argv, int32_t n); 2133 | JANET_API JanetFiber *janet_getfiber(const Janet *argv, int32_t n); 2134 | JANET_API JanetFunction *janet_getfunction(const Janet *argv, int32_t n); 2135 | JANET_API JanetCFunction janet_getcfunction(const Janet *argv, int32_t n); 2136 | JANET_API int janet_getboolean(const Janet *argv, int32_t n); 2137 | JANET_API void *janet_getpointer(const Janet *argv, int32_t n); 2138 | 2139 | JANET_API int32_t janet_getnat(const Janet *argv, int32_t n); 2140 | JANET_API int32_t janet_getinteger(const Janet *argv, int32_t n); 2141 | JANET_API int16_t janet_getinteger16(const Janet *argv, int32_t n); 2142 | JANET_API int64_t janet_getinteger64(const Janet *argv, int32_t n); 2143 | JANET_API uint32_t janet_getuinteger(const Janet *argv, int32_t n); 2144 | JANET_API uint16_t janet_getuinteger16(const Janet *argv, int32_t n); 2145 | JANET_API uint64_t janet_getuinteger64(const Janet *argv, int32_t n); 2146 | JANET_API size_t janet_getsize(const Janet *argv, int32_t n); 2147 | JANET_API JanetView janet_getindexed(const Janet *argv, int32_t n); 2148 | JANET_API JanetByteView janet_getbytes(const Janet *argv, int32_t n); 2149 | JANET_API JanetDictView janet_getdictionary(const Janet *argv, int32_t n); 2150 | JANET_API void *janet_getabstract(const Janet *argv, int32_t n, const JanetAbstractType *at); 2151 | JANET_API JanetRange janet_getslice(int32_t argc, const Janet *argv); 2152 | JANET_API int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const char *which); 2153 | JANET_API int32_t janet_getstartrange(const Janet *argv, int32_t argc, int32_t n, int32_t length); 2154 | JANET_API int32_t janet_getendrange(const Janet *argv, int32_t argc, int32_t n, int32_t length); 2155 | JANET_API int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which); 2156 | JANET_API uint64_t janet_getflags(const Janet *argv, int32_t n, const char *flags); 2157 | 2158 | /* Optionals */ 2159 | JANET_API double janet_optnumber(const Janet *argv, int32_t argc, int32_t n, double dflt); 2160 | JANET_API JanetTuple janet_opttuple(const Janet *argv, int32_t argc, int32_t n, JanetTuple dflt); 2161 | JANET_API JanetStruct janet_optstruct(const Janet *argv, int32_t argc, int32_t n, JanetStruct dflt); 2162 | JANET_API JanetString janet_optstring(const Janet *argv, int32_t argc, int32_t n, JanetString dflt); 2163 | JANET_API const char *janet_optcstring(const Janet *argv, int32_t argc, int32_t n, const char *dflt); 2164 | JANET_API const char *janet_optcbytes(const Janet *argv, int32_t argc, int32_t n, const char *dflt); 2165 | JANET_API JanetSymbol janet_optsymbol(const Janet *argv, int32_t argc, int32_t n, JanetString dflt); 2166 | JANET_API JanetKeyword janet_optkeyword(const Janet *argv, int32_t argc, int32_t n, JanetString dflt); 2167 | JANET_API JanetFiber *janet_optfiber(const Janet *argv, int32_t argc, int32_t n, JanetFiber *dflt); 2168 | JANET_API JanetFunction *janet_optfunction(const Janet *argv, int32_t argc, int32_t n, JanetFunction *dflt); 2169 | JANET_API JanetCFunction janet_optcfunction(const Janet *argv, int32_t argc, int32_t n, JanetCFunction dflt); 2170 | JANET_API int janet_optboolean(const Janet *argv, int32_t argc, int32_t n, int dflt); 2171 | JANET_API void *janet_optpointer(const Janet *argv, int32_t argc, int32_t n, void *dflt); 2172 | JANET_API int32_t janet_optnat(const Janet *argv, int32_t argc, int32_t n, int32_t dflt); 2173 | JANET_API int32_t janet_optinteger(const Janet *argv, int32_t argc, int32_t n, int32_t dflt); 2174 | JANET_API int64_t janet_optinteger64(const Janet *argv, int32_t argc, int32_t n, int64_t dflt); 2175 | JANET_API size_t janet_optsize(const Janet *argv, int32_t argc, int32_t n, size_t dflt); 2176 | JANET_API JanetAbstract janet_optabstract(const Janet *argv, int32_t argc, int32_t n, const JanetAbstractType *at, JanetAbstract dflt); 2177 | 2178 | /* Mutable optional types specify a size default, and construct a new value if none is provided */ 2179 | JANET_API JanetBuffer *janet_optbuffer(const Janet *argv, int32_t argc, int32_t n, int32_t dflt_len); 2180 | JANET_API JanetTable *janet_opttable(const Janet *argv, int32_t argc, int32_t n, int32_t dflt_len); 2181 | JANET_API JanetArray *janet_optarray(const Janet *argv, int32_t argc, int32_t n, int32_t dflt_len); 2182 | 2183 | JANET_API Janet janet_dyn(const char *name); 2184 | JANET_API void janet_setdyn(const char *name, Janet value); 2185 | 2186 | extern JANET_API const JanetAbstractType janet_file_type; 2187 | 2188 | #define JANET_FILE_WRITE 1 2189 | #define JANET_FILE_READ 2 2190 | #define JANET_FILE_APPEND 4 2191 | #define JANET_FILE_UPDATE 8 2192 | #define JANET_FILE_NOT_CLOSEABLE 16 2193 | #define JANET_FILE_CLOSED 32 2194 | #define JANET_FILE_BINARY 64 2195 | #define JANET_FILE_SERIALIZABLE 128 2196 | #define JANET_FILE_NONIL 512 2197 | 2198 | JANET_API Janet janet_makefile(FILE *f, int32_t flags); 2199 | JANET_API JanetFile *janet_makejfile(FILE *f, int32_t flags); 2200 | JANET_API FILE *janet_getfile(const Janet *argv, int32_t n, int32_t *flags); 2201 | JANET_API FILE *janet_dynfile(const char *name, FILE *def); 2202 | JANET_API JanetFile *janet_getjfile(const Janet *argv, int32_t n); 2203 | JANET_API JanetAbstract janet_checkfile(Janet j); 2204 | JANET_API FILE *janet_unwrapfile(Janet j, int32_t *flags); 2205 | JANET_API int janet_file_close(JanetFile *file); 2206 | 2207 | JANET_API int janet_cryptorand(uint8_t *out, size_t n); 2208 | 2209 | /* Marshal API */ 2210 | JANET_API void janet_marshal_size(JanetMarshalContext *ctx, size_t value); 2211 | JANET_API void janet_marshal_int(JanetMarshalContext *ctx, int32_t value); 2212 | JANET_API void janet_marshal_int64(JanetMarshalContext *ctx, int64_t value); 2213 | JANET_API void janet_marshal_ptr(JanetMarshalContext *ctx, const void *value); 2214 | JANET_API void janet_marshal_byte(JanetMarshalContext *ctx, uint8_t value); 2215 | JANET_API void janet_marshal_bytes(JanetMarshalContext *ctx, const uint8_t *bytes, size_t len); 2216 | JANET_API void janet_marshal_janet(JanetMarshalContext *ctx, Janet x); 2217 | JANET_API void janet_marshal_abstract(JanetMarshalContext *ctx, JanetAbstract abstract); 2218 | 2219 | JANET_API void janet_unmarshal_ensure(JanetMarshalContext *ctx, size_t size); 2220 | JANET_API size_t janet_unmarshal_size(JanetMarshalContext *ctx); 2221 | JANET_API int32_t janet_unmarshal_int(JanetMarshalContext *ctx); 2222 | JANET_API int64_t janet_unmarshal_int64(JanetMarshalContext *ctx); 2223 | JANET_API void *janet_unmarshal_ptr(JanetMarshalContext *ctx); 2224 | JANET_API uint8_t janet_unmarshal_byte(JanetMarshalContext *ctx); 2225 | JANET_API void janet_unmarshal_bytes(JanetMarshalContext *ctx, uint8_t *dest, size_t len); 2226 | JANET_API Janet janet_unmarshal_janet(JanetMarshalContext *ctx); 2227 | JANET_API JanetAbstract janet_unmarshal_abstract(JanetMarshalContext *ctx, size_t size); 2228 | JANET_API JanetAbstract janet_unmarshal_abstract_threaded(JanetMarshalContext *ctx, size_t size); 2229 | JANET_API void janet_unmarshal_abstract_reuse(JanetMarshalContext *ctx, void *p); 2230 | 2231 | JANET_API void janet_register_abstract_type(const JanetAbstractType *at); 2232 | JANET_API const JanetAbstractType *janet_get_abstract_type(Janet key); 2233 | 2234 | #ifdef JANET_PEG 2235 | 2236 | extern JANET_API const JanetAbstractType janet_peg_type; 2237 | 2238 | /* opcodes for peg vm */ 2239 | typedef enum { 2240 | RULE_LITERAL, /* [len, bytes...] */ 2241 | RULE_NCHAR, /* [n] */ 2242 | RULE_NOTNCHAR, /* [n] */ 2243 | RULE_RANGE, /* [lo | hi << 16 (1 word)] */ 2244 | RULE_SET, /* [bitmap (8 words)] */ 2245 | RULE_LOOK, /* [offset, rule] */ 2246 | RULE_CHOICE, /* [len, rules...] */ 2247 | RULE_SEQUENCE, /* [len, rules...] */ 2248 | RULE_IF, /* [rule_a, rule_b (b if a)] */ 2249 | RULE_IFNOT, /* [rule_a, rule_b (b if not a)] */ 2250 | RULE_NOT, /* [rule] */ 2251 | RULE_BETWEEN, /* [lo, hi, rule] */ 2252 | RULE_GETTAG, /* [searchtag, tag] */ 2253 | RULE_CAPTURE, /* [rule, tag] */ 2254 | RULE_POSITION, /* [tag] */ 2255 | RULE_ARGUMENT, /* [argument-index, tag] */ 2256 | RULE_CONSTANT, /* [constant, tag] */ 2257 | RULE_ACCUMULATE, /* [rule, tag] */ 2258 | RULE_GROUP, /* [rule, tag] */ 2259 | RULE_REPLACE, /* [rule, constant, tag] */ 2260 | RULE_MATCHTIME, /* [rule, constant, tag] */ 2261 | RULE_ERROR, /* [rule] */ 2262 | RULE_DROP, /* [rule] */ 2263 | RULE_BACKMATCH, /* [tag] */ 2264 | RULE_TO, /* [rule] */ 2265 | RULE_THRU, /* [rule] */ 2266 | RULE_LENPREFIX, /* [rule_a, rule_b (repeat rule_b rule_a times)] */ 2267 | RULE_READINT, /* [(signedness << 4) | (endianness << 5) | bytewidth, tag] */ 2268 | RULE_LINE, /* [tag] */ 2269 | RULE_COLUMN, /* [tag] */ 2270 | RULE_UNREF, /* [rule, tag] */ 2271 | RULE_CAPTURE_NUM, /* [rule, tag] */ 2272 | RULE_SUB, /* [rule, rule] */ 2273 | RULE_TIL, /* [rule, rule] */ 2274 | RULE_SPLIT, /* [rule, rule] */ 2275 | RULE_NTH, /* [nth, rule, tag] */ 2276 | RULE_ONLY_TAGS, /* [rule] */ 2277 | } JanetPegOpcod; 2278 | 2279 | typedef struct { 2280 | uint32_t *bytecode; 2281 | Janet *constants; 2282 | size_t bytecode_len; 2283 | uint32_t num_constants; 2284 | int has_backref; 2285 | } JanetPeg; 2286 | 2287 | #endif 2288 | 2289 | #ifdef JANET_INT_TYPES 2290 | 2291 | extern JANET_API const JanetAbstractType janet_s64_type; 2292 | extern JANET_API const JanetAbstractType janet_u64_type; 2293 | 2294 | typedef enum { 2295 | JANET_INT_NONE, 2296 | JANET_INT_S64, 2297 | JANET_INT_U64 2298 | } JanetIntType; 2299 | 2300 | JANET_API JanetIntType janet_is_int(Janet x); 2301 | JANET_API Janet janet_wrap_s64(int64_t x); 2302 | JANET_API Janet janet_wrap_u64(uint64_t x); 2303 | JANET_API int64_t janet_unwrap_s64(Janet x); 2304 | JANET_API uint64_t janet_unwrap_u64(Janet x); 2305 | JANET_API int janet_scan_int64(const uint8_t *str, int32_t len, int64_t *out); 2306 | JANET_API int janet_scan_uint64(const uint8_t *str, int32_t len, uint64_t *out); 2307 | 2308 | #endif 2309 | 2310 | /* Custom allocator support */ 2311 | JANET_API void *(janet_malloc)(size_t); 2312 | JANET_API void *(janet_realloc)(void *, size_t); 2313 | JANET_API void *(janet_calloc)(size_t, size_t); 2314 | JANET_API void (janet_free)(void *); 2315 | #ifndef janet_malloc 2316 | #define janet_malloc(X) malloc((X)) 2317 | #endif 2318 | #ifndef janet_realloc 2319 | #define janet_realloc(X, Y) realloc((X), (Y)) 2320 | #endif 2321 | #ifndef janet_calloc 2322 | #define janet_calloc(X, Y) calloc((X), (Y)) 2323 | #endif 2324 | #ifndef janet_free 2325 | #define janet_free(X) free((X)) 2326 | #endif 2327 | 2328 | /***** END SECTION MAIN *****/ 2329 | 2330 | /* Re-enable popped variable length array warnings */ 2331 | #ifdef _MSC_VER 2332 | #pragma warning( pop ) 2333 | #endif 2334 | 2335 | #ifdef __cplusplus 2336 | } 2337 | #endif 2338 | 2339 | #endif /* JANET_H_defined */ 2340 | --------------------------------------------------------------------------------