summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-04-22 10:53:43 +0200
committerAraq <rumpf_a@web.de>2011-04-22 10:53:43 +0200
commit8dda362fa67bcf75a24f2a60b7a124fdea319a64 (patch)
tree7e43b56fd522040989c5c64ddfef9ffab08b8594 /compiler
parent1985ac69951932d2882b63b13f9dcd853dd80c43 (diff)
downloadNim-8dda362fa67bcf75a24f2a60b7a124fdea319a64.tar.gz
slices are first class citizens
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/parser.nim41
-rwxr-xr-xcompiler/semexprs.nim28
-rwxr-xr-xcompiler/semstmts.nim19
-rwxr-xr-xcompiler/semtypes.nim42
-rwxr-xr-xcompiler/trees.nim12
5 files changed, 67 insertions, 75 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim
index b579d20be..c7e9cbac7 100755
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -123,7 +123,8 @@ proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode =
   result = newNodeP(kind, p)
   result.intVal = intVal
 
-proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, p: TParser): PNode = 
+proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, 
+                   p: TParser): PNode =
   result = newNodeP(kind, p)
   result.floatVal = floatVal
 
@@ -147,16 +148,18 @@ proc getPrecedence(tok: PToken): int =
   case tok.tokType
   of tkOpr: 
     case tok.ident.s[0]
-    of '$', '^': result = 7
-    of '*', '%', '/', '\\': result = 6
-    of '+', '-', '~', '|': result = 5
-    of '&': result = 4
-    of '=', '<', '>', '!': result = 3
-    else: result = 0
-  of tkDiv, tkMod, tkShl, tkShr: result = 6
-  of tkIn, tkNotIn, tkIs, tkIsNot: result = 3
-  of tkAnd: result = 2
-  of tkOr, tkXor: result = 1
+    of '$', '^': result = 9
+    of '*', '%', '/', '\\': result = 8
+    of '+', '-', '~', '|': result = 7
+    of '&': result = 6
+    of '=', '<', '>', '!': result = 4
+    of '.': result = 5
+    else: result = 1
+  of tkDiv, tkMod, tkShl, tkShr: result = 8
+  of tkIn, tkNotIn, tkIs, tkIsNot, tkNot: result = 4
+  of tkDotDot: result = 5
+  of tkAnd: result = 3
+  of tkOr, tkXor: result = 2
   else: result = - 10
   
 proc isOperator(tok: PToken): bool = 
@@ -202,7 +205,7 @@ proc parseSymbol(p: var TParser): PNode =
       addSon(result, newIdentNodeP(getIdent("()"), p))
       getTok(p)
       eat(p, tkParRi)
-    of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr: 
+    of tokKeywordLow..tokKeywordHigh, tkSymbol, tkOpr, tkDotDot: 
       var id = p.tok.ident
       getTok(p)
       if p.tok.tokType == tkEquals: 
@@ -494,7 +497,7 @@ proc identOrLiteral(p: var TParser): PNode =
 
 proc primary(p: var TParser): PNode = 
   # prefix operator?
-  if (p.tok.tokType == tkNot) or (p.tok.tokType == tkOpr): 
+  if isOperator(p.tok):
     result = newNodeP(nkPrefix, p)
     var a = newIdentNodeP(p.tok.ident, p)
     addSon(result, a)
@@ -553,18 +556,8 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): PToken =
     opPrec = getPrecedence(nextop)
   result = op                 # return first untreated operator
   
-proc otherExpr(p: var TParser): PNode = 
-  discard lowestExprAux(p, result, - 1)
-
 proc lowestExpr(p: var TParser): PNode = 
-  result = otherExpr(p)
-  while p.tok.tokType == tkDotDot:
-    getTok(p)
-    optInd(p, result)
-    var a = result
-    result = newNodeP(nkRange, p)
-    addSon(result, a)
-    addSon(result, otherExpr(p))
+  discard lowestExprAux(p, result, - 1)
 
 proc parseIfExpr(p: var TParser): PNode = 
   result = newNodeP(nkIfExpr, p)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 8f8a1dc17..56de998f5 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -828,15 +828,20 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
     # only semantic checking for all elements, later type checking:
     var typ: PType = nil
     for i in countup(0, sonsLen(n) - 1): 
-      if n.sons[i].kind == nkRange: 
-        checkSonsLen(n.sons[i], 2)
-        n.sons[i].sons[0] = semExprWithType(c, n.sons[i].sons[0])
+      if isRange(n.sons[i]): 
+        checkSonsLen(n.sons[i], 3)
         n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
