slices are first class citizens
This commit is contained in:
parent
1985ac6995
commit
8dda362fa6
12 changed files with 177 additions and 127 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue