diff options
author | Araq <rumpf_a@web.de> | 2011-04-22 10:53:43 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-04-22 10:53:43 +0200 |
commit | 8dda362fa67bcf75a24f2a60b7a124fdea319a64 (patch) | |
tree | 7e43b56fd522040989c5c64ddfef9ffab08b8594 /compiler | |
parent | 1985ac69951932d2882b63b13f9dcd853dd80c43 (diff) | |
download | Nim-8dda362fa67bcf75a24f2a60b7a124fdea319a64.tar.gz |
slices are first class citizens
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/parser.nim | 41 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 28 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 19 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 42 | ||||
-rwxr-xr-x | compiler/trees.nim | 12 |
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) + |