+        n.sons[i].sons[2] = semExprWithType(c, n.sons[i].sons[2])
         if typ == nil: 
+          typ = skipTypes(n.sons[i].sons[1].typ, 
+                          {tyGenericInst, tyVar, tyOrdinal})
+        n.sons[i].typ = n.sons[i].sons[2].typ # range node needs type too
+      elif n.sons[i].kind == nkRange:
+        # already semchecked
+        if typ == nil:
           typ = skipTypes(n.sons[i].sons[0].typ, 
                           {tyGenericInst, tyVar, tyOrdinal})
-        n.sons[i].typ = n.sons[i].sons[1].typ # range node needs type too
-      else: 
+      else:
         n.sons[i] = semExprWithType(c, n.sons[i])
         if typ == nil: 
           typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
@@ -848,11 +853,12 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
     addSon(result.typ, typ)
     for i in countup(0, sonsLen(n) - 1): 
       var m: PNode
-      if n.sons[i].kind == nkRange: 
+      if isRange(n.sons[i]):
         m = newNodeI(nkRange, n.sons[i].info)
-        addSon(m, fitNode(c, typ, n.sons[i].sons[0]))
         addSon(m, fitNode(c, typ, n.sons[i].sons[1]))
-      else: 
+        addSon(m, fitNode(c, typ, n.sons[i].sons[2]))
+      elif n.sons[i].kind == nkRange: m = n.sons[i] # already semchecked
+      else:
         m = fitNode(c, typ, n.sons[i])
       addSon(result, m)
 
@@ -1086,7 +1092,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     checkMinSonsLen(n, 2)
   of nkSymChoice: 
     GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
-  else: 
-    #InternalError(n.info, nodeKindToStr[n.kind]);
-    GlobalError(n.info, errInvalidExpressionX, renderTree(n, {renderNoComments}))
+  else:
+    GlobalError(n.info, errInvalidExpressionX, 
+                renderTree(n, {renderNoComments}))
   incl(result.flags, nfSem)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 71d523540..0a3daf79c 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -339,11 +339,11 @@ proc semConst(c: PContext, n: PNode): PNode =
     if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
     var def = semAndEvalConstExpr(c, a.sons[2]) 
     # check type compability between def.typ and typ:
-    if (typ != nil): 
+    if typ != nil:
       def = fitRemoveHiddenConv(c, typ, def)
-    else: 
+    else:
       typ = def.typ
-    if not typeAllowed(typ, skConst): 
+    if not typeAllowed(typ, skConst):
       GlobalError(a.info, errXisNoType, typeToString(typ))
     v.typ = typ
     v.ast = def               # no need to copy
@@ -423,25 +423,12 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
   var b = newNodeI(nkBreakStmt, n.info)
   b.add(ast.emptyNode)
   stmts.add(b)
-  
-proc createCountupNode(c: PContext, rangeNode: PNode): PNode = 
-  # convert ``in 3..5`` to ``in countup(3, 5)``
-  checkSonsLen(rangeNode, 2)
-  result = newNodeI(nkCall, rangeNode.info)
-  var countUp = StrTableGet(magicsys.systemModule.Tab, getIdent"countup")
-  if countUp == nil: GlobalError(rangeNode.info, errSystemNeeds, "countup")
-  newSons(result, 3)
-  result.sons[0] = newSymNode(countup)
-  result.sons[1] = rangeNode.sons[0]
-  result.sons[2] = rangeNode.sons[1]
 
 proc semFor(c: PContext, n: PNode): PNode = 
   result = n
   checkMinSonsLen(n, 3)
   var length = sonsLen(n)
   openScope(c.tab)
-  if n.sons[length-2].kind == nkRange:
-    n.sons[length-2] = createCountupNode(c, n.sons[length-2])
   n.sons[length-2] = semExprWithType(c, n.sons[length-2], {efWantIterator})
   var call = n.sons[length-2]
   if call.kind != nkCall or call.sons[0].kind != nkSym or
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index bb0bcdf93..ed9b9f4d5 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -116,14 +116,14 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
   else: GlobalError(n.info, errXExpectsOneTypeParam, "distinct")
   
 proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = 
-  if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
-  checkSonsLen(n, 2)
+  assert IsRange(n)
+  checkSonsLen(n, 3)
   result = newOrPrevType(tyRange, prev, c)
   result.n = newNodeI(nkRange, n.info)
-  if (n.sons[0].kind == nkEmpty) or (n.sons[1].kind == nkEmpty): 
+  if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): 
     GlobalError(n.Info, errRangeIsEmpty)
