Easy WASM with Nim / nlvm

2019-04-10 Thread arnetheduck
Here's a little mini-tutorial on using the latest WASM support in nlvm to call 
a Nim function from a web page - it's actually surprisingly easy :)

WASM is a simple IR / instruction format that comes with a virtual machine 
specification, similar - well - to any other virtual machine out there. What's 
particular about it is that it enjoys broad browser support, giving developers 
an easy way to deploy high-performance code. It can also be used standalone - 
using Wasmer ([https://wasmer.io/](https://wasmer.io/)) for example.

Let's start with a function we want to use from the web:


proc fib2(term, val, prev: int): int =
 if term == 0: prev
 else: fib2(term - 1, val + prev, val)

proc fib(term: int): int {.exportc.} = fib2(term, 1, 0)



Run

WASM works by compiling code to a binary format, a `.wasm` file. This file is 
loaded in the browser, and the code therein can be accessed as if it were 
JavaScript.

Compiling to WASM can be done in many ways - a popular way until now has been 
to compile to C, then use either Emscripten or clang to compile to WASM, 
sometimes with the help of tooling from the Binaryen project.

Recently, I threw in LLVM v8 support in nlvm which comes with a library for 
linking - lld. In the future, this library will be used to make nlvm completely 
standalone - no gcc or msvc needed - but for now, only WASM is enabled. Linking 
in the C world is surprisingly onerous and full of thorny legacy / 
compatibility issues.

Fortunately, compiling fib to wasm is a simple single-step process:


nlvm c -d:release --nlvm.target=wasm32 --gc:none -l:--no-entry fib


Run

wasm32 mode in nlvm implies `--os:standalone` \- the normal `C` functions like 
`printf` are not available here. Depending on where the wasm code runs, it will 
have a sandboxed environment available, such as the browser or WASI - but 
accessing this will require a little bit more work on both the nlvm and Nim 
standard library sides.

`--os:standalone` means that a panicoverride file is needed for the Nim 
standard library - we'll start with a bare-bones version of it - name it 
panicoverride.nim and drop it next to fib.nim:


proc rawoutput(s: string) = discard
proc panic(s: string) = rawoutput(s)


Run

The final piece of the puzzle is to load the wasm file in the browser:


http://www.w3.org/1999/xhtml;>

  Fib
  
//
  response.arrayBuffer()
  ).then(bytes =>
  WebAssembly.instantiate(bytes)
  ).then(obj => {
  document.getElementById("btn").addEventListener("click", function() {
  document.getElementById("here").textContent = 
obj.instance.exports.fib(document.getElementById("x").value);
  }, false);
  });
  //]]>
  



  
 
  
  
  Answer:
  
  




Run

Type in 10, and hopefully you get 55 back - type in 50, and a surprise is 
waiting for you - bonus points if you can figure it out :) You can tell I 
stopped writing HTML when blink was still around.

Behind the scenes, nlvm will translate the Nim code to LLVM IR that looks like 
this: 


; ModuleID = 'fib'
source_filename = "fib"
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32"

@nim_program_result = local_unnamed_addr global i32 0

; Function Attrs: norecurse nounwind readnone
define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 {
secArgs:
  ret i32 0
}

; Function Attrs: nounwind readnone
define i32 @fib(i32 %n) local_unnamed_addr #1 {
secAlloca:
  switch i32 %n, label %ifx.false.fib.2.13 [
i32 0, label %ifx.end.fib.2.1
i32 1, label %ifx.true.fib.2.12
  ]

ifx.true.fib.2.12:; preds = %secAlloca
  br label %ifx.end.fib.2.1

ifx.false.fib.2.13:   ; preds = %secAlloca
  %binop.Sub.fib.4.12 = add i32 %n, -1
  %call.res.fib.4.10 = tail call i32 @fib(i32 %binop.Sub.fib.4.12)
  %binop.Sub.fib.4.24 = add i32 %n, -2
  %call.res.fib.4.21 = tail call i32 @fib(i32 %binop.Sub.fib.4.24)
  %binop.Add.fib.4.16 = add i32 %call.res.fib.4.21, %call.res.fib.4.10
  ret i32 %binop.Add.fib.4.16

ifx.end.fib.2.1:  ; preds = %secAlloca, 
%ifx.true.fib.2.12
  %ifx.res.fib.2.1.0 = phi i32 [ 1, %ifx.true.fib.2.12 ], [ %n, %secAlloca ]
  ret i32 %ifx.res.fib.2.1.0
}

attributes #0 = { norecurse nounwind readnone }
attributes #1 = { nounwind readnone "no-frame-pointer-elim"="true" }



Run

Notice how there's some cruft in there - a main function and the 
`nim_program_result` global. What's nice however is that `llvm` has been able 
to transform the recursive 

Re: Ebnf Lexer and Parser generator in nim

