summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sigmatch.nim28
-rw-r--r--doc/manual.txt59
-rw-r--r--todo.txt1
-rw-r--r--web/news.txt1
4 files changed, 71 insertions, 18 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index a713fc0e2..9d1585c56 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -738,27 +738,17 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         result = typeRel(c, f.sons[0], a.sons[0])
         if result <= isConvertible: 
           result = isNone     # BUGFIX!
-  of tyPtr: 
-    case a.kind
-    of tyPtr:
-      for i in 0..min(f.len, a.len)-2:
+  of tyPtr, tyRef:
+    if a.kind == f.kind:
+      # ptr[R, T] can be passed to ptr[T], but not the other way round:
+      if a.len < f.len: return isNone
+      for i in 0..f.len-2:
         if typeRel(c, f.sons[i], a.sons[i]) == isNone: return isNone
       result = typeRel(c, f.lastSon, a.lastSon)
       if result <= isConvertible: result = isNone
       elif tfNotNil in f.flags and tfNotNil notin a.flags:
         result = isNilConversion
-    of tyNil: result = f.allowsNil
-    else: discard
-  of tyRef: 
-    case a.kind
-    of tyRef:
-      for i in 0..min(f.len, a.len)-2:
-        if typeRel(c, f.sons[i], a.sons[i]) == isNone: return isNone
-      result = typeRel(c, base(f), base(a))
-      if result <= isConvertible: result = isNone
-      elif tfNotNil in f.flags and tfNotNil notin a.flags:
-        result = isNilConversion
-    of tyNil: result = f.allowsNil
+    elif a.kind == tyNil: result = f.allowsNil
     else: discard
   of tyProc:
     result = procTypeRel(c, f, a)
@@ -774,7 +764,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     of tyNil: result = f.allowsNil
     of tyProc:
       if a.callConv != ccClosure: result = isConvertible
-    of tyPtr, tyCString: result = isConvertible
+    of tyPtr:
+      # 'pointer' is NOT compatible to regionized pointers
+      # so 'dealloc(regionPtr)' fails:
+      if a.len == 1: result = isConvertible
+    of tyCString: result = isConvertible
     else: discard
   of tyString: 
     case a.kind
diff --git a/doc/manual.txt b/doc/manual.txt
index 6526ba2cb..298f6329b 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -1366,6 +1366,65 @@ not nilable pointers. The details of this analysis are still to be specified
 here.
 
 
+Memory regions
+--------------
+
+The types ``ref`` and ``ptr`` can get an optional `region`:idx: annotation.
+A region has to be an object type.
+
+Regions are very useful to separate user space and kernel memory in the
+development of OS kernels:
+
+.. code-block:: nimrod
+  type
+    Kernel = object
+    Userspace = object
+
+  var a: ptr[Kernel, Stat]
+  var b: ptr[Userspace, Stat]
+
+  # the following does not compile as the pointer types are incompatible:
+  a = b
+
+In order to make generic code easier tor write ``ptr T`` is a subtype
+of ``ptr[R, T]`` for any ``R``.
+
+Furthermore the subtype relation of the region object types is lifted to
+the pointer types: If ``A <: B`` then ``ptr[T, A] <: ptr[T, B]``. This can be
+used to model subregions of memory. As a special typing rule ``ptr[R, T]`` is
+not compatible to ``pointer`` to prevent the following from compiling:
+
+.. code-block:: nimrod
+  # from system
+  proc dealloc(p: pointer)
+
+  # wrap some scripting language
+  type
+    PythonsHeap = object
+    PyObjectHeader = object
+      rc: int
+      typ: pointer
+    PyObject = ptr[PythonsHeap, PyObjectHeader]
+
+  proc createPyObject(): PyObject {.importc: "...".}
+  proc destroyPyObject(x: PyObject) {.importc: "...".}
+
+  var foo = createPyObject()
+  # type error here, how convenient:
+  dealloc(foo)
+
+
+Future directions:
+
+* Memory regions might become available for  ``string`` and ``seq`` too.
+* Bultin regions like ``private``, ``global`` and ``local`` will
+  prove very useful for the upcoming OpenCL target.
+* Bultin "regions" can model ``lent`` and ``unique`` pointers.
+* Syntactially ``ptr`` might become an infix operator so that ``region ptr T``
+  is transformed into ``ptr[region, T]``.
+
+
+
 Procedural type
 ---------------
 A `procedural type`:idx: is internally a pointer to a procedure. ``nil`` is
diff --git a/todo.txt b/todo.txt
index 6629bdeeb..bc7c7979a 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,6 @@
 version 0.9.4
 =============
 
-- document region pointers
 
 Bugs
 ====
diff --git a/web/news.txt b/web/news.txt
index 4aaf10992..f7a9d05fa 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -145,6 +145,7 @@ Language Additions
 - Anonymous iterators are now supported and iterators can capture variables
   of an outer proc.
 - The experimental ``strongSpaces`` parsing mode has been implemented.
+- You can annotate pointer types with regions for increased type safety.
 
 
 Tools improvements