Up to Main Index                            Up to Journal for August, 2022

                    JOURNAL FOR SATURDAY 20TH AUGUST, 2022
______________________________________________________________________________

SUBJECT: A mere update
   DATE: Sat 20 Aug 18:45:18 BST 2022

For the last few weeks I had been rather quiet. Then I pop up again, without
any warning, and chuck out a new WolfMUD release! From the large spike in
server traffic I assume people really wanted the combat update :) I can only
assume that the distant shouting and clanging of pitchforks is due to foes
being enthusiastically pummelled and not a mob coming after me :D

My absence was due to a number of things. I was working on my own programming
language Mere. At the same time I had to prepare to give a presentation on
Mere. For the presentation I embedded Mere into some web-assembly (WASM) and
created a live interactive coding environment in Chrome for presenting,
running demos and live coding.

Presentation was last Friday at the weekly company meeting. I think it went
okay, there were a few questions asked at the end… that’s good isn’t it?

While working on Mere, the Go team released Go 1.19. It was billed as having:
“important performance improvements (up to 20% for some generic programs)”.

I’d been doing a lot of benchmarking with Mere and so compared Mere compiled
with Go 1.18.4 and Go 1.19:


      >benchstat bench_1.18.4.txt bench_1.19.0.txt
      name        old time/op    new time/op    delta
      Tokenize-4     960ns ± 4%     948ns ± 1%     ~     (p=0.690 n=5+5)
      Compile-4     10.7µs ± 2%    10.7µs ± 3%     ~     (p=0.690 n=5+5)
      Execute-4      332µs ± 1%     367µs ± 2%  +10.48%  (p=0.008 n=5+5)
      Run-4          347µs ± 1%     382µs ± 1%  +10.08%  (p=0.008 n=5+5)

      name        old alloc/op   new alloc/op   delta
      Tokenize-4      232B ± 0%      232B ± 0%     ~     (all equal)
      Compile-4     3.03kB ± 0%    3.03kB ± 0%     ~     (all equal)
      Execute-4     12.0kB ± 0%    12.0kB ± 0%     ~     (all equal)
      Run-4         15.3kB ± 0%    15.3kB ± 0%     ~     (p=0.333 n=5+4)

      name        old allocs/op  new allocs/op  delta
      Tokenize-4      5.00 ± 0%      5.00 ± 0%     ~     (all equal)
      Compile-4       79.0 ± 0%      79.0 ± 0%     ~     (all equal)
      Execute-4      1.49k ± 0%     1.49k ± 0%     ~     (all equal)
      Run-4          1.57k ± 0%     1.57k ± 0%     ~     (all equal)
      >


Hrm, 10% slower is not an improvement ;( I’m still digging and trying to find
out what’s gone on there.

Mere has gained a lot of functionality. The code for the compiler and executer
are still ugly, but its warts are all my own :) Do I have a nice example of a
Mere program I can show? I was working on implementing type conversions before
writing this and whipped up this little ditty for some testing:


    # A mere poor man's Pi rounding...

    mult:float
    π:float = 22.0 ÷ 7.0

    scale:int = 0
    loop:
      mult = float ( "1e" + string scale )
      println float ( int ( π × mult ) ) ÷ mult
      if scale ++ < 10; goto loop


The code takes an approximation of Pi, multiplies[1] it to shift the decimal
point right, converts it to an int to truncate it, converts it back to a float
and divides to shift the decimal back again. Running the above gives:


    >mere roundPi
    3
    3.1
    3.14
    3.142
    3.1428
    3.14285
    3.142857
    3.1428571
    3.14285714
    3.142857142
    >


The program is horribly inefficient, but still quite quick at 83μs. Mere only
has IF/GOTO and labels implemented for control flow at the moment, programs
tend to look like assembler with JMPs all over the place :|

Actually I lie. I’m writing this on and off and just took a break to implement
subroutines with GOSUB and RETURN. A little ditty for testing GOSUB/RETURN:


    # A mere convoluted hello world...

    greet:string = ""
    gosub hello
    println greet
    exit 0

    hello:
      greet += "Hello"
      gosub comma
    return

    comma:
      greet += ", "
      gosub world
      gosub shreak
    return

    world:
      greet += "世界 "
    return

    shreak:
      greet += "!"
      if greet [ ( len greet ) - 3 ] <> "!"; gosub shreak
    return


The subroutine[2] shreak is even recursive ;) Running this produces:


    >mere gosub
    Hello, 世界 !!!
    >


What are some of the other nice features of Mere?

When embedding Mere, only a single compiled image of a program resides in
memory. Lightweight copies can then be executed, only allocating heap space
for variables and a call stack for subroutines. The compiled images can be
reduced in size further by stripping out the symbol table. In case of a
mishap, for example an infinite loop, programs can be terminated after a set
number of instructions have been executed[3]. A limit can also be set on the
size of the call stack. The embedded WASM environment makes use of these
features, otherwise an infinite loop or infinite recursion could lock-up the
browser tab.

This is all useful for embedding Mere into web servers and WolfMUD servers ;)

Finally, a screenshot of the “poor man’s Pi rounding” code running in the live
interactive coding environment: mere-wasm.jpg.

Mere is embedded in Go compiled to WASM with a little HTML, CSS & Javascript.
You edit code on the left, or select an example from the drop down at the top.
Run the code and output appears on the right hand side. The divider down the
middle can be moved left and right to resize the two areas. Accelerator keys
have been setup: Alt-A to select the drop down, Alt-O to select source window,
Alt-R to run the program. This enabled me to drive the environment quickly
when presenting. The top right corner also shows viewers the current key being
pressed.

Once the language is in better shape and documented then everything, including
the coding environment, will be made available. I may host the environment on
this site before releasing so that people can have a play and provide comments
and feedback — but it’s still early days.

--
Diddymus

  [1] In Vim entering ‘×’ and ‘÷’ is as easy as Alt+Shift+W and Alt+W. You can
      also use the digraphs ‘*X’ and ‘-:’ instead. The more conventional ‘*’
      and ‘/’ can also be used. I just like my code looking nice ;)

  [2] Wow! It’s been years since I’ve used actual subroutines :) At the moment
      they are simpler to implement than user defined functions.

  [3] When running programs in command line mode there is no instruction or
      call stack limit, you can hit Ctrl-C to terminate a rouge program. You
      can still set either limit in code if you want.


  Up to Main Index                            Up to Journal for August, 2022