summary refs log tree commit diff stats
path: root/lib/std/decls.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/decls.nim')
-rw-r--r--lib/std/decls.nim39
1 files changed, 26 insertions, 13 deletions
diff --git a/lib/std/decls.nim b/lib/std/decls.nim
index dd7d19da7..7b907f5e1 100644
--- a/lib/std/decls.nim
+++ b/lib/std/decls.nim
@@ -1,19 +1,32 @@
 # see `semLowerLetVarCustomPragma` for compiler support that enables these
 # lowerings
 
-template byaddr*(lhs, typ, ex) =
-  ## Allows a syntax for lvalue reference, exact analog to
-  ## `auto& a = ex;` in C++
+import macros
+
+macro byaddr*(sect) =
+  ## Allows a syntax for l-value references, being an exact analog to
+  ## `auto& a = ex;` in C++.
+  ## 
+  ## Warning: This makes use of 2 experimental features, namely nullary
+  ## templates instantiated as symbols and variable macro pragmas.
+  ## For this reason, its behavior is not stable. The current implementation
+  ## allows redefinition, but this is not an intended consequence.
   runnableExamples:
-    var s = @[10,11,12]
+    var s = @[10, 11, 12]
     var a {.byaddr.} = s[0]
-    a+=100
-    doAssert s == @[110,11,12]
-    doAssert a is int
+    a += 100
+    assert s == @[110, 11, 12]
+    assert a is int
     var b {.byaddr.}: int = s[0]
-    doAssert a.addr == b.addr
-  when typ is typeof(nil):
-    let tmp = addr(ex)
-  else:
-    let tmp: ptr typ = addr(ex)
-  template lhs: untyped = tmp[]
+    assert a.addr == b.addr
+  expectLen sect, 1
+  let def = sect[0]
+  let
+    lhs = def[0]
+    typ = def[1]
+    ex = def[2]
+    addrTyp = if typ.kind == nnkEmpty: typ else: newTree(nnkPtrTy, typ)
+  result = quote do:
+    let tmp: `addrTyp` = addr(`ex`)
+    template `lhs`: untyped = tmp[]
+  result.copyLineInfo(def)