Re: sl command of nim

2020-05-23 Thread zevv
Yeah, Nmimmin' like it's 1993!


Iterator arguments

2020-05-17 Thread zevv
I'm trying how far I can get mimicking Lua's asymmetric coroutines in Nim, 
using iterators and some macros - not unlike asyncmacro.

The manual is a bit vague about iterator arguments - it states that you need to 
provide the arguments to each call, or wrap the thing in a closure which does 
that for you. But I want to leverage the fact that I can pass _different_ 
arguments to each call - is that considered safe and well defined behaviour? It 
works for me now, but is this intented an something one can rely on to be like 
this in the future?


Re: Nim OS porting

2020-05-03 Thread zevv
For a "real" port, check the Git logs to see what was done for another 
platform, for example the nintendo switch and learn from that.

For a bit more lightweight port you might be able to compile with \--os:any and 
-d:useMalloc; in this case Nim will have very few dependencies on your 
operating system, apart from some basic ANSI C functions like 
malloc/free/fopen/fwrite.


Re: Finally, I can do functional programming on tiny embedded systems

2020-04-22 Thread zevv
@foldl: Consider adding these as well: --exceptions:goto -d:noSignalHandler to 
further decrease your binary size.


Re: generate c++ code from .nim file

2020-04-14 Thread zevv
Sorry, no. The Nim-generated C and C++ code is ment to be read by - and highly 
optimized for - compilers, not humans.


Looking for a new home for Nimz3

2020-04-02 Thread zevv
Some time ago I made a little Nim binding and DSL around the Z3 theorem prover, 
which can be found at 
[https://github.com/zevv/nimz3](https://github.com/zevv/nimz3).

I made this mostly for fun and learning purposes, but never got to properly 
maintain or document it. Nimz3 has recently be picked up by Araq for the new 
"DrNim" project, and I start getting some issues and pull requests on the repo 
as well.

Unfortunately I currently lack both time and motivation to give this package 
the love it deserves, so I'm looking for someone who wants to adopt to prevent 
it from gathering dust and unanswered github issues.


Re: Equivalent of VBA With structure

2020-02-05 Thread zevv
Same here: I'm also interested to hear exactly what problems you are seeing 
with the `with` package and happy to see if I can help you out.


Re: Fizzbuzz game

2020-01-25 Thread zevv
@miran: I was just hinting at using the `case` as an expression. I wonder 
though why you missed the obvious since you are trying so hard: :)


for n in 1..100:echo 
[$n,"Fizz","Buzz","FizzBuzz"][int(n%%3<1)+2*int(n%%5<1)]


Run

78


Re: Fizzbuzz game

2020-01-25 Thread zevv
for i in 1..100:
echo case i mod 15:

of 0:
"FizzBuzz"
of 3,6,9,12:
"Fizz"
of 5,10:
"Buzz"
else:
$i


Re: Trying to make program cycle-free with ARC

2020-01-24 Thread zevv
getAllocStats() only keeps track of allocations with `-d:allocStats`. It's only 
there for Nim's own test suite now and is of limited use, as some allocations 
will only be cleaned up after the main code, so these can not be properly 
reported from within your Nim program itself.

At this time Valgrind is probably still the best tool for hunting leaks.


Re: TXT DNS lookup

2019-12-08 Thread zevv
On the one side it would be nice to have native DNS lookup code in Nim, as this 
could play nice with async and could finally make connect() and dial() and 
friends really asynchronous. The downside is that resolving is historically 
really a task for the OS, as there are more potential sources for doing lookups 
(/etc/hosts, DNS cache, LDAP, etc).


Re: Most efficient way to implement a stack using Nim?

2019-12-05 Thread zevv
I use seqs as stacks extensively in one of my projects, and I found these are 
generally ok _unless_ you need to unwind your stack frames more then one item 
at a time: I believe `setLen()` can invoke the GC and cause performance 
degradation. Instead, I use a seq for storage but keep my own top value and 
provide some access functions which merely update the top value and read/write 
the seq's contents.


Re: Advent of Nim 2019 megathread

