diff options
Diffstat (limited to 'rod')
-rwxr-xr-x | rod/ast.nim | 3 | ||||
-rwxr-xr-x | rod/ccgexprs.nim | 13 | ||||
-rwxr-xr-x | rod/ccgstmts.nim | 195 | ||||
-rwxr-xr-x | rod/ccgutils.nim | 96 | ||||
-rwxr-xr-x | rod/cgen.nim | 19 | ||||
-rwxr-xr-x | rod/main.nim | 36 | ||||
-rwxr-xr-x | rod/pragmas.nim | 23 | ||||
-rwxr-xr-x | rod/rst.nim | 14 | ||||
-rwxr-xr-x | rod/semexprs.nim | 13 | ||||
-rwxr-xr-x | rod/semtypes.nim | 3 | ||||
-rwxr-xr-x | rod/transf.nim | 4 | ||||
-rwxr-xr-x | rod/wordrecg.nim | 30 |
12 files changed, 225 insertions, 224 deletions
diff --git a/rod/ast.nim b/rod/ast.nim index 2b0fc6d38..c7c0fa7d0 100755 --- a/rod/ast.nim +++ b/rod/ast.nim @@ -269,7 +269,8 @@ type tfNoSideEffect, # procedure type does not allow side effects tfFinal, # is the object final? tfAcyclic, # type is acyclic (for GC optimization) - tfEnumHasWholes # enum cannot be mapped into a range + tfEnumHasWholes, # enum cannot be mapped into a range + tfShallow # type can be shallow copied on assignment TTypeFlags* = set[TTypeFlag] diff --git a/rod/ccgexprs.nim b/rod/ccgexprs.nim index c8404fef6..65cc33fd4 100755 --- a/rod/ccgexprs.nim +++ b/rod/ccgexprs.nim @@ -215,20 +215,21 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) else: appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) - of tyArray, tyArrayConstr: + of tyObject: + # XXX: check for subtyping? if needsComplexAssignment(dest.t): appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n", [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) else: - appcg(p, cpsStmts, - "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n", - [rdLoc(dest), rdLoc(src)]) - of tyObject: # XXX: check for subtyping? + appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + of tyArray, tyArrayConstr: if needsComplexAssignment(dest.t): appcg(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n", [addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t)]) else: - appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + appcg(p, cpsStmts, + "memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1));$n", + [rdLoc(dest), rdLoc(src)]) of tyOpenArray: # open arrays are always on the stack - really? What if a sequence is # passed to an open array? diff --git a/rod/ccgstmts.nim b/rod/ccgstmts.nim index 572b60143..e87305065 100755 --- a/rod/ccgstmts.nim +++ b/rod/ccgstmts.nim @@ -10,6 +10,10 @@ const RangeExpandLimit = 256 # do not generate ranges # over 'RangeExpandLimit' elements + stringCaseThreshold = 8 + # above X strings a hash-switch for strings is generated + # this version sets it too high to avoid hashing, because this has not + # been tested for a long time proc genLineDir(p: BProc, t: PNode) = var line = toLinenumber(t.info) # BUGFIX @@ -229,13 +233,6 @@ proc genRaiseStmt(p: BProc, t: PNode) = else: appcg(p, cpsStmts, "#reraiseException();" & tnl) -const - stringCaseThreshold = 100000 - # above X strings a hash-switch for strings is generated - # this version sets it too high to avoid hashing, because this has not - # been tested for a long time - # XXX test and enable this optimization! - proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, rangeFormat, eqFormat: TFormatStr, labl: TLabel) = var @@ -251,90 +248,68 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, initLocExpr(p, b.sons[i], x) appcg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl]) -proc genCaseSecondPass(p: BProc, t: PNode, labId: int) = +proc genCaseSecondPass(p: BProc, t: PNode, labId, until: int): TLabel = var Lend = getLabel(p) - for i in countup(1, sonsLen(t) - 1): + for i in 1..until: appf(p.s[cpsStmts], "LA$1: ;$n", [toRope(labId + i)]) - if t.sons[i].kind == nkOfBranch: # else statement + if t.sons[i].kind == nkOfBranch: var length = sonsLen(t.sons[i]) genStmts(p, t.sons[i].sons[length - 1]) appf(p.s[cpsStmts], "goto $1;$n", [Lend]) else: genStmts(p, t.sons[i].sons[0]) - fixLabel(p, Lend) + result = Lend -proc genCaseGeneric(p: BProc, t: PNode, rangeFormat, eqFormat: TFormatStr) = +proc genIfForCaseUntil(p: BProc, t: PNode, rangeFormat, eqFormat: TFormatStr, + until: int, a: TLoc): TLabel = # generate a C-if statement for a Nimrod case statement - var a: TLoc - initLocExpr(p, t.sons[0], a) # fist pass: generate ifs+goto: var labId = p.labels - for i in countup(1, sonsLen(t) - 1): + for i in 1..until: inc(p.labels) if t.sons[i].kind == nkOfBranch: # else statement genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat, con("LA", toRope(p.labels))) else: appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.labels)]) - genCaseSecondPass(p, t, labId) - -proc hashString(s: string): biggestInt = - var - a: int32 - b: int64 - if CPU[targetCPU].bit == 64: - # we have to use the same bitwidth - # as the target CPU - b = 0 - for i in countup(0, len(s) - 1): - b = b +% Ord(s[i]) - b = b +% `shl`(b, 10) - b = b xor `shr`(b, 6) - b = b +% `shl`(b, 3) - b = b xor `shr`(b, 11) - b = b +% `shl`(b, 15) - result = b - else: - a = 0 - for i in countup(0, len(s) - 1): - a = a +% int32(Ord(s[i])) - a = a +% `shl`(a, int32(10)) - a = a xor `shr`(a, int32(6)) - a = a +% `shl`(a, int32(3)) - a = a xor `shr`(a, int32(11)) - a = a +% `shl`(a, int32(15)) - result = a + if until < t.len-1: + inc(p.labels) + var gotoTarget = p.labels + appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(gotoTarget)]) + result = genCaseSecondPass(p, t, labId, until) + appf(p.s[cpsStmts], "LA$1: ;$n", [toRope(gotoTarget)]) + else: + result = genCaseSecondPass(p, t, labId, until) -type - TRopeSeq = seq[PRope] +proc genCaseGeneric(p: BProc, t: PNode, rangeFormat, eqFormat: TFormatStr) = + var a: TLoc + initLocExpr(p, t.sons[0], a) + var Lend = genIfForCaseUntil(p, t, rangeFormat, eqFormat, sonsLen(t)-1, a) + fixLabel(p, Lend) proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel, - branches: var TRopeSeq) = - var - length, j: int - x: TLoc - length = sonsLen(b) + branches: var openArray[PRope]) = + var x: TLoc + var length = sonsLen(b) for i in countup(0, length - 2): assert(b.sons[i].kind != nkRange) initLocExpr(p, b.sons[i], x) assert(b.sons[i].kind in {nkStrLit..nkTripleStrLit}) - j = int(hashString(b.sons[i].strVal) and high(branches)) + var j = int(hashString(b.sons[i].strVal) and high(branches)) appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n", [rdLoc(e), rdLoc(x), labl]) proc genStringCase(p: BProc, t: PNode) = - var - strings, bitMask, labId: int - a: TLoc - branches: TRopeSeq # count how many constant strings there are in the case: - strings = 0 + var strings = 0 for i in countup(1, sonsLen(t) - 1): if t.sons[i].kind == nkOfBranch: inc(strings, sonsLen(t.sons[i]) - 1) if strings > stringCaseThreshold: - bitMask = math.nextPowerOfTwo(strings) - 1 + var bitMask = math.nextPowerOfTwo(strings) - 1 + var branches: seq[PRope] newSeq(branches, bitMask + 1) + var a: TLoc initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto: - labId = p.labels + var labId = p.labels for i in countup(1, sonsLen(t) - 1): inc(p.labels) if t.sons[i].kind == nkOfBranch: @@ -353,67 +328,72 @@ proc genStringCase(p: BProc, t: PNode) = if t.sons[sonsLen(t) - 1].kind != nkOfBranch: appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.labels)]) # third pass: generate statements - genCaseSecondPass(p, t, labId) + var Lend = genCaseSecondPass(p, t, labId, sonsLen(t)-1) + fixLabel(p, Lend) else: genCaseGeneric(p, t, "", "if (#eqStrings($1, $2)) goto $3;$n") proc branchHasTooBigRange(b: PNode): bool = - for i in countup(0, sonsLen(b) - 2): + for i in countup(0, sonsLen(b)-2): # last son is block if (b.sons[i].Kind == nkRange) and b.sons[i].sons[1].intVal - b.sons[i].sons[0].intVal > RangeExpandLimit: return true - result = false -proc genOrdinalCase(p: BProc, t: PNode) = - # We analyse if we have a too big switch range. If this is the case, - # we generate an ordinary if statement and rely on the C compiler - # to produce good code. - var - canGenerateSwitch, hasDefault: bool - length: int - a: TLoc - v: PNode - canGenerateSwitch = true - if not (hasSwitchRange in CC[ccompiler].props): - for i in countup(1, sonsLen(t) - 1): - if (t.sons[i].kind == nkOfBranch) and branchHasTooBigRange(t.sons[i]): - canGenerateSwitch = false - break - if canGenerateSwitch: - initLocExpr(p, t.sons[0], a) +proc IfSwitchSplitPoint(p: BProc, n: PNode): int = + for i in 1..n.len-1: + var branch = n[i] + var stmtBlock = lastSon(branch) + if stmtBlock.stmtsContainPragma(wLinearScanEnd): + result = i + elif hasSwitchRange notin CC[ccompiler].props: + if branch.kind == nkOfBranch and branchHasTooBigRange(branch): + result = i + +proc genOrdinalCase(p: BProc, n: PNode) = + # analyse 'case' statement: + var splitPoint = IfSwitchSplitPoint(p, n) + + # generate if part (might be empty): + var a: TLoc + initLocExpr(p, n.sons[0], a) + var Lend = if splitPoint > 0: genIfForCaseUntil(p, n, + rangeFormat = "if ($1 >= $2 && $1 <= $3) goto $4;$n", + eqFormat = "if ($1 == $2) goto $3;$n", + splitPoint, a) else: nil + + # generate switch part (might be empty): + if splitPoint+1 < n.len: appf(p.s[cpsStmts], "switch ($1) {$n", [rdCharLoc(a)]) - hasDefault = false - for i in countup(1, sonsLen(t) - 1): - if t.sons[i].kind == nkOfBranch: - length = sonsLen(t.sons[i]) - for j in countup(0, length - 2): - if t.sons[i].sons[j].kind == nkRange: - # a range + var hasDefault = false + for i in splitPoint+1 .. < n.len: + var branch = n[i] + if branch.kind == nkOfBranch: + var length = branch.len + for j in 0 .. length-2: + if branch[j].kind == nkRange: if hasSwitchRange in CC[ccompiler].props: appf(p.s[cpsStmts], "case $1 ... $2:$n", [ - genLiteral(p, t.sons[i].sons[j].sons[0]), - genLiteral(p, t.sons[i].sons[j].sons[1])]) + genLiteral(p, branch[j][0]), + genLiteral(p, branch[j][1])]) else: - v = copyNode(t.sons[i].sons[j].sons[0]) - while (v.intVal <= t.sons[i].sons[j].sons[1].intVal): + var v = copyNode(branch[j][0]) + while v.intVal <= branch[j][1].intVal: appf(p.s[cpsStmts], "case $1:$n", [genLiteral(p, v)]) Inc(v.intVal) else: - appf(p.s[cpsStmts], "case $1:$n", [genLiteral(p, t.sons[i].sons[j])]) - genStmts(p, t.sons[i].sons[length - 1]) + appf(p.s[cpsStmts], "case $1:$n", [genLiteral(p, branch[j])]) + genStmts(p, branch[length-1]) else: # else part of case statement: app(p.s[cpsStmts], "default:" & tnl) - genStmts(p, t.sons[i].sons[0]) + genStmts(p, branch[0]) hasDefault = true app(p.s[cpsStmts], "break;" & tnl) if (hasAssume in CC[ccompiler].props) and not hasDefault: app(p.s[cpsStmts], "default: __assume(0);" & tnl) app(p.s[cpsStmts], '}' & tnl) - else: - genCaseGeneric(p, t, "if ($1 >= $2 && $1 <= $3) goto $4;$n", - "if ($1 == $2) goto $3;$n") + if Lend != nil: fixLabel(p, Lend) proc genCaseStmt(p: BProc, t: PNode) = genLineDir(p, t) @@ -424,7 +404,6 @@ proc genCaseStmt(p: BProc, t: PNode) = genCaseGeneric(p, t, "if ($1 >= $2 && $1 <= $3) goto $4;$n", "if ($1 == $2) goto $3;$n") else: - # ordinal type: generate a switch statement genOrdinalCase(p, t) proc hasGeneralExceptSection(t: PNode): bool = @@ -629,19 +608,17 @@ proc genBreakPoint(p: BProc, t: PNode) = proc genPragma(p: BProc, n: PNode) = for i in countup(0, sonsLen(n) - 1): var it = n.sons[i] - var key = if it.kind == nkExprColonExpr: it.sons[0] else: it - if key.kind == nkIdent: - case whichKeyword(key.ident) - of wEmit: - genEmit(p, it) - of wBreakpoint: - genBreakPoint(p, it) - of wDeadCodeElim: - if not (optDeadCodeElim in gGlobalOptions): - # we need to keep track of ``deadCodeElim`` pragma - if (sfDeadCodeElim in p.module.module.flags): - addPendingModule(p.module) - else: nil + case whichPragma(it) + of wEmit: + genEmit(p, it) + of wBreakpoint: + genBreakPoint(p, it) + of wDeadCodeElim: + if not (optDeadCodeElim in gGlobalOptions): + # we need to keep track of ``deadCodeElim`` pragma + if (sfDeadCodeElim in p.module.module.flags): + addPendingModule(p.module) + else: nil proc genAsgn(p: BProc, e: PNode) = var a: TLoc diff --git a/rod/ccgutils.nim b/rod/ccgutils.nim index c7733c5ff..f1d66ca94 100755 --- a/rod/ccgutils.nim +++ b/rod/ccgutils.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2009 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -10,21 +10,58 @@ # This module declares some helpers for the C code generator. import - ast, astalgo, ropes, lists, nhashes, strutils, types, msgs + ast, astalgo, ropes, lists, nhashes, strutils, types, msgs, wordrecg, + platform -proc toCChar*(c: Char): string -proc makeCString*(s: string): PRope -proc makeLLVMString*(s: string): PRope -proc TableGetType*(tab: TIdTable, key: PType): PObject -proc GetUniqueType*(key: PType): PType -# implementation +proc whichPragma*(n: PNode): TSpecialWord = + var key = if n.kind == nkExprColonExpr: n.sons[0] else: n + if key.kind == nkIdent: result = whichKeyword(key.ident) + +proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode = + case n.kind + of nkStmtList: + for i in 0 .. < n.len: + result = getPragmaStmt(n[i], w) + if result != nil: break + of nkPragma: + for i in 0 .. < n.len: + if whichPragma(n[i]) == w: return n[i] + else: nil + +proc stmtsContainPragma*(n: PNode, w: TSpecialWord): bool = + result = getPragmaStmt(n, w) != nil + +proc hashString*(s: string): biggestInt = + # has to be the same algorithm as system.hashString! + if CPU[targetCPU].bit == 64: + # we have to use the same bitwidth + # as the target CPU + var b = 0'i64 + for i in countup(0, len(s) - 1): + b = b +% Ord(s[i]) + b = b +% `shl`(b, 10) + b = b xor `shr`(b, 6) + b = b +% `shl`(b, 3) + b = b xor `shr`(b, 11) + b = b +% `shl`(b, 15) + result = b + else: + var a = 0'i32 + for i in countup(0, len(s) - 1): + a = a +% Ord(s[i]).int32 + a = a +% `shl`(a, 10'i32) + a = a xor `shr`(a, 6'i32) + a = a +% `shl`(a, 3'i32) + a = a xor `shr`(a, 11'i32) + a = a +% `shl`(a, 15'i32) + result = a var gTypeTable: array[TTypeKind, TIdTable] proc initTypeTables() = for i in countup(low(TTypeKind), high(TTypeKind)): InitIdTable(gTypeTable[i]) -proc GetUniqueType(key: PType): PType = +proc GetUniqueType*(key: PType): PType = var t: PType k: TTypeKind @@ -32,33 +69,7 @@ proc GetUniqueType(key: PType): PType = result = key if key == nil: return k = key.kind - case k # - # case key.Kind of - # tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, - # tyInt..tyFloat128, tyProc, tyAnyEnum: begin end; - # tyNone, tyForward: - # InternalError('GetUniqueType: ' + typeToString(key)); - # tyGenericParam, tyGeneric, tyAbstract, tySequence, - # tyOpenArray, tySet, tyVar, tyRef, tyPtr, tyArrayConstr, - # tyArray, tyTuple, tyRange: begin - # // we have to do a slow linear search because types may need - # // to be compared by their structure: - # if IdTableHasObjectAsKey(gTypeTable, key) then exit; - # for h := 0 to high(gTypeTable.data) do begin - # t := PType(gTypeTable.data[h].key); - # if (t <> nil) and sameType(t, key) then begin result := t; exit end - # end; - # IdTablePut(gTypeTable, key, key); - # end; - # tyObject, tyEnum: begin - # result := PType(IdTableGet(gTypeTable, key)); - # if result = nil then begin - # IdTablePut(gTypeTable, key, key); - # result := key; - # end - # end; - # tyGenericInst, tyAbstract: result := GetUniqueType(lastSon(key)); - # end; + case k of tyObject, tyEnum: result = PType(IdTableGet(gTypeTable[k], key)) if result == nil: @@ -78,7 +89,7 @@ proc GetUniqueType(key: PType): PType = return t IdTablePut(gTypeTable[k], key, key) -proc TableGetType(tab: TIdTable, key: PType): PObject = +proc TableGetType*(tab: TIdTable, key: PType): PObject = var t: PType # returns nil if we need to declare this type result = IdTableGet(tab, key) @@ -91,13 +102,13 @@ proc TableGetType(tab: TIdTable, key: PType): PObject = if sameType(t, key): return tab.data[h].val -proc toCChar(c: Char): string = +proc toCChar*(c: Char): string = case c of '\0'..'\x1F', '\x80'..'\xFF': result = '\\' & toOctal(c) of '\'', '\"', '\\': result = '\\' & c else: result = $(c) -proc makeCString(s: string): PRope = +proc makeCString*(s: string): PRope = # BUGFIX: We have to split long strings into many ropes. Otherwise # this could trigger an InternalError(). See the ropes module for # further information. @@ -117,9 +128,8 @@ proc makeCString(s: string): PRope = add(res, '\"') app(result, toRope(res)) -proc makeLLVMString(s: string): PRope = - const - MaxLineLength = 64 +proc makeLLVMString*(s: string): PRope = + const MaxLineLength = 64 var res: string result = nil res = "c\"" @@ -135,4 +145,4 @@ proc makeLLVMString(s: string): PRope = add(res, "\\00\"") app(result, toRope(res)) -InitTypeTables() \ No newline at end of file +InitTypeTables() diff --git a/rod/cgen.nim b/rod/cgen.nim index 503cb8586..7df9f3d11 100755 --- a/rod/cgen.nim +++ b/rod/cgen.nim @@ -308,14 +308,19 @@ proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) = proc zeroTemp(p: BProc, loc: TLoc) = if skipTypes(loc.t, abstractVarRange).Kind notin {tyArray, tyArrayConstr, tySet, tyTuple, tyObject}: - var nilLoc: TLoc - initLoc(nilLoc, locTemp, loc.t, onStack) - nilLoc.r = toRope("NIM_NIL") - # puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``: - genRefAssign(p, loc, nilLoc, {afSrcIsNil}) + appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)]) + when false: + var nilLoc: TLoc + initLoc(nilLoc, locTemp, loc.t, onStack) + nilLoc.r = toRope("NIM_NIL") + # puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``: + genRefAssign(p, loc, nilLoc, {afSrcIsNil}) else: - appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", - [addrLoc(loc), genTypeInfo(p.module, loc.t)]) + appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n", + [addrLoc(loc), rdLoc(loc)]) + when false: + appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", + [addrLoc(loc), genTypeInfo(p.module, loc.t)]) proc initVariable(p: BProc, v: PSym) = var b = containsGarbageCollectedRef(v.typ) diff --git a/rod/main.nim b/rod/main.nim index 977a4ff1b..79059a874 100755 --- a/rod/main.nim +++ b/rod/main.nim @@ -193,23 +193,23 @@ proc MainCommand(cmd, filename: string) = setID(100) passes.gIncludeFile = syntaxes.parseFile passes.gImportModule = importModule - case whichKeyword(cmd) - of wCompile, wCompileToC, wC, wCC: + case cmd.normalize + of "c", "cc", "compile", "compiletoc": # compile means compileToC currently gCmd = cmdCompileToC wantFile(filename) CommandCompileToC(filename) - of wCompileToCpp: + of "compiletocpp": extccomp.cExt = ".cpp" gCmd = cmdCompileToCpp wantFile(filename) CommandCompileToC(filename) - of wCompileToOC, wOC: + of "oc", "compiletooc": extccomp.cExt = ".m" gCmd = cmdCompileToOC wantFile(filename) CommandCompileToC(filename) - of wRun: + of "run": gCmd = cmdRun wantFile(filename) when hasTinyCBackend: @@ -217,61 +217,61 @@ proc MainCommand(cmd, filename: string) = CommandCompileToC(filename) else: rawMessage(errInvalidCommandX, cmd) - of wCompileToEcmaScript, wJs: + of "js", "compiletoecmascript": gCmd = cmdCompileToEcmaScript wantFile(filename) CommandCompileToEcmaScript(filename) - of wCompileToLLVM: + of "compiletollvm": gCmd = cmdCompileToLLVM wantFile(filename) when has_LLVM_Backend: CommandCompileToLLVM(filename) else: rawMessage(errInvalidCommandX, cmd) - of wPretty: + of "pretty": gCmd = cmdPretty wantFile(filename) #CommandExportSymbols(filename); CommandPretty(filename) - of wDoc: + of "doc": gCmd = cmdDoc LoadSpecialConfig(DocConfig) wantFile(filename) CommandDoc(filename) - of wRst2html: + of "rst2html": gCmd = cmdRst2html LoadSpecialConfig(DocConfig) wantFile(filename) CommandRst2Html(filename) - of wRst2tex: + of "rst2tex": gCmd = cmdRst2tex LoadSpecialConfig(DocTexConfig) wantFile(filename) CommandRst2TeX(filename) - of wGenDepend: + of "gendepend": gCmd = cmdGenDepend wantFile(filename) CommandGenDepend(filename) - of wDump: + of "dump": gCmd = cmdDump condsyms.ListSymbols() for it in iterSearchPath(): MsgWriteln(it) - of wCheck: + of "check": gCmd = cmdCheck wantFile(filename) CommandCheck(filename) - of wParse: + of "parse": gCmd = cmdParse wantFile(filename) discard parseFile(addFileExt(filename, nimExt)) - of wScan: + of "scan": gCmd = cmdScan wantFile(filename) CommandScan(filename) MsgWriteln("Beware: Indentation tokens depend on the parser\'s state!") - of wI: + of "i": gCmd = cmdInteractive CommandInteractive() - of wIdeTools: + of "idetools": gCmd = cmdIdeTools wantFile(filename) CommandSuggest(filename) diff --git a/rod/pragmas.nim b/rod/pragmas.nim index 45543eb74..d7bda4099 100755 --- a/rod/pragmas.nim +++ b/rod/pragmas.nim @@ -34,12 +34,12 @@ const wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wBreakpoint, wCheckpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wFloatChecks, - wInfChecks, wNanChecks, wPragma, wEmit} + wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wLinearScanEnd} lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wPure, wDeprecated, wExtern} typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, - wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern} + wPure, wHeader, wCompilerProc, wFinal, wSize, wExtern, wShallow} fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern} varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, wMagic, wHeader, wDeprecated, wCompilerProc, wDynLib, wExtern} @@ -357,6 +357,19 @@ proc PragmaEmit(c: PContext, n: PNode) = proc noVal(n: PNode) = if n.kind == nkExprColonExpr: invalidPragma(n) +proc PragmaUnroll(c: PContext, n: PNode) = + if c.p.nestedLoopCounter <= 0: + invalidPragma(n) + elif n.kind == nkExprColonExpr: + var unrollFactor = expectIntLit(c, n) + if unrollFactor <% 32: + n.sons[1] = newIntNode(nkIntLit, unrollFactor) + else: + invalidPragma(n) + +proc PragmaLinearScanEnd(c: PContext, n: PNode) = + noVal(n) + proc processPragma(c: PContext, n: PNode, i: int) = var it = n.sons[i] if it.kind != nkExprColonExpr: invalidPragma(n) @@ -475,6 +488,10 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = noVal(it) if sym.typ == nil: invalidPragma(it) incl(sym.typ.flags, tfAcyclic) + of wShallow: + noVal(it) + if sym.typ == nil: invalidPragma(it) + incl(sym.typ.flags, tfShallow) of wTypeCheck: noVal(it) incl(sym.flags, sfTypeCheck) @@ -509,6 +526,8 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = if sym.typ == nil: invalidPragma(it) sym.typ.callConv = wordToCallConv(k) of wEmit: PragmaEmit(c, it) + of wUnroll: PragmaUnroll(c, it) + of wLinearScanEnd: PragmaLinearScanEnd(c, it) else: invalidPragma(it) else: invalidPragma(it) else: processNote(c, it) diff --git a/rod/rst.nim b/rod/rst.nim index efda9bd9a..dace43a44 100755 --- a/rod/rst.nim +++ b/rod/rst.nim @@ -188,7 +188,7 @@ proc rawGetTok(L: var TLexer, tok: var TToken) = of '\x0D', '\x0A': getIndent(L, tok) of '!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', - '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', + '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~': getAdornment(L, tok) if len(tok.symbol) <= 3: tok.kind = tkPunct @@ -257,16 +257,16 @@ type value*: PRstNode TSharedState{.final.} = object - uLevel*, oLevel*: int # counters for the section levels - subs*: seq[TSubstitution] # substitutions - refs*: seq[TSubstitution] # references + uLevel*, oLevel*: int # counters for the section levels + subs*: seq[TSubstitution] # substitutions + refs*: seq[TSubstitution] # references underlineToLevel*: TLevelMap # Saves for each possible title adornment # character its level in the # current document. # This is for single underline adornments. - overlineToLevel*: TLevelMap # Saves for each possible title adornment - # character its level in the current document. - # This is for over-underline adornments. + overlineToLevel*: TLevelMap # Saves for each possible title adornment + # character its level in the current document. + # This is for over-underline adornments. PSharedState = ref TSharedState TRstParser = object of TObject diff --git a/rod/semexprs.nim b/rod/semexprs.nim index 1d20e5253..7a14b931a 100755 --- a/rod/semexprs.nim +++ b/rod/semexprs.nim @@ -410,10 +410,13 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = proc semDirectCallAnalyseEffects(c: PContext, n: PNode, flags: TExprFlags): PNode = - if not (efWantIterator in flags): - result = semDirectCall(c, n, {skProc, skMethod, skConverter}) - else: - result = semDirectCall(c, n, {skIterator}) + var symflags = {skProc, skMethod, skConverter} + if efWantIterator in flags: + symflags = {skIterator} + elif efAllowType in flags: + # for ``type countup(1,3)``, see ``tests/ttoseq``. + symflags.incl(skIterator) + result = semDirectCall(c, n, symflags) if result != nil: if result.sons[0].kind != nkSym: InternalError("semDirectCallAnalyseEffects") @@ -1037,7 +1040,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of paNone: result = nil of paTuplePositions: result = semTuplePositionsConstr(c, n) of paTupleFields: result = semTupleFieldsConstr(c, n) - of paSingle: result = semExpr(c, n.sons[0]) + of paSingle: result = semExpr(c, n.sons[0], flags) of nkCurly: result = semSetConstr(c, n) of nkBracket: result = semArrayConstr(c, n) of nkLambda: result = semLambda(c, n) diff --git a/rod/semtypes.nim b/rod/semtypes.nim index 4a676e00a..8dae5c27b 100755 --- a/rod/semtypes.nim +++ b/rod/semtypes.nim @@ -574,7 +574,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = case n.kind of nkEmpty: nil of nkTypeOfExpr: - result = semExprWithType(c, n, {efAllowType}).typ + checkSonsLen(n, 1) + result = semExprWithType(c, n.sons[0], {efAllowType}).typ of nkPar: if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) else: GlobalError(n.info, errTypeExpected) diff --git a/rod/transf.nim b/rod/transf.nim index 5b62c7f16..c7c4e3db8 100755 --- a/rod/transf.nim +++ b/rod/transf.nim @@ -340,10 +340,6 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode = #result = newTransNode(n.sons[0]) #result[1] = transform(c, m.sons[0]) - #if skipTypes(n.sons[0].typ, abstractVar).kind == tyOpenArray: - # debug(result.pnode) - # liMessage(n.info, warnUser, - # "nkPassAsOpenArray introduced here " & renderTree(n)) else: result = transformSons(c, n) else: diff --git a/rod/wordrecg.nim b/rod/wordrecg.nim index f9ea37158..8376fa01b 100755 --- a/rod/wordrecg.nim +++ b/rod/wordrecg.nim @@ -53,12 +53,8 @@ type 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, - wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, - wCompileToOC, - wPretty, - wDoc, wGenDepend, wDump, wCheck, wParse, wScan, wJs, wOC, - wRst2html, wRst2tex, wI, + wAcyclic, wShallow, wUnroll, wLinearScanEnd, + wIndex, wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads, wRecursivePath, wStdout, @@ -105,33 +101,25 @@ 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", - "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", - "compiletooc", - "pretty", "doc", "gendepend", "dump", "check", "parse", "scan", - "js", "oc", "rst2html", "rst2tex", "i", + "nomain", "subschar", "acyclic", "shallow", "unroll", "linearscanend", + "index", "write", "putenv", "prependenv", "appendenv", "threadvar", "emit", "threads", "recursivepath", "stdout", "idetools", "suggest", "track", "def", "context"] -proc whichKeyword*(id: PIdent): TSpecialWord -proc whichKeyword*(id: String): TSpecialWord -proc findStr*(a: openarray[string], s: string): int -# implementation - -proc findStr(a: openarray[string], s: string): int = +proc findStr*(a: openarray[string], s: string): int = for i in countup(low(a), high(a)): if cmpIgnoreStyle(a[i], s) == 0: return i result = - 1 -proc whichKeyword(id: String): TSpecialWord = - result = whichKeyword(getIdent(id)) - -proc whichKeyword(id: PIdent): TSpecialWord = +proc whichKeyword*(id: PIdent): TSpecialWord = if id.id < 0: result = wInvalid else: result = TSpecialWord(id.id) + +proc whichKeyword*(id: String): TSpecialWord = + result = whichKeyword(getIdent(id)) proc initSpecials() = # initialize the keywords: |