[HN Gopher] WASM Instructions
       ___________________________________________________________________
        
       WASM Instructions
        
       Author : peter_d_sherman
       Score  : 102 points
       Date   : 2024-02-18 13:44 UTC (9 hours ago)
        
 (HTM) web link (webassembly.github.io)
 (TXT) w3m dump (webassembly.github.io)
        
       | andrea81 wrote:
       | Is there a way to download the BNF as a single file so I can
       | parse it?
        
         | marianoguerra wrote:
         | You can parse many things from this file, what are you trying
         | to extract?
         | 
         | https://github.com/WebAssembly/spec/blob/main/document/core/...
        
         | UncleEntity wrote:
         | The grammar doesn't get you too far since the WASM is designed
         | around a binary format. Plus they do some weird stuff around
         | the names of the operators which has to be dealt with.
         | 
         | That being said...https://pastebin.com/mhtgjSjZ
        
       | pwdisswordfishc wrote:
       | > MathJax internal buffer size exceeded; is there a recursive
       | macro call?
       | 
       | That is so informative.
       | 
       | Seriously though, wouldn't one expect the authors of this spec to
       | be experts on web technologies who eat their own dog food (of web
       | standards) instead of relying on a pale imitation of a dated
       | typesetting technology like TeX?
        
         | diggan wrote:
         | Rather than jumping to conclusions, maybe a more favorable
         | position would be to try to look into what's happening, before
         | judging what others are doing/not doing?
         | 
         | FWIW, it works perfectly fine for me on Linux with both Chrome
         | and Firefox, so I'd say probably something is wonky in your
         | environment, or a temporary issue on the website.
        
           | burke wrote:
           | Even when it works (I've never seen this failure), this site
           | is offensively unusable. Anchors don't go to useful places;
           | search doesn't work in the MathJax regions... the writing
           | also does a fairly poor job of communicating details in many
           | cases.
           | 
           | It's really a truly terrible spec site.
        
         | mike_hock wrote:
         | > dated typesetting technology like TeX
         | 
         | You seem to be confusing "mature" with "dated."
        
           | pwdisswordfishc wrote:
           | No, I am not. TeX, by itself, really shows its age, and how
           | it was built as a "a faster horse" rather than hypertext's
           | automobile:
           | 
           | - despite the window dressing of LaTeX, it is ultimately
           | presentation-oriented instead of structure-oriented; many
           | widely-used forms of formatting markup rely on precise
           | character dimensions and positioning; changing page
           | dimensions may sometimes require fixes throughout the whole
           | document
           | 
           | - bad character set support: things like \mathcal{3} displays
           | the wrong character WITH ZERO WARNING: see
           | https://tex.stackexchange.com/q/84041/ and duplicates
           | 
           | - parsing is undecidable; the parser can be arbitrarily
           | reconfigured at runtime, and can perform Turing-complete
           | computations, which means processing arbitrary TeX code in
           | any other way than to execute it as written is next to
           | impossible; even a 100% correct syntax highlighter is
           | unachievable
           | 
           | MathJax fixes or ameliorates some of these flaws, but in
           | trying to be compatible with TeX, it cannot avoid all of
           | them; and in the meantime, it imposes its own syntax quirks
           | and burdens the client with running bloated JavaScript,
           | incurs significant pop-in latency, and leaves indecipherable
           | mess of TeX code to clients which do not run JS. TeX is just
           | PDF that's easier to edit, and MathJax is the Cufon of math
           | markup. (Remember Cufon? Be thankful if you don't. Good
           | riddance!)
        
             | pests wrote:
             | What is the relevance for the stack exchange post? User was
             | using \cal, they told him to use \mathcal. Or is it an
             | issue still or?
        
         | RodgerTheGreat wrote:
         | On the contrary: static documentation rendered via complex
         | client-side code, producing _seconds_ of visible pop-in and an
         | atrocious user experience is entirely in line with the ethos of
         | people who thought the web needed a more developer-convenient
         | way of dumping huge opaque blobs of cross-compiled code into
         | pages.
        
           | pwdisswordfishc wrote:
           | Point taken, I should have realized.
        
           | pests wrote:
           | Why create the document once on the server, when you can have
           | your users generate it on-demand, on their device, every time
           | they load the page! Imagine the cost savings.
        
         | marwis wrote:
         | Strange choice to use MathJax when much better alternatives
         | exist like KaTeX
        
       | peter_d_sherman wrote:
       | Related:
       | 
       | "A fast Pascal (Delphi) WebAssembly interpreter":
       | 
       | https://github.com/marat1961/wasm
       | 
       | "WASM-4":
       | 
       | https://github.com/aduros/wasm4
       | 
       | "Curated list of awesome things regarding WebAssembly (wasm)
       | ecosystem":
       | 
       | https://github.com/mbasso/awesome-wasm
       | 
       | Google Chromium/Chrome V8 (JavaScript Engine) WASM Source Code
       | branch:
       | 
       | https://github.com/v8/v8/tree/main/src/wasm
       | 
       | Also... it would be nice if there was a WASM software/soft CPU
       | for QEMU, which (if it existed!) would go here:
       | 
       | https://github.com/qemu/qemu/tree/master/target
        
         | GuestHNUser wrote:
         | Orca is also worth checking out. Still in development, but very
         | usable.
         | 
         | https://github.com/orca-app/orca
        
           | peter_d_sherman wrote:
           | Excellent link!
           | 
           | I was looking for something _exactly like that(!)_ to test
           | running off-line (and out of the web browser) WASM code
           | locally!
           | 
           | Thanks extremely much!
        
       | pxmpxm wrote:
       | I still entirely don't understand the point of web assembly - at
       | best isn't it a pretend emulation layer?
       | 
       | You have to have some sort translation layer/virtual machine
       | consuming the fake assembly and spitting out the real hardware
       | assembly... which begs the question of why is that better than
       | mapping stuff into intrinsics.
       | 
       | So far the only use case I can gather is obfuscation for content
       | management a la tiktok, where as the people behind WASM seem to
       | be going with the "super ~native performance" marketing angle.
        
         | azangru wrote:
         | - Adobe has a C-based codebase of Photoshop developed over
         | decades for the desktop app         - Adobe wants to bring
         | Photoshop to the web for easier distribution and tighter
         | control         - Adobe engineers compile the existing C-based
         | codebase to webassembly instead of rewriting it from scratch in
         | javascript         - Photoshop for the Web is born         -
         | ...         - Profit?
        
           | pxmpxm wrote:
           | That's great for the actual meat and potatoes, but like half
           | of the codebase will be tied to whatever UX libraries (MFC on
           | windows / Cocoa in osx) that won't port over. So you will be
           | rewriting most of it in java script anyway?
           | 
           | That argument feels a bit academic.
        
             | whizzter wrote:
             | Partially, much of what makes Photoshop photoshop that
             | clones can't replicate is the actual image
             | manipulations,layer adjustments,etc that needs to be
             | carrier over 1:1 or people will just be annoyed that it's
             | not exactly right.
             | 
             | Also Asm.JS (Wasm's predecessor) was born to port GAMES,
             | games often have their own GL,etc UI's that they render
             | themselves and then tons upon tons of gameplay logic code
             | that runs in C/C++ (or whatever scripting language the
             | engine supports like C#).
             | 
             | That was the most important part initially, even if people
             | on the outside are starting to benefit like the Figma folks
             | that uses Wasm, kinda like GPU's were for gaming and now
             | power a ton of modern UI and AI workloads.
        
             | macNchz wrote:
             | Applications like Photoshop typically have fully custom UI
             | frameworks that are not tightly tied to the OS, so porting
             | to run in a browser is less about rewriting the entire UI
             | to work with html elements, and more about writing a
             | renderer for the UI kit that can draw it to a canvas.
             | 
             | If you're not writing a fully custom UI, you might choose
             | something like Qt, which has wasm built in:
             | https://www.qt.io/web-assembly-example-
             | slate?hsCtaTracking=3...
        
               | spankalee wrote:
               | Photoshop for the Web's UI is built with Lit.
        
             | flohofwoe wrote:
             | Here are a couple of real-world examples, these are all
             | written in C and some C++ and run across Linux, macOS,
             | Windows, iOS, Android and in browsers from the same code,
             | the web is basically "just another target platform":
             | 
             | Home computer emulators:
             | 
             | https://floooh.github.io/tiny8bit/
             | 
             | CPU simulators for Z80 and 6502 (based on the netlists from
             | visual6502.org):
             | 
             | https://floooh.github.io/visualz80remix/
             | 
             | https://floooh.github.io/visual6502remix/
             | 
             | The shareware version of Doom:
             | 
             | https://floooh.github.io/doom-sokol/
             | 
             | A Pacman clone in C:
             | 
             | https://floooh.github.io/pacman.c/pacman.html
             | 
             | ...and the same in Zig:
             | 
             | https://floooh.github.io/pacman.zig/pacman.html
             | 
             | This is all relatively small hobby stuff written just by
             | me, but there's nothing that would prevent scaling to
             | bigger projects.
             | 
             | Finally here are the examples for the cross-platform
             | libraries this stuff is built on top:
             | 
             | https://floooh.github.io/sokol-html5/
             | 
             | Also specifically about Photoshop: since PS is already a
             | cross-platform application I would expect that they
             | abstracted their UI layer enough to be portable to other UI
             | frameworks without too much hassle. Hybrid WASM/JS
             | applications are in fact a pretty good idea for some use
             | cases (e.g. compile the core logic written in
             | C/C++/Rust/Zig... to WASM, but implement the UI layer via
             | HTML+CSS).
        
               | DonHopkins wrote:
               | Here's something I'm working on right this moment, using
               | ChatGPT to help generate emscripten embind wrappers for
               | the MicropolisCore MicropolisEngine (based on the
               | original SimCity game). The idea is to be able to make
               | plugin zones and robots (like the monster or tornado or
               | train) by subclassing with JavaScript!
               | 
               | https://github.com/SimHacker/MicropolisCore/blob/main/src
               | /Mi...                 //////////////////////////////////
               | //////////////////////////////////////       // This file
               | uses emscripten's embind to bind C++ classes,       // C
               | structures, functions, enums, and contents into
               | JavaScript,       // so you can even subclass C++ classes
               | in JavaScript,       // for implementing plugins and user
               | interfaces.       //       // Wrapping the entire
               | Micropolis class from the Micropolis (open-source
               | // version of SimCity) code into Emscripten for
               | JavaScript access is a       // large and complex task,
               | mainly due to the size and complexity of the       //
               | class. The class encompasses almost every aspect of the
               | simulation,       // including map generation, simulation
               | logic, user interface       // interactions, and more.
               | //       // Strategy for Wrapping       //        // 1.
               | Core Simulation Logic: Focus on the core simulation
               | aspects, such       //    as the methods to run the
               | simulation, update game states, and handle       //
               | user inputs (like building tools and disaster
               | simulations). This is       //    crucial for any
               | gameplay functionality.       //        // 2. Memory and
               | Performance Considerations: JavaScript and WebAssembly
               | //    run in a browser context, which can have memory
               | limitations and       //    performance constraints.
               | Carefully manage memory allocation,       //
               | especially when dealing with the game's map and various
               | buffers.       //        // 3. Direct Memory Access:
               | Provide JavaScript access to critical game       //
               | data structures like the map buffer for efficient reading
               | and       //    writing. This can be done using
               | Emscripten's heap access functions       //    (HEAP8,
               | HEAP16, HEAP32, etc.).       //        // 4. User
               | Interface and Rendering: This part might not be necessary
               | to       //    wrap, as modern web technologies (HTML,
               | CSS, WebGL) can be used for       //    UI. However,
               | providing some hooks for game state (like score, budget,
               | //    etc.) to JavaScript might be helpful.       //
               | // 5. Callbacks and Interactivity: Ensure that key game
               | events and       //    callbacks are exposed to
               | JavaScript, allowing for interactive and       //
               | responsive gameplay.       //        // 6. Optimizations:
               | Where possible, optimize C++ code for WebAssembly,
               | //    focusing on critical paths in the simulation loop.
               | //        // Decisions and Explanations       //       //
               | - Excluded Elements:       //              //     - Low-
               | level rendering or platform-specific code, as this can be
               | //       handled more efficiently with web technologies.
               | //              //     - Parts of the code that handle
               | file I/O directly, as file access       //       in a web
               | context is typically handled differently (e.g., using
               | //       browser APIs or server-side support).       //
               | //     - Any networking or multiplayer code, as web-based
               | //       implementations would differ significantly from
               | desktop-based       //       network code.       //
               | // - Included Elements:       //              //     -
               | Core game mechanics, such as map generation, zone
               | simulation       //       (residential, commercial,
               | industrial), disaster simulation, and       //
               | basic utilities.       //              //     - Game
               | state management, including budgeting, scoring, and city
               | //       evaluation.       //              //     -
               | Direct memory access to critical structures like the map
               | //       buffer, allowing efficient manipulation from
               | JavaScript.       //        //     - Essential callbacks
               | and event handling mechanisms to ensure       //
               | interactivity.       //       // Conclusion       //
               | // Given the complexity and size of the Micropolis class,
               | wrapping the       // entire class directly is
               | impractical. However, focusing on key areas       //
               | essential for gameplay and providing efficient interfaces
               | for       // critical data structures can create a
               | functional and interactive city       // simulation in a
               | web context. Further optimizations and adjustments
               | // would likely be needed based on testing and specific
               | requirements of       // the web implementation.
        
             | krona wrote:
             | Dunno, seems to have worked well for Figma.
        
         | grishka wrote:
         | It's a replacement for Flash's bytecode VM. Supposedly.
        
         | pdpi wrote:
         | It's significantly faster than JS, but still has a solid
         | security model that makes it appropriate for contexts where
         | you're running untrusted code. More or less like a lower-level
         | JVM.
        
         | cornstalks wrote:
         | Outside of the web, Wasm is useful anywhere that you might use
         | a scripting language embedded in a program. For example, Lua
         | with game engines. You could replace the scripting layer (e.g.,
         | Lua) with Wasm. Some might see this as pointless, but others,
         | like myself, see this as an opportunity to do some cool things.
         | Some things I'm excited for are (1) wasm-c-api, which creates a
         | VM-agnostic API so I can swap out VM implementations without
         | recoding my app; (2) great performance, since there are many
         | Wasm VMs that are heavily optimized for both quick startup and
         | maximum speed; (3) the ability to use many languages, which
         | means I can use a consistent language for the main game and the
         | scripting files.
        
           | rockwotj wrote:
           | I think the wasm C API is not going to live up to the
           | promise. To actually use high performance features you need
           | many additions to that API that most implementations provide,
           | thus making it less portable.
           | 
           | Source: I contribute a lot to wasmtime's C API and build
           | Redpanda's Wasm Data Transforms using it
        
             | cornstalks wrote:
             | Yeah and wasm-c-api has stalled (they still don't support
             | v128, for example). I'm currently exploring starting an
             | unsanctioned v2 wasm-c-api that aims to be feature complete
             | and hopefully more performance focused.
        
               | rockwotj wrote:
               | Would be super interested in this if you explore this
               | more! Feel free to reach out (contact info linked from my
               | bio) if you're interested in collaborating.
        
             | kelp wrote:
             | I'd been hoping projects like wasmtime could end up looking
             | like a Docker alternative for server side things. Do you
             | think that's unlikely to pan out without a lot more work
             | that doesn't seem to be happening?
        
               | rockwotj wrote:
               | Oh it's certainly looking like that IMO depending on your
               | use case for docker
               | 
               | You can run wasm in k8s: https://krustlet.dev/
               | 
               | Docker itself can run wasm:
               | https://wasmlabs.dev/articles/docker-without-containers/
               | 
               | There are a few serverless runtimes based on wasm:
               | https://wasmcloud.com/
               | 
               | A lot of those are powered by wasmtime or WasmEdge.
               | 
               | If you're wanting to be able to just pull down a random
               | app and run it as wasm, that's inherently harder with
               | wasm, because you have to recompile, and amazing
               | compiling stuff is always harder than it should be. For
               | example I compiled jq to wasm to other day, so you dont
               | have to worry (as much) about the CVEs that was issued
               | recently. https://github.com/rockwotj/jq-wasi
        
         | apignotti wrote:
         | The point is to have a more efficient solution to deploy large
         | scale Web applications. Efficiency here is measured in
         | comparison to JavaScript, and it's based on 3 main points
         | 1. More compact representation due to binary encoding compared
         | to text            2. Improved compilation times, since
         | WebAssembly is "lower-level" compared to JS and the engines can
         | assume code has been already optimized and can skip a good
         | chunk of the normal JIT optimization pipeline.            3.
         | Improved runtime performance due to strict typing. No type-
         | checks, no bailouts, etc
         | 
         | These come with their set of drawbacks, the main one being that
         | WebAssembly cannot _really_ use the DOM or interact with
         | JavaScript directly and is effectively just a computational
         | engine. Any interaction with the outside word is abstracted to
         | "imports": calls with arbitrary semantics come from outside of
         | WebAssembly.
         | 
         | At some point WebAssembly also had the advantage of predictable
         | performance, with the idea being that code would be compiled
         | once-and-for-all during module loading.
         | 
         | This promise was, as far as I understand, effectively abandoned
         | first by the introduction of "Baseline" compilers (Liftoff, in
         | V8 terminology) and in more recent times by the requirement of
         | WasmGC, which (I think) has reintroduced the need for bailouts
         | and dynamic recompilation.
        
           | azakai wrote:
           | I wouldn't say that predictable performance was abandoned,
           | but you are right that it is less of a strict guarantee these
           | days:
           | 
           | 1. Baseline compilers are generally 2x slower than optimizing
           | ones. That's noticeable, but it is still a far smaller
           | difference than JS has between its tiers.
           | 
           | 2. Even WasmGC doesn't require bailouts - in fact no VM
           | implements them for Wasm AFAIK. However WasmGC is often
           | compiled by languages that do benefit significantly from
           | dynamic inlining, which adds unpredictability, but again the
           | effect (30% [0]) is far smaller than typical differences in
           | JS.
           | 
           | [0] https://v8.dev/blog/wasm-gc-porting
        
           | UncleEntity wrote:
           | > This promise was, as far as I understand, effectively
           | abandoned first by the introduction of "Baseline" compilers
           | (Liftoff, in V8 terminology)...
           | 
           | This, I don't understand...
           | 
           | AFAICT the "baseline" compiler's entire job is to get pixels
           | on the screen as fast as possible and then they use
           | optimization strategies to recompile code sections or
           | functions or whatever to speed it up based on $reasons.
        
           | endorphine wrote:
           | Is lack of GC another reason that wasm is more performant
           | than JS?
           | 
           | P.S. I assume JS has a GC and WASM does not.
        
             | pjmlp wrote:
             | WASM now has GC support as well,
             | https://developer.chrome.com/blog/wasmgc
        
             | daxfohl wrote:
             | Not really. Sure it adds some overhead but it's well
             | optimized and not overly significant, especially for
             | incremental collections. It can even pay for itself by
             | defragging your memory, making subsequent allocations
             | cheaper. The big problem with GC is the pauses it causes
             | when doing full "stop the world" collections, which can be
             | noticeable in animations, or even on server-side in high-
             | volume latency-sensitive services. But there are strategies
             | you can use to reduce or eliminate the need for those if
             | you're willing to put in the effort (beyond the scope of
             | this comment).
             | 
             | Note that pauses _can_ happen in non-GC languages too, if
             | you have to delete something that references a bunch of
             | other stuff that you have to recursively delete as well,
             | though in the real world this is not very common.
        
             | crq-yml wrote:
             | GC changes the performance profile of allocations,
             | specifically. If your code is written to use static memory
             | you won't experience GC pauses, but languages like JS that
             | employ GC intentionally steer you towards allocating to do,
             | e.g. string processing, so you have to go out of your way
             | to make JS fast in this way.
             | 
             | WASM now has GC, since a goal is to support alternative
             | scripting environments and e.g. run a mixture of Rust and
             | Python code in the browser.
        
         | jedisct1 wrote:
         | Among other things, WebAssembly is very useful for
         | decentralized apps. Check out zkWASM and CosmWasm.
        
         | flohofwoe wrote:
         | It's just the name that's confusing. It has nothing to do with
         | assembly code, and it doesn't require the web. It's just
         | another instruction set for a virtual machine which can be
         | distributed in a CPU-agnostic format and compiled to native CPU
         | instructions on the user's machine (much like JVM, .NET or
         | Flash).
        
         | xipix wrote:
         | Quite simply: it lets you build portable apps with near-native
         | performance. Same source for both your desktop browser and your
         | phone. I really love using it to make audio apps like this one:
         | https://bungee.parabolaresearch.com/bungee-web-demo, also it's
         | great for other real time rendering / visualisation in the
         | browser.
        
         | paulddraper wrote:
         | > emulation layer
         | 
         | Absolutely. E.g. JVM byte code
         | 
         | > why is that better
         | 
         | Portability and sandboxing
        
       | marianoguerra wrote:
       | If you are interested in learning about wasm instructions you may
       | like https://wasmgroundup.com/
       | 
       | > This book takes a hands-on, bottoms-up approach: you'll go from
       | hand crafting bytecodes to writing a real compiler for a simple
       | programming language.
       | 
       | disclaimer: I'm the co-author
        
         | emnudge wrote:
         | If we're doing self promo, I've got something similar but
         | significantly smaller in scope:
         | 
         | https://github.com/EmNudge/watlings
        
           | marianoguerra wrote:
           | Let's keep it going :D
           | 
           | Writing a Minimum Viable Cartridge for WASM4
           | (https://wasm4.org/) using WAT:
           | 
           | https://twitter.com/warianoguerra/status/1748382204508410149
           | 
           | Wasm compilers in a tweet:
           | 
           | https://twitter.com/warianoguerra/status/1576166873296941056
           | 
           | A WebAssembly compiler for a reverse polish notation
           | calculator in 269 bytes of JavaScript:
           | 
           | https://twitter.com/warianoguerra/status/1677271664009138177
        
         | milliams wrote:
         | Look interesting.
         | 
         | From the linked page.
         | 
         | > This book takes a hands-on, bottoms-up approach
         | 
         | I think you mean "bottom-up". "bottoms-up" is a toast.
        
       | ghusbands wrote:
       | The use of MathJax for simple layouts that would easily work as
       | HTML makes things a lot less usable for screen readers, for link
       | behaviour, and for find-in-page.
        
         | 01HNNWZ0MV43FF wrote:
         | Yeah it's not gracefully degrading. I have JS disabled by
         | default and it's just sigil spam.
         | 
         | Couldn't they have an option like alt text where it shows
         | something less pretty but useful before JS is on?
        
           | beeboobaa wrote:
           | Disabling standard features of your webbrowser leads to a
           | degraded experience. Who could have seen that coming?
        
       | gumby wrote:
       | Are jumps unrestricted or block only? ISTR in the first draft of
       | WASM it was impossible to write continuation-passing code,
       | coroutines, or even tail call.
        
         | cornstalks wrote:
         | Block only. There's a tail call proposal[1] that's in phase 4
         | (nearly standardized).
         | 
         | [1]: https://github.com/WebAssembly/proposals
        
           | azakai wrote:
           | Note that phase 4 is the final stage of the standard process.
           | Tail calls are at phase 4, which means that is a finalized
           | and complete standard.
           | 
           | All that is left after that is for VMs to implement the
           | standard, which is tracked here:
           | 
           | https://webassembly.org/features/
           | 
           | Most major VMs do support tail calls today, but not all.
        
             | sestep wrote:
             | Also note that that webpage can be somewhat out of date;
             | for instance, see here for some recent edits to it (e.g.
             | features Node had implemented that were marked as
             | unavailable):
             | https://github.com/WebAssembly/website/commits/main/
        
         | marianoguerra wrote:
         | There's a proposal for effect handlers that allows for
         | continuatios, coroutines and others.
         | 
         | > effect handlers as a unifying mechanism to enable efficient
         | compilation of control idioms, such as async/await,
         | generators/iterators, first-class continuations, etc.
         | 
         | https://wasmfx.dev/
        
           | gumby wrote:
           | So a coroutine would be a "stack" one frame deep?
        
             | marianoguerra wrote:
             | Here's a good explanation:
             | https://github.com/WebAssembly/stack-
             | switching/blob/main/pro...
        
       | sestep wrote:
       | Note that this page doesn't currently include instructions from
       | WasmGC which is starting to become supported in some engines;
       | that spec can be found here:
       | https://webassembly.github.io/gc/core/syntax/instructions.ht...
        
         | marianoguerra wrote:
         | For a full list of proposals you can check
         | https://github.com/WebAssembly/proposals
        
       | ilaksh wrote:
       | One thing I didn't realize for awhile is that it's not actually
       | an assembly language. At least not in a traditional way. Because
       | it is high level, with things like loop and if-else, etc.
       | 
       | I assume it was initially intended to be more like a "real"
       | assembly language but then they realized how much more optimized
       | things could be if they went with higher level constructs.
        
       ___________________________________________________________________
       (page generated 2024-02-18 23:00 UTC)