2019-12-01 Thread zevv
I almost got convinced to defect to Ocaml, but sticking to Nim for this year: 
[https://github.com/zevv/aoc2019](https://github.com/zevv/aoc2019). Enjoy 
people!


Re: What does the ``.inject.`` pragma do? Where is it defined?

2019-11-04 Thread zevv
Explained in 
[https://nim-lang.github.io/Nim/manual.html#templates-hygiene-in-templates](https://nim-lang.github.io/Nim/manual.html#templates-hygiene-in-templates)

Any variables declared in a template annotated with {.inject.} will be 
accessible in the scope where the template is called, effectively injecting the 
variable from the template into the location of the call. 


Re: pegs: match without guessing openarray size

2019-10-22 Thread zevv
Not part of the stdlib, but NPeg shoild be able to do this for you at compile 
time:


import npeg

static:
let p = peg rule:
  rule <- "cd" * +Space * >Alpha * ":":
echo $1

discard p.match("cd c:\blue\monkey\bike")


Run


Re: code to unpack (msgpack) and "cast" object to

2019-10-22 Thread zevv
There is the excellent msgpack4nim library that does exactly what you are 
requesting:

[https://github.com/jangko/msgpack4nim](https://github.com/jangko/msgpack4nim)

Does that not fit your needs?


Re: Is there a way to write tests & benchmarks for functions operating on NimNode?

2019-10-02 Thread zevv
The default unittest module also works at compile time, so you should be able 
to use this for your testing needs.

I recently found the need for benchmarking at compile time as well, but none of 
the obvious methods are available at compile time. I found myself printing dots 
to my terminal ever 10ms and then counting dots between echo output - not the 
most productive method. I guess we should file an issue for this and see if we 
can get a basic cpuTime() and a monotonous clock available in the Nim VM.


Re: How can I limit VM addresses size using Nim type system?

2019-09-04 Thread zevv
Do subrange types not offer what you are looking for?


type VmAddr = range[0..63]


Run

PS: I wrote a forth once, and it's even in production in a few embedded 
devices! See [https://github.com/zevv/zForth](https://github.com/zevv/zForth)


Re: getFilePos - inconsistent output

2019-08-17 Thread zevv
Hmm, reading the implementation of open() I just realized there is no way to 
_not_ open in binary mode. So then again I'm not really sure what your problem 
is. I'm afraid I can't help you out here, I don't have access to a windows 
machine to see if I can reproduce.


Re: Ebnf Lexer and Parser generator in nim

2019-08-16 Thread zevv
Hi @spip,

Sorry, only noticed your post just now - for future communication feel free to 
post into the NPeg issues at github so I get properly notified.

> It has its own grammar syntax for rules that does not follow (E)BNF like 
> Nim's pegs

This is a design choice: having a grammar parseable by the Nim compiler has a 
number of advantages:

  * Reduced code size because there is no need to create a parser for the 
grammars itself. Of course this could be made in NPeg itself, but that's a bit 
of a chicken-and-egg problem :)
  * Implementation in Nim macros allows for smooth mixing of grammars and nim 
code, so there is no need for nasty tricks to get nim code back from string 
grammars etc
  * Not very important but still nice: syntax highlighting generally keeps 
working withing macro DSLs



This said, it would probably be not too hard to create a (E)BNF compatible 
parser with everything that is now in place. I do see some problems with this 
though: (E)BNF and PEG grammers may _look_ similar, but are not trivially 
compatible (for example, ordered choice in PEGs). You simply can not parse any 
arbitrary (E)BNF grammar with a PEG, there are always things that need some 
reordering or rewriting to make them PEG compatible, or at least more efficient 
to limit backtracking. (On the other hand: the current syntax is not too far 
from (E)BNF. For example, take a look at src/npeg/lib/uri.nim for a PEG 
translation of RFC3984.)

Also, the (E)BNF syntax would need a number of extensions in order to specify 
captures or other actions to perform at parse time, which kind of defies the 
purpose of having a compatible grammar to start with. Last but not least: I see 
no clean way to mix grammar and Nim code. I'm very much open to any ideas and 
experiments, so let me hear if you have any practical suggestions!

> It does not support Unicode, meaning being able to parse UTF-8 strings using 
> Runes

Like I said in the manual: there is rudimentary UTF-8 support available, and 
I'm not sure what exactly would be needed to make NPeg really "UTF-8 
compatible". Over the last few days I added proper library support for NPeg, 
and started a bare minimum utf8 lib. The same applies here: I'd be glad to hear 
any ideas you might have and I'm happy to see if we can make NPeg suit your 
needs!


Return a table from a macro: "Error the field 'data' is not accessible'

2019-08-08 Thread zevv
I'm trying to return a Table from a macro using "quote do", but the generated 
AST contains fields that are no accesible outside the tables module


/tmp/t.nim(8, 3) Error: the field 'data' is not accessible.


Run


import macros
import tables

macro foo(): untyped =
  var a = { "one": 1 }.toTable
  quote do:
`a`

let b = foo()
echo b


Run

The AST for the table itself looks like this:


(data: [(34912920694978458, "one", 1), ...], counter: 1)


Run


Re: Passing a type through a macro?

2019-08-06 Thread zevv
So, now I ended up with this (thanks Jasper):


template skel(T: untyped): untyped =
  let fn = proc(): T =
echo "I am fn"
  fn

proc gen(T: NimNode): NimNode =
  getAst skel(T)

macro foo(T: typedesc): untyped =
  gen(T)

discard foo(int)()


Run

I know there are very good reasons why things work the way they do, but the 
above is not obvious, trivial or simple. There is a thing called generics, but 
you can't use it for macros, and all macro arguments are NimNodes, except for 
typedescs. The generics/Nim-idiomatic way to do this would be something like 
this:


template skel[T](): untyped =
  let fn = proc(): T =
echo "I am fn"
  fn

proc gen[T](): NimNode =
  getAst skel[T]()

macro foo[T](): untyped =
  gen[T]()

discard foo[int]()()


Run

Maybe one day in Nim 2.0 :)


Re: What text editor are you using for Nim?

2019-08-02 Thread zevv
I used to use Vim, but @leorize made me change to nvim because he is still 
refusing to port his _excellent_ nim.nvim plugin to vim8. (hint! hint!)


Re: Passing a type through a macro?

2019-07-23 Thread zevv
Well, do I feel _stupid_ now :)

Thanks!


Re: Passing a type through a macro?

2019-07-23 Thread zevv
@kaushalmodi: also tried the static variants, no luck

@jasper: No reason other then I just happened to write down these two of the 
numerous posibillities I have tried - `proc gen(T: NimNode): NimNode` also 
doesn't work.

Have I hit some bug?


Passing a type through a macro?

2019-07-23 Thread zevv
I have been trying to figure out how to get this working for the last few days, 
but no luck yet. Consider this snippet:


template skel(T: untyped): untyped =
  let fn = proc(): T =
echo "I am fn"
  fn

proc gen(): NimNode =
 result = getAst skel(int)

macro foo(): untyped =
  gen()

let f = foo()


Run

This is the bare minimum I can reduce my real life code to. The macro `foo()` 
calls proc `gen()` to generate code. `gen()` runs `getAst()` on template 
`skel()` which contains the code that should be generated.

The code is organized like this for good reasons: in my real code `gen()` 
generates a bit more code which gets injected in the `skel()` template, so I 
think I can not easily make big structural changes.

The above works, but I am looking for a way to get the type `T` all the way out 
as a parameter the `foo()` macro. Ideally, this is what I would like to do, 
although it does not compile:


template skel(T: untyped): untyped =
  let fn = proc(): T =
echo "I am fn"
  fn

proc gen[T](): NimNode =
 result = getAst skel(T)   # <-- error: Error: getAst takes a call, but got 
getAst

macro foo(T: typedesc): untyped =
  gen[T]()

let fn = foo(int)


Run

I do not understand what Nim is trying to say here `getAst takes a call but got 
getAst`? So let's pass the type as an argument:


template skel(T: untyped): untyped =
  let fn = proc(): T =
echo "I am fn"
  fn

proc gen(T: typedesc): NimNode =
 result = getAst skel(T)

macro foo(T: typedesc): untyped =
  gen(T)  # <-- Error: type mismatch: got 

let fn = foo(int)


Run

Nope, doesn't work - the `typedesc` argument of the macro gets converted to a 
`NimNode` and I can't figure out how to turn it back into a `typedesc`

I've tried numerous permutations resulting in numerous other interesting error 
messages, I went through the manual a number of times and I discussed this on 
#nim, but I am still lost. How to solve this?

Thanks! 


Passing a type through a macro to a generic?

2019-07-23 Thread zevv
How can I pass a type through a macro to instantiate a proc with the given type?

Heavily reduced from my real code, I end up with something like this:


import macros
  
  proc bar[T]() =
var a: T
echo "T=", typeof(a)# <-- T=NimNode, but want int
  
  macro foo(T: typedesc): untyped =
   bar[T]()
  
  foo(int)


Run

I


Re: Macro to create a dictionary (table) like in python!

2019-07-12 Thread zevv
Github pull request: 
[https://github.com/nim-lang/Nim/pull/11702](https://github.com/nim-lang/Nim/pull/11702).
 


Re: What's the most idiomatic way to call ``execCmdEx`` in parallel?

2019-07-12 Thread zevv
osproc execProcesses?

[https://nim-lang.github.io/Nim/osproc.html#execProcesses%2CopenArray%5Bstring%5D%2Cproc%28int%29%2Cproc%28int%2CProcess%29](https://nim-lang.github.io/Nim/osproc.html#execProcesses%2CopenArray%5Bstring%5D%2Cproc%28int%29%2Cproc%28int%2CProcess%29)


Re: Trouble when converting c code to nim

2019-05-16 Thread zevv
It would be helpful to others to indicate your exact problem, like why does it 
not compile and why you can not solve this? Your above snippet has problems 
with converting types, because you are trying to mix Nim integers and C 
unsigned chars. Fixing this is not too hard:


proc utf8str_codepoint_len*(s: cstring, utf8len: cint): cint =
  var codepointLen: cint = 0
  let m4 = 128 + 64 + 32 + 16
  let m3 = 128 + 64 + 32
  let m2 = 128 + 64
  var i: cint = 0
  while i < utf8len:
var c = s[i].int
if (c and m4) == m4:
  inc(i, 3)
elif (c and m3) == m3:
  inc(i, 2)
elif (c and m2) == m2:
  inc(i, 1)
inc(i)
inc(codepointLen)
  return codepointLen


Run

As an alternative you might look into the nim unicode module which offers the 
runelen() proc which does almost exactly what your above code does.


Re: Modern way to pass a sequence to a c function as a void pointer and to cast it back as seq

2019-05-16 Thread zevv
Well, C _can_ understand it. But that does not mean you should _want_ it to :)


{.emit: """

typedef long long int nim_int;

struct nim_seq_hdr {
  nim_int len;
  nim_int reserved;
};

struct nim_string {
  struct nim_seq_hdr seq;
  char *data[0];
};

struct nim_string_seq {
  struct nim_seq_hdr seq;
  struct nim_string *data[0];
};


void foo(void *ptr)
{
  struct nim_string_seq *n = *(struct nim_string_seq **)ptr;
  nim_int i;
  for(i=0; iseq.len; i++) {
struct nim_string *s = *(struct nim_string **)(>data[i]);
printf("%d -> %d: %s\n", i, s->seq.len, s->data);
  }
}


"""}

proc foo(a1: pointer) {.cdecl, importc.}
var a = @["one", "two", "three"]
foo(addr a)


Run


Re: pegs module: how to use captures in enter/leave procs?

2019-04-17 Thread zevv
Hi Amenhotep,

Please drop an issue on the NPeg github page with a description and/or some 
examples of what you're trying to do, I'd be glad to help you out and see if we 
can get that to work.

[https://github.com/zevv/npeg/issues](https://github.com/zevv/npeg/issues)


Re: Ebnf Lexer and Parser generator in nim

2019-04-04 Thread zevv
I'm taking the liberty to shamelessly mention my recent project here, as this 
seems the appropriate thread to do so: NPeg is a PEG-style parser generator 
which allows free mixing of grammar and Nim code, which should be suitable for 
the task of lexing and parsing.

It can collect simple string captures, complex captures as a JSON tree, or run 
arbitrary Nim code at match time.

NPeg is available in nimble, the manual and project page are at 
[https://github.com/zevv/npeg](https://github.com/zevv/npeg)


Re: scopes, templates and UFCS

2019-04-03 Thread zevv
Indeed, charlie was mispasted, fixed that.

Thanks 


scopes, templates and UFCS

2019-04-03 Thread zevv
Given the following three small source files below, why does the call c.dump() 
generate an error (attempting to call undeclared routine: 'dump'), but is it ok 
if I change this to dump(c)?

alpha.nim: 


import bravo
bravo()


Run

bravo.nim: 


import charlie

template bravo_aux() =
  var c = Charlie()
  c.dump()

template bravo*() =
  bravo_aux()


Run

charlie.nim: 


import charlie

template bravo_aux() =
  var c = Charlie()
  c.dump()

template bravo*() =
  bravo_aux()


Run


Re: I wrote some nim code that works, but I don't understand how/why it works.

2019-04-03 Thread zevv
well, ignore that, as that will not yield a HashSet.


Re: symbol "&"

2019-04-03 Thread zevv
I'm not sure if I understand your question right, but you are trying to export 
a nim function to take a C++ ref, right?

How about


keyDown(eventType:stringHash,eventData:var variantMap)


Run


Re: How to keep the output of a recursive proc?

2019-01-30 Thread zevv
You should be able to pass an additional variable of type 'var string' around 
your recursive functions, and simply use add() to add characters as you go - 
strings in Nim are modifiable and adding to them is cheap.

When you've fully bubbled back up the call stack the result is there for you in 
your string.


Re: Convert float to its corresponding bytes?

2019-01-26 Thread zevv
Does it also use an union when compiling to C++?


Re: Convert float to its corresponding bytes?

2019-01-26 Thread zevv
The following should also be safe, this translates to a memcpy() at the C 
level. This may seem like overkill, but the C compiler should recognize the use 
of memcpy for type punning and optimize it away and generate a register to 
register move.


proc flt2arr(f: var float64, a: var array[8, uint8]) =
  assert sizeof(a) == sizeof(f)
  copyMem(addr a[0], addr f, sizeof f)

proc arr2flt(a: var array[8, uint8], f: var float64) =
  assert sizeof(a) == sizeof(f)
  copyMem(addr f, addr a[0], sizeof f)


Run


Re: Associating data to types

2019-01-12 Thread zevv
> If you want to set them at the type definition you can use custom annotations

That's pretty much exactly what I need - thanks for pointing that out!


Re: Best practices of meta-programming

2019-01-11 Thread zevv
> Write the macro transformation carefully. Ensure that the lineinfo in the 
> nodes remains useful.

Where can I find any examples of this?


Re: Some nim builtin libs not doing enough error checking?

2019-01-11 Thread zevv
An empty directory is something else then a non-existing directory, IMHO. I 
would expect a exception in this case.


Re: Associating data to types

2019-01-11 Thread zevv
@deansher: Well, I was also looking for a way that would make the definition of 
messages nice-looking and trivial. The drum-roll-overloaded-procs are so simple 
I didn't even think of this, although I do not like the syntax for defining 
messages like this.

But this is Nim: macro -> DSL to the rescue, all solved. Thanks! 


Associating data to types

2019-01-10 Thread zevv
(asked this some time ago on #Nim, but still haven't found a solution)

I'm trying to assign some data to a type, which can then be accessed by a 
generic instantiation using the specific type. Here is what I'm trying to do 
(but does not compile).


import msgpack4nim
import strutils
import typetraits

type
  
  MsgAlpha = object
id: int
x, y: int
url: string
  
  MsgBeta = object
id: int
resource: string
  
  # ...

const info = {
  MsgAlpha: (id: 1),
  MsgBeta: (id: 2),
  # ...
}

proc serialize[T](msg: T) =
  var msgcopy = msg
  msgcopy.id = info[msg.type].id # Too bad!
  echo msgcopy.pack.stringify

serialize MsgAlpha(x: 10, y: 30, url: "http://foo.bar;)
serialize MsgBeta(resource: "GLES2")


Run

My goal is to do serialization of protocol data where the caller does not have 
to know the details of the message being serialized (in this example the "id" 
field, in real life there is more message specific data). The culprit is the 
line marked # Too bad!. Here I'd like to get the data associated to the type T 
of msg.

The const info above compiles, but Nim does not seem to be sure of its type. 
When asked (typetraits) it tells me array[0..1, tuple of (type MsgAlpha, 
tuple[id: int])], which is almost right, but not quite.

Is there a way to do this without referencing to type names as strings?


Re: PEG.js-like API for the pegs module

2019-01-06 Thread zevv
I also spent some time yesterday to see what pegs needs to run at compile time. 
My first quick hack was the same as chrishellers: drop init() and move its 
contents into parsePeg.

After that I ran into a few places where the pattern buffer is accessed out of 
bounds (always len+1). I suspect this is by design, because the PegLexer buf is 
declared as cstring instead of normal string, which makes this valid because of 
the trailing '0'. I guess this works fine at run time, but the VM does not like 
this trick.

Fixing these three or four places results in my peg expression properly being 
parsed at compile time, but then I ran into this one: `Error: invalid type for 
const: Peg`

Unfortunately, I'm lost here. It seems that inherited types can not be used for 
consts, but I have no clue why, and if there is a possible mitigation for this. 


Re: Getting the original type of an 'upcasted' object

2018-12-29 Thread zevv
Thanks for pointing me to that thread, that explains some of the details I did 
not yet grasp.

For now I'm good with a bit of redesign: I store a ref to object with some proc 
pointers for that specific type in each node. If this is solvable with a macro 
I can save a pointer per object though, which would be nice.


Re: Getting the original type of an 'upcasted' object

2018-12-29 Thread zevv
Here's an extract of my code.

My issue is with the `proc `$`(s: SNodeAny): string =` function.

Basically, it is just a long list of `if` statements (could be a `case` as 
well, doesn't matter) to check if the object is of some type, and then apply 
the `$` operator on the casted type. I feel this could be replaced by a two 
line macro or template, but for this I need to be able to deduce the original 
type of the passed SNode before I can cast and apply the `$` operator.

My real code now includes 4 of these kind of functions where I need to check 
for every possible node kind, cast it, and apply some kind of generic function 
to it.


import strutils

type
  
  IPv4Address = distinct string
  IPv6Address = distinct string
  MacAddress = distinct string
  Interval = distinct float
  # ... many more distinct types


type
  
  SNodeAny = ref object of Rootobj
id: string
parent: SNodeAny
  
  SNodeGroup = ref object of SNodeAny
children: seq[SNodeAny]
  
  SNodeParam = ref object of SNodeAny
  
  SNode[T] = ref object of SNodeParam
val: T


proc newSNode[T](id: string, val: T): SNodeAny =
  SNode[T](id: id, val: val).SNodeAny


proc newSNodeGroup(id: string, children: openarray[SNodeAny]): SNodeAny =
  var s = SNodeGroup(id: id)
  for c in children.items:
s.children.add c
c.parent = result
  return s

proc `$`(v: IPv4Address): string = v.string
proc `$`(v: IPv6Address): string = v.string
proc `$`(v: MacAddress): string = v.string
proc `$`(v: Interval): string = $ v.float


proc `$`(s: SNodeAny): string =
  if s of SNode[bool]:
result = $ s.SNode[:bool].val
  if s of SNode[int]:
result = $ s.SNode[:int].val
  if s of SNode[IPv4Address]:
result = $ s.SNode[:IPv4Address].val
  if s of SNode[IPv6Address]:
result = $ s.SNode[:IPv6Address].val
  if s of SNode[MacAddress]:
result = $ s.SNode[:MacAddress].val
  if s of SNode[Interval]:
result = $ s.SNode[:Interval].val
  # many more of those


proc dump(s: SNodeAny, depth: int = 0) =
  
  var l = repeat(" ", depth)
  l.add s.id
  
  if s of SNodeParam:
l.add "=" & $ s
  
  echo l
  
  if s of SNodeGroup:
for c in s.SNodeGroup.children.items:
  dump(c, depth+1)


var s = newSNodeGroup("system", [
  newSNodeGroup("identification", [
newSNode("name", "device 123"),
newSNode("location", "rack J2"),
newSNode("weight", 42.1),
newSNode("enabled", true),
newSNode("address", IPv4Address("10.0.0.3")),
  ])
])

s.dump


Run


Re: Getting the original type of an 'upcasted' object

2018-12-29 Thread zevv
Sorry Stefan, my original question was indeed lacking background info of what I 
am actually trying to achieve.

I'm trying to port a data model which was originally implemented in Lua to Nim. 
This consists of a tree of nodes, of which the leaves are heterogenous 
containers for a relatively large number of types. (tens, and growing)

My first implementation used object hierarchies, but I ran unto problems caused 
by mixing generics and multimethods. Araq explained that combining those is 
currently not a good idea, so I am looking for a way to drop the methods. Using 
object variants turned out to be cumbersome, so I am now back for a second try 
using object inheritance.

This basically works now, but I find myself writing long case statements 
handling all the possible object types in a few places, so I am looking to 
generalize things to avoid code repetition.

I will try to compile a compact example of my current implementation for 
comments.


Getting the original type of an 'upcasted' object

2018-12-29 Thread zevv
Hi,

How can I find out the original type of an object that has been 
promoted/demoted/casted (what is the right term here?) to a parent type without 
testing for each individual type with the of operator?


import macros

macro test(a: typed): untyped =
  # how to get "T2" here?

type
  T1 = ref object of RootObj
  
  T2 = ref object of T1

var a = T1(T2())
test a


Run


Re: Unexpected behaviour

2018-12-18 Thread zevv
Thanks for explaining.

I'll leave this thread and continue discussion in the github issue.


Re: Unexpected behaviour

2018-12-18 Thread zevv
https://github.com/nim-lang/Nim/issues/10038


Unexpected behaviour

2018-12-18 Thread zevv
I've been hunting strange behaviour in my code base which I have reduced to the 
following snippet.


type
  SNodeAny = ref object of RootObj
  SNode[T] = ref object of SNodeAny
  DNode[T] = ref object

method getStr(s: SNode[float]): string {.base.} = "blahblah"

method newDNode(s: SNodeAny) {.base.} =
  echo "newDNode base"

method newDNode[T](s: SNode[T]) =
  echo "newDNode generic"

let s = SNodeAny(SNode[float]())
newDnode(s)



Run

What I expect to happen: variable `s` is a `SNode[float]` disguised as a 
`SNodeAny`. Calling `newDnode(s)` should dispatch the `newDnode[T](s: 
SNode[T])` and the string `newDNode generic` should be printed.

Instead what happens is that the "super" method `newDnode(s: SNodeAny)` gets 
called, printing the string `newDnode base`

Now the strangest part: when the `getStr()` method is removed from the code, 
the behaviour changes to the expected behaviour, and all is well. 
Alternatively, removing the `SNodeAny()` cast from the second last line also 
restores the expected behaviour.

How does the existence of the `getStr()` method affect the behaviour of the 
`newDNode()` dispatch?


Re: Looking for efficient API for regexp library

2018-03-01 Thread zevv
True, it does not support UTF-8, just as the original Lua patterns do not. I 
guess having proper support for UTF-8 would probably include supporting Unicode 
as well and would complicate things a lot- for example, matching any unicode 
upper case character with %u would not be trivial.

BTW: YEs, I've seen nim-regex, which is also very nice. The lua pattern port is 
mainly for my personal use, because I'm leaving Lua more then 10 years of Lua 
behind, but I dearly miss the patterns. The advantage is that they are much 
more simple then regular expressions, which often result in something that I 
can read and understand a year after I wrote it - which is often not the case 
with full fledged PCRE regular expressions.

(Personally, I'd prefer pure Nim regex handing in the Nim stdlib over a PCRE 
based solution which requires external libs, would nim-regex not be a nice 
candidate?)


Re: Looking for efficient API for regexp library

2018-03-01 Thread zevv
This is also usable, although it requires the variables to receive the captures 
to be declared ahead of time:


proc match(src: string, pat: string, c0: var string): bool =
  let caps = src.match(pat)
  if caps.len == 1:
c0 = caps[0]
return true

proc match(src: string, pat: string, c0, c1: var string): bool =
  let caps = src.match(pat)
  if caps.len == 2:
c0 = caps[0]
c1 = caps[1]
return true

proc match(src: string, pat: string, c0, c1, c2: var string): bool =
  let caps = src.match(pat)
  if caps.len == 3:
c0 = caps[0]
c1 = caps[1]
c2 = caps[1]
return true

let src = "3 foxes: 0x1234"

var a, b: string
if src.match("(%a+).*0x(%x+)", a, b):
  echo "a = " & a
  echo "b = " & b



Re: Looking for efficient API for regexp library

2018-03-01 Thread zevv
Yeah, I guess providing multiple functions would work, since in practice 
patterns are usually limited to a handful of captures.

Thanks, 


Looking for efficient API for regexp library

2018-02-28 Thread zevv
I'm working on a Nim port of the Lua pattern matching code. Lua patterns are a 
bit like regular expressions, but simpler. The implementation is pretty small, 
however, compared to regular expressions, and the port is pure Nim and does not 
require any shared libraries like PCRE for the re and nre libs.

The current code is available at 
[https://github.com/zevv/nimpat](https://github.com/zevv/nimpat)/

The basic pattern matching is functional, a single proc 'match' is implemented, 
and can be used like this:


proc match(src: string, pat: string): seq[string]

let src = "3 foxes: 0x44111"
let pat = "(%d+) ([^:]+): 0x(%x+)"
let caps = src.match("(%d+) ([^:]+): 0x(%x+)")
echo "$1 $2 $3" % [ caps[0], caps[1], caps[2]]


The pattern "(%d+) ([^:]+): 0x(%x+)" translates to

  * (%d+): a maximum number of numeric chars
  * ([^:]+): all characters up to a colon
  * (%x+): one or more hex characters



I am now looking for a friendly API for the library, as getting the returned 
matches in a seq is a bit cumbersome to use. Ideally I would like to do pattern 
captures like in Lua allowing direct assignment to variables from a proc and/or 
iterator:


local a, b, c = src:match(pat)

for a, b, c in src:gmatch(pat) do
   ...
end


In Nim that would be something like this, using tuples.


let (a, b, c) = src.match(pat)

for a, b, c in src.gmatch(pat):
   ...


I have been trying to implement this in Nim, but I can not get this to work 
because (quote Araq) "overloading doesn't look at the return types"

So this does not work:


iterator gmatch(src, pat: string): (string) =
  let c = src.match(pat)
  yield (c[0])

iterator gmatch(src, pat: string): (string, string) =
  let c = src.match(pat)
  yield (c[0], c[1])

iterator gmatch(src, pat: string): (string, string, string) =
  let c = src.match(pat)
  yield (c[0], c[1], c[2])

nimpat.nim(357, 14) Error: ambiguous call; both nimpat.gmatch(src: string, 
pat: string)[declared in nimpat.nim(348, 9)] and nimpat.gmatch(src: string, 
pat: string)[declared in nimpat.nim(352, 9)] match for: (string, string)


Araqs next remark was to "write a macro", but my Nim-fu is not up to that yet, 
I'm afraid.

So, would it be possible to get this to work, and how would I proceed from here?

Thanks,

Ico


String pattern matching / regular expression libs

2017-07-21 Thread zevv
I've been looking into available libraries for string pattern matching and 
regular expressions, I found those:

  * re/nre: both come with Nim, but have dependency on pcre lib (quit large, 
requires .dll on win32)
  * peg: more of a parser, very powerful but cumbersome for quick string 
matching



Are there any other available options, preferably something small without 
external dependencies?

If not, I'm considering porting the Lua string pattern matching code [1] to 
Nim; it's pretty concise (approx 500 LOC), and handles about 99% of the 
matching/capturing cases I usually need in real life.

1\. 
[https://www.lua.org/manual/5.3/manual.html#6.4.1](https://www.lua.org/manual/5.3/manual.html#6.4.1)