Re: Language Design Question: Backend C vs LLVM IR

2019-06-15 Thread Stefan_Salewski
> In a nutshell, how does newruntime make the GC obsolete?

The basic idea was sketched here:

[https://nim-lang.org/araq/ownedrefs.html](https://nim-lang.org/araq/ownedrefs.html)

but it has been revised a few times. For the most important Nim data structures 
like strings and seqs it seems to work fine, so that many Nim programs just 
will not need the GC. And other programs, maybe with very complicated data 
structures, can continue using the old runtime with one of the provided GCs.

cumulonimbus gave you the link to Nim's LLVM backend, it has some restrictions 
currently. 


Re: Help getting this macro to work in a for loop

2019-06-15 Thread kaushalmodi
Thank you! That was a very good explanation; it now helps me understand why 
macros cannot work in for loops.


Re: Help getting this macro to work in a for loop

2019-06-15 Thread kaushalmodi
Thank you!

I am a real beginner in Nim macros. Your example snippet will serve really 
helpful to me as I am learning this more.

\---

I'd also like to thank @JasperJenkins (from Gitter) for offering his solution 
to this problem on IRC here: 
[https://irclogs.nim-lang.org/14-06-2019.html#18:34:24](https://irclogs.nim-lang.org/14-06-2019.html#18:34:24)

Here's the Nim playground link he shared: 
[https://play.nim-lang.org/index.html?ix=1LMY](https://play.nim-lang.org/index.html?ix=1LMY)

For convenience, that solution is inlined below:


import macros
{.experimental: "forLoopMacros".}

type
  Obj = object
a, b, c: int

proc replace(n: NimNode, symbolic, real: NimNode): NimNode =
  if n.kind == nnkIdent and n.eqIdent(symbolic):
# this identifier is the for loop variable: return a real field ident 
instead
return real
  else:
result = n # return unchanged verbatim
# continure recursion on children
for i in 0 ..< n.len:
  n[i] = replace(n[i], symbolic, real)

macro replaceField(forLoop: ForLoopStmt): untyped =
  echo "\nCode before:\n", toStrLit(forLoop).strVal
  result = newTree(nnkStmtList)
  let
forVar = forLoop[0] # k
fields = forLoop[1][1] # ["a", "b", "c"]
stmts = forLoop[2] # loop body
  for f in fields:
# Copy the loop body since the loop gets unrolled.
# We need a block so any variables don't collide.
let stmtsCopy = newBlockStmt(copyNimTree(stmts))
# recursively replace the forVar with a new identifer.
result.add(replace(
  stmtsCopy, # this fields copy of the stmts
  forVar, # identifier to replace
  ident(f.strVal))) # new identifer made from one of the real obj fields
  echo "\nCode after:", toStrLit(result).strVal, "\n"

var obj = Obj(a: 1, b: 2, c: 3)
echo obj

for k in replaceField(["a", "b", "c"]):
  # more elaborate example that would fail without a block statement
  let num = obj.k
  for i in 1 .. num:
obj.k *= i

echo obj


Run

\---

This is awesome! I now have more than one solutions to understand more complex 
macros than the `quote do` ones.


Sponsors page bugged?

2019-06-15 Thread ivankek
[https://nim-lang.org/sponsors.html](https://nim-lang.org/sponsors.html)

Status has been a sponsor for 10 months, yet the total amount equals only 1 
month of sponsorship.


Re: Language Design Question: Backend C vs LLVM IR

2019-06-15 Thread cumulonimbus
But there's also 
[https://github.com/arnetheduck/nlvm](https://github.com/arnetheduck/nlvm) \- 
so you'll likely get to choose the one you prefer.


Re: Best way to represent AST

2019-06-15 Thread i_am_hal
Araq, when I try to make a function newBinOp (which just abstracts making a 
binary operation from a Node), I get ".. you must provide compile-time value 
for discriminator 'op'" This is what the proc looks like: 


proc newBinOp(left_node: Node, oper: Operation, right_node: Node): Node =
  return Node(op: oper, left: left_node, right: right_node)


Run

What am I doing wrong?


Re: Help getting this macro to work in a for loop

2019-06-15 Thread solo989
try this: 


import macros

proc replaceSymAndIdent(a : NimNode, b : NimNode, c : NimNode, isLit : 
static[bool] = true) =
for i in 0..len(a)-1:
  if a[i].kind == nnkSym:
if ident(strVal(a[i])) == b:
  a[i] = c
  elif a[i].kind == nnkClosedSymChoice or a[i].kind == nnkOpenSymChoice:
if ident(strVal(a[i][^1])) == b:
  a[i] = c
  elif a[i].kind == nnkIdent:
if a[i] == b:
  a[i] = c
  elif a[i].len != 0:
if a[i].kind == nnkDotExpr:
  when not isLit:
if a[i][0].kind == nnkSym:
  if ident(strVal(a[i][0])) == b:
a[i][0] = c
elif a[i][0].kind == nnkClosedSymChoice or a[i][0].kind == 
nnkOpenSymChoice:
  if ident(strVal(a[i][0][^1])) == b:
a[i][0] = c
elif a[i][0].kind == nnkIdent:
  if a[i][0] == b:
a[i][0] = c
else:
  replaceSymAndIdent(a[i], b, c, isLit)

macro iterateSeq(a : untyped, b : static[seq[string]], code : untyped) : 
untyped =
  let a =
if a.kind == nnkSym:
  ident($a)
elif a.kind == nnkClosedSymChoice or a.kind == nnkOpenSymChoice:
  ident($a[^1])
else:
  a
  #echo type(a)
  result = newStmtList()
  for item in b:
var newCode = code.copy()
replaceSymAndIdent(newCode, a, newLit(item), isLit = true)
result.add(newCode)
  #echo treeRepr result
  #echo repr result
  #echo ""
  #result = newStmtList()

macro assignField*(obj, fieldName, value: typed) : untyped =
  let fieldSym = newIdentNode($`fieldName`)
  result = quote do:
`obj`.`fieldSym`=`value`

type
  SomeObj* = object
a* : int
b* : int
c* : int

var
  foo = SomeObj()

iterateSeq(field, @["a", "c"]):
  assignField(foo, field, 50)

echo foo

assignField(foo, "a", 100)
assignField(foo, "c", 200)

block:
  assignField(foo, "b", 300)

echo foo


Run

Also, I noticed you were missing a return type on your macro so I don't know 
how your code compiled at all.


Re: Generic methods are deprecated?

2019-06-15 Thread Araq
Well yes, the problem is that we don't attach methods to a type so when you 
write `G[T]` we cannot instantiate every method that "belongs to" `G`. And 
methods we don't generate cannot participate in the dispatching process.

Now that I've written that, maybe we can instantiate generics during dispatcher 
generation...


Re: Generic methods are deprecated?

2019-06-15 Thread bluenote
> AFAIK removal of generic methods is so that under-the-hood we can switch the 
> methods implementation to a vtable

But shouldn't a vtable be able to handle generics that are attached to the base 
just fine? For instance, the `Test` class has a vtable with a single slot for 
`call`. An instantiation `Test[int]` would point to an `int` instantiation of 
`call`, and a `Test[float]` would point to the `float` instantiation. To my 
knowledge that's how it works in C++.

On the other hand, generics not attached to the base, can result in multiple 
instantiations for a single method. This requires full program analysis, and 
doesn't play well with vtables.


Re: Best way to represent AST

2019-06-15 Thread bluenote
Or if you prefer inheritance, you can extend the inheritance tree:


type
  Node = ref object of RootObj
  
  LitOrOp = ref object of Node
  
  Number = object of LitOrOp
value: int
  
  BinOp = object of LitOrOp
left: LitOrOp
op: string
right: LitOrOp


Run


Re: Language Design Question: Backend C vs LLVM IR

2019-06-15 Thread Stefan_Salewski
First, Nim generally is not slower than C. You can write Nim code which is 
translated straight to C. But of course you may use high level constructs, 
which may be a bit slower, or you may do too many heap allocations for example, 
which can make your code a bit slower. And maybe some library modules are not 
yet as fast as they could be.

Advantage of C++ backend can be, that C++ supports exceptions, with no or 
minimal runtime overhead. Plain C does not, so some people may prefer compiling 
to C++.

Java-Script backend -- well that is the language of the web, so it is good that 
Nim supports it. And finally, there is also a LLVM backend available already, 
with some restrictions.

When you are really looking for disadvantages of Nim compared to C -- well Nim 
executables are small, but not so tiny as a C hello-world of only about 10k. 
Because Nim has a small runtime library and Garbage-Collector support in its 
executable. But thinking about that, my former statement is not really true, as 
we can compile Nim using runtime and GC as external libs, so executable is 
indeed only a few kB. So maybe GC is only remaining disadvantages. But with 
newruntime we may be able to use Nim without GC, and for most apps GC is no 
problem at all. 


Re: Language Design Question: Backend C vs LLVM IR

2019-06-15 Thread kartoffel
Thank you for your answer. Nevertheless, Nim translates to C, C ++ and others. 
Why? To offer better interoperability with C besides C ++? And what are the 
differences in performance? Is C ++ generally faster than the target? And by 
what percentage is a program written in Nim slower on average than direct 
writing in C or C ++?


Re: Introducing Norm: a Nim ORM

2019-06-15 Thread moigagoo
I have some great news: Norm 1.0.11 supports inserting and retrieving NULL 
values for SQLite databases.

This was made possible thanks to the great 
[ndb](https://github.com/xzfc/ndb.nim) module. The transition from std 
db_sqlite to ndb/sqlite was really smooth. I can't wait to see ndb replace all 
db_* modules in stdlib.

As soon as ndb supports PostreSQL, we'll be able to port norm/postgres to it as 
well, which will make NULL support universal.


Re: Language Design Question: Backend C vs LLVM IR

2019-06-15 Thread Araq
Compiling to C(++) gives us C(++)'s portability and a dirty/better way to 
interop with C(++): features like `.emit`, `.header`, `.incompleteStruct`, 
`.codegenDecl` are harder to do with LLVM.

That said, C is a pretty bad compiler target language because it doesn't 
support precise stack tracing for GCs nor efficient exception handling. Thanks 
to its preprocessor you never know which identifiers might actually be unusable 
as object fields (`obj->unix` can fail to compile...). LLVM doesn't have these 
problems.


Re: Best way to represent AST

2019-06-15 Thread Araq
Like so:


type
  Operation = enum
lit, plus, minus, mul, division
  Node = ref object
case op: Operation
of lit:
  value: int
else:
  le, ri: Node


Run


Re: Natural is not positive

2019-06-15 Thread lscrd
It depends on authors. I said that French people generally consider 0 as being 
neither positive nor negative. For instance, a positive temperature is above 
0°C.

For the french mathematician group Nicolas Bourbaki, which is a well known 
reference, zero is both positive and negative. But that not means that all 
mathematicians (being french or not) agree with this. I rather think that it is 
a non standard definition of positive (and negative). Bourbaki had certainly 
good reasons to do this, but I think it makes things more complicated. It’s 
better when the mathematical definitions are consistent with the common sense. 
And, in fact, I do not know of any other mathematicians who have adopted this 
point of view.

For Wikipedia in english – see 
[https://en.wikipedia.org/wiki/Positive_real_numbers](https://en.wikipedia.org/wiki/Positive_real_numbers)
 – a positive number is clearly greater than zero and, this, from a 
mathematical point of view. But, even in English, your video shows that there 
is still discussion on this topic.


Re: Where's the code in `tut1.rst`?

2019-06-15 Thread Araq
The code is right there, Nim uses an RST version that is not as picky as 
docutils', so github doesn't show it properly.

[https://raw.githubusercontent.com/nim-lang/Nim/devel/doc/tut1.rst](https://raw.githubusercontent.com/nim-lang/Nim/devel/doc/tut1.rst)


Where's the code in `tut1.rst`?

2019-06-15 Thread ankush981
Hello, I was trying to send a pull request for Tutorial 1, but I can't seem to 
spot any code in 
[https://github.com/nim-lang/Nim/blob/devel/doc/tut1.rst](https://github.com/nim-lang/Nim/blob/devel/doc/tut1.rst).
 Maybe this isn't the content that shows up at 
[https://nim-lang.org/docs/tut1.html](https://nim-lang.org/docs/tut1.html)? If 
it is, are the code snippets pulled in magically from somewhere while building 
the docs? 樂


Best way to represent AST

2019-06-15 Thread i_am_hal
So I'm trying to write my typical calculator program I typically write when 
learning any language, and I'm having troubles with representing the expression 
as an AST (by making object which represent each node type, such as BinOp, 
Number, etc), but am having troubles with the recursive nature of it. Here's 
basically what I have


type
  Node = ref object of RootObj
  
  Number = object of Node
value: int
  
  BinOp = object of Node
left: Node
op: string
right: Node


Run

The problem is I want the BinOp object to either take a Number node or another 
BinOp node as it's left and right fields. How can I achieve this? Should I just 
abandon using objects and try to use perhaps a tuple instead? (For background, 
I have light experience with C, Rust, but am much more capable with Python)