summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorMax Zerzouri <maxdamantus@gmail.com>2015-03-04 11:52:48 +1300
committerMax Zerzouri <maxdamantus@gmail.com>2015-03-06 12:23:31 +1300
commitdba25d2622eb3b1414c847caa6d5a675ddc34344 (patch)
tree5f535a03c0d7e0d0a4fda7c3654fd2b76742ac49 /compiler
parent9c126282b2da1c3916627a81537a456e1aeb63c8 (diff)
downloadNim-dba25d2622eb3b1414c847caa6d5a675ddc34344.tar.gz
enable syntax for anonymous tuples.
Turns out to be slightly problematic as `(int, int)` could be logically
thought of as an expression evaluating to a tuple value containing
two typedesc[int]s.

To disambiguate, the zero-tuple's type must still be written as
`tuple[]`, and what would be tuple value expressions containing only
typedescs are interpreted as types.

() # value of type `tuple[]`
(int, int) # tuple type
(int, int, ()) # value of type `(typedesc[int], typedesc[int], tuple[])`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semexprs.nim17
-rw-r--r--compiler/semtypes.nim13
-rw-r--r--compiler/types.nim8
3 files changed, 31 insertions, 7 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 40d6ef0b2..5fa812f3a 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1866,6 +1866,14 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
     addSonSkipIntLit(typ, n.sons[i].typ)
   result.typ = typ
 
+proc isTupleType(n: PNode): bool =
+  if n.len == 0:
+    return false # don't interpret () as type
+  for i in countup(0, n.len - 1):
+    if n[i].typ == nil or n[i].typ.kind != tyTypeDesc:
+      return false
+  return true
+
 proc checkInitialized(n: PNode, ids: IntSet, info: TLineInfo) =
   case n.kind
   of nkRecList:
@@ -2129,7 +2137,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkPar: 
     case checkPar(n)
     of paNone: result = errorNode(c, n)
-    of paTuplePositions: result = semTuplePositionsConstr(c, n, flags)
+    of paTuplePositions:
+      var tupexp = semTuplePositionsConstr(c, n, flags)
+      if isTupleType(tupexp):
+        # reinterpret as type
+        var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc, tyIter})
+        result.typ = makeTypeDesc(c, typ)
+      else:
+        result = tupexp
     of paTupleFields: result = semTupleFieldsConstr(c, n, flags)
     of paSingle: result = semExpr(c, n.sons[0], flags)
   of nkCurly: result = semSetConstr(c, n)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 520c4154a..ac0636211 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -344,7 +344,14 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
     else:
       localError(n.info, errIdentifierExpected)
       result = errorSym(c, n)
-  
+
+proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType =
+  if sonsLen(n) == 0:
+    localError(n.info, errTypeExpected)
+  result = newOrPrevType(tyTuple, prev, c)
+  for i in countup(0, sonsLen(n) - 1):
+    addSonSkipIntLit(result, semTypeNode(c, n.sons[i], nil))
+
 proc semTuple(c: PContext, n: PNode, prev: PType): PType = 
   var typ: PType
   result = newOrPrevType(tyTuple, prev, c)
@@ -1116,9 +1123,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   of nkPar:
     if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
     else:
-      # XXX support anon tuple here
-      localError(n.info, errTypeExpected)
-      result = newOrPrevType(tyError, prev, c)
+      result = semAnonTuple(c, n, prev)
   of nkCallKinds:
     if isRange(n):
       result = semRangeAux(c, n, prev)
diff --git a/compiler/types.nim b/compiler/types.nim
index 0cc5a212b..89a3c6f96 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -507,18 +507,22 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       if prefer == preferModuleInfo: preferModuleInfo else: preferName)
   of tyTuple:
     # we iterate over t.sons here, because t.n may be nil
-    result = "tuple["
     if t.n != nil:
+      result = "tuple["
       assert(sonsLen(t.n) == sonsLen(t))
       for i in countup(0, sonsLen(t.n) - 1):
         assert(t.n.sons[i].kind == nkSym)
         add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
         if i < sonsLen(t.n) - 1: add(result, ", ")
+      add(result, ']')
+    elif sonsLen(t) == 0:
+      result = "tuple[]"
     else:
+      result = "("
       for i in countup(0, sonsLen(t) - 1):
         add(result, typeToString(t.sons[i]))
         if i < sonsLen(t) - 1: add(result, ", ")
-    add(result, ']')
+      add(result, ')')
   of tyPtr, tyRef, tyVar, tyMutable, tyConst:
     result = typeToStr[t.kind]
     if t.len >= 2: