summary refs log tree commit diff stats
path: root/tests/run
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-10-15 16:36:00 +0300
committerZahary Karadjov <zahary@gmail.com>2012-10-15 21:00:29 +0300
commit3c9e3a6a716326c48e509e7b09596e2a1bf900fa (patch)
tree23e098d426ec369ef49215ffb50e147a65117963 /tests/run
parent7424a60ba103fc5a6ddcee71a771e8a68c4699a7 (diff)
downloadNim-3c9e3a6a716326c48e509e7b09596e2a1bf900fa.tar.gz
Improved support for nkSymChoices in type coercions
For example, this allows you to pick up a proc with a specific signature from
an overload set.

bugfix: nimrod generated invalid code when a RVO function had a single
compile-time param

bugfix: nkHiddenDerefs were not neutralised properly for indirect proc calls
Diffstat (limited to 'tests/run')
-rwxr-xr-xtests/run/tvtable.nim74
1 files changed, 74 insertions, 0 deletions
diff --git a/tests/run/tvtable.nim b/tests/run/tvtable.nim
new file mode 100755
index 000000000..36b67277a
--- /dev/null
+++ b/tests/run/tvtable.nim
@@ -0,0 +1,74 @@
+discard """
+  output: '''
+OBJ 1 foo
+10
+OBJ 1 bar
+OBJ 2 foo
+5
+OBJ 2 bar
+'''
+"""
+
+type
+  # these are the signatures of the virtual procs for each type
+  fooProc[T] = proc (o: var T): int
+  barProc[T] = proc (o: var T)
+
+  # an untyped table to store the proc pointers
+  # it's also possible to use a strontly typed tuple here
+  VTable = array[0..1, pointer]
+  
+  TBase = object {.inheritable.}
+    vtbl: ptr VTable
+
+  TUserObject1 = object of TBase
+    x: int
+
+  TUserObject2 = object of TBase
+    y: int
+
+proc foo(o: var TUserObject1): int =
+  echo "OBJ 1 foo"
+  return 10
+
+proc bar(o: var TUserObject1) =
+  echo "OBJ 1 bar"
+
+proc foo(o: var TUserObject2): int =
+  echo "OBJ 2 foo"
+  return 5
+
+proc bar(o: var TUserObject2) =
+  echo "OBJ 2 bar"
+
+proc getVTable(T: typedesc): ptr VTable =
+  # pay attention to what's going on here
+  # this will initialize the vtable for each type at program start-up
+  #
+  # fooProc[T](foo) is a type coercion - it looks for a proc named foo
+  # matching the signature fooProc[T] (e.g. proc (o: var TUserObject1): int)
+  var vtbl {.global.} = [
+    cast[pointer](fooProc[T](foo)),
+    cast[pointer](barProc[T](bar))
+  ]
+
+  return vtbl.addr
+
+proc create(T: typedesc): T =
+  result.vtbl = getVTable(T)
+
+proc baseFoo(o: var TBase): int =
+  return cast[fooProc[TBase]](o.vtbl[0]) (o)
+
+proc baseBar(o: var TBase) =
+  cast[barProc[TBase]](o.vtbl[1]) (o)
+
+var a = TUserObject1.create
+var b = TUserObject2.create
+
+echo a.baseFoo
+a.baseBar
+
+echo b.baseFoo
+b.baseBar
+