-  var a = semConstExpr(c, n.sons[0])
-  var b = semConstExpr(c, n.sons[1])
+  var a = semConstExpr(c, n[1])
+  var b = semConstExpr(c, n[2])
   if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch)
   if not (a.typ.kind in
       {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): 
@@ -138,7 +138,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
 proc semRange(c: PContext, n: PNode, prev: PType): PType = 
   result = nil
   if sonsLen(n) == 2: 
-    if n.sons[1].kind == nkRange: result = semRangeAux(c, n.sons[1], prev)
+    if isRange(n[1]): result = semRangeAux(c, n[1], prev)
     else: GlobalError(n.sons[0].info, errRangeExpected)
   else: 
     GlobalError(n.info, errXExpectsOneTypeParam, "range")
@@ -148,7 +148,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
   result = newOrPrevType(tyArray, prev, c)
   if sonsLen(n) == 3: 
     # 3 = length(array indx base)
-    if n.sons[1].kind == nkRange: indx = semRangeAux(c, n.sons[1], nil)
+    if isRange(n[1]): indx = semRangeAux(c, n[1], nil)
     else: indx = semTypeNode(c, n.sons[1], nil)
     addSon(result, indx)
     if indx.kind == tyGenericInst: indx = lastSon(indx)
@@ -276,26 +276,26 @@ proc checkForOverlap(c: PContext, t, ex: PNode, branchIndex: int) =
       if overlap(t.sons[i].sons[j], ex): 
         LocalError(ex.info, errDuplicateCaseLabel)
   
-proc semBranchExpr(c: PContext, t: PNode, ex: var PNode) = 
-  ex = semConstExpr(c, ex)
+proc semBranchExpr(c: PContext, t, e: PNode): PNode = 
+  result = semConstExpr(c, e)
   checkMinSonsLen(t, 1)
-  if (cmpTypes(t.sons[0].typ, ex.typ) <= isConvertible): 
-    typeMismatch(ex, t.sons[0].typ, ex.typ)
+  if cmpTypes(t.sons[0].typ, result.typ) <= isConvertible: 
+    typeMismatch(result, t.sons[0].typ, result.typ)
 
 proc SemCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, 
                    covered: var biggestInt) = 
   for i in countup(0, sonsLen(branch) - 2): 
     var b = branch.sons[i]
-    if b.kind == nkRange: 
-      checkSonsLen(b, 2)
-      semBranchExpr(c, t, b.sons[0])
-      semBranchExpr(c, t, b.sons[1])
-      if emptyRange(b.sons[0], b.sons[1]): 
-        #MessageOut(renderTree(t));
-        GlobalError(b.info, errRangeIsEmpty)
-      covered = covered + getOrdValue(b.sons[1]) - getOrdValue(b.sons[0]) + 1
-    else: 
-      semBranchExpr(c, t, branch.sons[i]) # NOT: `b`, because of var-param!
+    if isRange(b): 
+      checkSonsLen(b, 3)
+      var r = newNodeI(nkRange, b.info)
+      r.add(semBranchExpr(c, t, b.sons[1]))
+      r.add(semBranchExpr(c, t, b.sons[2]))
+      if emptyRange(r[0], r[1]): GlobalError(b.info, errRangeIsEmpty)
+      covered = covered + getOrdValue(r[1]) - getOrdValue(r[0]) + 1
+      branch.sons[i] = r
+    else:
+      branch.sons[i] = semBranchExpr(c, t, b)
       inc(covered)
     checkForOverlap(c, t, branch.sons[i], branchIndex)
 
diff --git a/compiler/trees.nim b/compiler/trees.nim
index 54f688103..3c8775b87 100755
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2008 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -10,7 +10,7 @@
 # tree helper routines
 
 import 
-  ast, astalgo, lexer, msgs, strutils
+  ast, astalgo, lexer, msgs, strutils, wordrecg
 
 proc getMagic*(op: PNode): TMagic
 
@@ -106,7 +106,8 @@ proc getOpSym(op: PNode): PSym =
   
 proc getMagic(op: PNode): TMagic = 
   case op.kind
-  of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit: 
+  of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkPrefix, nkPostfix,
+     nkInfix: 
     case op.sons[0].Kind
     of nkSym: result = op.sons[0].sym.magic
     else: result = mNone
@@ -138,3 +139,8 @@ proc SwapOperands(op: PNode) =
   var tmp = op.sons[1]
   op.sons[1] = op.sons[2]
   op.sons[2] = tmp
+
+proc IsRange*(n: PNode): bool {.inline.} = 
+  result = n.kind == nkInfix and n[0].kind == nkIdent and 
+    n[0].ident.id == ord(wDotDot)
+