diff options
-rwxr-xr-x | config/nimrod.cfg | 1 | ||||
-rwxr-xr-x | lib/pure/strutils.nim | 23 | ||||
-rwxr-xr-x | rod/commands.nim | 4 | ||||
-rwxr-xr-x | rod/lists.nim | 13 | ||||
-rwxr-xr-x | rod/main.nim | 65 | ||||
-rwxr-xr-x | rod/options.nim | 4 | ||||
-rwxr-xr-x | rod/pas2nim/pas2nim.nim | 67 | ||||
-rwxr-xr-x | rod/pas2nim/paslex.nim (renamed from rod/paslex.nim) | 345 | ||||
-rwxr-xr-x | rod/pas2nim/pasparse.nim (renamed from rod/pasparse.nim) | 275 | ||||
-rwxr-xr-x | rod/wordrecg.nim | 74 | ||||
-rwxr-xr-x | web/news.txt | 15 |
11 files changed, 352 insertions, 534 deletions
diff --git a/config/nimrod.cfg b/config/nimrod.cfg index 6a9289a5e..5f4c12786 100755 --- a/config/nimrod.cfg +++ b/config/nimrod.cfg @@ -15,7 +15,6 @@ cc = gcc @end path="$lib/pure" -path="$lib/devel" path="$lib/impure" path="$lib/wrappers" path="$lib/wrappers/cairo" diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 1dfb070bc..5cf1cf6a3 100755 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -326,6 +326,10 @@ proc ParseFloat*(s: string): float {.noSideEffect, procvar.} ## a valid floating point number, `EInvalidValue` is raised. ``NAN``, ## ``INF``, ``-INF`` are also supported (case insensitive comparison). +proc ParseHexInt*(s: string): int {.noSideEffect, procvar.} + ## Parses a hexadecimal integer value contained in `s`. If `s` is not + ## a valid integer, `EInvalidValue` is raised. + # the stringify and format operators: proc toString*[Ty](x: Ty): string {.deprecated.} ## This generic proc is the same as the stringify operator `$`. @@ -731,6 +735,25 @@ proc ParseBiggestInt(s: string): biggestInt = if index == -1: raise newException(EInvalidValue, "invalid integer: " & s) + +proc ParseHexInt(s: string): int = + var i = 0 + if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2) + while true: + case s[i] + of '_': inc(i) + of '0'..'9': + result = result shl 4 or (ord(s[i]) - ord('0')) + inc(i) + of 'a'..'f': + result = result shl 4 or (ord(s[i]) - ord('a') + 10) + inc(i) + of 'A'..'F': + result = result shl 4 or (ord(s[i]) - ord('A') + 10) + inc(i) + of '\0': break + else: raise newException(EInvalidValue, "invalid integer: " & s) + proc ParseFloat(s: string): float = var esign = 1.0 diff --git a/rod/commands.nim b/rod/commands.nim index f6079d6d5..17c946292 100755 --- a/rod/commands.nim +++ b/rod/commands.nim @@ -232,7 +232,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of wPath, wP: expectArg(switch, arg, pass, info) path = processPath(arg) - discard lists.IncludeStr(options.searchPaths, path) + if not contains(options.searchPaths, path): + lists.PrependStr(options.searchPaths, path) + #discard lists.IncludeStr(options.searchPaths, path) of wOut, wO: expectArg(switch, arg, pass, info) options.outFile = arg diff --git a/rod/lists.nim b/rod/lists.nim index 2e3467f43..b4610ab2f 100755 --- a/rod/lists.nim +++ b/rod/lists.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2008 Andreas Rumpf +# (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -60,15 +60,16 @@ proc AppendStr(list: var TLinkedList, data: string) = proc PrependStr(list: var TLinkedList, data: string) = prepend(list, newStrEntry(data)) -proc IncludeStr(list: var TLinkedList, data: string): bool = - var it: PListEntry - it = list.head +proc Contains*(list: TLinkedList, data: string): bool = + var it = list.head while it != nil: if PStrEntry(it).data == data: - return true # already in list + return true it = it.next + +proc IncludeStr(list: var TLinkedList, data: string): bool = + if Contains(list, data): return true AppendStr(list, data) # else: add to list - result = false proc InsertBefore(list: var TLinkedList, pos, entry: PListEntry) = assert(pos != nil) diff --git a/rod/main.nim b/rod/main.nim index 6cdd026b5..3221f531e 100755 --- a/rod/main.nim +++ b/rod/main.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf +# (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -12,7 +12,7 @@ import llstream, strutils, ast, astalgo, scanner, syntaxes, rnimsyn, options, msgs, - os, lists, condsyms, paslex, pasparse, rodread, rodwrite, ropes, trees, + os, lists, condsyms, rodread, rodwrite, ropes, trees, wordrecg, sem, semdata, idents, passes, docgen, extccomp, cgen, ecmasgen, platform, interact, nimconf, importer, passaux, depends, transf, evals, types @@ -47,7 +47,6 @@ proc getModule(filename: string): PSym = for i in countup(0, high(compMods)): if sameFile(compMods[i].filename, filename): return compMods[i].module - result = nil proc newModule(filename: string): PSym = # We cannot call ``newSym`` here, because we have to circumvent the ID @@ -152,61 +151,11 @@ proc CommandInteractive() = incl(m.flags, sfMainModule) processModule(m, "stdin", LLStreamOpenStdIn(), nil) -proc exSymbols(n: PNode) = - case n.kind - of nkEmpty..nkNilLit: nil - of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos]) - of nkWhenStmt, nkStmtList: - for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i]) - of nkVarSection, nkConstSection: - for i in countup(0, sonsLen(n) - 1): exSymbol(n.sons[i].sons[0]) - 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): - fixRecordDef(n.sons[i].sons[2]) - else: nil - -proc CommandExportSymbols(filename: string) = - # now unused! - var module = parseFile(addFileExt(filename, NimExt)) - if module != nil: - exSymbols(module) - renderModule(module, getOutFile(filename, "pretty." & NimExt)) - proc CommandPretty(filename: string) = var module = parseFile(addFileExt(filename, NimExt)) if module != nil: renderModule(module, getOutFile(filename, "pretty." & NimExt)) -proc CommandLexPas(filename: string) = - var f = addFileExt(filename, "pas") - var stream = LLStreamOpen(f, fmRead) - if stream != nil: - var - L: TPasLex - tok: TPasTok - OpenLexer(L, f, stream) - getPasTok(L, tok) - while tok.xkind != pxEof: - printPasTok(tok) - getPasTok(L, tok) - closeLexer(L) - else: rawMessage(errCannotOpenFile, f) - -proc CommandPas(filename: string) = - var f = addFileExt(filename, "pas") - var stream = LLStreamOpen(f, fmRead) - if stream != nil: - var p: TPasParser - OpenPasParser(p, f, stream) - var module = parseUnit(p) - closePasParser(p) - renderModule(module, getOutFile(filename, NimExt)) - else: - rawMessage(errCannotOpenFile, f) - proc CommandScan(filename: string) = var f = addFileExt(filename, nimExt) var stream = LLStreamOpen(f, fmRead) @@ -274,14 +223,6 @@ proc MainCommand(cmd, filename: string) = LoadSpecialConfig(DocTexConfig) wantFile(filename) CommandRst2TeX(filename) - of wPas: - gCmd = cmdPas - wantFile(filename) - CommandPas(filename) - of wBoot: - gCmd = cmdBoot - wantFile(filename) - CommandPas(filename) of wGenDepend: gCmd = cmdGenDepend wantFile(filename) @@ -306,4 +247,4 @@ proc MainCommand(cmd, filename: string) = gCmd = cmdInteractive CommandInteractive() else: rawMessage(errInvalidCommandX, cmd) - \ No newline at end of file + diff --git a/rod/options.nim b/rod/options.nim index c6db17509..514c3db3b 100755 --- a/rod/options.nim +++ b/rod/options.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf +# (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -41,7 +41,7 @@ type # please make sure we have under 32 options TGlobalOptions* = set[TGlobalOption] TCommands* = enum # Nimrod's commands cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToEcmaScript, - cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc, cmdPas, cmdBoot, + cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc, cmdGenDepend, cmdListDef, cmdCheck, # semantic checking for whole project cmdParse, # parse a single file (for debugging) cmdScan, # scan a single file (for debugging) diff --git a/rod/pas2nim/pas2nim.nim b/rod/pas2nim/pas2nim.nim new file mode 100755 index 000000000..54e4784c8 --- /dev/null +++ b/rod/pas2nim/pas2nim.nim @@ -0,0 +1,67 @@ +# +# +# Pas2nim - Pascal to Nimrod source converter +# (c) Copyright 2010 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# + +import + llstream, strutils, os, ast, rnimsyn, options, msgs, + paslex, pasparse + +proc exSymbols(n: PNode) = + case n.kind + of nkEmpty..nkNilLit: nil + of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos]) + of nkWhenStmt, nkStmtList: + for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i]) + of nkVarSection, nkConstSection: + for i in countup(0, sonsLen(n) - 1): exSymbol(n.sons[i].sons[0]) + 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): + fixRecordDef(n.sons[i].sons[2]) + else: nil + +proc CommandExportSymbols(filename: string) = + # now unused! + var module = parseFile(addFileExt(filename, NimExt)) + if module != nil: + exSymbols(module) + renderModule(module, getOutFile(filename, "pretty." & NimExt)) + +proc CommandLexPas(filename: string) = + var f = addFileExt(filename, "pas") + var stream = LLStreamOpen(f, fmRead) + if stream != nil: + var + L: TPasLex + tok: TPasTok + OpenLexer(L, f, stream) + getPasTok(L, tok) + while tok.xkind != pxEof: + printPasTok(tok) + getPasTok(L, tok) + closeLexer(L) + else: rawMessage(errCannotOpenFile, f) + +proc CommandPas(filename: string) = + var f = addFileExt(filename, "pas") + var stream = LLStreamOpen(f, fmRead) + if stream != nil: + var p: TPasParser + OpenPasParser(p, f, stream) + var module = parseUnit(p) + closePasParser(p) + renderModule(module, getOutFile(filename, NimExt)) + else: + rawMessage(errCannotOpenFile, f) + + + diff --git a/rod/paslex.nim b/rod/pas2nim/paslex.nim index e29e549ba..9159c5de7 100755 --- a/rod/paslex.nim +++ b/rod/pas2nim/paslex.nim @@ -1,44 +1,31 @@ # # -# The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf +# Pas2nim - Pascal to Nimrod source converter +# (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -# This module implements a FreePascal scanner. This is a adaption from +# This module implements a FreePascal scanner. This is an adaption from # the scanner module. import - nhashes, options, msgs, strutils, platform, idents, lexbase, wordrecg, scanner + nhashes, options, msgs, strutils, platform, idents, lexbase const MaxLineLength* = 80 # lines longer than this lead to a warning - numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'} # we support up to base 36 + numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'} SymChars*: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'} SymStartChars*: TCharSet = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'} OpChars*: TCharSet = {'+', '-', '*', '/', '<', '>', '!', '?', '^', '.', '|', '=', ':', '%', '&', '$', '@', '~', '\x80'..'\xFF'} -type # order is important for TPasTokKind +# keywords are sorted! + +type TPasTokKind* = enum - pxInvalid, pxEof, # keywords: - #[[[cog - #from string import capitalize - #keywords = eval(open("data/pas_keyw.yml").read()) - #idents = "" - #strings = "" - #i = 1 - #for k in keywords: - # idents = idents + "px" + capitalize(k) + ", " - # strings = strings + "'" + k + "', " - # if i % 4 == 0: - # idents = idents + "\n" - # strings = strings + "\n" - # i = i + 1 - #cog.out(idents) - #]]] + pxInvalid, pxEof, pxAnd, pxArray, pxAs, pxAsm, pxBegin, pxCase, pxClass, pxConst, pxConstructor, pxDestructor, pxDiv, pxDo, pxDownto, pxElse, pxEnd, pxExcept, pxExports, pxFinalization, pxFinally, pxFor, pxFunction, pxGoto, pxIf, @@ -47,13 +34,13 @@ type # order is important for TPasTokKind pxOr, pxOut, pxPacked, pxProcedure, pxProgram, pxProperty, pxRaise, pxRecord, pxRepeat, pxResourcestring, pxSet, pxShl, pxShr, pxThen, pxThreadvar, pxTo, pxTry, pxType, pxUnit, pxUntil, pxUses, pxVar, pxWhile, - pxWith, pxXor, #[[[end]]] + pxWith, pxXor, pxComment, # ordinary comment pxCommand, # {@} pxAmp, # {&} pxPer, # {%} pxStrLit, pxSymbol, # a symbol - pxIntLit, pxInt64Lit, # long constant like 0x00000070fffffff or out of int range + pxIntLit, pxInt64Lit, # long constant like 0x70fffffff or out of int range pxFloatLit, pxParLe, pxParRi, pxBracketLe, pxBracketRi, pxComma, pxSemiColon, pxColon, # operators pxAsgn, pxEquals, pxDot, pxDotDot, pxHat, pxPlus, pxMinus, pxStar, pxSlash, @@ -62,10 +49,7 @@ type # order is important for TPasTokKind TPasTokKinds* = set[TPasTokKind] const - PasTokKindToStr*: array[TPasTokKind, string] = ["pxInvalid", "[EOF]", #[[[cog - #cog.out(strings) - #]]] - "and", "array", "as", "asm", "begin", "case", "class", "const", + Keywords = ["and", "array", "as", "asm", "begin", "case", "class", "const", "constructor", "destructor", "div", "do", "downto", "else", "end", "except", "exports", "finalization", "finally", "for", "function", "goto", "if", "implementation", "in", "inherited", "initialization", "inline", @@ -73,23 +57,74 @@ const "or", "out", "packed", "procedure", "program", "property", "raise", "record", "repeat", "resourcestring", "set", "shl", "shr", "then", "threadvar", "to", "try", "type", "unit", "until", "uses", "var", "while", - "with", "xor", #[[[end]]] - "pxComment", "pxCommand", "{&}", "{%}", "pxStrLit", "[IDENTIFIER]", - "pxIntLit", "pxInt64Lit", "pxFloatLit", "(", ")", "[", "]", ",", ";", ":", - ":=", "=", ".", "..", "^", "+", "-", "*", "/", "<=", "<", ">=", ">", "<>", - "@", "(*$", "*)", "{$", "}"] + "with", "xor"] + + firstKeyword = pxAnd + lastKeyword = pxXor type - TPasTok* = object of TToken # a Pascal token + TPasTok* = object xkind*: TPasTokKind # the type of the token + ident*: PIdent # the parsed identifier + iNumber*: BiggestInt # the parsed integer literal + fNumber*: BiggestFloat # the parsed floating point literal + base*: TNumericalBase # the numerical base; only valid for int + # or float literals + literal*: string # the parsed (string) literal + + TPasLex* = object + filename*: string - TPasLex* = object of TLexer proc getPasTok*(L: var TPasLex, tok: var TPasTok) proc PrintPasTok*(tok: TPasTok) proc pasTokToStr*(tok: TPasTok): string # implementation +var dummyIdent: PIdent + +proc fillToken(L: var TToken) = + L.TokType = tkInvalid + L.iNumber = 0 + L.Indent = 0 + L.literal = "" + L.fNumber = 0.0 + L.base = base10 + L.ident = dummyIdent # this prevents many bugs! + +proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) = + openBaseLexer(lex, inputstream) + lex.indentStack = @[0] + lex.filename = filename + lex.indentAhead = - 1 + +proc closeLexer(lex: var TLexer) = + inc(gLinesCompiled, lex.LineNumber) + closeBaseLexer(lex) + +proc getColumn(L: TLexer): int = + result = getColNumber(L, L.bufPos) + +proc getLineInfo(L: TLexer): TLineInfo = + result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos)) + +proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = + msgs.liMessage(getLineInfo(L), msg, arg) + +proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = + var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) + msgs.liMessage(info, msg, arg) + +proc binaryStrSearch(x: openarray[string], y: string): int = + var a = 0 + var b = len(x) + while a < b: + var mid = (a + b) div 2 + if x[mid] < y: a = mid + 1 + else: b = mid + if a < len(x) and x[a] == y: result = a + else: result = -1 + proc pastokToStr(tok: TPasTok): string = case tok.xkind of pxIntLit, pxInt64Lit: result = $(tok.iNumber) @@ -105,144 +140,14 @@ proc PrintPasTok(tok: TPasTok) = writeln(stdout, pastokToStr(tok)) proc setKeyword(L: var TPasLex, tok: var TPasTok) = - case tok.ident.id #[[[cog - #for k in keywords: - # m = capitalize(k) - # cog.outl("ord(w%s):%s tok.xkind := px%s;" % (m, ' '*(18-len(m)), m)) - #]]] - of ord(wAnd): - tok.xkind = pxAnd - of ord(wArray): - tok.xkind = pxArray - of ord(wAs): - tok.xkind = pxAs - of ord(wAsm): - tok.xkind = pxAsm - of ord(wBegin): - tok.xkind = pxBegin - of ord(wCase): - tok.xkind = pxCase - of ord(wClass): - tok.xkind = pxClass - of ord(wConst): - tok.xkind = pxConst - of ord(wConstructor): - tok.xkind = pxConstructor - of ord(wDestructor): - tok.xkind = pxDestructor - of ord(wDiv): - tok.xkind = pxDiv - of ord(wDo): - tok.xkind = pxDo - of ord(wDownto): - tok.xkind = pxDownto - of ord(wElse): - tok.xkind = pxElse - of ord(wEnd): - tok.xkind = pxEnd - of ord(wExcept): - tok.xkind = pxExcept - of ord(wExports): - tok.xkind = pxExports - of ord(wFinalization): - tok.xkind = pxFinalization - of ord(wFinally): - tok.xkind = pxFinally - of ord(wFor): - tok.xkind = pxFor - of ord(wFunction): - tok.xkind = pxFunction - of ord(wGoto): - tok.xkind = pxGoto - of ord(wIf): - tok.xkind = pxIf - of ord(wImplementation): - tok.xkind = pxImplementation - of ord(wIn): - tok.xkind = pxIn - of ord(wInherited): - tok.xkind = pxInherited - of ord(wInitialization): - tok.xkind = pxInitialization - of ord(wInline): - tok.xkind = pxInline - of ord(wInterface): - tok.xkind = pxInterface - of ord(wIs): - tok.xkind = pxIs - of ord(wLabel): - tok.xkind = pxLabel - of ord(wLibrary): - tok.xkind = pxLibrary - of ord(wMod): - tok.xkind = pxMod - of ord(wNil): - tok.xkind = pxNil - of ord(wNot): - tok.xkind = pxNot - of ord(wObject): - tok.xkind = pxObject - of ord(wOf): - tok.xkind = pxOf - of ord(wOr): - tok.xkind = pxOr - of ord(wOut): - tok.xkind = pxOut - of ord(wPacked): - tok.xkind = pxPacked - of ord(wProcedure): - tok.xkind = pxProcedure - of ord(wProgram): - tok.xkind = pxProgram - of ord(wProperty): - tok.xkind = pxProperty - of ord(wRaise): - tok.xkind = pxRaise - of ord(wRecord): - tok.xkind = pxRecord - of ord(wRepeat): - tok.xkind = pxRepeat - of ord(wResourcestring): - tok.xkind = pxResourcestring - of ord(wSet): - tok.xkind = pxSet - of ord(wShl): - tok.xkind = pxShl - of ord(wShr): - tok.xkind = pxShr - of ord(wThen): - tok.xkind = pxThen - of ord(wThreadvar): - tok.xkind = pxThreadvar - of ord(wTo): - tok.xkind = pxTo - of ord(wTry): - tok.xkind = pxTry - of ord(wType): - tok.xkind = pxType - of ord(wUnit): - tok.xkind = pxUnit - of ord(wUntil): - tok.xkind = pxUntil - of ord(wUses): - tok.xkind = pxUses - of ord(wVar): - tok.xkind = pxVar - of ord(wWhile): - tok.xkind = pxWhile - of ord(wWith): - tok.xkind = pxWith - of ord(wXor): - tok.xkind = pxXor #[[[end]]] - else: tok.xkind = pxSymbol + var x = binaryStrSearch(keywords, toLower(tok.ident.s)) + if x < 0: tok.xkind = pxSymbol + else: tok.xKind = TPasTokKind(x + ord(firstKeyword)) proc matchUnderscoreChars(L: var TPasLex, tok: var TPasTok, chars: TCharSet) = # matches ([chars]_)* - var - pos: int - buf: cstring - pos = L.bufpos # use registers for pos, buf - buf = L.buf + var pos = L.bufpos # use registers for pos, buf + var buf = L.buf while true: if buf[pos] in chars: add(tok.literal, buf[pos]) @@ -255,16 +160,12 @@ proc matchUnderscoreChars(L: var TPasLex, tok: var TPasTok, chars: TCharSet) = L.bufPos = pos proc isFloatLiteral(s: string): bool = - for i in countup(0, len(s) + 0 - 1): + for i in countup(0, len(s)-1): if s[i] in {'.', 'e', 'E'}: return true - result = false proc getNumber2(L: var TPasLex, tok: var TPasTok) = - var - pos, bits: int - xi: biggestInt - pos = L.bufpos + 1 # skip % + var pos = L.bufpos + 1 # skip % if not (L.buf[pos] in {'0'..'1'}): # BUGFIX for %date% tok.xkind = pxInvalid @@ -272,8 +173,8 @@ proc getNumber2(L: var TPasLex, tok: var TPasTok) = inc(L.bufpos) return tok.base = base2 - xi = 0 - bits = 0 + var xi: biggestInt = 0 + var bits = 0 while true: case L.buf[pos] of 'A'..'Z', 'a'..'z', '2'..'9', '.': @@ -287,27 +188,21 @@ proc getNumber2(L: var TPasLex, tok: var TPasTok) = inc(bits) else: break tok.iNumber = xi - if (bits > 32): - tok.xkind = pxInt64Lit - else: - tok.xkind = pxIntLit + if (bits > 32): tok.xkind = pxInt64Lit + else: tok.xkind = pxIntLit L.bufpos = pos proc getNumber16(L: var TPasLex, tok: var TPasTok) = - var - pos, bits: int - xi: biggestInt - pos = L.bufpos + 1 # skip $ + var pos = L.bufpos + 1 # skip $ tok.base = base16 - xi = 0 - bits = 0 + var xi: biggestInt = 0 + var bits = 0 while true: case L.buf[pos] of 'G'..'Z', 'g'..'z', '.': lexMessage(L, errInvalidNumber) inc(pos) - of '_': - inc(pos) + of '_': inc(pos) of '0'..'9': xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0')) inc(pos) @@ -357,11 +252,9 @@ proc HandleCRLF(L: var TLexer, pos: int): int = else: result = pos proc getString(L: var TPasLex, tok: var TPasTok) = - var - pos, xi: int - buf: cstring - pos = L.bufPos - buf = L.buf + var xi: int + var pos = L.bufPos + var buf = L.buf while true: if buf[pos] == '\'': inc(pos) @@ -408,16 +301,11 @@ proc getString(L: var TPasLex, tok: var TPasTok) = L.bufpos = pos proc getSymbol(L: var TPasLex, tok: var TPasTok) = - var - pos: int - c: Char - buf: cstring - h: THash # hashing algorithm inlined - h = 0 - pos = L.bufpos - buf = L.buf + var h: THash = 0 + var pos = L.bufpos + var buf = L.buf while true: - c = buf[pos] + var c = buf[pos] case c of 'a'..'z', '0'..'9', '\x80'..'\xFF': h = h +% Ord(c) @@ -428,8 +316,7 @@ proc getSymbol(L: var TPasLex, tok: var TPasTok) = h = h +% Ord(c) h = h +% h shl 10 h = h xor (h shr 6) - of '_': - nil + of '_': nil else: break Inc(pos) h = h +% h shl 3 @@ -440,15 +327,12 @@ proc getSymbol(L: var TPasLex, tok: var TPasTok) = setKeyword(L, tok) proc scanLineComment(L: var TPasLex, tok: var TPasTok) = - var - buf: cstring - pos, col: int - indent: int - pos = L.bufpos - buf = L.buf # a comment ends if the next line does not start with the // on the same - # column after only whitespace + var pos = L.bufpos + var buf = L.buf + # a comment ends if the next line does not start with the // on the same + # column after only whitespace tok.xkind = pxComment - col = getColNumber(L, pos) + var col = getColNumber(L, pos) while true: inc(pos, 2) # skip // add(tok.literal, '#') @@ -457,7 +341,7 @@ proc scanLineComment(L: var TPasLex, tok: var TPasTok) = inc(pos) pos = handleCRLF(L, pos) buf = L.buf - indent = 0 + var indent = 0 while buf[pos] == ' ': inc(pos) inc(indent) @@ -468,11 +352,8 @@ proc scanLineComment(L: var TPasLex, tok: var TPasTok) = L.bufpos = pos proc scanCurlyComment(L: var TPasLex, tok: var TPasTok) = - var - buf: cstring - pos: int - pos = L.bufpos - buf = L.buf + var pos = L.bufpos + var buf = L.buf tok.literal = "#" tok.xkind = pxComment while true: @@ -480,23 +361,19 @@ proc scanCurlyComment(L: var TPasLex, tok: var TPasTok) = of CR, LF: pos = HandleCRLF(L, pos) buf = L.buf - tok.literal = tok.literal & "\n" & '#' + add(tok.literal, "\n#") of '}': inc(pos) break - of lexbase.EndOfFile: - lexMessage(L, errTokenExpected, "}") + of lexbase.EndOfFile: lexMessage(L, errTokenExpected, "}") else: add(tok.literal, buf[pos]) inc(pos) L.bufpos = pos proc scanStarComment(L: var TPasLex, tok: var TPasTok) = - var - buf: cstring - pos: int - pos = L.bufpos - buf = L.buf + var pos = L.bufpos + var buf = L.buf tok.literal = "#" tok.xkind = pxComment while true: @@ -504,7 +381,7 @@ proc scanStarComment(L: var TPasLex, tok: var TPasTok) = of CR, LF: pos = HandleCRLF(L, pos) buf = L.buf - tok.literal = tok.literal & "\n" & '#' + add(tok.literal, "\n#") of '*': inc(pos) if buf[pos] == ')': @@ -520,11 +397,8 @@ proc scanStarComment(L: var TPasLex, tok: var TPasTok) = L.bufpos = pos proc skip(L: var TPasLex, tok: var TPasTok) = - var - buf: cstring - pos: int - pos = L.bufpos - buf = L.buf + var pos = L.bufpos + var buf = L.buf while true: case buf[pos] of ' ', Tabulator: @@ -537,11 +411,10 @@ proc skip(L: var TPasLex, tok: var TPasTok) = L.bufpos = pos proc getPasTok(L: var TPasLex, tok: var TPasTok) = - var c: Char tok.xkind = pxInvalid fillToken(tok) skip(L, tok) - c = L.buf[L.bufpos] + var c = L.buf[L.bufpos] if c in SymStartChars: getSymbol(L, tok) elif c in {'0'..'9'}: diff --git a/rod/pasparse.nim b/rod/pas2nim/pasparse.nim index e9eabe175..79d5620e7 100755 --- a/rod/pasparse.nim +++ b/rod/pas2nim/pasparse.nim @@ -1,7 +1,7 @@ # # -# The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf +# Pas2nim - Pascal to Nimrod source converter +# (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -9,11 +9,10 @@ # This module implements the parser of the Pascal variant Nimrod is written in. # It transfers a Pascal module into a Nimrod AST. Then the renderer can be -# used to generate the Nimrod version of the compiler. +# used to convert the AST to its text representation. import - os, llstream, scanner, paslex, idents, wordrecg, strutils, ast, astalgo, msgs, - options + os, llstream, paslex, idents, strutils, ast, astalgo, msgs, options type TPasSection* = enum @@ -96,7 +95,7 @@ proc skipCom(p: var TPasParser, n: PNode) = while p.tok.xkind == pxComment: if (n != nil): if n.comment == nil: n.comment = p.tok.literal - else: n.comment = n.comment & "\n" & p.tok.literal + else: add(n.comment, "\n" & p.tok.literal) else: parMessage(p, warnCommentXIgnored, p.tok.literal) getTok(p) @@ -119,7 +118,8 @@ proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TPasParser): PNode = result = newNodeP(kind, p) result.intVal = intVal -proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, p: TPasParser): PNode = +proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, + p: TPasParser): PNode = result = newNodeP(kind, p) result.floatVal = floatVal @@ -132,17 +132,16 @@ proc newIdentNodeP(ident: PIdent, p: TPasParser): PNode = result.ident = ident proc createIdentNodeP(ident: PIdent, p: TPasParser): PNode = - var x: PIdent result = newNodeP(nkIdent, p) - x = PIdent(IdTableGet(p.repl, ident)) + var x = PIdent(IdTableGet(p.repl, ident)) if x != nil: result.ident = x else: result.ident = ident proc parseExpr(p: var TPasParser): PNode proc parseStmt(p: var TPasParser): PNode proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode + proc parseEmit(p: var TPasParser, definition: PNode): PNode = - var a: PNode getTok(p) # skip 'emit' result = nil if p.tok.xkind != pxCurlyDirRi: @@ -152,7 +151,7 @@ proc parseEmit(p: var TPasParser, definition: PNode): PNode = of conStmt: result = parseStmt(p) if p.tok.xkind != pxCurlyDirRi: - a = result + var a = result result = newNodeP(nkStmtList, p) addSon(result, a) while p.tok.xkind != pxCurlyDirRi: @@ -162,7 +161,6 @@ proc parseEmit(p: var TPasParser, definition: PNode): PNode = eat(p, pxCurlyDirRi) proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode = - var a: PNode result = nil getTok(p) if p.tok.ident.id == getIdent("discard").id: @@ -179,7 +177,7 @@ proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode = elif p.tok.ident.id == getIdent("cast").id: getTok(p) eat(p, pxCurlyDirRi) - a = parseExpr(p) + var a = parseExpr(p) if (a.kind == nkCall) and (sonsLen(a) == 2): result = newNodeP(nkCast, p) addSon(result, a.sons[0]) @@ -230,16 +228,15 @@ proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode = proc getPrecedence(kind: TPasTokKind): int = case kind of pxDiv, pxMod, pxStar, pxSlash, pxShl, pxShr, pxAnd: - result = 5 # highest + result = 5 of pxPlus, pxMinus, pxOr, pxXor: result = 4 of pxIn, pxEquals, pxLe, pxLt, pxGe, pxGt, pxNeq, pxIs: result = 3 - else: result = - 1 + else: result = -1 proc rangeExpr(p: var TPasParser): PNode = - var a: PNode - a = parseExpr(p) + var a = parseExpr(p) if p.tok.xkind == pxDotDot: result = newNodeP(nkRange, p) addSon(result, a) @@ -250,7 +247,6 @@ proc rangeExpr(p: var TPasParser): PNode = result = a proc bracketExprList(p: var TPasParser, first: PNode): PNode = - var a: PNode result = newNodeP(nkBracketExpr, p) addSon(result, first) getTok(p) @@ -262,16 +258,16 @@ proc bracketExprList(p: var TPasParser, first: PNode): PNode = if p.tok.xkind == pxEof: parMessage(p, errTokenExpected, PasTokKindToStr[pxBracketRi]) break - a = rangeExpr(p) + var a = rangeExpr(p) skipCom(p, a) if p.tok.xkind == pxComma: getTok(p) skipCom(p, a) addSon(result, a) -proc exprColonEqExpr(p: var TPasParser, kind: TNodeKind, tok: TPasTokKind): PNode = - var a: PNode - a = parseExpr(p) +proc exprColonEqExpr(p: var TPasParser, kind: TNodeKind, + tok: TPasTokKind): PNode = + var a = parseExpr(p) if p.tok.xkind == tok: result = newNodeP(kind, p) getTok(p) @@ -283,7 +279,6 @@ proc exprColonEqExpr(p: var TPasParser, kind: TNodeKind, tok: TPasTokKind): PNod proc exprListAux(p: var TPasParser, elemKind: TNodeKind, endTok, sepTok: TPasTokKind, result: PNode) = - var a: PNode getTok(p) skipCom(p, result) while true: @@ -293,7 +288,7 @@ proc exprListAux(p: var TPasParser, elemKind: TNodeKind, if p.tok.xkind == pxEof: parMessage(p, errTokenExpected, PasTokKindToStr[endtok]) break - a = exprColonEqExpr(p, elemKind, sepTok) + var a = exprColonEqExpr(p, elemKind, sepTok) skipCom(p, a) if (p.tok.xkind == pxComma) or (p.tok.xkind == pxSemicolon): getTok(p) @@ -301,7 +296,6 @@ proc exprListAux(p: var TPasParser, elemKind: TNodeKind, addSon(result, a) proc qualifiedIdent(p: var TPasParser): PNode = - var a: PNode if p.tok.xkind == pxSymbol: result = createIdentNodeP(p.tok.ident, p) else: @@ -313,7 +307,7 @@ proc qualifiedIdent(p: var TPasParser): PNode = getTok(p) skipCom(p, result) if p.tok.xkind == pxSymbol: - a = result + var a = result result = newNodeI(nkDotExpr, a.info) addSon(result, a) addSon(result, createIdentNodeP(p.tok.ident, p)) @@ -321,8 +315,8 @@ proc qualifiedIdent(p: var TPasParser): PNode = else: parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) -proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind, result: PNode) = - var a: PNode +proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind, + result: PNode) = getTok(p) skipCom(p, result) while true: @@ -332,7 +326,7 @@ proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind, result: PNode if p.tok.xkind == pxEof: parMessage(p, errTokenExpected, PasTokKindToStr[endtok]) break - a = qualifiedIdent(p) + var a = qualifiedIdent(p) skipCom(p, a) if p.tok.xkind == pxComma: getTok(p) @@ -346,17 +340,12 @@ proc exprColonEqExprList(p: var TPasParser, kind, elemKind: TNodeKind, proc setBaseFlags(n: PNode, base: TNumericalBase) = case base - of base10: - nil - of base2: - incl(n.flags, nfBase2) - of base8: - incl(n.flags, nfBase8) - of base16: - incl(n.flags, nfBase16) + of base10: nil + of base2: incl(n.flags, nfBase2) + of base8: incl(n.flags, nfBase8) + of base16: incl(n.flags, nfBase16) proc identOrLiteral(p: var TPasParser): PNode = - var a: PNode case p.tok.xkind of pxSymbol: result = createIdentNodeP(p.tok.ident, p) @@ -382,8 +371,9 @@ proc identOrLiteral(p: var TPasParser): PNode = getTok(p) of pxParLe: # () constructor - result = exprColonEqExprList(p, nkPar, nkExprColonExpr, pxParRi, pxColon) #if hasSonWith(result, nkExprColonExpr) then - # replaceSons(result, nkExprColonExpr, nkExprEqExpr) + result = exprColonEqExprList(p, nkPar, nkExprColonExpr, pxParRi, pxColon) + #if hasSonWith(result, nkExprColonExpr) then + # replaceSons(result, nkExprColonExpr, nkExprEqExpr) if (sonsLen(result) > 1) and not hasSonWith(result, nkExprColonExpr): result.kind = nkBracket # is an array constructor of pxBracketLe: @@ -392,7 +382,7 @@ proc identOrLiteral(p: var TPasParser): PNode = getTok(p) skipCom(p, result) while (p.tok.xkind != pxBracketRi) and (p.tok.xkind != pxEof): - a = rangeExpr(p) + var a = rangeExpr(p) if a.kind == nkRange: result.kind = nkCurly # it is definitely a set literal opt(p, pxComma) @@ -404,17 +394,16 @@ proc identOrLiteral(p: var TPasParser): PNode = result = parseCommand(p) else: parMessage(p, errExprExpected, pasTokToStr(p.tok)) - getTok(p) # we must consume a token here to prevend endless loops! + getTok(p) # we must consume a token here to prevend endless loops! result = nil if result != nil: skipCom(p, result) proc primary(p: var TPasParser): PNode = - var a: PNode # prefix operator? if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or (p.tok.xkind == pxPlus): result = newNodeP(nkPrefix, p) - a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) + var a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) addSon(result, a) getTok(p) skipCom(p, a) @@ -422,7 +411,7 @@ proc primary(p: var TPasParser): PNode = return elif p.tok.xkind == pxAt: result = newNodeP(nkAddr, p) - a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) + var a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) getTok(p) if p.tok.xkind == pxBracketLe: result = newNodeP(nkPrefix, p) @@ -435,12 +424,12 @@ proc primary(p: var TPasParser): PNode = while true: case p.tok.xkind of pxParLe: - a = result + var a = result result = newNodeP(nkCall, p) addSon(result, a) exprListAux(p, nkExprEqExpr, pxParRi, pxEquals, result) of pxDot: - a = result + var a = result result = newNodeP(nkDotExpr, p) addSon(result, a) getTok(p) # skip '.' @@ -451,7 +440,7 @@ proc primary(p: var TPasParser): PNode = else: parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) of pxHat: - a = result + var a = result result = newNodeP(nkDerefExpr, p) addSon(result, a) getTok(p) @@ -461,12 +450,11 @@ proc primary(p: var TPasParser): PNode = proc lowestExprAux(p: var TPasParser, v: var PNode, limit: int): TPasTokKind = var - op, nextop: TPasTokKind - opPred: int + nextop: TPasTokKind v2, node, opNode: PNode - v = primary(p) # expand while operators have priorities higher than 'limit' - op = p.tok.xkind - opPred = getPrecedence(op) + v = primary(p) # expand while operators have priorities higher than 'limit' + var op = p.tok.xkind + var opPred = getPrecedence(op) while (opPred > limit): node = newNodeP(nkInfix, p) opNode = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) # skip operator: @@ -530,8 +518,7 @@ proc fixExpr(n: PNode): PNode = for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i]) proc parseExpr(p: var TPasParser): PNode = - var oldcontext: TPasContext - oldcontext = p.context + var oldcontext = p.context p.context = conExpr if p.tok.xkind == pxCommand: result = parseCommand(p) @@ -541,15 +528,12 @@ proc parseExpr(p: var TPasParser): PNode = p.context = oldcontext proc parseExprStmt(p: var TPasParser): PNode = - var - a, b: PNode - info: TLineInfo - info = parLineInfo(p) - a = parseExpr(p) + var info = parLineInfo(p) + var a = parseExpr(p) if p.tok.xkind == pxAsgn: getTok(p) skipCom(p, a) - b = parseExpr(p) + var b = parseExpr(p) result = newNodeI(nkAsgn, info) addSon(result, a) addSon(result, b) @@ -560,7 +544,6 @@ proc inImportBlackList(ident: PIdent): bool = for i in countup(low(ImportBlackList), high(ImportBlackList)): if ident.id == getIdent(ImportBlackList[i]).id: return true - result = false proc parseUsesStmt(p: var TPasParser): PNode = var a: PNode @@ -586,10 +569,9 @@ proc parseUsesStmt(p: var TPasParser): PNode = if sonsLen(result) == 0: result = nil proc parseIncludeDir(p: var TPasParser): PNode = - var filename: string result = newNodeP(nkIncludeStmt, p) getTok(p) # skip `include` - filename = "" + var filename = "" while true: case p.tok.xkind of pxSymbol, pxDot, pxDotDot, pxSlash: @@ -635,14 +617,11 @@ proc parseStmtList(p: var TPasParser): PNode = if sonsLen(result) == 1: result = result.sons[0] proc parseIfDirAux(p: var TPasParser, result: PNode) = - var - s: PNode - endMarker: TPasTokKind addSon(result.sons[0], parseStmtList(p)) if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: - endMarker = succ(p.tok.xkind) + var endMarker = succ(p.tok.xkind) if whichKeyword(p.tok.ident) == wElse: - s = newNodeP(nkElse, p) + var s = newNodeP(nkElse, p) while (p.tok.xkind != pxEof) and (p.tok.xkind != endMarker): getTok(p) eat(p, endMarker) addSon(s, parseStmtList(p)) @@ -666,11 +645,10 @@ proc parseIfdefDir(p: var TPasParser, endMarker: TPasTokKind): PNode = parseIfDirAux(p, result) proc parseIfndefDir(p: var TPasParser, endMarker: TPasTokKind): PNode = - var e: PNode result = newNodeP(nkWhenStmt, p) addSon(result, newNodeP(nkElifBranch, p)) getTok(p) - e = newNodeP(nkCall, p) + var e = newNodeP(nkCall, p) addSon(e, newIdentNodeP(getIdent("not"), p)) addSon(e, definedExprAux(p)) eat(p, endMarker) @@ -686,21 +664,17 @@ proc parseIfDir(p: var TPasParser, endMarker: TPasTokKind): PNode = parseIfDirAux(p, result) proc parseDirective(p: var TPasParser): PNode = - var endMarker: TPasTokKind result = nil if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return - endMarker = succ(p.tok.xkind) + var endMarker = succ(p.tok.xkind) if p.tok.ident != nil: case whichKeyword(p.tok.ident) of wInclude: result = parseIncludeDir(p) eat(p, endMarker) - of wIf: - result = parseIfDir(p, endMarker) - of wIfdef: - result = parseIfdefDir(p, endMarker) - of wIfndef: - result = parseIfndefDir(p, endMarker) + of wIf: result = parseIfDir(p, endMarker) + of wIfdef: result = parseIfdefDir(p, endMarker) + of wIfndef: result = parseIfndefDir(p, endMarker) else: # skip unknown compiler directive while (p.tok.xkind != pxEof) and (p.tok.xkind != endMarker): getTok(p) @@ -716,11 +690,10 @@ proc parseRaise(p: var TPasParser): PNode = else: addSon(result, nil) proc parseIf(p: var TPasParser): PNode = - var branch: PNode result = newNodeP(nkIfStmt, p) while true: getTok(p) # skip ``if`` - branch = newNodeP(nkElifBranch, p) + var branch = newNodeP(nkElifBranch, p) skipCom(p, branch) addSon(branch, parseExpr(p)) eat(p, pxThen) @@ -750,26 +723,24 @@ proc parseWhile(p: var TPasParser): PNode = addSon(result, parseStmt(p)) proc parseRepeat(p: var TPasParser): PNode = - var a, b, c, s: PNode result = newNodeP(nkWhileStmt, p) getTok(p) skipCom(p, result) addSon(result, newIdentNodeP(getIdent("true"), p)) - s = newNodeP(nkStmtList, p) + var s = newNodeP(nkStmtList, p) while (p.tok.xkind != pxEof) and (p.tok.xkind != pxUntil): addSon(s, parseStmt(p)) eat(p, pxUntil) - a = newNodeP(nkIfStmt, p) + var a = newNodeP(nkIfStmt, p) skipCom(p, a) - b = newNodeP(nkElifBranch, p) - c = newNodeP(nkBreakStmt, p) + var b = newNodeP(nkElifBranch, p) + var c = newNodeP(nkBreakStmt, p) addSon(c, nil) addSon(b, parseExpr(p)) skipCom(p, a) addSon(b, c) addSon(a, b) - if (b.sons[0].kind == nkIdent) and - (b.sons[0].ident.id == getIdent("false").id): + if b.sons[0].kind == nkIdent and b.sons[0].ident.id == getIdent("false").id: nil else: addSon(s, a) @@ -800,11 +771,10 @@ proc parseCase(p: var TPasParser): PNode = eat(p, pxEnd) proc parseTry(p: var TPasParser): PNode = - var b, e: PNode result = newNodeP(nkTryStmt, p) getTok(p) skipCom(p, result) - b = newNodeP(nkStmtList, p) + var b = newNodeP(nkStmtList, p) while not (p.tok.xkind in {pxFinally, pxExcept, pxEof, pxEnd}): addSon(b, parseStmt(p)) addSon(result, b) @@ -813,7 +783,7 @@ proc parseTry(p: var TPasParser): PNode = while p.tok.ident.id == getIdent("on").id: b = newNodeP(nkExceptBranch, p) getTok(p) - e = qualifiedIdent(p) + var e = qualifiedIdent(p) if p.tok.xkind == pxColon: getTok(p) e = qualifiedIdent(p) @@ -830,7 +800,7 @@ proc parseTry(p: var TPasParser): PNode = if p.tok.xkind == pxFinally: b = newNodeP(nkFinally, p) getTok(p) - e = newNodeP(nkStmtList, p) + var e = newNodeP(nkStmtList, p) while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): addSon(e, parseStmt(p)) if sonsLen(e) == 0: addSon(e, newNodeP(nkNilLit, p)) @@ -1062,8 +1032,7 @@ proc parseEnum(p: var TPasParser): PNode = proc identVis(p: var TPasParser): PNode = # identifier with visability - var a: PNode - a = createIdentNodeP(p.tok.ident, p) + var a = createIdentNodeP(p.tok.ident, p) if p.section == seInterface: result = newNodeP(nkPostfix, p) addSon(result, newIdentNodeP(getIdent("*"), p)) @@ -1079,7 +1048,8 @@ proc rawIdent(p: var TPasParser): PNode = result = createIdentNodeP(p.tok.ident, p) getTok(p) -proc parseIdentColonEquals(p: var TPasParser, identParser: TSymbolParser): PNode = +proc parseIdentColonEquals(p: var TPasParser, + identParser: TSymbolParser): PNode = var a: PNode result = newNodeP(nkIdentDefs, p) while true: @@ -1171,41 +1141,38 @@ proc parseRecordPart(p: var TPasParser): PNode = break proc exSymbol(n: var PNode) = - var a: PNode case n.kind of nkPostfix: nil of nkPragmaExpr: exSymbol(n.sons[0]) of nkIdent, nkAccQuoted: - a = newNodeI(nkPostFix, n.info) + var a = newNodeI(nkPostFix, n.info) addSon(a, newIdentNode(getIdent("*"), n.info)) addSon(a, n) n = a else: internalError(n.info, "exSymbol(): " & $n.kind) proc fixRecordDef(n: var PNode) = - var length: int if n == nil: return case n.kind of nkRecCase: fixRecordDef(n.sons[0]) for i in countup(1, sonsLen(n) - 1): - length = sonsLen(n.sons[i]) + var length = sonsLen(n.sons[i]) fixRecordDef(n.sons[i].sons[length - 1]) of nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch, nkObjectTy: 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: nil else: internalError(n.info, "fixRecordDef(): " & $n.kind) proc addPragmaToIdent(ident: var PNode, pragma: PNode) = - var e, pragmasNode: PNode + var pragmasNode: PNode if ident.kind != nkPragmaExpr: pragmasNode = newNodeI(nkPragma, ident.info) - e = newNodeI(nkPragmaExpr, ident.info) + var e = newNodeI(nkPragmaExpr, ident.info) addSon(e, ident) addSon(e, pragmasNode) ident = e @@ -1216,9 +1183,8 @@ proc addPragmaToIdent(ident: var PNode, pragma: PNode) = addSon(pragmasNode, pragma) proc parseRecordBody(p: var TPasParser, result, definition: PNode) = - var a: PNode skipCom(p, result) - a = parseRecordPart(p) + var a = parseRecordPart(p) if result.kind != nkTupleTy: fixRecordDef(a) addSon(result, a) eat(p, pxEnd) @@ -1242,12 +1208,11 @@ proc parseRecordBody(p: var TPasParser, result, definition: PNode) = proc parseRecordOrObject(p: var TPasParser, kind: TNodeKind, definition: PNode): PNode = - var a: PNode result = newNodeP(kind, p) getTok(p) addSon(result, nil) if p.tok.xkind == pxParLe: - a = newNodeP(nkOfInherit, p) + var a = newNodeP(nkOfInherit, p) getTok(p) addSon(a, parseTypeDesc(p)) addSon(result, a) @@ -1257,10 +1222,7 @@ proc parseRecordOrObject(p: var TPasParser, kind: TNodeKind, parseRecordBody(p, result, definition) proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode = - var - oldcontext: TPasContext - a, r: PNode - oldcontext = p.context + var oldcontext = p.context p.context = conTypeDesc if p.tok.xkind == pxPacked: getTok(p) case p.tok.xkind @@ -1274,7 +1236,7 @@ proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode = result = parseCommand(p) if result.kind != nkTupleTy: InternalError(result.info, "parseTypeDesc") parseRecordBody(p, result, definition) - a = lastSon(result) # embed nkRecList directly into nkTupleTy + var a = lastSon(result) # embed nkRecList directly into nkTupleTy for i in countup(0, sonsLen(a) - 1): if i == 0: result.sons[sonsLen(result) - 1] = a.sons[0] else: addSon(result, a.sons[i]) @@ -1287,10 +1249,8 @@ proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode = addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p)) else: InternalError(result.info, "anonymous record is not supported") - of pxObject: - result = parseRecordOrObject(p, nkObjectTy, definition) - of pxParLe: - result = parseEnum(p) + of pxObject: result = parseRecordOrObject(p, nkObjectTy, definition) + of pxParLe: result = parseEnum(p) of pxArray: result = newNodeP(nkBracketExpr, p) getTok(p) @@ -1320,10 +1280,10 @@ proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode = getTok(p) result = parseTypeDesc(p) else: - a = primary(p) + var a = primary(p) if p.tok.xkind == pxDotDot: result = newNodeP(nkBracketExpr, p) - r = newNodeP(nkRange, p) + var r = newNodeP(nkRange, p) addSon(result, newIdentNodeP(getIdent("range"), p)) getTok(p) addSon(r, a) @@ -1386,13 +1346,13 @@ proc parseVar(p: var TPasParser): PNode = result = newNodeP(nkVarSection, p) getTok(p) skipCom(p, result) - while p.tok.xkind == pxSymbol: + while p.tok.xkind == pxSymbol: addSon(result, parseIdentColonEquals(p, identVis)) p.lastVarSection = result proc parseRoutine(p: var TPasParser): PNode = var - a, stmts: PNode + stmts: PNode noBody: bool result = newNodeP(nkProcDef, p) getTok(p) @@ -1417,19 +1377,16 @@ proc parseRoutine(p: var TPasParser): PNode = else: parMessage(p, errTokenExpected, "begin") break - a = parseStmt(p) + var a = parseStmt(p) for i in countup(0, sonsLen(a) - 1): addSon(stmts, a.sons[i]) addSon(result, stmts) proc fixExit(p: var TPasParser, n: PNode): bool = - var - length: int - a: PNode result = false if (p.tok.ident.id == getIdent("exit").id): - length = sonsLen(n) + var length = sonsLen(n) if (length <= 0): return - a = n.sons[length - 1] + var a = n.sons[length-1] if (a.kind == nkAsgn) and (a.sons[0].kind == nkIdent) and (a.sons[0].ident.id == getIdent("result").id): delSon(a, 0) @@ -1440,11 +1397,10 @@ proc fixExit(p: var TPasParser, n: PNode): bool = skipCom(p, a) proc fixVarSection(p: var TPasParser, counter: PNode) = - var v: PNode if p.lastVarSection == nil: return assert(counter.kind == nkIdent) for i in countup(0, sonsLen(p.lastVarSection) - 1): - v = p.lastVarSection.sons[i] + var v = p.lastVarSection.sons[i] for j in countup(0, sonsLen(v) - 3): if v.sons[j].ident.id == counter.ident.id: delSon(v, j) @@ -1456,64 +1412,47 @@ proc parseBegin(p: var TPasParser, result: PNode) = getTok(p) while true: case p.tok.xkind - of pxComment: - addSon(result, parseStmt(p)) + of pxComment: addSon(result, parseStmt(p)) of pxSymbol: if not fixExit(p, result): addSon(result, parseStmt(p)) of pxEnd: getTok(p) break - of pxSemicolon: - getTok(p) - of pxEof: - parMessage(p, errExprExpected) + of pxSemicolon: getTok(p) + of pxEof: parMessage(p, errExprExpected) else: addSonIfNotNil(result, parseStmt(p)) if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p)) proc parseStmt(p: var TPasParser): PNode = - var oldcontext: TPasContext - oldcontext = p.context + var oldcontext = p.context p.context = conStmt result = nil case p.tok.xkind of pxBegin: result = newNodeP(nkStmtList, p) parseBegin(p, result) - of pxCommand: - result = parseCommand(p) + of pxCommand: result = parseCommand(p) of pxCurlyDirLe, pxStarDirLe: if isHandledDirective(p): result = parseDirective(p) - of pxIf: - result = parseIf(p) - of pxWhile: - result = parseWhile(p) - of pxRepeat: - result = parseRepeat(p) - of pxCase: - result = parseCase(p) - of pxTry: - result = parseTry(p) - of pxProcedure, pxFunction: - result = parseRoutine(p) - of pxType: - result = parseTypeSection(p) - of pxConst: - result = parseConstSection(p) - of pxVar: - result = parseVar(p) + of pxIf: result = parseIf(p) + of pxWhile: result = parseWhile(p) + of pxRepeat: result = parseRepeat(p) + of pxCase: result = parseCase(p) + of pxTry: result = parseTry(p) + of pxProcedure, pxFunction: result = parseRoutine(p) + of pxType: result = parseTypeSection(p) + of pxConst: result = parseConstSection(p) + of pxVar: result = parseVar(p) of pxFor: result = parseFor(p) fixVarSection(p, result.sons[0]) - of pxRaise: - result = parseRaise(p) - of pxUses: - result = parseUsesStmt(p) + of pxRaise: result = parseRaise(p) + of pxUses: result = parseUsesStmt(p) of pxProgram, pxUnit, pxLibrary: # skip the pointless header while not (p.tok.xkind in {pxSemicolon, pxEof}): getTok(p) getTok(p) - of pxInitialization: - getTok(p) # just skip the token + of pxInitialization: getTok(p) # just skip the token of pxImplementation: p.section = seImplementation result = newNodeP(nkCommentStmt, p) @@ -1525,8 +1464,7 @@ proc parseStmt(p: var TPasParser): PNode = of pxComment: result = newNodeP(nkCommentStmt, p) skipCom(p, result) - of pxSemicolon: - getTok(p) + of pxSemicolon: getTok(p) of pxSymbol: if p.tok.ident.id == getIdent("break").id: result = newNodeP(nkBreakStmt, p) @@ -1545,8 +1483,7 @@ proc parseStmt(p: var TPasParser): PNode = addSon(result, nil) else: result = parseExprStmt(p) - of pxDot: - getTok(p) # BUGFIX for ``end.`` in main program + of pxDot: getTok(p) # BUGFIX for ``end.`` in main program else: result = parseExprStmt(p) opt(p, pxSemicolon) if result != nil: skipCom(p, result) @@ -1557,10 +1494,8 @@ proc parseUnit(p: var TPasParser): PNode = getTok(p) # read first token while true: case p.tok.xkind - of pxEof, pxEnd: - break - of pxBegin: - parseBegin(p, result) + of pxEof, pxEnd: break + of pxBegin: parseBegin(p, result) of pxCurlyDirLe, pxStarDirLe: if isHandledDirective(p): addSon(result, parseDirective(p)) else: parMessage(p, errXNotAllowedHere, p.tok.ident.s) diff --git a/rod/wordrecg.nim b/rod/wordrecg.nim index 9054dcc88..b090d5a35 100755 --- a/rod/wordrecg.nim +++ b/rod/wordrecg.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf +# (c) Copyright 2010 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -16,33 +16,21 @@ import nhashes, strutils, idents +# Keywords must be kept sorted and within a range + type TSpecialWord* = enum - wInvalid, # these are mapped to Nimrod keywords: - #[[[cog - #from string import split, capitalize - #keywords = split(open("data/keywords.txt").read()) - #idents = "" - #strings = "" - #i = 1 - #for k in keywords: - # idents = idents + "w" + capitalize(k) + ", " - # strings = strings + "'" + k + "', " - # if i % 4 == 0: - # idents = idents + "\n" - # strings = strings + "\n" - # i = i + 1 - #cog.out(idents) - #]]] + wInvalid, + wAddr, wAnd, wAs, wAsm, wBind, wBlock, wBreak, wCase, wCast, wConst, wContinue, wConverter, wDiscard, wDistinct, wDiv, wElif, wElse, wEnd, wEnum, wExcept, wFinally, wFor, wFrom, wGeneric, wIf, wImplies, wImport, wIn, wInclude, wIs, wIsnot, wIterator, wLambda, wMacro, wMethod, wMod, wNil, wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn, wShl, wShr, wTemplate, wTry, wTuple, wType, wVar, wWhen, wWhile, wWith, - wWithout, wXor, wYield, #[[[end]]] - # other special tokens: - wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus, # pragmas and command line options: + wWithout, wXor, wYield, + + wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus, wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc, wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader, wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar, @@ -60,39 +48,30 @@ type wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu, wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH, wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced, wSkipcfg, wSkipProjCfg, - wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar, wAcyclic, wIndex, # - # commands: + wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar, + wAcyclic, wIndex, wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty, wDoc, wPas, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy, - wRst2html, wRst2tex, wI, # special for the preprocessor of configuration files: - wWrite, wPutEnv, wPrependEnv, wAppendEnv, # additional Pascal keywords: - wArray, wBegin, wClass, wConstructor, wDestructor, wDo, wDownto, wExports, - wFinalization, wFunction, wGoto, wImplementation, wInherited, - wInitialization, wInterface, wLabel, wLibrary, wPacked, wProcedure, - wProgram, wProperty, wRecord, wRepeat, wResourcestring, wSet, wThen, - wThreadvar, wTo, wUnit, wUntil, wUses, # Pascal special tokens: - wExternal, wOverload, wFar, wAssembler, wForward, wIfdef, wIfndef, wEndif + wRst2html, wRst2tex, wI, + wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar + TSpecialWords* = set[TSpecialWord] const oprLow* = ord(wColon) oprHigh* = ord(wHat) - specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", # - # keywords: - # - #[[[cog - # - #cog.out(strings) - #]]] + specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", + "addr", "and", "as", "asm", "bind", "block", "break", "case", "cast", "const", "continue", "converter", "discard", "distinct", "div", "elif", "else", "end", "enum", "except", "finally", "for", "from", "generic", "if", "implies", "import", "in", "include", "is", "isnot", "iterator", "lambda", "macro", "method", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template", - "try", "tuple", "type", "var", "when", "while", "with", "without", "xor", "yield", #[[[end]]] - # other special tokens: - ":", "=", ".", "..", "^", "*", "-", # pragmas and command line options: + "try", "tuple", "type", "var", "when", "while", "with", "without", "xor", + "yield", + + ":", "=", ".", "..", "^", "*", "-", "magic", "typecheck", "final", "profiler", "objchecks", "importc", "exportc", "align", "nodecl", "pure", "volatile", "register", "sideeffect", "header", "nosideeffect", "noreturn", "merge", "lib", "dynlib", @@ -113,18 +92,11 @@ const "cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v", "help", "h", "symbolfiles", "fieldchecks", "x", "version", "advanced", "skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "checkpoints", - "nomain", "subschar", "acyclic", "index", # commands: + "nomain", "subschar", "acyclic", "index", "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", "pretty", "doc", "pas", "gendepend", "listdef", "check", "parse", "scan", - "boot", "lazy", "rst2html", "rst2tex", "i", # special for the preprocessor of configuration files: - "write", "putenv", "prependenv", "appendenv", "array", "begin", "class", - "constructor", "destructor", "do", "downto", "exports", "finalization", - "function", "goto", "implementation", "inherited", "initialization", - "interface", "label", "library", "packed", "procedure", "program", - "property", "record", "repeat", "resourcestring", "set", "then", - "threadvar", "to", "unit", "until", "uses", # Pascal special tokens - "external", "overload", "far", "assembler", "forward", "ifdef", "ifndef", - "endif"] + "boot", "lazy", "rst2html", "rst2tex", "i", + "write", "putenv", "prependenv", "appendenv", "threadvar"] proc whichKeyword*(id: PIdent): TSpecialWord proc whichKeyword*(id: String): TSpecialWord @@ -149,4 +121,4 @@ proc initSpecials() = for s in countup(succ(low(specialWords)), high(specialWords)): getIdent(specialWords[s], getNormalizedHash(specialWords[s])).id = ord(s) -initSpecials() \ No newline at end of file +initSpecials() diff --git a/web/news.txt b/web/news.txt index 5ab91ccd3..bc8d5ff56 100755 --- a/web/news.txt +++ b/web/news.txt @@ -5,6 +5,9 @@ News 2010-XX-XX Version 0.8.8 released ================================= +Version 0.8.8 has been released! Get it `here <download.html>`_. + + Bugfixes -------- - The Posix version of ``os.copyFile`` has better error handling. @@ -33,16 +36,18 @@ Changes affecting backwards compatibility - Overloading of the subscript operator only works if the type does not provide a built-in one. - - +- The search order for libraries which is affected by the ``path`` option + has been reversed, so that the project's path is searched before + the standard library's path. +- The compiler does not include a Pascal parser for bootstrapping purposes any + more. Instead there is a ``pas2nim`` tool that contains the old functionality. 2009-12-21 Version 0.8.6 released ================================= -Version 0.8.6 has been released! Get it `here <download.html>`_. The version -jump from 0.8.2 to 0.8.6 acknowledges the fact that all development of the -compiler is now done in Nimrod. +The version jump from 0.8.2 to 0.8.6 acknowledges the fact that all development +of the compiler is now done in Nimrod. Bugfixes |