summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-04-22 16:03:28 +0200
committerAraq <rumpf_a@web.de>2013-04-22 16:03:28 +0200
commitadc75d020180da8b83fc3d22f5dfbc54d71060a8 (patch)
treefaec23cb9dbb56a2d3fe6d825f9bedc41f3cca93
parentf7c7d95d8906b77df246bebd219133842033c2a1 (diff)
downloadNim-adc75d020180da8b83fc3d22f5dfbc54d71060a8.tar.gz
first version of commonType
-rw-r--r--compiler/sem.nim31
-rw-r--r--compiler/types.nim20
-rw-r--r--todo.txt6
3 files changed, 57 insertions, 0 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 805af9e31..88249fedb 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -58,6 +58,37 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
     result = copyNode(arg)
     result.typ = formal
 
+proc commonType*(x, y: PType): PType =
+  # new type relation that is used for array constructors,
+  # if expressions, etc.:
+  if x == nil: return y
+  var a = skipTypes(x, {tyGenericInst})
+  var b = skipTypes(y, {tyGenericInst})
+  result = x
+  if a.kind in {tyExpr, tyNil}: return y
+  elif b.kind in {tyExpr, tyNil}: return x
+  elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and 
+      a.kind == b.kind:
+    # check for seq[empty] vs. seq[int]
+    let idx = ord(b.kind in {tyArray, tyArrayConstr})
+    if a.sons[idx].kind == tyEmpty: return y
+    #elif b.sons[idx].kind == tyEmpty: return x
+  else:
+    var k = tyNone
+    if a.kind in {tyRef, tyPtr}:
+      k = a.kind
+      if b.kind != a.kind: return x
+      a = a.sons[0]
+      b = b.sons[0]
+    if a.kind == tyObject and b.kind == tyObject:
+      result = commonSuperclass(a, b)
+      # this will trigger an error later:
+      if result.isNil: return x
+      if k != tyNone:
+        let r = result
+        result = NewType(k, r.owner)
+        result.addSonSkipIntLit(r)
+
 proc isTopLevel(c: PContext): bool {.inline.} = 
   result = c.tab.tos <= 2
 
diff --git a/compiler/types.nim b/compiler/types.nim
index 4b528d9a2..5b1da74d4 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -904,6 +904,26 @@ proc inheritanceDiff*(a, b: PType): int =
     inc(result)
   result = high(int)
 
+proc commonSuperclass*(a, b: PType): PType =
+  # quick check: are they the same?
+  if sameObjectTypes(a, b): return a
+
+  # simple algorithm: we store all ancestors of 'a' in a ID-set and walk 'b'
+  # up until the ID is found:
+  assert a.kind == tyObject
+  assert b.kind == tyObject
+  var x = a
+  var ancestors = initIntSet()
+  while x != nil:
+    x = skipTypes(x, skipPtrs)
+    ancestors.incl(x.id)
+    x = x.sons[0]
+  var y = b
+  while y != nil:
+    y = skipTypes(y, skipPtrs)
+    if ancestors.contains(y.id): return y
+    y = y.sons[0]
+
 proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool
 proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind): bool = 
   result = true
diff --git a/todo.txt b/todo.txt
index dd41bf4a3..8b1ecd358 100644
--- a/todo.txt
+++ b/todo.txt
@@ -12,6 +12,12 @@ version 0.9.2
     allow 'of (var x = 23; nkIdent)'
   * allow (var x = 12; for i in ... ; x) construct
   * try except as an expression
+- make use of commonType relation in expressions
+- further expr/stmt unification:
+  - nkIfStmt vs nkIfExpr
+  - start with JS backend and support exprs everywhere
+  - then enhance C backend
+  - OR: do the temp stuff in transf
 
 Bugs
 ====