diff options
author | Araq <rumpf_a@web.de> | 2013-04-22 16:03:28 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-04-22 16:03:28 +0200 |
commit | adc75d020180da8b83fc3d22f5dfbc54d71060a8 (patch) | |
tree | faec23cb9dbb56a2d3fe6d825f9bedc41f3cca93 | |
parent | f7c7d95d8906b77df246bebd219133842033c2a1 (diff) | |
download | Nim-adc75d020180da8b83fc3d22f5dfbc54d71060a8.tar.gz |
first version of commonType
-rw-r--r-- | compiler/sem.nim | 31 | ||||
-rw-r--r-- | compiler/types.nim | 20 | ||||
-rw-r--r-- | todo.txt | 6 |
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 ==== |