first step to get rid of nil in the AST

This commit is contained in:
Araq
2011-02-09 00:26:41 +01:00
parent 134f24f579
commit 27dc54cbda
17 changed files with 505 additions and 436 deletions

View File

@@ -577,12 +577,10 @@ proc newSons*(father: PNode, length: int)
proc newSons*(father: PType, length: int)
proc addSon*(father, son: PNode)
proc addSon*(father, son: PType)
proc addSonIfNotNil*(father, n: PNode)
proc delSon*(father: PNode, idx: int)
proc hasSonWith*(n: PNode, kind: TNodeKind): bool
proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool
proc replaceSons*(n: PNode, oldKind, newKind: TNodeKind)
proc sonsNotNil*(n: PNode): bool
proc copyNode*(src: PNode): PNode
# does not copy its sons!
proc copyTree*(src: PNode): PNode
@@ -590,6 +588,10 @@ proc copyTree*(src: PNode): PNode
proc discardSons*(father: PNode)
var emptyNode* = newNode(nkEmpty)
# There is a single empty node that is shared! Do not overwrite it!
const # for all kind of hash tables:
GrowthFactor* = 2 # must be power of 2, > 0
StartSize* = 8 # must be power of 2, > 0
@@ -868,6 +870,7 @@ proc len*(n: PNode): int {.inline.} =
else: result = len(n.sons)
proc add*(father, son: PNode) =
assert son != nil
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
@@ -879,6 +882,7 @@ proc newSons(father: PNode, length: int) =
setlen(father.sons, len(father.sons) + length)
proc addSon(father, son: PNode) =
assert son != nil
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
@@ -947,7 +951,7 @@ proc lastSon(n: PType): PType =
proc hasSonWith(n: PNode, kind: TNodeKind): bool =
for i in countup(0, sonsLen(n) - 1):
if (n.sons[i] != nil) and (n.sons[i].kind == kind):
if n.sons[i].kind == kind:
return true
result = false
@@ -956,9 +960,8 @@ proc hasSubnodeWith(n: PNode, kind: TNodeKind): bool =
of nkEmpty..nkNilLit: result = n.kind == kind
else:
for i in countup(0, sonsLen(n) - 1):
if n.sons[i] != nil:
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
return true
if (n.sons[i].kind == kind) or hasSubnodeWith(n.sons[i], kind):
return true
result = false
proc replaceSons(n: PNode, oldKind, newKind: TNodeKind) =
@@ -971,9 +974,6 @@ proc sonsNotNil(n: PNode): bool =
return false
result = true
proc addSonIfNotNil(father, n: PNode) =
if n != nil: addSon(father, n)
proc getInt*(a: PNode): biggestInt =
case a.kind
of nkIntLit..nkInt64Lit: result = a.intVal

View File