2019-04-10 Thread loloiccl
Add option and repeat in 
[https://github.com/loloiccl/nimly/pull/22](https://github.com/loloiccl/nimly/pull/22)


create lib*.so

2019-04-10 Thread Nimrookie
trying to link a library created in Nim to R

proc sumTillNegative(x: varargs[int]): int =


for i in x:


if i < 0:
return

result = result + i

proc sumTillNegative(): int {.cdecl, exportc, dynlib.}

# compiled with
nim c --app:lib test.nim

# in R x<-dyn.load("libtest.so") getDLLRegisteredRoutines(x) >data frame with 0 
columns and 0 rows

what went wrong? Thanks in advance!


Re: Why Nim so inconsistent?

2019-04-10 Thread yglukhov
Let me question Java/Go/Nim readability... What is more readable? 


addConstraint(x.plus(y).lessThanOrEqual(x.times(newConst(5).plus(z))


Run

or 


addConstraint(x + t <= x * (5 + z))


Run

I would say, if you want to write readable code nim gives you means to do so. 
If you want to write unreadable code, no language shall prevent you from doing 
that.


Re: nimpretty non installed by choosenim stable

2019-04-10 Thread SolitudeSF
or you could just clone the nim repo and build it yourself


Re: nimpretty non installed by choosenim stable

2019-04-10 Thread fstiffo
Then to install it have I only to wait next releases?


Re: Why Nim so inconsistent?

2019-04-10 Thread arnetheduck
> Human beings write code.

YMMV, but most devs I know read a lot more code than they write - their own and 
others' \- optimizing for human reading seems like a reasonable priority then, 
if you're trying to save time.. it compounds too - if a dev is able to read 
somebody else's code, they might not have to write any code at all :)


Printing Unicode characters (Runes) and UTF8 Strings

2019-04-10 Thread indiocolifa
Hi guys.

I'm trying to use the box-drawing characters of Unicode to draw some fancy 
dialogs at the terminal. I could do it without problems but I'm trying to find 
if there is a more "straightforward" form.

The codepoints are defined as:


type
DialogBorderRunes = enum
dbrHLine = 0x2500
dbrVLine = 0x2502
dbrTopLeft = 0x250C
dbrTopRight =0x2510
dbrBottomLeft = 0x2514
dbrBottomRight = 0x2518


Run

I can "draw"the top of the dialog with styledWrite in this manner:


setCursorPos(left, top)
stdout.styledWrite(bg, Rune(dbrTopLeft).toUTF8() &
Rune(dbrHLine).toUTF8().repeat(dlgWidth-2) &
Rune(dbrTopRight).toUTF8())


Run

All works ok, but how about the efficiency in instancing `Rune` and converting 
to UTF8 repeatedly?

Considering that Nim string is UTF8, I'm wondering if I can do something like:


   stdout.styledWrite(bg, "\x250C") & "\x2500".repeat(dlgWidth-2) & "\x2510)


Run

I mean embedding the character codepoint in the string itself instead of 
creating a Rune a converting it to UTF8 subsequently?

Thank you very much. 


Re: nimpretty non installed by choosenim stable

2019-04-10 Thread dom96
You're not doing anything wrong, choosenim just hasn't been updated yet to 
support installing nimpretty..


nimpretty non installed by choosenim stable

2019-04-10 Thread fstiffo
I have installed nim on Ubuntu with choosenim the stable channel, nim-0.19.4. 
The installed tools are: choosenim, nim, nimble, nimgrep, nimsuggest. Why 
nimpretty has not been installed? What I'm doing wrong? Thanks in advance for 
any help.


Re: Are the docs wrong, or is there a compiler bug?

2019-04-10 Thread Araq
@mratsim I don't like this change and as we can see, it doesn't even work.


Re: Are the docs wrong, or is there a compiler bug?

2019-04-10 Thread mratsim
I thought "type" was supposed to replace typedesc in parameter passing?


Re: getch() vs Cyrillic on Windows.

2019-04-10 Thread zulu
Winim library from Ward has a lot of facilities to deal with windows strings. 
Look it up on github.


Re: getch() vs Cyrillic on Windows.

2019-04-10 Thread Aiesha_Nazarothi
Feel your pain. I gave up and ended with this project myself already: 
[https://github.com/Guevara-chan/ConIO](https://github.com/Guevara-chan/ConIO)


Re: Owned refs

2019-04-10 Thread Araq
> Don't try the templates, they will lead you into a dead end...

"People who think they know everything really annoy those of us who know we 
don't."

> I had a pool allocator in mind, where the allocator draws memspace from a 
> list of memory regions and the refcount bookkeeps the refs (summarized) into 
> entire regions. When such a refcount becomes zero, then the entire memory 
> region will get freed and therefore, you will get some speed.

That's coarse grained refcounting, you save the inner-region pointer update RC 
ops, but the stack RC ops remain. It also has nothing to do with Bacon/Dingle. 
Just like a

> if there are some. The primary problem of Bacon/Dingle are the abundant 
> refcount updates coming from local refs on the stack. Something that the 
> recent GC avoids. Deterministic deallocation is not automatically making 
> Bacon/Dingle a better design.

No, indeed, it's not automatically better, but I wrote about its benefits, for 
Nim, and I don't like repeating myself.