@@ -1,7 +1,7 @@
#
#
# c2nim - C to Nimrod source converter
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -15,7 +15,7 @@ const
Version = NimrodVersion
Usage = """
c2nim - C to Nimrod source converter
(c) 2010 Andreas Rumpf
(c) 2011 Andreas Rumpf
Usage: c2nim [options] inputfile [options]
Options:
-o, --out:FILE set output filename

View File

@@ -197,7 +197,7 @@ proc parLineInfo(p: TParser): TLineInfo =
result = getLineInfo(p.lex)
proc skipComAux(p: var TParser, n: PNode) =
if (n != nil):
if n != nil and n.kind != nkEmpty:
if pfSkipComments notin p.options.flags:
if n.comment == nil: n.comment = p.tok.s
else: add(n.comment, "\n" & p.tok.s)
@@ -216,8 +216,7 @@ proc getTok(p: var TParser, n: PNode) =
skipCom(p, n)
proc ExpectIdent(p: TParser) =
if p.tok.xkind != pxSymbol:
parMessage(p, errIdentifierExpected, $(p.tok^))
if p.tok.xkind != pxSymbol: parMessage(p, errIdentifierExpected, $(p.tok^))
proc Eat(p: var TParser, xkind: TTokKind, n: PNode) =
if p.tok.xkind == xkind: getTok(p, n)
@@ -375,7 +374,7 @@ proc skipTypeIdentExport(p: var TParser, prefix='T'): PNode =
proc markTypeIdent(p: var TParser, typ: PNode) =
if pfTypePrefixes in p.options.flags:
var prefix = ""
if typ == nil:
if typ == nil or typ.kind == nkEmpty:
prefix = "T"
else:
var t = typ
@@ -479,11 +478,12 @@ proc newProcPragmas(p: TParser): PNode =
proc addPragmas(father, pragmas: PNode) =
if sonsLen(pragmas) > 0: addSon(father, pragmas)
else: addSon(father, nil)
else: addSon(father, ast.emptyNode)
proc addReturnType(params, rettyp: PNode) =
if rettyp == nil or rettyp.kind != nkNilLit: addSon(params, rettyp)
else: addson(params, nil)
if rettyp == nil: addSon(params, ast.emptyNode)
elif rettyp.kind != nkNilLit: addSon(params, rettyp)
else: addson(params, ast.emptyNode)
proc parseFormalParams(p: var TParser, params, pragmas: PNode)
@@ -527,9 +527,6 @@ proc parseTypeSuffix(p: var TParser, typ: PNode): PNode =
else: break
proc typeDesc(p: var TParser): PNode =
#result = typeAtom(p)
#if result != nil:
# result = pointer(p, result)
result = pointer(p, typeAtom(p))
proc parseField(p: var TParser, kind: TNodeKind): PNode =
@@ -560,7 +557,7 @@ proc parseStructBody(p: var TParser, isUnion: bool,
var t = pointer(p, baseTyp)
var i = parseField(p, kind)
t = parseTypeSuffix(p, t)
addSon(def, i, t, nil)
addSon(def, i, t, ast.emptyNode)
if not takeOnlyFirstField(p, isUnion) or sonsLen(result) < 1:
addSon(result, def)
if p.tok.xkind != pxComma: break
@@ -591,7 +588,7 @@ proc enumPragmas(p: TParser, name: PNode): PNode =
proc parseStruct(p: var TParser, isUnion: bool): PNode =
result = newNodeP(nkObjectTy, p)
addSon(result, nil, nil) # no pragmas, no inheritance
addSon(result, ast.emptyNode, ast.emptyNode) # no pragmas, no inheritance
if p.tok.xkind == pxCurlyLe:
addSon(result, parseStructBody(p, isUnion))
else:
@@ -616,7 +613,7 @@ proc parseParam(p: var TParser, params: PNode) =
getTok(p, x)
addSon(x, assignmentExpression(p))
else:
addSon(x, nil)
addSon(x, ast.emptyNode)
addSon(params, x)
proc parseFormalParams(p: var TParser, params, pragmas: PNode) =
@@ -662,15 +659,16 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
if p.inTypeDef == 0:
result = newNodeP(nkVarSection, p)
var def = newNodeP(nkIdentDefs, p)
addSon(def, name, procType, nil)
addSon(def, name, procType, ast.emptyNode)
addSon(result, def)
else:
result = newNodeP(nkTypeDef, p)
addSon(result, name, nil, procType)
addSon(result, name, ast.emptyNode, procType)
assert result != nil
proc addTypeDef(section, name, t: PNode) =
var def = newNodeI(nkTypeDef, name.info)
addSon(def, name, nil, t)
addSon(def, name, ast.emptyNode, t)
addSon(section, def)
proc otherTypeDef(p: var TParser, section, typ: PNode) =
@@ -705,7 +703,7 @@ proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) =
proc enumFields(p: var TParser): PNode =
result = newNodeP(nkEnumTy, p)
addSon(result, nil) # enum does not inherit from anything
addSon(result, ast.emptyNode) # enum does not inherit from anything
while true:
var e = skipIdent(p)
if p.tok.xkind == pxAsgn:
@@ -846,7 +844,7 @@ proc addInitializer(p: var TParser, def: PNode) =
getTok(p, def)
addSon(def, parseInitializer(p))
else:
addSon(def, nil)
addSon(def, ast.emptyNode)
proc parseVarDecl(p: var TParser, baseTyp, typ: PNode,
origName: string): PNode =
@@ -921,22 +919,24 @@ proc declaration(p: var TParser): PNode =
addSon(pragmas, newIdentNodeP("cdecl", p))
elif pfStdcall in p.options.flags:
addSon(pragmas, newIdentNodeP("stdcall", p))
addSon(result, exportSym(p, name, origName), nil) # no generics
addSon(result, exportSym(p, name, origName), ast.emptyNode) # no generics
addSon(result, params, pragmas)
case p.tok.xkind
of pxSemicolon:
getTok(p)
addSon(result, nil) # nobody
addSon(result, ast.emptyNode) # nobody
if p.scopeCounter == 0: DoImport(origName, pragmas, p)
of pxCurlyLe:
addSon(result, compoundStatement(p))
else:
parMessage(p, errTokenExpected, ";")
if sonsLen(result.sons[pragmasPos]) == 0: result.sons[pragmasPos] = nil
if sonsLen(result.sons[pragmasPos]) == 0:
result.sons[pragmasPos] = ast.emptyNode
of pxAsgn, pxSemicolon, pxComma:
result = parseVarDecl(p, baseTyp, rettyp, origName)
else:
parMessage(p, errTokenExpected, ";")
assert result != nil
proc createConst(name, typ, val: PNode, p: TParser): PNode =
result = newNodeP(nkConstDef, p)
@@ -963,7 +963,7 @@ proc enumSpecifier(p: var TParser): PNode =
else:
val = newIntNodeP(nkIntLit, i, p)
inc(i)
var c = createConst(name, nil, val, p)
var c = createConst(name, ast.emptyNode, val, p)
addSon(result, c)
if p.tok.xkind != pxComma: break
getTok(p, c)
@@ -984,7 +984,7 @@ proc enumSpecifier(p: var TParser): PNode =
var t = newNodeP(nkTypeDef, p)
getTok(p, t)
var e = enumFields(p)
addSon(t, exportSym(p, name, origName), nil, e) # nil for generic params
addSon(t, exportSym(p, name, origName), ast.emptyNode, e)
addSon(result, t)
eat(p, pxCurlyRi, result)
eat(p, pxSemicolon)
@@ -998,6 +998,7 @@ proc enumSpecifier(p: var TParser): PNode =
else:
closeContext(p)
parMessage(p, errTokenExpected, "{")
result = ast.emptyNode
# Expressions
@@ -1085,7 +1086,7 @@ proc primaryExpression(p: var TParser): PNode =
of pxParLe:
result = castExpression(p)
else:
result = nil
result = ast.emptyNode
proc multiplicativeExpression(p: var TParser): PNode =
result = castExpression(p)
@@ -1309,7 +1310,7 @@ proc andExpression(p: var TParser): PNode =
getTok(p, result)
var a = result
var b = equalityExpression(p)
result = newBinary("&", a, b, p)
result = newBinary("and", a, b, p)
proc exclusiveOrExpression(p: var TParser): PNode =
result = andExpression(p)
@@ -1390,10 +1391,12 @@ proc expressionStatement(p: var TParser): PNode =
# do not skip the comment after a semicolon to make a new nkCommentStmt
if p.tok.xkind == pxSemicolon:
getTok(p)
result = ast.emptyNode
else:
result = expression(p)
if p.tok.xkind == pxSemicolon: getTok(p)
else: parMessage(p, errTokenExpected, ";")
assert result != nil
proc parseIf(p: var TParser): PNode =
# we parse additional "else if"s too here for better Nimrod code
@@ -1431,7 +1434,7 @@ proc parseDoWhile(p: var TParser): PNode =
# ``block: stmt``
result = newNodeP(nkBlockStmt, p)
getTok(p, result) # skip "do"
addSon(result, nil, nestedStatement(p))
addSon(result, ast.emptyNode, nestedStatement(p))
eat(p, "while", result)
eat(p, pxParLe, result)
if p.tok.xkind == pxIntLit and p.tok.iNumber == 0: getTok(p, result)
@@ -1465,6 +1468,7 @@ proc declarationOrStatement(p: var TParser): PNode =
else:
backtrackContext(p)
result = expressionStatement(p)
assert result != nil
proc parseTuple(p: var TParser, isUnion: bool): PNode =
result = parseStructBody(p, isUnion, nkTupleTy)
@@ -1516,15 +1520,16 @@ proc parseFor(p: var TParser, result: PNode) =
getTok(p, result)
eat(p, pxParLe, result)
var initStmt = declarationOrStatement(p)
addSonIfNotNil(result, initStmt)
if initStmt.kind != nkEmpty:
addSon(result, initStmt)
var w = newNodeP(nkWhileStmt, p)
var condition = expressionStatement(p)
if condition == nil: condition = newIdentNodeP("true", p)
if condition.kind == nkEmpty: condition = newIdentNodeP("true", p)
addSon(w, condition)
var step = if p.tok.xkind != pxParRi: expression(p) else: nil
var step = if p.tok.xkind != pxParRi: expression(p) else: ast.emptyNode
eat(p, pxParRi, step)
var loopBody = nestedStatement(p)
if step != nil:
if step.kind != nkEmpty:
loopBody = buildStmtList(loopBody)
addSon(loopBody, step)
addSon(w, loopBody)
@@ -1604,7 +1609,7 @@ proc embedStmts(sl, a: PNode) =
addStmt(sl, a)
else:
for i in 0..sonsLen(a)-1:
if a[i] != nil: addStmt(sl, a[i])
if a[i].kind != nkEmpty: addStmt(sl, a[i])
proc compoundStatement(p: var TParser): PNode =
result = newNodeP(nkStmtList, p)
@@ -1612,7 +1617,7 @@ proc compoundStatement(p: var TParser): PNode =
inc(p.scopeCounter)
while p.tok.xkind notin {pxEof, pxCurlyRi}:
var a = statement(p)
if a == nil: break
if a.kind == nkEmpty: break
embedStmts(result, a)
if sonsLen(result) == 0:
# translate ``{}`` to Nimrod's ``nil`` statement
@@ -1644,12 +1649,12 @@ proc statement(p: var TParser): PNode =
result = newNodeP(nkContinueStmt, p)
getTok(p)
eat(p, pxSemicolon)
addSon(result, nil)
addSon(result, ast.emptyNode)
of "break":
result = newNodeP(nkBreakStmt, p)
getTok(p)
eat(p, pxSemicolon)
addSon(result, nil)
addSon(result, ast.emptyNode)
of "return":
result = newNodeP(nkReturnStmt, p)
getTok(p)
@@ -1662,18 +1667,13 @@ proc statement(p: var TParser): PNode =
elif p.tok.xkind != pxSemicolon:
addSon(result, expression(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
eat(p, pxSemicolon)
of "enum":
result = enumSpecifier(p)
of "typedef":
result = parseTypeDef(p)
of "struct":
result = parseStandaloneStruct(p, isUnion=false)
of "union":
result = parseStandaloneStruct(p, isUnion=true)
else:
result = declarationOrStatement(p)
of "enum": result = enumSpecifier(p)
of "typedef": result = parseTypeDef(p)
of "struct": result = parseStandaloneStruct(p, isUnion=false)
of "union": result = parseStandaloneStruct(p, isUnion=true)
else: result = declarationOrStatement(p)
of pxCurlyLe:
result = compoundStatement(p)
of pxDirective, pxDirectiveParLe:
@@ -1691,12 +1691,12 @@ proc statement(p: var TParser): PNode =
result = newNodeP(nkNilLit, p)
else:
result = expressionStatement(p)
#parMessage(p, errStmtExpected)
assert result != nil
proc parseUnit(p: var TParser): PNode =
result = newNodeP(nkStmtList, p)
getTok(p) # read first token
while p.tok.xkind != pxEof:
var s = statement(p)
if s != nil: embedStmts(result, s)
if s.kind != nkEmpty: embedStmts(result, s)

View File

@@ -45,7 +45,7 @@ proc parseDefine(p: var TParser): PNode =
eat(p, pxParLe)
var params = newNodeP(nkFormalParams, p)
# return type; not known yet:
addSon(params, nil)
addSon(params, ast.emptyNode)
var identDefs = newNodeP(nkIdentDefs, p)
while p.tok.xkind != pxParRi:
addSon(identDefs, skipIdent(p))
@@ -53,13 +53,13 @@ proc parseDefine(p: var TParser): PNode =
if p.tok.xkind != pxComma: break
getTok(p)
addSon(identDefs, newIdentNodeP("expr", p))
addSon(identDefs, nil)
addSon(identDefs, ast.emptyNode)
addSon(params, identDefs)
eat(p, pxParRi)
addSon(result, nil) # no generic parameters
addSon(result, ast.emptyNode) # no generic parameters
addSon(result, params)
addSon(result, nil) # no pragmas
addSon(result, ast.emptyNode) # no pragmas
var kind = parseDefineBody(p, result)
params.sons[0] = newIdentNodeP(kind, p)
eatNewLine(p, result)
@@ -70,7 +70,7 @@ proc parseDefine(p: var TParser): PNode =
getTok(p) # skip #define
var c = newNodeP(nkConstDef, p)
addSon(c, skipIdentExport(p))
addSon(c, nil)
addSon(c, ast.emptyNode)
skipStarCom(p, c)
if p.tok.xkind in {pxLineComment, pxNewLine, pxEof}:
addSon(c, newIdentNodeP("true", p))
@@ -78,6 +78,7 @@ proc parseDefine(p: var TParser): PNode =
addSon(c, expression(p))
addSon(result, c)
eatNewLine(p, c)
assert result != nil
proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) =
m.body = @[]
@@ -147,7 +148,7 @@ proc parseInclude(p: var TParser): PNode =
skipLine(p)
if sonsLen(result) == 0:
# we only parsed includes that we chose to ignore:
result = nil
result = ast.emptyNode
proc definedExprAux(p: var TParser): PNode =
result = newNodeP(nkCall, p)
@@ -226,6 +227,7 @@ proc parseIfdef(p: var TParser): PNode =
case p.tok.s
of "__cplusplus":
skipUntilEndif(p)
result = ast.emptyNode
of c2nimSymbol:
skipLine(p)
result = parseStmtList(p)
@@ -238,6 +240,7 @@ proc parseIfdef(p: var TParser): PNode =
parseIfDirAux(p, result)
proc parseIfndef(p: var TParser): PNode =
result = ast.emptyNode
getTok(p) # skip #ifndef
ExpectIdent(p)
if p.tok.s == c2nimSymbol:
@@ -295,6 +298,7 @@ proc parseMangleDir(p: var TParser) =
eatNewLine(p, nil)
proc parseDir(p: var TParser): PNode =
result = ast.emptyNode
assert(p.tok.xkind in {pxDirective, pxDirectiveParLe})
case p.tok.s
of "define": result = parseDefine(p)

View File

@@ -29,7 +29,6 @@ proc addDependencyAux(importing, imported: string) =
proc addDotDependency(c: PPassContext, n: PNode): PNode =
result = n
if n == nil: return
var g = PGen(c)
case n.kind
of nkImportStmt:

View File

@@ -771,7 +771,6 @@ proc traceDeps(d: PDoc, n: PNode) =
"$1", [toRope(getModuleFile(n))])
proc generateDoc(d: PDoc, n: PNode) =
if n == nil: return
case n.kind
of nkCommentStmt: app(d.modDesc, genComment(d, n))
of nkProcDef: genItem(d, n, n.sons[namePos], skProc)

View File

@@ -54,8 +54,6 @@ const
evalMaxIterations = 10000000 # max iterations of all loops
evalMaxRecDepth = 100000 # max recursion depth for evaluation
var emptyNode: PNode
proc newStackFrame(): PStackFrame =
new(result)
initIdNodeTable(result.mapping)
@@ -136,7 +134,7 @@ proc evalWhile(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1], {})
case result.kind
of nkBreakStmt:
if result.sons[0] == nil:
if result.sons[0].kind == nkEmpty:
result = emptyNode # consume ``break`` token
break
of nkExceptBranch, nkReturnToken:
@@ -153,7 +151,7 @@ proc evalBlock(c: PEvalContext, n: PNode): PNode =
if result.kind == nkBreakStmt:
if result.sons[0] != nil:
assert(result.sons[0].kind == nkSym)
if n.sons[0] != nil:
if n.sons[0].kind != nkempty:
assert(n.sons[0].kind == nkSym)
if result.sons[0].sym.id == n.sons[0].sym.id: result = emptyNode
else:
@@ -228,7 +226,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
assert(a.kind == nkIdentDefs)
assert(a.sons[0].kind == nkSym)
var v = a.sons[0].sym
if a.sons[2] != nil:
if a.sons[2].kind != nkEmpty:
result = evalAux(c, a.sons[2], {})
if isSpecial(result): return
else:
@@ -507,7 +505,7 @@ proc evalConvCStrToStr(c: PEvalContext, n: PNode): PNode =
result.typ = n.typ
proc evalRaise(c: PEvalContext, n: PNode): PNode =
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
result = evalAux(c, n.sons[0], {})
if isSpecial(result): return
var a = result
@@ -519,17 +517,17 @@ proc evalRaise(c: PEvalContext, n: PNode): PNode =
else:
stackTrace(c, n, errExceptionAlreadyHandled)
result = newNodeIT(nkExceptBranch, n.info, nil)
addSon(result, nil)
addSon(result, ast.emptyNode)
proc evalReturn(c: PEvalContext, n: PNode): PNode =
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
result = evalAsgn(c, n.sons[0])
if isSpecial(result): return
result = newNodeIT(nkReturnToken, n.info, nil)
proc evalProc(c: PEvalContext, n: PNode): PNode =
if n.sons[genericParamsPos] == nil:
if (resultPos < sonsLen(n)) and (n.sons[resultPos] != nil):
if n.sons[genericParamsPos].kind == nkEmpty:
if (resultPos < sonsLen(n)) and (n.sons[resultPos].kind != nkEmpty):
var v = n.sons[resultPos].sym
result = getNullValue(v.typ, n.info)
IdNodeTablePut(c.tos.mapping, v, result)
@@ -740,8 +738,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
if isSpecial(result): return
var k = getOrdValue(b)
if (k >= 0) and (k < sonsLen(a)) and not (a.kind in {nkEmpty..nkNilLit}):
if result.kind == nkEmpty: a.sons[int(k)] = nil
else: a.sons[int(k)] = result
a.sons[int(k)] = result
else:
stackTrace(c, n, errIndexOutOfBounds)
result = emptyNode
@@ -1055,4 +1052,3 @@ proc evalPass(): TPass =
result.close = myProcess
result.process = myProcess
emptyNode = newNode(nkEmpty)

View File

@@ -109,6 +109,7 @@ proc CommandGenDepend(filename: string) =
changeFileExt(filename, "dot"))
proc CommandCheck(filename: string) =
msgs.gErrorMax = high(int) # do not stop after first error
semanticPasses() # use an empty backend for semantic checking only
compileProject(filename)

View File

@@ -62,7 +62,7 @@ type
errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValue,
errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice,
errInvalidOrderInArrayConstructor,
errInvalidOrderInEnumX, errEnumXHasWholes, errExceptExpected, errInvalidTry,
errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry,
errOptionExpected, errXisNoLabel, errNotAllCasesCovered,
errUnkownSubstitionVar, errComplexStmtRequiresInd, errXisNotCallable,
errNoPragmasAllowedForX, errNoGenericParamsAllowedForX,
@@ -96,154 +96,245 @@ type
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintUser
const
MsgKindToStr*: array[TMsgKind, string] = ["unknown error",
"illformed AST: $1", "cannot open \'$1\'", "internal error: $1", "$1",
"\'$1\' compiler does not support C++", "string literal expected",
"integer literal expected", "invalid character constant",
"closing \"\"\" expected, but end of file reached", "closing \" expected",
"tabulators are not allowed", "invalid token: $1", "line too long",
"$1 is not a valid number", "number $1 out of valid range",
"\\n not allowed in character literal",
"closing \']\' expected, but end of file reached", "missing final \'",
"identifier expected, but found \'$1\'",
"operator expected, but found \'$1\'", "\'$1\' expected",
"string after \'include\' expected", "recursive dependency: \'$1\'",
"\'on\' or \'off\' expected", "\'none\', \'speed\' or \'size\' expected",
"invalid pragma", "unknown pragma: \'$1\'", "invalid directive: \'$1\'",
"\'pop\' without a \'push\' pragma", "empty asm statement",
"invalid indentation", "exception expected", "exception already handled",
"\'yield\' only allowed in a loop of an iterator",
"invalid number of \'yield\' expresions",
"current routine cannot return an expression", "attempt to redefine \'$1\'",
"statement not allowed after \'return\', \'break\' or \'raise\'",
"statement expected", "\'$1\' is no label",
"invalid command line option: \'$1\'",
"argument for command line option expected: \'$1\'",
"invalid argument for command line option: \'$1\'",
"invalid variable substitution in \'$1\'", "unknown variable: \'$1\'",
"unknown C compiler: \'$1\'",
"\'on\' or \'off\' expected, but \'$1\' found",
"\'none\', \'boehm\' or \'refc\' expected, but \'$1\' found",
"\'none\', \'speed\' or \'size\' expected, but \'$1\' found",
"\'gui\', \'console\' or \'lib\' expected, but \'$1\' found",
"unknown OS: \'$1\'", "unknown CPU: \'$1\'",
"\'c\', \'c++\' or \'yaml\' expected, but \'$1\' found",
"arguments can only be given if the \'--run\' option is selected",
"multiple assignment is not allowed",
"\':\' or \'=\' expected, but found \'$1\'",
"expression expected, but found \'$1\'", "undeclared identifier: \'$1\'",
"ambiguous identifier: \'$1\' -- use a qualifier", "type expected",
"system module needs \'$1\'", "execution of an external program failed",
"overloaded \'$1\' leads to ambiguous calls", "invalid argument for \'$1\'",
"statement has no effect", "\'$1\' expects a type or value",
"\'$1\' expects an array type",
"\'$1\' cannot be instantiated because its body has not been compiled yet",
"expression \'$1\' ambiguous in this context", "constant division by zero",
"ordinal type expected", "ordinal or float type expected",
"over- or underflow",
"cannot evalutate \'$1\' because type is not defined completely",
"\'chr\' expects an int in the range 0..255",
"\'dynlib\' requires \'exportc\'", "undeclared field: \'$1\'",
"attempt to access a nil address", "index out of bounds",
"index types do not match", "\'[]\' operator invalid for this type",
"value out of set bounds", "field initialized twice: \'$1\'",
"field \'$1\' not initialized", "expression \'$1\' cannot be called",
"expression has no type", "expression \'$1\' has no type (or is ambiguous)",
"\'cast\' not allowed in safe mode", "expression cannot be casted to $1",
"\',\' or \')\' expected", "\'{\' or \'(\' expected",
"section (\'type\', \'proc\', etc.) expected", "range expected",
"attempt to redefine \'$1\'", "\'magic\' only allowed in system module",
"power of two expected", "string literal may not be empty",
"calling convention expected",
"a proc can only have one calling convention",
"symbol must be imported if \'lib\' pragma is used",
"expression must be of type \'bool\'", "constant expression expected",
"duplicate case label", "range is empty",
"selector must be of an ordinal type, real or string",
"selector must be of an ordinal type", "ord($1) must not be negative",
"len($1) must be less than 32768", "wrong number of variables",
"only objects can be raised", "\'break\' only allowed in loop construct",
"type \'$1\' has unknown size",
"a constant can only be initialized with a constant expression",
"a constant needs a value", "the result type cannot be on open array",
"computing the type\'s size produced an overflow", "set is too large",
"base type of a set must be an ordinal",
"inheritance only works with non-final objects",
"inheritance only works with an enum", "illegal recursion in type \'$1\'",
"cannot instantiate: \'$1\'", "expression has no address",
"for a \'var\' type a variable needs to be passed", "type mismatch",
"type mismatch: got (", "but expected one of: ", "but expected \'$1\'",
"ambiguous call; both $1 and $2 match for: $3", "wrong number of arguments",
"\'$1\' cannot be passed to a procvar",
"$1 cannot be declared in parameter declaration",
"pragmas are only in the header of a proc allowed",
"implementation of \'$1\' is not allowed",
"implementation of \'$1\' expected", "no symbol to borrow from found",
"value returned by statement has to be discarded",
"statement returns no value that can be discarded",
"conversion from $1 to $2 is invalid", "cannot bind parameter \'$1\' twice",
"invalid order in array constructor",
"invalid order in enum \'$1\'", "enum \'$1\' has wholes",
"\'except\' or \'finally\' expected",
"after catch all \'except\' or \'finally\' no section may follow",
"option expected, but found \'$1\'", "\'$1\' is not a label",
"not all cases are covered", "unknown substitution variable: \'$1\'",
"complex statement requires indentation", "\'$1\' is not callable",
"no pragmas allowed for $1", "no generic parameters allowed for $1",
"invalid param kind: \'$1\'", "default argument invalid",
"named parameter has to be an identifier", "no return type for $1 allowed",
"a type conversion needs exactly one argument", "invalid pragma: $1",
"$1 not allowed here", "invalid control flow: $1", "a type has no value",
"invalid type: \'$1\'", "\'^\' needs a pointer or reference type",
"invalid expression", "invalid expression: \'$1\'",
"enum has no value \'$1\'", "named expression expected",
"named expression not allowed here", "\'$1\' expects one type parameter",
"array expects two type parameters", "invalid visibility: \'$1\'",
"initialization not allowed here", "\'$1\' cannot be assigned to",
"iterators can only be defined at the module\'s top level",
"$1 needs a return type", "invalid command: \'$1\'",
"\'$1\' is only allowed at top level",
"'$1' needs a parameter that has an object type",
"template/macro instantiation too nested", "instantiation from here",
"invalid index value for tuple subscript",
"command expects a filename argument", "\'$1\' expected",
"invalid section start", "grid table is not implemented",
"general parse error", "new section expected",
"whitespace expected, got \'$1\'", "\'$1\' is no valid index file",
"cannot render reStructuredText element \'$1\'",
"type \'var var\' is not allowed", "\'is\' expects two arguments",
"\'is\' expects object types", "\'$1\' can never be of this subtype",
"interpretation requires too many iterations",
"cannot interpret node kind \'$1\'", "field \'$1\' cannot be found",
"invalid conversion from type \'$1\'", "assertion failed",
"cannot generate code for \'$1\'", "$1 requires one parameter",
"unhandled exception: $1", "macro returned a cyclic abstract syntax tree",
"\'$1\' is no macro or template", "\'$1\' can have side effects",
"iterator within for loop context expected", "$1",
"cannot open \'$1\' [CannotOpenFile]", "octal escape sequences do not exist; leading zero is ignored [OctalEscape]",
"\'$1\' is never read [XIsNeverRead]",
"\'$1\' might not have been initialized [XmightNotBeenInit]",
"cannot write file \'$1\' [CannotWriteMO2]",
"cannot read file \'$1\' [CannotReadMO2]",
"\'$1\' is deprecated [Deprecated]", "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]",
"unknown magic \'$1\' might crash the compiler [UnknownMagic]",
"redefinition of label \'$1\' [RedefinitionOfLabel]",
"unknown substitution \'$1\' [UnknownSubstitutionX]",
"language \'$1\' not supported [LanguageXNotSupported]",
"comment \'$1\' ignored [CommentXIgnored]",
"\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]",
"$1 [User]", "operation successful [Success]",
"operation successful ($1 lines compiled; $2 sec total) [SuccessX]",
"line too long [LineTooLong]",
"\'$1\' is declared but not used [XDeclaredButNotUsed]",
"conversion to base object is not needed [ConvToBaseNotNeeded]",
"conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]",
"expression evaluates always to \'$1\' [ExprAlwaysX]",
"quit() called [QuitCalled]", "$1 [Processing]",
"generated code listing: [CodeBegin]", "end of listing [CodeEnd]",
"used config file \'$1\' [Conf]",
"added path: '$1' [Path]",
"$1 [User]"]
MsgKindToStr*: array[TMsgKind, string] = [
errUnknown: "unknown error",
errIllFormedAstX: "illformed AST: $1",
errCannotOpenFile: "cannot open \'$1\'",
errInternal: "internal error: $1",
errGenerated: "$1",
errXCompilerDoesNotSupportCpp: "\'$1\' compiler does not support C++",
errStringLiteralExpected: "string literal expected",
errIntLiteralExpected: "integer literal expected",
errInvalidCharacterConstant: "invalid character constant",
errClosingTripleQuoteExpected: "closing \"\"\" expected, but end of file reached",
errClosingQuoteExpected: "closing \" expected",
errTabulatorsAreNotAllowed: "tabulators are not allowed",
errInvalidToken: "invalid token: $1",
errLineTooLong: "line too long",
errInvalidNumber: "$1 is not a valid number",
errNumberOutOfRange: "number $1 out of valid range",
errNnotAllowedInCharacter: "\\n not allowed in character literal",
errClosingBracketExpected: "closing ']' expected, but end of file reached",
errMissingFinalQuote: "missing final \'",
errIdentifierExpected: "identifier expected, but found \'$1\'",
errOperatorExpected: "operator expected, but found \'$1\'",
errTokenExpected: "\'$1\' expected",
errStringAfterIncludeExpected: "string after \'include\' expected",
errRecursiveDependencyX: "recursive dependency: \'$1\'",
errOnOrOffExpected: "\'on\' or \'off\' expected",
errNoneSpeedOrSizeExpected: "\'none\', \'speed\' or \'size\' expected",
errInvalidPragma: "invalid pragma",
errUnknownPragma: "unknown pragma: \'$1\'",
errInvalidDirectiveX: "invalid directive: \'$1\'",
errAtPopWithoutPush: "\'pop\' without a \'push\' pragma",
errEmptyAsm: "empty asm statement",
errInvalidIndentation: "invalid indentation",
errExceptionExpected: "exception expected",
errExceptionAlreadyHandled: "exception already handled",
errYieldNotAllowedHere: "\'yield\' only allowed in a loop of an iterator",
errInvalidNumberOfYieldExpr: "invalid number of \'yield\' expresions",
errCannotReturnExpr: "current routine cannot return an expression",
errAttemptToRedefine: "attempt to redefine \'$1\'",
errStmtInvalidAfterReturn: "statement not allowed after \'return\', \'break\' or \'raise\'",
errStmtExpected: "statement expected",
errInvalidLabel: "\'$1\' is no label",
errInvalidCmdLineOption: "invalid command line option: \'$1\'",
errCmdLineArgExpected: "argument for command line option expected: \'$1\'",
errCmdLineNoArgExpected: "invalid argument for command line option: \'$1\'",
errInvalidVarSubstitution: "invalid variable substitution in \'$1\'",
errUnknownVar: "unknown variable: \'$1\'",
errUnknownCcompiler: "unknown C compiler: \'$1\'",
errOnOrOffExpectedButXFound: "\'on\' or \'off\' expected, but \'$1\' found",
errNoneBoehmRefcExpectedButXFound: "'none', 'boehm' or 'refc' expected, but '$1' found",
errNoneSpeedOrSizeExpectedButXFound: "'none', 'speed' or 'size' expected, but '$1' found",
errGuiConsoleOrLibExpectedButXFound: "'gui', 'console' or 'lib' expected, but '$1' found",
errUnknownOS: "unknown OS: '$1'",
errUnknownCPU: "unknown CPU: '$1'",
errGenOutExpectedButXFound: "'c', 'c++' or 'yaml' expected, but '$1' found",
errArgsNeedRunOption: "arguments can only be given if the '--run' option is selected",
errInvalidMultipleAsgn: "multiple assignment is not allowed",
errColonOrEqualsExpected: "\':\' or \'=\' expected, but found \'$1\'",
errExprExpected: "expression expected, but found \'$1\'",
errUndeclaredIdentifier: "undeclared identifier: \'$1\'",
errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier",
errTypeExpected: "type expected",
errSystemNeeds: "system module needs \'$1\'",
errExecutionOfProgramFailed: "execution of an external program failed",
errNotOverloadable: "overloaded \'$1\' leads to ambiguous calls",
errInvalidArgForX: "invalid argument for \'$1\'",
errStmtHasNoEffect: "statement has no effect",
errXExpectsTypeOrValue: "\'$1\' expects a type or value",
errXExpectsArrayType: "\'$1\' expects an array type",
errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet",
errExprXAmbiguous: "expression '$1' ambiguous in this context",
errConstantDivisionByZero: "constant division by zero",
errOrdinalTypeExpected: "ordinal type expected",
errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
errOverOrUnderflow: "over- or underflow",
errCannotEvalXBecauseIncompletelyDefined: "cannot evalutate '$1' because type is not defined completely",
errChrExpectsRange0_255: "\'chr\' expects an int in the range 0..255",
errDynlibRequiresExportc: "\'dynlib\' requires \'exportc\'",
errUndeclaredFieldX: "undeclared field: \'$1\'",
errNilAccess: "attempt to access a nil address",
errIndexOutOfBounds: "index out of bounds",
errIndexTypesDoNotMatch: "index types do not match",
errBracketsInvalidForType: "\'[]\' operator invalid for this type",
errValueOutOfSetBounds: "value out of set bounds",
errFieldInitTwice: "field initialized twice: \'$1\'",
errFieldNotInit: "field \'$1\' not initialized",
errExprXCannotBeCalled: "expression \'$1\' cannot be called",
errExprHasNoType: "expression has no type",
errExprXHasNoType: "expression \'$1\' has no type (or is ambiguous)",
errCastNotInSafeMode: "\'cast\' not allowed in safe mode",
errExprCannotBeCastedToX: "expression cannot be casted to $1",
errCommaOrParRiExpected: "',' or ')' expected",
errCurlyLeOrParLeExpected: "\'{\' or \'(\' expected",
errSectionExpected: "section (\'type\', \'proc\', etc.) expected",
errRangeExpected: "range expected",
errAttemptToRedefineX: "attempt to redefine \'$1\'",
errMagicOnlyInSystem: "\'magic\' only allowed in system module",
errPowerOfTwoExpected: "power of two expected",
errStringMayNotBeEmpty: "string literal may not be empty",
errCallConvExpected: "calling convention expected",
errProcOnlyOneCallConv: "a proc can only have one calling convention",
errSymbolMustBeImported: "symbol must be imported if 'lib' pragma is used",
errExprMustBeBool: "expression must be of type 'bool'",
errConstExprExpected: "constant expression expected",
errDuplicateCaseLabel: "duplicate case label",
errRangeIsEmpty: "range is empty",
errSelectorMustBeOfCertainTypes: "selector must be of an ordinal type, float or string",
errSelectorMustBeOrdinal: "selector must be of an ordinal type",
errOrdXMustNotBeNegative: "ord($1) must not be negative",
errLenXinvalid: "len($1) must be less than 32768",
errWrongNumberOfVariables: "wrong number of variables",
errExprCannotBeRaised: "only objects can be raised",
errBreakOnlyInLoop: "'break' only allowed in loop construct",
errTypeXhasUnknownSize: "type \'$1\' has unknown size",
errConstNeedsConstExpr: "a constant can only be initialized with a constant expression",
errConstNeedsValue: "a constant needs a value",
errResultCannotBeOpenArray: "the result type cannot be on open array",
errSizeTooBig: "computing the type\'s size produced an overflow",
errSetTooBig: "set is too large",
errBaseTypeMustBeOrdinal: "base type of a set must be an ordinal",
errInheritanceOnlyWithNonFinalObjects: "inheritance only works with non-final objects",
errInheritanceOnlyWithEnums: "inheritance only works with an enum",
errIllegalRecursionInTypeX: "illegal recursion in type \'$1\'",
errCannotInstantiateX: "cannot instantiate: \'$1\'",
errExprHasNoAddress: "expression has no address",
errVarForOutParamNeeded: "for a \'var\' type a variable needs to be passed",
errPureTypeMismatch: "type mismatch",
errTypeMismatch: "type mismatch: got (",
errButExpected: "but expected one of: ",
errButExpectedX: "but expected \'$1\'",
errAmbiguousCallXYZ: "ambiguous call; both $1 and $2 match for: $3",
errWrongNumberOfArguments: "wrong number of arguments",
errXCannotBePassedToProcVar: "\'$1\' cannot be passed to a procvar",
errXCannotBeInParamDecl: "$1 cannot be declared in parameter declaration",
errPragmaOnlyInHeaderOfProc: "pragmas are only in the header of a proc allowed",
errImplOfXNotAllowed: "implementation of \'$1\' is not allowed",
errImplOfXexpected: "implementation of \'$1\' expected",
errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
errDiscardValue: "value returned by statement has to be discarded",
errInvalidDiscard: "statement returns no value that can be discarded",
errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
errCannotBindXTwice: "cannot bind parameter \'$1\' twice",
errInvalidOrderInArrayConstructor: "invalid order in array constructor",
errInvalidOrderInEnumX: "invalid order in enum \'$1\'",
errEnumXHasHoles: "enum \'$1\' has holes",
errExceptExpected: "\'except\' or \'finally\' expected",
errInvalidTry: "after catch all \'except\' or \'finally\' no section may follow",
errOptionExpected: "option expected, but found \'$1\'",
errXisNoLabel: "\'$1\' is not a label",
errNotAllCasesCovered: "not all cases are covered",
errUnkownSubstitionVar: "unknown substitution variable: \'$1\'",
errComplexStmtRequiresInd: "complex statement requires indentation",
errXisNotCallable: "\'$1\' is not callable",
errNoPragmasAllowedForX: "no pragmas allowed for $1",
errNoGenericParamsAllowedForX: "no generic parameters allowed for $1",
errInvalidParamKindX: "invalid param kind: \'$1\'",
errDefaultArgumentInvalid: "default argument invalid",
errNamedParamHasToBeIdent: "named parameter has to be an identifier",
errNoReturnTypeForX: "no return type for $1 allowed",
errConvNeedsOneArg: "a type conversion needs exactly one argument",
errInvalidPragmaX: "invalid pragma: $1",
errXNotAllowedHere: "$1 not allowed here",
errInvalidControlFlowX: "invalid control flow: $1",
errATypeHasNoValue: "a type has no value",
errXisNoType: "invalid type: \'$1\'",
errCircumNeedsPointer: "\'^\' needs a pointer or reference type",
errInvalidExpression: "invalid expression",
errInvalidExpressionX: "invalid expression: \'$1\'",
errEnumHasNoValueX: "enum has no value \'$1\'",
errNamedExprExpected: "named expression expected",
errNamedExprNotAllowed: "named expression not allowed here",
errXExpectsOneTypeParam: "\'$1\' expects one type parameter",
errArrayExpectsTwoTypeParams: "array expects two type parameters",
errInvalidVisibilityX: "invalid visibility: \'$1\'",
errInitHereNotAllowed: "initialization not allowed here",
errXCannotBeAssignedTo: "\'$1\' cannot be assigned to",
errIteratorNotAllowed: "iterators can only be defined at the module\'s top level",
errXNeedsReturnType: "$1 needs a return type",
errInvalidCommandX: "invalid command: \'$1\'",
errXOnlyAtModuleScope: "\'$1\' is only allowed at top level",
errXNeedsParamObjectType: "'$1' needs a parameter that has an object type",
errTemplateInstantiationTooNested: "template/macro instantiation too nested",
errInstantiationFrom: "instantiation from here",
errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
errCommandExpectsFilename: "command expects a filename argument",
errXExpected: "\'$1\' expected",
errInvalidSectionStart: "invalid section start",
errGridTableNotImplemented: "grid table is not implemented",
errGeneralParseError: "general parse error",
errNewSectionExpected: "new section expected",
errWhitespaceExpected: "whitespace expected, got \'$1\'",
errXisNoValidIndexFile: "\'$1\' is no valid index file",
errCannotRenderX: "cannot render reStructuredText element \'$1\'",
errVarVarTypeNotAllowed: "type \'var var\' is not allowed",
errIsExpectsTwoArguments: "\'is\' expects two arguments",
errIsExpectsObjectTypes: "\'is\' expects object types",
errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype",
errTooManyIterations: "interpretation requires too many iterations",
errCannotInterpretNodeX: "cannot interpret node kind \'$1\'",
errFieldXNotFound: "field \'$1\' cannot be found",
errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'",
errAssertionFailed: "assertion failed",
errCannotGenerateCodeForX: "cannot generate code for \'$1\'",
errXRequiresOneArgument: "$1 requires one parameter",
errUnhandledExceptionX: "unhandled exception: $1",
errCyclicTree: "macro returned a cyclic abstract syntax tree",
errXisNoMacroOrTemplate: "\'$1\' is no macro or template",
errXhasSideEffects: "\'$1\' can have side effects",
errIteratorExpected: "iterator within for loop context expected",
errUser: "$1",
warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]",
warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]",
warnXIsNeverRead: "\'$1\' is never read [XIsNeverRead]",
warnXmightNotBeenInit: "\'$1\' might not have been initialized [XmightNotBeenInit]",
warnCannotWriteMO2: "cannot write file \'$1\' [CannotWriteMO2]",
warnCannotReadMO2: "cannot read file \'$1\' [CannotReadMO2]",
warnDeprecated: "\'$1\' is deprecated [Deprecated]",
warnSmallLshouldNotBeUsed: "\'l\' should not be used as an identifier; may look like \'1\' (one) [SmallLshouldNotBeUsed]",
warnUnknownMagic: "unknown magic \'$1\' might crash the compiler [UnknownMagic]",
warnRedefinitionOfLabel: "redefinition of label \'$1\' [RedefinitionOfLabel]",
warnUnknownSubstitutionX: "unknown substitution \'$1\' [UnknownSubstitutionX]",
warnLanguageXNotSupported: "language \'$1\' not supported [LanguageXNotSupported]",
warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]",
warnXisPassedToProcVar: "\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]",
warnUser: "$1 [User]",
hintSuccess: "operation successful [Success]",
hintSuccessX: "operation successful ($1 lines compiled; $2 sec total) [SuccessX]",
hintLineTooLong: "line too long [LineTooLong]",
hintXDeclaredButNotUsed: "\'$1\' is declared but not used [XDeclaredButNotUsed]",
hintConvToBaseNotNeeded: "conversion to base object is not needed [ConvToBaseNotNeeded]",
hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]",
hintExprAlwaysX: "expression evaluates always to \'$1\' [ExprAlwaysX]",
hintQuitCalled: "quit() called [QuitCalled]",
hintProcessing: "$1 [Processing]",
hintCodeBegin: "generated code listing: [CodeBegin]",
hintCodeEnd: "end of listing [CodeEnd]",
hintConf: "used config file \'$1\' [Conf]",
hintPath: "added path: '$1' [Path]",
hintUser: "$1 [User]"]
const
WarningsToStr*: array[0..14, string] = ["CannotOpenFile", "OctalEscape",
@@ -353,7 +444,7 @@ proc checkpoint(info: TLineInfo, filename: string, line: int): bool =
(ChangeFileExt(extractFilename(filenames[info.fileIndex]), "") ==
filename)
var checkPoints: seq[TLineInfo] = @ []
var checkPoints: seq[TLineInfo] = @[]
proc addCheckpoint(info: TLineInfo) =
var length: int

View File

@@ -141,7 +141,7 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode
proc parseEmit(p: var TParser, definition: PNode): PNode =
getTok(p) # skip 'emit'
result = nil
result = ast.emptyNode
if p.tok.xkind != pxCurlyDirRi:
case p.context
of conExpr:
@@ -159,7 +159,7 @@ proc parseEmit(p: var TParser, definition: PNode): PNode =
eat(p, pxCurlyDirRi)
proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
result = nil
result = ast.emptyNode
getTok(p)
if p.tok.ident.id == getIdent("discard").id:
result = newNodeP(nkDiscardStmt, p)
@@ -170,8 +170,8 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
getTok(p)
eat(p, pxCurlyDirRi)
result = parseExpr(p)
if result.kind == nkEmpty: InternalError("emptyNode modified")
result.kind = nkCurly
assert(sonsNotNil(result))
elif p.tok.ident.id == getIdent("cast").id:
getTok(p)
eat(p, pxCurlyDirRi)
@@ -181,7 +181,7 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
addSon(result, a.sons[0])
addSon(result, a.sons[1])
else:
parMessage(p, errInvalidDirectiveX, $(p.tok))
parMessage(p, errInvalidDirectiveX, $p.tok)
result = a
elif p.tok.ident.id == getIdent("emit").id:
result = parseEmit(p, definition)
@@ -216,12 +216,12 @@ proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
getTok(p)
eat(p, pxCurlyDirRi)
else:
parMessage(p, errInvalidDirectiveX, $(p.tok))
parMessage(p, errInvalidDirectiveX, $p.tok)
while true:
getTok(p)
if (p.tok.xkind == pxCurlyDirRi) or (p.tok.xkind == pxEof): break
if p.tok.xkind == pxCurlyDirRi or p.tok.xkind == pxEof: break
eat(p, pxCurlyDirRi)
result = nil
result = ast.emptyNode
proc getPrecedence(kind: TTokKind): int =
case kind
@@ -295,7 +295,7 @@ proc qualifiedIdent(p: var TParser): PNode =
result = createIdentNodeP(p.tok.ident, p)
else:
parMessage(p, errIdentifierExpected, $p.tok)
return nil
return ast.emptyNode
getTok(p)
skipCom(p, result)
if p.tok.xkind == pxDot:
@@ -390,15 +390,15 @@ proc identOrLiteral(p: var TParser): PNode =
else:
parMessage(p, errExprExpected, $(p.tok))
getTok(p) # we must consume a token here to prevend endless loops!
result = nil
if result != nil: skipCom(p, result)
result = ast.emptyNode
if result.kind != nkEmpty: skipCom(p, result)
proc primary(p: var TParser): PNode =
# prefix operator?
if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or
(p.tok.xkind == pxPlus):
result = newNodeP(nkPrefix, p)
var a = newIdentNodeP(getIdent($(p.tok)), p)
var a = newIdentNodeP(getIdent($p.tok), p)
addSon(result, a)
getTok(p)
skipCom(p, a)
@@ -406,7 +406,7 @@ proc primary(p: var TParser): PNode =
return
elif p.tok.xkind == pxAt:
result = newNodeP(nkAddr, p)
var a = newIdentNodeP(getIdent($(p.tok)), p)
var a = newIdentNodeP(getIdent($p.tok), p)
getTok(p)
if p.tok.xkind == pxBracketLe:
result = newNodeP(nkPrefix, p)
@@ -433,7 +433,7 @@ proc primary(p: var TParser): PNode =
addSon(result, createIdentNodeP(p.tok.ident, p))
getTok(p)
else:
parMessage(p, errIdentifierExpected, $(p.tok))
parMessage(p, errIdentifierExpected, $p.tok)
of pxHat:
var a = result
result = newNodeP(nkDerefExpr, p)
@@ -490,7 +490,6 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
proc fixExpr(n: PNode): PNode =
result = n
if n == nil: return
case n.kind
of nkInfix:
if n.sons[1].kind == nkBracket: n.sons[1].kind = nkCurly
@@ -559,7 +558,7 @@ proc parseUsesStmt(p: var TParser): PNode =
skipCom(p, a)
else:
break
if sonsLen(result) == 0: result = nil
if sonsLen(result) == 0: result = ast.emptyNode
proc parseIncludeDir(p: var TParser): PNode =
result = newNodeP(nkIncludeStmt, p)
@@ -568,7 +567,7 @@ proc parseIncludeDir(p: var TParser): PNode =
while true:
case p.tok.xkind
of pxSymbol, pxDot, pxDotDot, pxSlash:
filename = filename & $(p.tok)
add(filename, $p.tok)
getTok(p)
of pxStrLit:
filename = p.tok.literal
@@ -577,10 +576,10 @@ proc parseIncludeDir(p: var TParser): PNode =
of pxCurlyDirRi:
break
else:
parMessage(p, errIdentifierExpected, $(p.tok))
parMessage(p, errIdentifierExpected, $p.tok)
break
addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, "nim"), p))
if filename == "config.inc": result = nil
if filename == "config.inc": result = ast.emptyNode
proc definedExprAux(p: var TParser): PNode =
result = newNodeP(nkCall, p)
@@ -590,7 +589,6 @@ proc definedExprAux(p: var TParser): PNode =
getTok(p)
proc isHandledDirective(p: TParser): bool =
result = false
if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}:
case toLower(p.tok.ident.s)
of "else", "endif": result = false
@@ -657,7 +655,7 @@ proc parseIfDir(p: var TParser, endMarker: TTokKind): PNode =
parseIfDirAux(p, result)
proc parseDirective(p: var TParser): PNode =
result = nil
result = ast.emptyNode
if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return
var endMarker = succ(p.tok.xkind)
if p.tok.ident != nil:
@@ -680,7 +678,7 @@ proc parseRaise(p: var TParser): PNode =
getTok(p)
skipCom(p, result)
if p.tok.xkind != pxSemicolon: addSon(result, parseExpr(p))
else: addSon(result, nil)
else: addSon(result, ast.emptyNode)
proc parseIf(p: var TParser): PNode =
result = newNodeP(nkIfStmt, p)
@@ -721,14 +719,14 @@ proc parseRepeat(p: var TParser): PNode =
skipCom(p, result)
addSon(result, newIdentNodeP(getIdent("true"), p))
var s = newNodeP(nkStmtList, p)
while (p.tok.xkind != pxEof) and (p.tok.xkind != pxUntil):
while p.tok.xkind != pxEof and p.tok.xkind != pxUntil:
addSon(s, parseStmt(p))
eat(p, pxUntil)
var a = newNodeP(nkIfStmt, p)
skipCom(p, a)
var b = newNodeP(nkElifBranch, p)
var c = newNodeP(nkBreakStmt, p)
addSon(c, nil)
addSon(c, ast.emptyNode)
addSon(b, parseExpr(p))
skipCom(p, a)
addSon(b, c)
@@ -809,7 +807,7 @@ proc parseFor(p: var TParser): PNode =
getTok(p)
eat(p, pxAsgn)
var a = parseExpr(p)
var b: PNode = nil
var b = ast.emptyNode
var c = newNodeP(nkCall, p)
if p.tok.xkind == pxTo:
addSon(c, newIdentNodeP(getIdent("countup"), p))
@@ -829,9 +827,9 @@ proc parseFor(p: var TParser): PNode =
addSon(result, parseStmt(p))
proc parseParam(p: var TParser): PNode =
var a, v: PNode
var a: PNode
result = newNodeP(nkIdentDefs, p)
v = nil
var v = ast.emptyNode
case p.tok.xkind
of pxConst:
getTok(p)
@@ -848,7 +846,7 @@ proc parseParam(p: var TParser): PNode =
of pxSymbol: a = createIdentNodeP(p.tok.ident, p)
of pxColon, pxEof, pxParRi, pxEquals: break
else:
parMessage(p, errIdentifierExpected, $(p.tok))
parMessage(p, errIdentifierExpected, $p.tok)
return
getTok(p) # skip identifier
skipCom(p, a)
@@ -859,24 +857,24 @@ proc parseParam(p: var TParser): PNode =
if p.tok.xkind == pxColon:
getTok(p)
skipCom(p, result)
if v != nil: addSon(v, parseTypeDesc(p))
if v.kind != nkEmpty: addSon(v, parseTypeDesc(p))
else: v = parseTypeDesc(p)
addSon(result, v)
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
if p.tok.xkind != pxEquals:
parMessage(p, errColonOrEqualsExpected, $(p.tok))
parMessage(p, errColonOrEqualsExpected, $p.tok)
if p.tok.xkind == pxEquals:
getTok(p)
skipCom(p, result)
addSon(result, parseExpr(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
proc parseParamList(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkFormalParams, p)
addSon(result, nil) # return type
addSon(result, ast.emptyNode) # return type
if p.tok.xkind == pxParLe:
p.inParamList = true
getTok(p)
@@ -903,7 +901,7 @@ proc parseParamList(p: var TParser): PNode =
result.sons[0] = parseTypeDesc(p)
proc parseCallingConvention(p: var TParser): PNode =
result = nil
result = ast.emptyNode
if p.tok.xkind == pxSymbol:
case toLower(p.tok.ident.s)
of "stdcall", "cdecl", "safecall", "syscall", "inline", "fastcall":
@@ -935,7 +933,7 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
of "importc":
# This is a fake for platform module. There is no ``importc``
# directive in Pascal.
if result == nil: result = newNodeP(nkPragma, p)
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
addSon(result, newIdentNodeP(getIdent("importc"), p))
noBody = true
getTok(p)
@@ -943,7 +941,7 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
of "noconv":
# This is a fake for platform module. There is no ``noconv``
# directive in Pascal.
if result == nil: result = newNodeP(nkPragma, p)
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
addSon(result, newIdentNodeP(getIdent("noconv"), p))
noBody = true
getTok(p)
@@ -951,17 +949,17 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
of "procvar":
# This is a fake for the Nimrod compiler. There is no ``procvar``
# directive in Pascal.
if result == nil: result = newNodeP(nkPragma, p)
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
addSon(result, newIdentNodeP(getIdent("procvar"), p))
getTok(p)
opt(p, pxSemicolon)
of "varargs":
if result == nil: result = newNodeP(nkPragma, p)
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
addSon(result, newIdentNodeP(getIdent("varargs"), p))
getTok(p)
opt(p, pxSemicolon)
of "external":
if result == nil: result = newNodeP(nkPragma, p)
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
getTok(p)
noBody = true
e = newNodeP(nkExprColonExpr, p)
@@ -981,8 +979,8 @@ proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
opt(p, pxSemicolon)
else:
e = parseCallingConvention(p)
if e == nil: break
if result == nil: result = newNodeP(nkPragma, p)
if e.kind == nkEmpty: break
if result.kind == nkEmpty: result = newNodeP(nkPragma, p)
addSon(result, e.sons[0])
proc parseRoutineType(p: var TParser): PNode =
@@ -999,7 +997,7 @@ proc parseEnum(p: var TParser): PNode =
result = newNodeP(nkEnumTy, p)
getTok(p)
skipCom(p, result)
addSon(result, nil) # it does not inherit from any enumeration
addSon(result, ast.emptyNode) # it does not inherit from any enumeration
while true:
case p.tok.xkind
of pxEof, pxParRi: break
@@ -1061,7 +1059,7 @@ proc parseIdentColonEquals(p: var TParser,
skipCom(p, result)
addSon(result, parseTypeDesc(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
if p.tok.xkind != pxEquals:
parMessage(p, errColonOrEqualsExpected, $(p.tok))
if p.tok.xkind == pxEquals:
@@ -1069,20 +1067,20 @@ proc parseIdentColonEquals(p: var TParser,
skipCom(p, result)
addSon(result, parseExpr(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
if p.tok.xkind == pxSemicolon:
getTok(p)
skipCom(p, result)
proc parseRecordCase(p: var TParser): PNode =
var a, b, c: PNode
var b, c: PNode
result = newNodeP(nkRecCase, p)
getTok(p)
a = newNodeP(nkIdentDefs, p)
var a = newNodeP(nkIdentDefs, p)
addSon(a, rawIdent(p))
eat(p, pxColon)
addSon(a, parseTypeDesc(p))
addSon(a, nil)
addSon(a, ast.emptyNode)
addSon(result, a)
eat(p, pxOf)
skipCom(p, result)
@@ -1116,9 +1114,9 @@ proc parseRecordCase(p: var TParser): PNode =
if b.kind == nkElse: break
proc parseRecordPart(p: var TParser): PNode =
result = nil
result = ast.emptyNode
while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd):
if result == nil: result = newNodeP(nkRecList, p)
if result.kind == nkEmpty: result = newNodeP(nkRecList, p)
case p.tok.xkind
of pxSymbol:
addSon(result, parseIdentColonEquals(p, rawIdent))
@@ -1129,8 +1127,8 @@ proc parseRecordPart(p: var TParser): PNode =
of pxComment:
skipCom(p, lastSon(result))
else:
parMessage(p, errIdentifierExpected, $(p.tok))
break
parMessage(p, errIdentifierExpected, $p.tok)
break
proc exSymbol(n: var PNode) =
case n.kind
@@ -1146,7 +1144,6 @@ proc exSymbol(n: var PNode) =
else: internalError(n.info, "exSymbol(): " & $n.kind)
proc fixRecordDef(n: var PNode) =
if n == nil: return
case n.kind
of nkRecCase:
fixRecordDef(n.sons[0])
@@ -1157,7 +1154,7 @@ proc fixRecordDef(n: var PNode) =
for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i])
of nkIdentDefs:
for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i])
of nkNilLit: nil
of nkNilLit, nkEmpty: nil
else: internalError(n.info, "fixRecordDef(): " & $n.kind)
proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
@@ -1202,7 +1199,7 @@ proc parseRecordOrObject(p: var TParser, kind: TNodeKind,
definition: PNode): PNode =
result = newNodeP(kind, p)
getTok(p)
addSon(result, nil)
addSon(result, ast.emptyNode)
if p.tok.xkind == pxParLe:
var a = newNodeP(nkOfInherit, p)
getTok(p)
@@ -1210,7 +1207,7 @@ proc parseRecordOrObject(p: var TParser, kind: TNodeKind,
addSon(result, a)
eat(p, pxParRi)
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
parseRecordBody(p, result, definition)
proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
@@ -1234,8 +1231,8 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
else: addSon(result, a.sons[i])
else:
result = newNodeP(nkObjectTy, p)
addSon(result, nil)
addSon(result, nil)
addSon(result, ast.emptyNode)
addSon(result, ast.emptyNode)
parseRecordBody(p, result, definition)
if definition != nil:
addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p))
@@ -1288,13 +1285,13 @@ proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
proc parseTypeDef(p: var TParser): PNode =
result = newNodeP(nkTypeDef, p)
addSon(result, identVis(p))
addSon(result, nil) # generic params
addSon(result, ast.emptyNode) # generic params
if p.tok.xkind == pxEquals:
getTok(p)
skipCom(p, result)
addSon(result, parseTypeDesc(p, result))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
if p.tok.xkind == pxSemicolon:
getTok(p)
skipCom(p, result)
@@ -1314,7 +1311,7 @@ proc parseConstant(p: var TParser): PNode =
skipCom(p, result)
addSon(result, parseTypeDesc(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
if p.tok.xkind != pxEquals:
parMessage(p, errColonOrEqualsExpected, $(p.tok))
if p.tok.xkind == pxEquals:
@@ -1322,7 +1319,7 @@ proc parseConstant(p: var TParser): PNode =
skipCom(p, result)
addSon(result, parseExpr(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
if p.tok.xkind == pxSemicolon:
getTok(p)
skipCom(p, result)
@@ -1349,12 +1346,12 @@ proc parseRoutine(p: var TParser): PNode =
skipCom(p, result)
expectIdent(p)
addSon(result, identVis(p))
addSon(result, nil) # generic parameters
addSon(result, ast.emptyNode) # generic parameters
addSon(result, parseParamList(p))
opt(p, pxSemicolon)
addSon(result, parseRoutineSpecifiers(p, noBody))
if (p.section == seInterface) or noBody:
addSon(result, nil)
addSon(result, ast.emptyNode)
else:
var stmts = newNodeP(nkStmtList, p)
while true:
@@ -1408,8 +1405,7 @@ proc exSymbols(n: PNode) =
of nkTypeSection:
for i in countup(0, sonsLen(n) - 1):
exSymbol(n.sons[i].sons[0])
if (n.sons[i].sons[2] != nil) and
(n.sons[i].sons[2].kind == nkObjectTy):
if n.sons[i].sons[2].kind == nkObjectTy:
fixRecordDef(n.sons[i].sons[2])
else: nil
@@ -1425,13 +1421,15 @@ proc parseBegin(p: var TParser, result: PNode) =
break
of pxSemicolon: getTok(p)
of pxEof: parMessage(p, errExprExpected)
else: addSonIfNotNil(result, parseStmt(p))
else:
var a = parseStmt(p)
if a.kind != nkEmpty: addSon(result, a)
if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p))
proc parseStmt(p: var TParser): PNode =
var oldcontext = p.context
p.context = conStmt
result = nil
result = ast.emptyNode
case p.tok.xkind
of pxBegin:
result = newNodeP(nkStmtList, p)
@@ -1475,23 +1473,23 @@ proc parseStmt(p: var TParser): PNode =
result = newNodeP(nkBreakStmt, p)
getTok(p)
skipCom(p, result)
addSon(result, nil)
addSon(result, ast.emptyNode)
elif p.tok.ident.id == getIdent("continue").id:
result = newNodeP(nkContinueStmt, p)
getTok(p)
skipCom(p, result)
addSon(result, nil)
addSon(result, ast.emptyNode)
elif p.tok.ident.id == getIdent("exit").id:
result = newNodeP(nkReturnStmt, p)
getTok(p)
skipCom(p, result)
addSon(result, nil)
addSon(result, ast.emptyNode)
else:
result = parseExprStmt(p)
of pxDot: getTok(p) # BUGFIX for ``end.`` in main program
else: result = parseExprStmt(p)
opt(p, pxSemicolon)
if result != nil: skipCom(p, result)
if result.kind != nkEmpty: skipCom(p, result)
p.context = oldcontext
proc parseUnit(p: var TParser): PNode =

View File

@@ -104,7 +104,7 @@ proc processTopLevelStmtCached(n: PNode, a: var TPassContextArray) =
if not isNil(gPasses[i].openCached): m = gPasses[i].process(a[i], m)
proc closePassesCached(a: var TPassContextArray) =
var m: PNode = nil
var m = ast.emptyNode
for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].openCached) and not isNil(gPasses[i].close):
m = gPasses[i].close(a[i], m)
@@ -114,7 +114,6 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
rd: PRodReader) =
var
p: TParsers
n: PNode
a: TPassContextArray
s: PLLStream
if rd == nil:
@@ -129,8 +128,8 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
while true:
openParsers(p, filename, s)
while true:
n = parseTopLevelStmt(p)
if n == nil: break
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break
processTopLevelStmt(n, a)
closeParsers(p)
if s.kind != llsStdIn: break
@@ -139,7 +138,7 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
IDsynchronizationPoint(1000)
else:
openPassesCached(a, module, filename, rd)
n = loadInitSection(rd) #MessageOut('init section' + renderTree(n));
var n = loadInitSection(rd) #MessageOut('init section' + renderTree(n));
for i in countup(0, sonsLen(n) - 1): processTopLevelStmtCached(n.sons[i], a)
closePassesCached(a)

View File

@@ -28,8 +28,8 @@ proc ParseAll*(p: var TParser): PNode
proc openParser*(p: var TParser, filename: string, inputstream: PLLStream)
proc closeParser*(p: var TParser)
proc parseTopLevelStmt*(p: var TParser): PNode
# implements an iterator. Returns the next top-level statement or nil if end
# of stream.
# implements an iterator. Returns the next top-level statement or
# emtyNode if end of stream.
# helpers for the other parsers
proc getPrecedence*(tok: PToken): int
@@ -94,7 +94,7 @@ proc optInd(p: var TParser, n: PNode) =
skipInd(p)
proc expectIdentOrKeyw(p: TParser) =
if (p.tok.tokType != tkSymbol) and not isKeyword(p.tok.tokType):
if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType):
lexMessage(p.lex^, errIdentifierExpected, tokToStr(p.tok))
proc ExpectIdent(p: TParser) =
@@ -217,18 +217,17 @@ proc parseSymbol(p: var TParser): PNode =
addSon(result, newIdentNodeP(id, p))
else:
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
result = nil
result = ast.emptyNode
eat(p, tkAccent)
else:
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
result = nil
result = ast.emptyNode
proc accExpr(p: var TParser): PNode =
var x, y: PNode
result = newNodeP(nkAccQuoted, p)
getTok(p) # skip `
x = nil
y = nil
var x = ast.emptyNode
var y = ast.emptyNode
case p.tok.tokType
of tkSymbol, tkOpr, tokKeywordLow..tokKeywordHigh:
x = newIdentNodeP(p.tok.ident, p)
@@ -255,9 +254,9 @@ proc optExpr(p: var TParser): PNode =
(p.tok.tokType != tkDotDot):
result = parseExpr(p)
else:
result = nil
result = ast.emptyNode
proc dotdotExpr(p: var TParser, first: PNode = nil): PNode =
proc dotdotExpr(p: var TParser, first: PNode): PNode =
result = newNodeP(nkRange, p)
addSon(result, first)
getTok(p)
@@ -266,20 +265,19 @@ proc dotdotExpr(p: var TParser, first: PNode = nil): PNode =
proc indexExpr(p: var TParser): PNode =
# indexExpr ::= '..' [expr] | expr ['=' expr | '..' expr]
var a, b: PNode
if p.tok.tokType == tkDotDot:
result = dotdotExpr(p)
result = dotdotExpr(p, ast.emptyNode)
else:
a = parseExpr(p)
var a = parseExpr(p)
case p.tok.tokType
of tkEquals:
result = newNodeP(nkExprEqExpr, p)
addSon(result, a)
getTok(p)
if p.tok.tokType == tkDotDot:
addSon(result, dotdotExpr(p))
addSon(result, dotdotExpr(p, ast.emptyNode))
else:
b = parseExpr(p)
var b = parseExpr(p)
if p.tok.tokType == tkDotDot: b = dotdotExpr(p, b)
addSon(result, b)
of tkDotDot:
@@ -305,7 +303,8 @@ proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode =
var a = parseExpr(p)
if p.tok.tokType == tok:
result = newNodeP(kind, p)
getTok(p) #optInd(p, result);
getTok(p)
#optInd(p, result)
addSon(result, a)
addSon(result, parseExpr(p))
else:
@@ -481,14 +480,13 @@ proc identOrLiteral(p: var TParser): PNode =
else:
parMessage(p, errExprExpected, tokToStr(p.tok))
getTok(p) # we must consume a token here to prevend endless loops!
result = nil
result = ast.emptyNode
proc primary(p: var TParser): PNode =
var a: PNode
# prefix operator?
if (p.tok.tokType == tkNot) or (p.tok.tokType == tkOpr):
result = newNodeP(nkPrefix, p)
a = newIdentNodeP(p.tok.ident, p)
var a = newIdentNodeP(p.tok.ident, p)
addSon(result, a)
getTok(p)
optInd(p, a)
@@ -504,12 +502,12 @@ proc primary(p: var TParser): PNode =
while true:
case p.tok.tokType
of tkParLe:
a = result
var a = result
result = newNodeP(nkCall, p)
addSon(result, a)
exprColonEqExprListAux(p, nkExprEqExpr, tkParRi, tkEquals, result)
of tkDot:
a = result
var a = result
result = newNodeP(nkDotExpr, p)
addSon(result, a)
getTok(p) # skip '.'
@@ -517,7 +515,7 @@ proc primary(p: var TParser): PNode =
addSon(result, parseSymbol(p))
result = parseGStrLit(p, result)
of tkHat:
a = result
var a = result
result = newNodeP(nkDerefExpr, p)
addSon(result, a)
getTok(p)
@@ -549,30 +547,28 @@ proc lowestExpr(p: var TParser): PNode =
discard lowestExprAux(p, result, - 1)
proc parseIfExpr(p: var TParser): PNode =
var branch: PNode
result = newNodeP(nkIfExpr, p)
while true:
getTok(p) # skip `if`, `elif`
branch = newNodeP(nkElifExpr, p)
var branch = newNodeP(nkElifExpr, p)
addSon(branch, parseExpr(p))
eat(p, tkColon)
addSon(branch, parseExpr(p))
addSon(result, branch)
if p.tok.tokType != tkElif: break
branch = newNodeP(nkElseExpr, p)
var branch = newNodeP(nkElseExpr, p)
eat(p, tkElse)
eat(p, tkColon)
addSon(branch, parseExpr(p))
addSon(result, branch)
proc parsePragma(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkPragma, p)
getTok(p)
optInd(p, result)
while (p.tok.tokType != tkCurlyDotRi) and (p.tok.tokType != tkCurlyRi) and
(p.tok.tokType != tkEof) and (p.tok.tokType != tkSad):
a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
var a = exprColonEqExpr(p, nkExprColonExpr, tkColon)
addSon(result, a)
if p.tok.tokType == tkComma:
getTok(p)
@@ -583,8 +579,7 @@ proc parsePragma(p: var TParser): PNode =
proc identVis(p: var TParser): PNode =
# identifier with visability
var a: PNode
a = parseSymbol(p)
var a = parseSymbol(p)
if p.tok.tokType == tkOpr:
result = newNodeP(nkPostfix, p)
addSon(result, newIdentNodeP(p.tok.ident, p))
@@ -594,8 +589,7 @@ proc identVis(p: var TParser): PNode =
result = a
proc identWithPragma(p: var TParser): PNode =
var a: PNode
a = identVis(p)
var a = identVis(p)
if p.tok.tokType == tkCurlyDotLe:
result = newNodeP(nkPragmaExpr, p)
addSon(result, a)
@@ -617,7 +611,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
of tkSymbol, tkAccent:
if withPragma in flags: a = identWithPragma(p)
else: a = parseSymbol(p)
if a == nil: return
if a.kind == nkEmpty: return
else: break
addSon(result, a)
if p.tok.tokType != tkComma: break
@@ -628,7 +622,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
optInd(p, result)
addSon(result, parseTypeDesc(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
if (p.tok.tokType != tkEquals) and not (withBothOptional in flags):
parMessage(p, errColonOrEqualsExpected, tokToStr(p.tok))
if p.tok.tokType == tkEquals:
@@ -636,16 +630,15 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
optInd(p, result)
addSon(result, parseExpr(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
proc parseTuple(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkTupleTy, p)
getTok(p)
eat(p, tkBracketLe)
optInd(p, result)
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
a = parseIdentColonEquals(p, {})
var a = parseIdentColonEquals(p, {})
addSon(result, a)
if p.tok.tokType != tkComma: break
getTok(p)
@@ -656,7 +649,7 @@ proc parseTuple(p: var TParser): PNode =
proc parseParamList(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkFormalParams, p)
addSon(result, nil) # return type
addSon(result, ast.emptyNode) # return type
if p.tok.tokType == tkParLe:
getTok(p)
optInd(p, result)
@@ -689,11 +682,11 @@ proc parseProcExpr(p: var TParser, isExpr: bool): PNode =
getTok(p)
params = parseParamList(p)
if p.tok.tokType == tkCurlyDotLe: pragmas = parsePragma(p)
else: pragmas = nil
else: pragmas = ast.emptyNode
if (p.tok.tokType == tkEquals) and isExpr:
result = newNodeI(nkLambda, info)
addSon(result, nil) # no name part
addSon(result, nil) # no generic parameters
addSon(result, ast.emptyNode) # no name part
addSon(result, ast.emptyNode) # no generic parameters
addSon(result, params)
addSon(result, pragmas)
getTok(p)
@@ -744,12 +737,11 @@ proc isExprStart(p: TParser): bool =
else: result = false
proc parseExprStmt(p: var TParser): PNode =
var a, b, e: PNode
a = lowestExpr(p)
var a = lowestExpr(p)
if p.tok.tokType == tkEquals:
getTok(p)
optInd(p, result)
b = parseExpr(p)
var b = parseExpr(p)
result = newNodeI(nkAsgn, a.info)
addSon(result, a)
addSon(result, b)
@@ -759,7 +751,7 @@ proc parseExprStmt(p: var TParser): PNode =
addSon(result, a)
while true:
if not isExprStart(p): break
e = parseExpr(p)
var e = parseExpr(p)
addSon(result, e)
if p.tok.tokType != tkComma: break
getTok(p)
@@ -778,6 +770,7 @@ proc parseExprStmt(p: var TParser): PNode =
addSon(result, parseStmt(p))
while true:
if p.tok.tokType == tkSad: getTok(p)
var b: PNode
case p.tok.tokType
of tkOf:
b = newNodeP(nkOfBranch, p)
@@ -871,7 +864,7 @@ proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
getTok(p)
optInd(p, result)
case p.tok.tokType
of tkEof, tkSad, tkDed: addSon(result, nil)
of tkEof, tkSad, tkDed: addSon(result, ast.emptyNode)
else: addSon(result, parseExpr(p))
proc parseYieldOrDiscard(p: var TParser, kind: TNodeKind): PNode =
@@ -885,15 +878,14 @@ proc parseBreakOrContinue(p: var TParser, kind: TNodeKind): PNode =
getTok(p)
optInd(p, result)
case p.tok.tokType
of tkEof, tkSad, tkDed: addSon(result, nil)
of tkEof, tkSad, tkDed: addSon(result, ast.emptyNode)
else: addSon(result, parseSymbol(p))
proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
var branch: PNode
result = newNodeP(kind, p)
while true:
getTok(p) # skip `if`, `when`, `elif`
branch = newNodeP(nkElifBranch, p)
var branch = newNodeP(nkElifBranch, p)
optInd(p, branch)
addSon(branch, parseExpr(p))
eat(p, tkColon)
@@ -903,7 +895,7 @@ proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
addSon(result, branch)
if p.tok.tokType != tkElif: break
if p.tok.tokType == tkElse:
branch = newNodeP(nkElse, p)
var branch = newNodeP(nkElse, p)
eat(p, tkElse)
eat(p, tkColon)
skipComment(p, branch)
@@ -954,13 +946,12 @@ proc parseCase(p: var TParser): PNode =
if b.kind == nkElse: break
proc parseTry(p: var TParser): PNode =
var b: PNode
result = newNodeP(nkTryStmt, p)
getTok(p)
eat(p, tkColon)
skipComment(p, result)
addSon(result, parseStmt(p))
b = nil
var b: PNode = nil
while true:
if p.tok.tokType == tkSad: getTok(p)
case p.tok.tokType
@@ -979,11 +970,10 @@ proc parseTry(p: var TParser): PNode =
if b == nil: parMessage(p, errTokenExpected, "except")
proc parseFor(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkForStmt, p)
getTok(p)
optInd(p, result)
a = parseSymbol(p)
var a = parseSymbol(p)
addSon(result, a)
while p.tok.tokType == tkComma:
getTok(p)
@@ -1001,7 +991,7 @@ proc parseBlock(p: var TParser): PNode =
getTok(p)
optInd(p, result)
case p.tok.tokType
of tkEof, tkSad, tkDed, tkColon: addSon(result, nil)
of tkEof, tkSad, tkDed, tkColon: addSon(result, ast.emptyNode)
else: addSon(result, parseSymbol(p))
eat(p, tkColon)
skipComment(p, result)
@@ -1012,7 +1002,7 @@ proc parseAsm(p: var TParser): PNode =
getTok(p)
optInd(p, result)
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
else: addSon(result, nil)
else: addSon(result, ast.emptyNode)
case p.tok.tokType
of tkStrLit: addSon(result, newStrNodeP(nkStrLit, p.tok.literal, p))
of tkRStrLit: addSon(result, newStrNodeP(nkRStrLit, p.tok.literal, p))
@@ -1020,17 +1010,16 @@ proc parseAsm(p: var TParser): PNode =
newStrNodeP(nkTripleStrLit, p.tok.literal, p))
else:
parMessage(p, errStringLiteralExpected)
addSon(result, nil)
addSon(result, ast.emptyNode)
return
getTok(p)
proc parseGenericParamList(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkGenericParams, p)
getTok(p)
optInd(p, result)
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
a = parseIdentColonEquals(p, {withBothOptional})
var a = parseIdentColonEquals(p, {withBothOptional})
addSon(result, a)
if p.tok.tokType != tkComma: break
getTok(p)
@@ -1044,16 +1033,16 @@ proc parseRoutine(p: var TParser, kind: TNodeKind): PNode =
optInd(p, result)
addSon(result, identVis(p))
if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
else: addSon(result, nil)
else: addSon(result, ast.emptyNode)
addSon(result, parseParamList(p))
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
else: addSon(result, nil)
else: addSon(result, ast.emptyNode)
if p.tok.tokType == tkEquals:
getTok(p)
skipComment(p, result)
addSon(result, parseStmt(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
indAndComment(p, result) # XXX: document this in the grammar!
proc newCommentStmt(p: var TParser): PNode =
@@ -1065,13 +1054,12 @@ type
proc parseSection(p: var TParser, kind: TNodeKind,
defparser: TDefParser): PNode =
var a: PNode
result = newNodeP(kind, p)
getTok(p)
skipComment(p, result)
case p.tok.tokType
of tkInd:
pushInd(p.lex^ , p.tok.indent)
pushInd(p.lex^, p.tok.indent)
getTok(p)
skipComment(p, result)
while true:
@@ -1079,7 +1067,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
of tkSad:
getTok(p)
of tkSymbol, tkAccent:
a = defparser(p)
var a = defparser(p)
skipComment(p, a)
addSon(result, a)
of tkDed:
@@ -1088,13 +1076,13 @@ proc parseSection(p: var TParser, kind: TNodeKind,
of tkEof:
break # BUGFIX
of tkComment:
a = newCommentStmt(p)
var a = newCommentStmt(p)
skipComment(p, a)
addSon(result, a)
else:
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
break
popInd(p.lex^ )
popInd(p.lex^)
of tkSymbol, tkAccent, tkParLe:
# tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
addSon(result, defparser(p))
@@ -1108,7 +1096,7 @@ proc parseConstant(p: var TParser): PNode =
optInd(p, result)
addSon(result, parseTypeDesc(p))
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
eat(p, tkEquals)
optInd(p, result)
addSon(result, parseExpr(p))
@@ -1126,7 +1114,7 @@ proc parseEnum(p: var TParser): PNode =
addSon(a, parseTypeDesc(p))
addSon(result, a)
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
optInd(p, result)
while true:
case p.tok.tokType
@@ -1148,11 +1136,10 @@ proc parseEnum(p: var TParser): PNode =
proc parseObjectPart(p: var TParser): PNode
proc parseObjectWhen(p: var TParser): PNode =
var branch: PNode
result = newNodeP(nkRecWhen, p)
while true:
getTok(p) # skip `when`, `elif`
branch = newNodeP(nkElifBranch, p)
var branch = newNodeP(nkElifBranch, p)
optInd(p, branch)
addSon(branch, parseExpr(p))
eat(p, tkColon)
@@ -1162,7 +1149,7 @@ proc parseObjectWhen(p: var TParser): PNode =
addSon(result, branch)
if p.tok.tokType != tkElif: break
if p.tok.tokType == tkElse:
branch = newNodeP(nkElse, p)
var branch = newNodeP(nkElse, p)
eat(p, tkElse)
eat(p, tkColon)
skipComment(p, branch)
@@ -1170,18 +1157,18 @@ proc parseObjectWhen(p: var TParser): PNode =
addSon(result, branch)
proc parseObjectCase(p: var TParser): PNode =
var a, b: PNode
result = newNodeP(nkRecCase, p)
getTok(p)
a = newNodeP(nkIdentDefs, p)
var a = newNodeP(nkIdentDefs, p)
addSon(a, identWithPragma(p))
eat(p, tkColon)
addSon(a, parseTypeDesc(p))
addSon(a, nil)
addSon(a, ast.emptyNode)
addSon(result, a)
skipComment(p, result)
while true:
if p.tok.tokType == tkSad: getTok(p)
var b: PNode
case p.tok.tokType
of tkOf:
b = newNodeP(nkOfBranch, p)
@@ -1200,7 +1187,7 @@ proc parseObjectPart(p: var TParser): PNode =
case p.tok.tokType
of tkInd:
result = newNodeP(nkRecList, p)
pushInd(p.lex^ , p.tok.indent)
pushInd(p.lex^, p.tok.indent)
getTok(p)
skipComment(p, result)
while true:
@@ -1228,21 +1215,20 @@ proc parseObjectPart(p: var TParser): PNode =
of tkNil:
result = newNodeP(nkNilLit, p)
getTok(p)
else: result = nil
else: result = ast.emptyNode
proc parseObject(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkObjectTy, p)
getTok(p)
if p.tok.tokType == tkCurlyDotLe: addSon(result, parsePragma(p))
else: addSon(result, nil)
else: addSon(result, ast.emptyNode)
if p.tok.tokType == tkOf:
a = newNodeP(nkOfInherit, p)
var a = newNodeP(nkOfInherit, p)
getTok(p)
addSon(a, parseTypeDesc(p))
addSon(result, a)
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
skipComment(p, result)
addSon(result, parseObjectPart(p))
@@ -1253,14 +1239,14 @@ proc parseDistinct(p: var TParser): PNode =
addSon(result, parseTypeDesc(p))
proc parseTypeDef(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkTypeDef, p)
addSon(result, identWithPragma(p))
if p.tok.tokType == tkBracketLe: addSon(result, parseGenericParamList(p))
else: addSon(result, nil)
else: addSon(result, ast.emptyNode)
if p.tok.tokType == tkEquals:
getTok(p)
optInd(p, result)
var a: PNode
case p.tok.tokType
of tkObject: a = parseObject(p)
of tkEnum: a = parseEnum(p)
@@ -1268,21 +1254,20 @@ proc parseTypeDef(p: var TParser): PNode =
else: a = parseTypeDesc(p)
addSon(result, a)
else:
addSon(result, nil)
addSon(result, ast.emptyNode)
indAndComment(p, result) # special extension!
proc parseVarTuple(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkVarTuple, p)
getTok(p) # skip '('
optInd(p, result)
while (p.tok.tokType == tkSymbol) or (p.tok.tokType == tkAccent):
a = identWithPragma(p)
var a = identWithPragma(p)
addSon(result, a)
if p.tok.tokType != tkComma: break
getTok(p)
optInd(p, a)
addSon(result, nil) # no type desc
addSon(result, ast.emptyNode) # no type desc
optPar(p)
eat(p, tkParRi)
eat(p, tkEquals)
@@ -1309,8 +1294,8 @@ proc simpleStmt(p: var TParser): PNode =
of tkComment: result = newCommentStmt(p)
else:
if isExprStart(p): result = parseExprStmt(p)
else: result = nil
if result != nil: skipComment(p, result)
else: result = ast.emptyNode
if result.kind != nkEmpty: skipComment(p, result)
proc complexOrSimpleStmt(p: var TParser): PNode =
case p.tok.tokType
@@ -1334,10 +1319,9 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
else: result = simpleStmt(p)
proc parseStmt(p: var TParser): PNode =
var a: PNode
if p.tok.tokType == tkInd:
result = newNodeP(nkStmtList, p)
pushInd(p.lex^ , p.tok.indent)
pushInd(p.lex^, p.tok.indent)
getTok(p)
while true:
case p.tok.tokType
@@ -1347,8 +1331,8 @@ proc parseStmt(p: var TParser): PNode =
getTok(p)
break
else:
a = complexOrSimpleStmt(p)
if a == nil: break
var a = complexOrSimpleStmt(p)
if a.kind == nkEmpty: break
addSon(result, a)
popInd(p.lex^ )
else:
@@ -1357,14 +1341,13 @@ proc parseStmt(p: var TParser): PNode =
of tkIf, tkWhile, tkCase, tkTry, tkFor, tkBlock, tkAsm, tkProc, tkIterator,
tkMacro, tkType, tkConst, tkWhen, tkVar:
parMessage(p, errComplexStmtRequiresInd)
result = nil
result = ast.emptyNode
else:
result = simpleStmt(p)
if result == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
if result.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
if p.tok.tokType == tkSad: getTok(p)
proc parseAll(p: var TParser): PNode =
var a: PNode
result = newNodeP(nkStmtList, p)
while true:
case p.tok.tokType
@@ -1372,20 +1355,20 @@ proc parseAll(p: var TParser): PNode =
of tkDed, tkInd: parMessage(p, errInvalidIndentation)
of tkEof: break
else:
a = complexOrSimpleStmt(p)
if a == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
var a = complexOrSimpleStmt(p)
if a.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
addSon(result, a)
proc parseTopLevelStmt(p: var TParser): PNode =
result = nil
result = ast.emptyNode
while true:
case p.tok.tokType
of tkSad: getTok(p)
of tkDed, tkInd:
parMessage(p, errInvalidIndentation)
break
getTok(p)
of tkEof: break
else:
result = complexOrSimpleStmt(p)
if result == nil: parMessage(p, errExprExpected, tokToStr(p.tok))
if result.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
break

View File

@@ -323,13 +323,13 @@ proc lsons(n: PNode, start: int = 0, theEnd: int = - 1): int =
proc lsub(n: PNode): int =
# computes the length of a tree
if n == nil: return 0
if n.comment != nil: return maxLineLen + 1
case n.kind
of nkEmpty: result = 0
of nkTripleStrLit:
if containsNL(n.strVal): result = maxLineLen + 1
else: result = len(atom(n))
of nkEmpty..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
result = len(atom(n))
of nkCall, nkBracketExpr, nkConv: result = lsub(n.sons[0]) + lcomma(n, 1) + 2
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: result = lsub(n[1])
@@ -348,8 +348,8 @@ proc lsub(n: PNode): int =
of nkConstDef, nkIdentDefs:
result = lcomma(n, 0, - 3)
var L = sonsLen(n)
if n.sons[L - 2] != nil: result = result + lsub(n.sons[L - 2]) + 2
if n.sons[L - 1] != nil: result = result + lsub(n.sons[L - 1]) + 3
if n.sons[L - 2].kind != nkEmpty: result = result + lsub(n.sons[L - 2]) + 2
if n.sons[L - 1].kind != nkEmpty: result = result + lsub(n.sons[L - 1]) + 3
of nkVarTuple: result = lcomma(n, 0, - 3) + len("() = ") + lsub(lastSon(n))
of nkChckRangeF: result = len("chckRangeF") + 2 + lcomma(n)
of nkChckRange64: result = len("chckRange64") + 2 + lcomma(n)
@@ -401,7 +401,7 @@ proc lsub(n: PNode): int =
of nkGenericParams: result = lcomma(n) + 2
of nkFormalParams:
result = lcomma(n, 1) + 2
if n.sons[0] != nil: result = result + lsub(n.sons[0]) + 2
if n.sons[0].kind != nkEmpty: result = result + lsub(n.sons[0]) + 2
of nkExceptBranch:
result = lcomma(n, 0, -2) + lsub(lastSon(n)) + len("except_:_")
else: result = maxLineLen + 1
@@ -430,7 +430,6 @@ proc gsub(g: var TSrcGen, n: PNode) =
proc hasCom(n: PNode): bool =
result = false
if n == nil: return
if n.comment != nil: return true
case n.kind
of nkEmpty..nkNilLit: nil
@@ -496,7 +495,7 @@ proc longMode(n: PNode, start: int = 0, theEnd: int = - 1): bool =
break
proc gstmts(g: var TSrcGen, n: PNode, c: TContext) =
if n == nil: return
if n.kind == nkEmpty: return
if (n.kind == nkStmtList) or (n.kind == nkStmtListExpr):
indentNL(g)
for i in countup(0, sonsLen(n) - 1):
@@ -598,7 +597,7 @@ proc gproc(g: var TSrcGen, n: PNode) =
gsub(g, n.sons[2])
gsub(g, n.sons[3])
if not (renderNoBody in g.flags):
if n.sons[4] != nil:
if n.sons[4].kind != nkEmpty:
put(g, tkSpaces, Space)
putWithSpace(g, tkEquals, "=")
indentNL(g)
@@ -615,7 +614,7 @@ proc gproc(g: var TSrcGen, n: PNode) =
proc gblock(g: var TSrcGen, n: PNode) =
var c: TContext
initContext(c)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
putWithSpace(g, tkBlock, "block")
gsub(g, n.sons[0])
else:
@@ -656,11 +655,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
var
L: int
a: TContext
if n == nil: return
if n.comment != nil: pushCom(g, n)
case n.kind # atoms:
of nkTripleStrLit: putRawStr(g, tkTripleStrLit, n.strVal)
of nkEmpty, nkType: put(g, tkInvalid, atom(n))
of nkEmpty: nil
of nkType: put(g, tkInvalid, atom(n))
of nkSym, nkIdent: gident(g, n)
of nkIntLit: put(g, tkIntLit, atom(n))
of nkInt8Lit: put(g, tkInt8Lit, atom(n))
@@ -765,7 +764,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref:
gsub(g, n.sons[0])
of nkLambda:
assert(n.sons[genericParamsPos] == nil)
assert(n.sons[genericParamsPos].kind == nkEmpty)
putWithSpace(g, tkLambda, "lambda")
gsub(g, n.sons[paramsPos])
gsub(g, n.sons[pragmasPos])
@@ -775,10 +774,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
of nkConstDef, nkIdentDefs:
gcomma(g, n, 0, - 3)
var L = sonsLen(n)
if n.sons[L - 2] != nil:
if n.sons[L - 2].kind != nkEmpty:
putWithSpace(g, tkColon, ":")
gsub(g, n.sons[L - 2])
if n.sons[L - 1] != nil:
if n.sons[L - 1].kind != nkEmpty:
put(g, tkSpaces, Space)
putWithSpace(g, tkEquals, "=")
gsub(g, n.sons[L - 1], c)
@@ -855,7 +854,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gsub(g, n.sons[0])
gsub(g, n.sons[1])
put(g, tkSpaces, Space)
if n.sons[2] != nil:
if n.sons[2].kind != nkEmpty:
putWithSpace(g, tkEquals, "=")
gsub(g, n.sons[2])
of nkObjectTy:
@@ -1029,7 +1028,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkParLe, "(")
gcomma(g, n, 1)
put(g, tkParRi, ")")
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
putWithSpace(g, tkColon, ":")
gsub(g, n.sons[0])
of nkTupleTy:
@@ -1055,10 +1054,9 @@ proc renderModule(n: PNode, filename: string, renderFlags: TRenderFlags = {}) =
for i in countup(0, sonsLen(n) - 1):
gsub(g, n.sons[i])
optNL(g)
if n.sons[i] != nil:
case n.sons[i].kind
of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
else: nil
case n.sons[i].kind
of nkTypeSection, nkConstSection, nkVarSection, nkCommentStmt: putNL(g)
else: nil
gcoms(g)
if open(f, filename, fmWrite):
write(f, g.buf)

View File

@@ -175,7 +175,6 @@ proc findIdent(L: TLexer, indent: int): bool =
for i in countdown(len(L.indentStack) - 1, 0):
if L.indentStack[i] == indent:
return true
result = false
proc tokToStr(tok: PToken): string =
case tok.tokType
@@ -574,7 +573,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
of '_':
if buf[pos+1] notin SymChars:
lexMessage(L, errInvalidToken, "_")
return
break
else: break
Inc(pos)
h = h +% h shl 3
@@ -587,11 +586,6 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
tok.tokType = tkSymbol
else:
tok.tokType = TTokType(tok.ident.id + ord(tkSymbol))
when false:
if buf[pos] == '\"':
getString(L, tok, true)
if tok.tokType == tkRStrLit: tok.tokType = tkCallRStrLit
else: tok.tokType = tkCallTripleStrLit
proc getOperator(L: var TLexer, tok: var TToken) =
var pos = L.bufpos

View File

@@ -133,7 +133,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
liMessage(n.info, errOrdinalTypeExpected)
if enumHasWholes(a.typ):
liMessage(n.info, errEnumXHasWholes, a.typ.sym.name.s)
liMessage(n.info, errEnumXHasHoles, a.typ.sym.name.s)
if not leValue(a, b): liMessage(n.Info, errRangeIsEmpty)
addSon(result.n, a)
addSon(result.n, b)
@@ -160,7 +160,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
if not isOrdinalType(indx):
liMessage(n.sons[1].info, errOrdinalTypeExpected)
if enumHasWholes(indx):
liMessage(n.sons[1].info, errEnumXHasWholes, indx.sym.name.s)
liMessage(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
base = semTypeNode(c, n.sons[2], nil)
addSon(result, base)
else:

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -59,6 +59,7 @@ proc parseAll(p: var TParsers): PNode =
result = pbraces.parseAll(p.parser)
of skinEndX:
InternalError("parser to implement")
result = ast.emptyNode
# skinEndX: result := pendx.parseAll(p.parser);
proc parseTopLevelStmt(p: var TParsers): PNode =
@@ -69,6 +70,7 @@ proc parseTopLevelStmt(p: var TParsers): PNode =
result = pbraces.parseTopLevelStmt(p.parser)
of skinEndX:
InternalError("parser to implement")
result = ast.emptyNode
#skinEndX: result := pendx.parseTopLevelStmt(p.parser);
proc UTF8_BOM(s: string): int =
@@ -84,6 +86,7 @@ proc containsShebang(s: string, i: int): bool =
result = s[j] == '/'
proc parsePipe(filename: string, inputStream: PLLStream): PNode =
result = ast.emptyNode
var s = LLStreamOpen(filename, fmRead)
if s != nil:
var line = LLStreamReadLine(s)
@@ -143,7 +146,7 @@ proc applyFilter(p: var TParsers, n: PNode, filename: string,
proc evalPipe(p: var TParsers, n: PNode, filename: string,
start: PLLStream): PLLStream =
result = start
if n == nil: return
if n.kind == nkEmpty: return
if (n.kind == nkInfix) and (n.sons[0].kind == nkIdent) and
IdentEq(n.sons[0].ident, "|"):
for i in countup(1, 2):

View File

@@ -1,3 +1,8 @@
- ban ``nil`` from the AST. This might also fix bugs concerning macros.
TODO:
* semantic checking (keep in mind incremental parsing!)
* code generators
- thread support: threadvar on Windows seems broken;
add --deadlock_prevention:on|off switch
- built-in serialization
@@ -68,7 +73,6 @@ Low priority
- fast assignment optimization for TPeg
- better error messages for used keywords as identifiers
- case statement branches should support constant sets
- ban ``nil`` from the AST. This might also fix bugs concerning macros.
Library